Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8477f7f79c | |||
| ee9d4d7fed | |||
| 53872e7259 | |||
| 3d6bedf14f | |||
| 12b0fabde2 | |||
| 3b3c86ade2 | |||
| 110e3afd11 | |||
| 35284b6c48 |
@@ -1,6 +0,0 @@
|
||||
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.
|
||||
+42
-127
@@ -22,7 +22,7 @@ TOP = @abs_srcdir@
|
||||
#
|
||||
BCC = @BUILD_CC@ @BUILD_CFLAGS@
|
||||
|
||||
# TCC is the C Compile and options for use in building executables that
|
||||
# TCC is the C Compile and options for use in building executables that
|
||||
# will run on the target platform. (BCC and TCC are usually the
|
||||
# same unless your are cross-compiling.) Separate CC and CFLAGS macros
|
||||
# are provide so that these aspects of the build process can be changed
|
||||
@@ -32,11 +32,10 @@ CC = @CC@
|
||||
CFLAGS = @CPPFLAGS@ @CFLAGS@
|
||||
TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu
|
||||
TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session
|
||||
TCC += -I${TOP}/ext/userauth
|
||||
|
||||
# Define this for the autoconf-based build, so that the code knows it can
|
||||
# include the generated config.h
|
||||
#
|
||||
#
|
||||
TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
|
||||
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
|
||||
@@ -67,7 +66,7 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
|
||||
TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
|
||||
|
||||
# Any target libraries which libsqlite must be linked against
|
||||
#
|
||||
#
|
||||
TLIBS = @LIBS@ $(LIBS)
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
@@ -79,8 +78,8 @@ TLIBS = @LIBS@ $(LIBS)
|
||||
TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
|
||||
@@ -127,8 +126,8 @@ SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
|
||||
# If gcov support was enabled by the configure script, add the appropriate
|
||||
# flags here. It's not always as easy as just having the user add the right
|
||||
# CFLAGS / LDFLAGS, because libtool wants to use CFLAGS when linking, which
|
||||
# causes build errors with -fprofile-arcs -ftest-coverage with some GCCs.
|
||||
# Supposedly GCC does the right thing if you use --coverage, but in
|
||||
# causes build errors with -fprofile-arcs -ftest-coverage with some GCCs.
|
||||
# Supposedly GCC does the right thing if you use --coverage, but in
|
||||
# practice it still fails. See:
|
||||
#
|
||||
# http://www.mail-archive.com/debian-gcc@lists.debian.org/msg26197.html
|
||||
@@ -188,10 +187,9 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo \
|
||||
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
|
||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||
update.lo userauth.lo upsert.lo util.lo vacuum.lo \
|
||||
update.lo upsert.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo vdbevtab.lo \
|
||||
wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
window.lo utf.lo vtab.lo
|
||||
|
||||
# Object files for the amalgamation.
|
||||
@@ -297,7 +295,6 @@ SRC = \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbesort.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbevtab.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/vxworks.h \
|
||||
@@ -358,9 +355,6 @@ SRC += \
|
||||
SRC += \
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/session/sqlite3session.h
|
||||
SRC += \
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
@@ -424,7 +418,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_tclsh.c \
|
||||
$(TOP)/src/test_tclvar.c \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vdbecov.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_window.c \
|
||||
@@ -432,7 +425,7 @@ TESTSRC = \
|
||||
$(TOP)/ext/fts3/fts3_term.c \
|
||||
$(TOP)/ext/fts3/fts3_test.c \
|
||||
$(TOP)/ext/session/test_session.c \
|
||||
$(TOP)/ext/rbu/test_rbu.c
|
||||
$(TOP)/ext/rbu/test_rbu.c
|
||||
|
||||
# Statically linked extensions
|
||||
#
|
||||
@@ -443,7 +436,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/carray.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/csv.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/explain.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
@@ -456,7 +448,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/prefixes.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
@@ -464,8 +455,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/userauth/userauth.c
|
||||
$(TOP)/ext/misc/zipfile.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
#
|
||||
@@ -481,7 +471,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/dbstat.c \
|
||||
$(TOP)/src/expr.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/global.c \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/main.c \
|
||||
@@ -505,7 +494,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/vdbe.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbevtab.c \
|
||||
$(TOP)/src/where.c \
|
||||
$(TOP)/src/wherecode.c \
|
||||
$(TOP)/src/whereexpr.c \
|
||||
@@ -519,7 +507,7 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c \
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -572,8 +560,6 @@ EXTHDR += \
|
||||
$(TOP)/ext/icu/sqliteicu.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/rtree/sqlite3rtree.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
|
||||
# executables needed for testing
|
||||
#
|
||||
@@ -593,9 +579,7 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db \
|
||||
$(TOP)/test/fuzzdata6.db \
|
||||
$(TOP)/test/fuzzdata7.db \
|
||||
$(TOP)/test/fuzzdata8.db
|
||||
$(TOP)/test/fuzzdata6.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@@ -611,23 +595,14 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
DBFUZZ_OPT =
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
@@ -684,43 +659,11 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
|
||||
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
|
||||
$(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
|
||||
|
||||
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
DBFUZZ2_OPTS = \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_DESERIALIZE \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_ENABLE_FTS5
|
||||
|
||||
dbfuzz2$(TEXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
|
||||
$(CC) $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
|
||||
-DSTANDALONE -o dbfuzz2 \
|
||||
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
|
||||
mkdir -p dbfuzz2-dir
|
||||
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
|
||||
|
||||
dbfuzz2-asan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
|
||||
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
|
||||
-fsanitize=fuzzer,undefined,address -o dbfuzz2-asan \
|
||||
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
|
||||
mkdir -p dbfuzz2-dir
|
||||
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
|
||||
|
||||
dbfuzz2-msan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
|
||||
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
|
||||
-fsanitize=fuzzer,undefined,memory -o dbfuzz2-msan \
|
||||
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
|
||||
mkdir -p dbfuzz2-dir
|
||||
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
|
||||
|
||||
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
@@ -1012,9 +955,6 @@ vdbesort.lo: $(TOP)/src/vdbesort.c $(HDR)
|
||||
vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c
|
||||
|
||||
vdbevtab.lo: $(TOP)/src/vdbevtab.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbevtab.c
|
||||
|
||||
vtab.lo: $(TOP)/src/vtab.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c
|
||||
|
||||
@@ -1061,19 +1001,16 @@ opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon$(BEXE)
|
||||
parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
|
||||
cp $(TOP)/src/parse.y .
|
||||
./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
rm -f parse.h
|
||||
./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
mv parse.h parse.h.temp
|
||||
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
|
||||
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
|
||||
|
||||
sqlite3rc.h: $(TOP)/src/sqlite3.rc $(TOP)/VERSION
|
||||
echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
|
||||
echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
|
||||
cat $(TOP)/VERSION | $(TCLSH_CMD) $(TOP)/tool/replace.tcl exact . , >>$@
|
||||
echo '#endif' >>sqlite3rc.h
|
||||
|
||||
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
|
||||
./mkkeywordhash$(BEXE) >keywordhash.h
|
||||
@@ -1082,17 +1019,13 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
SHELL_SRC = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/src/test_windirent.c
|
||||
|
||||
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
|
||||
@@ -1166,9 +1099,6 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
userauth.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
|
||||
|
||||
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
@@ -1197,10 +1127,10 @@ FTS5_SRC = \
|
||||
$(TOP)/ext/fts5/fts5_varint.c \
|
||||
$(TOP)/ext/fts5/fts5_vocab.c \
|
||||
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon$(BEXE)
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
cp $(TOP)/ext/fts5/fts5parse.y .
|
||||
rm -f fts5parse.h
|
||||
./lemon$(BEXE) $(OPTS) -S fts5parse.y
|
||||
./lemon$(BEXE) $(OPTS) fts5parse.y
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
@@ -1224,14 +1154,12 @@ sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
|
||||
#
|
||||
TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
|
||||
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
||||
TESTFIXTURE_FLAGS += -DBUILD_sqlite
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||
TESTFIXTURE_SRC1 = sqlite3.c
|
||||
@@ -1242,10 +1170,6 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
|
||||
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
|
||||
|
||||
coretestprogs: $(TESTPROGS)
|
||||
|
||||
testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)
|
||||
|
||||
# A very detailed test running most or all test cases
|
||||
fulltest: $(TESTPROGS) fuzztest
|
||||
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
|
||||
@@ -1263,6 +1187,10 @@ fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuz
|
||||
./fuzzcheck$(TEXE) $(FUZZDATA)
|
||||
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
|
||||
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
|
||||
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
@@ -1280,7 +1208,7 @@ quicktest: ./testfixture$(TEXE)
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
# Run a test using valgrind. This can take a really long time
|
||||
# because valgrind is so much slower than a native machine.
|
||||
@@ -1295,16 +1223,13 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||
|
||||
shelltest: $(TESTPROGS)
|
||||
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
|
||||
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
|
||||
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
|
||||
|
||||
sqltclsh$(TEXE): sqltclsh.c
|
||||
@@ -1333,9 +1258,6 @@ dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
|
||||
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
|
||||
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
|
||||
|
||||
dbtotxt$(TEXE): $(TOP)/tool/dbtotxt.c
|
||||
$(LTLINK)-o $@ $(TOP)/tool/dbtotxt.c
|
||||
|
||||
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
|
||||
|
||||
@@ -1351,15 +1273,9 @@ showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
|
||||
showshm$(TEXE): $(TOP)/tool/showshm.c
|
||||
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
|
||||
|
||||
index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
|
||||
$(LTLINK) $(SHELL_OPT) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
|
||||
|
||||
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
|
||||
|
||||
changesetfuzz$(TEXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(TLIBS)
|
||||
|
||||
rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)
|
||||
|
||||
@@ -1380,7 +1296,7 @@ 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)
|
||||
|
||||
loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
|
||||
@@ -1391,25 +1307,24 @@ loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la
|
||||
# releasetest.tcl script.
|
||||
#
|
||||
VALIDIDS=' sqlite3(changeset|changegroup|session)?_'
|
||||
checksymbols: sqlite3.o
|
||||
nm -g --defined-only sqlite3.o
|
||||
nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
|
||||
checksymbols: sqlite3.lo
|
||||
nm -g --defined-only sqlite3.lo | egrep -v $(VALIDIDS); test $$? -ne 0
|
||||
echo '0 errors out of 1 tests'
|
||||
|
||||
# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
|
||||
# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
|
||||
# The snapshot-tarball target builds a tarball named by the SHA1 hash
|
||||
#
|
||||
amalgamation-tarball: sqlite3.c sqlite3rc.h
|
||||
amalgamation-tarball: sqlite3.c
|
||||
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal
|
||||
|
||||
snapshot-tarball: sqlite3.c sqlite3rc.h
|
||||
snapshot-tarball: sqlite3.c
|
||||
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
|
||||
|
||||
# The next two rules are used to support the "threadtest" target. Building
|
||||
# threadtest runs a few thread-safety tests that are implemented in C. This
|
||||
# target is invoked by the releasetest.tcl script.
|
||||
#
|
||||
#
|
||||
THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_checkpoint.c \
|
||||
$(TOP)/test/tt3_index.c \
|
||||
@@ -1423,7 +1338,7 @@ threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
|
||||
threadtest: threadtest3$(TEXE)
|
||||
./threadtest3$(TEXE)
|
||||
|
||||
releasetest:
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
|
||||
|
||||
# Standard install and cleanup targets
|
||||
@@ -1431,7 +1346,7 @@ releasetest:
|
||||
lib_install: libsqlite3.la
|
||||
$(INSTALL) -d $(DESTDIR)$(libdir)
|
||||
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
|
||||
|
||||
|
||||
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
$(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
|
||||
@@ -1442,14 +1357,14 @@ install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
|
||||
$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
pkgIndex.tcl:
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
|
||||
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
|
||||
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
|
||||
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
|
||||
rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
|
||||
$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
|
||||
|
||||
clean:
|
||||
clean:
|
||||
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
|
||||
rm -f sqlite3.h opcodes.*
|
||||
rm -rf .libs .deps
|
||||
|
||||
+17
-9
@@ -19,7 +19,7 @@ TOP = ../sqlite
|
||||
#### C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
BCC = gcc -g -O0
|
||||
BCC = gcc -g -O2
|
||||
#BCC = /opt/ancic/bin/c89 -0
|
||||
|
||||
#### If the target operating system supports the "usleep()" system
|
||||
@@ -38,8 +38,8 @@ THREADSAFE = -DTHREADSAFE=0
|
||||
#### Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
THREADLIB = -lpthread -lm -ldl
|
||||
#THREADLIB =
|
||||
#THREADLIB = -lpthread
|
||||
THREADLIB =
|
||||
|
||||
#### Specify any extra libraries needed to access required functions.
|
||||
#
|
||||
@@ -54,9 +54,11 @@ TLIBS =
|
||||
# You can make the library go almost twice as fast if you compile
|
||||
# with -DNDEBUG=1
|
||||
#
|
||||
OPTS += -DSQLITE_DEBUG=1
|
||||
OPTS += -DSQLITE_ENABLE_WHERETRACE
|
||||
OPTS += -DSQLITE_ENABLE_SELECTTRACE
|
||||
#OPTS = -DSQLITE_DEBUG=2
|
||||
#OPTS = -DSQLITE_DEBUG=1
|
||||
#OPTS =
|
||||
OPTS = -DNDEBUG=1
|
||||
OPTS += -DHAVE_FDATASYNC=1
|
||||
|
||||
#### The suffix to add to executable files. ".exe" for windows.
|
||||
# Nothing for unix.
|
||||
@@ -68,7 +70,7 @@ EXE =
|
||||
# will run on the target platform. This is usually the same
|
||||
# as BCC, unless you are cross-compiling.
|
||||
#
|
||||
TCC = gcc -O0
|
||||
TCC = gcc -O6
|
||||
#TCC = gcc -g -O0 -Wall
|
||||
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
|
||||
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
|
||||
@@ -89,12 +91,18 @@ SHPREFIX = lib
|
||||
|
||||
#### Extra compiler options needed for programs that use the TCL library.
|
||||
#
|
||||
TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6
|
||||
#TCL_FLAGS =
|
||||
#TCL_FLAGS = -DSTATIC_BUILD=1
|
||||
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
|
||||
|
||||
#### Linker options needed to link against the TCL library.
|
||||
#
|
||||
#LIBTCL = -ltcl -lm -ldl
|
||||
LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz
|
||||
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
|
||||
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
|
||||
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
|
||||
|
||||
#### Additional objects for SQLite library when TCL support is enabled.
|
||||
#TCLOBJ =
|
||||
|
||||
+36
-145
@@ -73,7 +73,7 @@ API_ARMOR = 0
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -234,15 +234,6 @@ OSTRACE = 0
|
||||
DEBUG = 0
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
# Disable use of the --linemacros argument to the mksqlite3c.tcl tool, which
|
||||
# is used to build the amalgamation.
|
||||
#
|
||||
!IFNDEF NO_LINEMACROS
|
||||
NO_LINEMACROS = 0
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
# Enable use of available compiler optimizations? Normally, this should be
|
||||
# non-zero. Setting this to zero, thus disabling all compiler optimizations,
|
||||
# can be useful for testing.
|
||||
@@ -257,12 +248,6 @@ OPTIMIZATIONS = 2
|
||||
SESSION = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for the rbu extension.
|
||||
#
|
||||
!IFNDEF RBU
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -335,13 +320,6 @@ SQLITETCLH = sqlite_tcl.h
|
||||
SQLITETCLDECLSH = sqlite_tclDecls.h
|
||||
!ENDIF
|
||||
|
||||
# This is the name to use for the dynamic link library (DLL) containing the
|
||||
# Tcl bindings for SQLite.
|
||||
#
|
||||
!IFNDEF SQLITE3TCLDLL
|
||||
SQLITE3TCLDLL = tclsqlite3.dll
|
||||
!ENDIF
|
||||
|
||||
# These are the additional targets that the targets that integrate with the
|
||||
# Tcl library should depend on when compiling, etc.
|
||||
#
|
||||
@@ -366,8 +344,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -380,13 +357,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
!ENDIF
|
||||
|
||||
# Should the rbu extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
!IF $(RBU)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
||||
!ENDIF
|
||||
|
||||
# These are the "extended" SQLite compilation options used when compiling for
|
||||
# the Windows 10 platform.
|
||||
#
|
||||
@@ -524,9 +494,9 @@ UCRTLIBPATH = $(UCRTLIBPATH:\\=\)
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
BCC = $(NCC) -nologo -W4 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
|
||||
!ELSE
|
||||
BCC = $(NCC) -nologo -W3 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
@@ -785,7 +755,7 @@ MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF MKSQLITE3C_ARGS
|
||||
!IF $(DEBUG)>1 && $(NO_LINEMACROS)==0
|
||||
!IF $(DEBUG)>1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
@@ -882,14 +852,6 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
|
||||
# prior to running nmake in order to match the actual installed location and
|
||||
# version on this machine.
|
||||
#
|
||||
!IFNDEF TCLVERSION
|
||||
TCLVERSION = 86
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLSUFFIX
|
||||
TCLSUFFIX =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLDIR
|
||||
TCLDIR = $(TOP)\compat\tcl
|
||||
!ENDIF
|
||||
@@ -903,11 +865,11 @@ TCLLIBDIR = $(TCLDIR)\lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCL
|
||||
LIBTCL = tcl$(TCLVERSION)$(TCLSUFFIX).lib
|
||||
LIBTCL = tcl86.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLSTUB
|
||||
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
|
||||
LIBTCLSTUB = tclstub86.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLPATH
|
||||
@@ -1100,7 +1062,7 @@ RCC = $(RCC) -I$(ICUINCDIR)
|
||||
# Command line prefixes for compiling code, compiling resources,
|
||||
# linking, etc.
|
||||
#
|
||||
LTCOMPILE = $(TCC) -Fo$@ -Fd$*.pdb
|
||||
LTCOMPILE = $(TCC) -Fo$@
|
||||
LTRCOMPILE = $(RCC) -r
|
||||
LTLIB = lib.exe
|
||||
LTLINK = $(TCC) -Fe$@
|
||||
@@ -1118,11 +1080,6 @@ LTLIBS = $(LTLIBS) rpcrt4.lib
|
||||
!IFDEF PLATFORM
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
!ELSEIF "$(VISUALSTUDIOVERSION)"=="12.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="14.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="15.0"
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:x86
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:x86
|
||||
!ELSE
|
||||
LTLINKOPTS = /NOLOGO
|
||||
LTLIBOPTS = /NOLOGO
|
||||
@@ -1256,8 +1213,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||
update.lo upsert.lo util.lo vacuum.lo \
|
||||
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo vdbevtab.lo wal.lo walker.lo where.lo wherecode.lo \
|
||||
whereexpr.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
window.lo utf.lo vtab.lo
|
||||
# <</mark>>
|
||||
|
||||
@@ -1364,7 +1320,6 @@ SRC01 = \
|
||||
$(TOP)\src\vdbemem.c \
|
||||
$(TOP)\src\vdbesort.c \
|
||||
$(TOP)\src\vdbetrace.c \
|
||||
$(TOP)\src\vdbevtab.c \
|
||||
$(TOP)\src\vtab.c \
|
||||
$(TOP)\src\wal.c \
|
||||
$(TOP)\src\walker.c \
|
||||
@@ -1495,7 +1450,7 @@ SRC12 =
|
||||
|
||||
# All source code files.
|
||||
#
|
||||
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) $(SRC12)
|
||||
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
|
||||
|
||||
# Source code to the test files.
|
||||
#
|
||||
@@ -1541,7 +1496,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test_tclsh.c \
|
||||
$(TOP)\src\test_tclvar.c \
|
||||
$(TOP)\src\test_thread.c \
|
||||
$(TOP)\src\test_vdbecov.c \
|
||||
$(TOP)\src\test_vfs.c \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_window.c \
|
||||
@@ -1560,7 +1514,6 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\carray.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
$(TOP)\ext\misc\csv.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\eval.c \
|
||||
$(TOP)\ext\misc\explain.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
@@ -1573,7 +1526,6 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\nextchar.c \
|
||||
$(TOP)\ext\misc\normalize.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\prefixes.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
@@ -1671,9 +1623,7 @@ FUZZDATA = \
|
||||
$(TOP)\test\fuzzdata3.db \
|
||||
$(TOP)\test\fuzzdata4.db \
|
||||
$(TOP)\test\fuzzdata5.db \
|
||||
$(TOP)\test\fuzzdata6.db \
|
||||
$(TOP)\test\fuzzdata7.db \
|
||||
$(TOP)\test\fuzzdata8.db
|
||||
$(TOP)\test\fuzzdata6.db
|
||||
# <</mark>>
|
||||
|
||||
# Additional compiler options for the shell. These are only effective
|
||||
@@ -1683,7 +1633,6 @@ FUZZDATA = \
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
@@ -1691,14 +1640,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
@@ -1712,7 +1654,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
|
||||
# Extra targets for the "all" target that require Tcl.
|
||||
#
|
||||
!IF $(NO_TCL)==0
|
||||
ALL_TCL_TARGETS = $(SQLITE3TCLDLL)
|
||||
ALL_TCL_TARGETS = libtclsqlite3.lib
|
||||
!ELSE
|
||||
ALL_TCL_TARGETS =
|
||||
!ENDIF
|
||||
@@ -1744,22 +1686,7 @@ libsqlite3.lib: $(LIBOBJ)
|
||||
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
|
||||
|
||||
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
|
||||
$(LTLIB) $(LTLIBOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
|
||||
|
||||
tclsqlite3.def: tclsqlite.lo
|
||||
echo EXPORTS > tclsqlite3.def
|
||||
dumpbin /all tclsqlite.lo \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+/EXPORT:_?((?:Sqlite3|Tclsqlite3)_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| sort >> tclsqlite3.def
|
||||
|
||||
pkgIndex.tcl: $(TOP)\VERSION
|
||||
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
|
||||
echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] sqlite3] \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact @version@ %%V > pkgIndex.tcl \
|
||||
)
|
||||
|
||||
$(SQLITE3TCLDLL): libtclsqlite3.lib $(LIBRESOBJS) tclsqlite3.def pkgIndex.tcl
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:tclsqlite3.def /OUT:$@ libtclsqlite3.lib $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
|
||||
# <</mark>>
|
||||
|
||||
$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
@@ -1769,7 +1696,7 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
sqlite3.def: libsqlite3.lib
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all libsqlite3.lib \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| sort >> sqlite3.def
|
||||
# <</block2>>
|
||||
|
||||
@@ -1800,10 +1727,10 @@ dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
|
||||
@@ -1847,16 +1774,15 @@ mptest: mptester.exe
|
||||
for %i in ($(SRC11)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC12)) do copy /Y %i tsrc
|
||||
copy /Y fts5.c tsrc
|
||||
copy /B tsrc\fts5.c +,,
|
||||
copy /Y fts5.h tsrc
|
||||
copy /B tsrc\fts5.h +,,
|
||||
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
|
||||
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
|
||||
move vdbe.new tsrc\vdbe.c
|
||||
echo > .target_source
|
||||
|
||||
sqlite3.c: .target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL)
|
||||
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
|
||||
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
|
||||
copy $(TOP)\ext\session\sqlite3session.h .
|
||||
|
||||
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
|
||||
@@ -1871,8 +1797,7 @@ sqlite3.lo: $(SQLITE3C)
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lempar.c: $(TOP)\tool\lempar.c
|
||||
copy /Y $(TOP)\tool\lempar.c .
|
||||
copy /B lempar.c +,,
|
||||
copy $(TOP)\tool\lempar.c .
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) $(NO_WARN) -Daccess=_access \
|
||||
@@ -1901,7 +1826,7 @@ opcodes.lo: opcodes.c
|
||||
#
|
||||
!IF $(USE_RC)!=0
|
||||
# <<block1>>
|
||||
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) $(TOP)\VERSION
|
||||
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H)
|
||||
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
|
||||
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
|
||||
echo #define SQLITE_RESOURCE_VERSION %%V \
|
||||
@@ -2125,9 +2050,6 @@ vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR)
|
||||
vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c
|
||||
|
||||
vdbevtab.lo: $(TOP)\src\vdbevtab.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbevtab.c
|
||||
|
||||
vtab.lo: $(TOP)\src\vtab.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c
|
||||
|
||||
@@ -2170,11 +2092,12 @@ opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)\src\parse.y lemon.exe
|
||||
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
|
||||
del /Q parse.y parse.h parse.h.temp 2>NUL
|
||||
copy /Y $(TOP)\src\parse.y .
|
||||
copy /B parse.y +,,
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
copy $(TOP)\src\parse.y .
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
move parse.h parse.h.temp
|
||||
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
@@ -2186,13 +2109,8 @@ sqlite3ext.h: .target_source
|
||||
copy /Y sqlite3ext.h tsrc\sqlite3ext.h
|
||||
!ELSE
|
||||
copy /Y tsrc\sqlite3ext.h sqlite3ext.h
|
||||
copy /B sqlite3ext.h +,,
|
||||
!ENDIF
|
||||
|
||||
sqlite3session.h: $(TOP)\ext\session\sqlite3session.h
|
||||
copy /Y $(TOP)\ext\session\sqlite3session.h .
|
||||
copy /B sqlite3session.h +,,
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
|
||||
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
@@ -2204,15 +2122,11 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
SHELL_SRC = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\src\test_windirent.c
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
@@ -2340,22 +2254,19 @@ LSM1_SRC = \
|
||||
$(TOP)\ext\lsm1\lsm_win32.c
|
||||
|
||||
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
|
||||
copy /Y $(TOP)\ext\fts5\fts5parse.y .
|
||||
copy /B fts5parse.y +,,
|
||||
copy $(TOP)\ext\fts5\fts5parse.y .
|
||||
del /Q fts5parse.h 2>NUL
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S fts5parse.y
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
fts5.c: $(FTS5_SRC)
|
||||
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
|
||||
copy /Y $(TOP)\ext\fts5\fts5.h .
|
||||
copy /B fts5.h +,,
|
||||
copy $(TOP)\ext\fts5\fts5.h .
|
||||
|
||||
lsm1.c: $(LSM1_SRC)
|
||||
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
|
||||
copy /Y $(TOP)\ext\lsm1\lsm.h .
|
||||
copy /B lsm.h +,,
|
||||
copy $(TOP)\ext\lsm1\lsm.h .
|
||||
|
||||
fts5.lo: fts5.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
|
||||
@@ -2383,9 +2294,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||
@@ -2426,10 +2335,6 @@ extensiontest: testfixture.exe testloadext.dll
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
|
||||
|
||||
coretestprogs: $(TESTPROGS)
|
||||
|
||||
testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe
|
||||
|
||||
fulltest: $(TESTPROGS) fuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
|
||||
@@ -2449,6 +2354,9 @@ queryplantest: testfixture.exe shell
|
||||
fuzztest: fuzzcheck.exe
|
||||
.\fuzzcheck.exe $(FUZZDATA)
|
||||
|
||||
fastfuzztest: fuzzcheck.exe
|
||||
.\fuzzcheck.exe --limit-mem 100M $(FUZZDATA)
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||
#
|
||||
quicktest: testfixture.exe sourcetest
|
||||
@@ -2458,7 +2366,7 @@ quicktest: testfixture.exe sourcetest
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest
|
||||
test: $(TESTPROGS) sourcetest fastfuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
|
||||
|
||||
@@ -2466,9 +2374,6 @@ smoketest: $(TESTPROGS)
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
|
||||
|
||||
shelltest: $(TESTPROGS)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
|
||||
@@ -2513,9 +2418,6 @@ testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
|
||||
testloadext.dll: testloadext.lo
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
|
||||
|
||||
dbtotxt.exe: $(TOP)\tool\dbtotxt.c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbtotxt.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
@@ -2535,20 +2437,11 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
|
||||
showshm.exe: $(TOP)\tool\showshm.c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
index_usage.exe: $(TOP)\tool\index_usage.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(TOP)\tool\index_usage.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
|
||||
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
changesetfuzz.exe: $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
|
||||
$(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
@@ -2592,7 +2485,6 @@ clean:
|
||||
del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
# <<mark>>
|
||||
del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
|
||||
del /Q opcodes.c opcodes.h 2>NUL
|
||||
del /Q lemon.* lempar.c parse.* 2>NUL
|
||||
del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
|
||||
@@ -2603,7 +2495,6 @@ clean:
|
||||
del /Q .target_source 2>NUL
|
||||
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
|
||||
del /Q lsm.dll lsmtest.exe 2>NUL
|
||||
del /Q atrc.exe changesetfuzz.exe dbtotxt.exe index_usage.exe 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||
|
||||
@@ -5,28 +5,16 @@ This repository contains the complete source code for the
|
||||
are also included. However, many other test scripts
|
||||
and most of the documentation are managed separately.
|
||||
|
||||
## Version Control
|
||||
|
||||
SQLite sources are managed using the
|
||||
[Fossil](https://www.fossil-scm.org/), a distributed version control system
|
||||
that was specifically designed and written to support SQLite development.
|
||||
The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.
|
||||
|
||||
If you are reading this on GitHub or some other Git repository or service,
|
||||
then you are looking at a mirror. The names of check-ins and
|
||||
other artifacts in a Git mirror are different from the official
|
||||
names for those objects. The offical names for check-ins are
|
||||
found in a footer on the check-in comment for authorized mirrors.
|
||||
The official check-in name can also be seen in the `manifest.uuid` file
|
||||
in the root of the tree. Always use the official name, not the
|
||||
Git-name, when communicating about an SQLite check-in.
|
||||
|
||||
If you pulled your SQLite source code from a secondary source and want to
|
||||
verify its integrity, there are hints on how to do that in the
|
||||
[Verifying Code Authenticity](#vauth) section below.
|
||||
SQLite [does not use Git](https://sqlite.org/whynotgit.html).
|
||||
If you are reading this on GitHub, then you are looking at an
|
||||
unofficial mirror. See <https://sqlite.org/src> for the official
|
||||
repository.
|
||||
|
||||
## 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 or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
|
||||
@@ -41,7 +29,7 @@ archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).
|
||||
|
||||
* For other check-ins, substitute an appropriate branch name or
|
||||
tag or hash prefix in place of "release" in the URLs of the previous
|
||||
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
|
||||
@@ -175,8 +163,11 @@ the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
|
||||
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
|
||||
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
|
||||
template for generating its parser.
|
||||
|
||||
Lemon also generates the **parse.h** header file, at the same time it
|
||||
generates parse.c.
|
||||
generates parse.c. But the parse.h header file is
|
||||
modified further (to add additional symbols) using the ./addopcodes.tcl
|
||||
Tcl script.
|
||||
|
||||
The **opcodes.h** header file contains macros that define the numbers
|
||||
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
|
||||
@@ -303,25 +294,10 @@ Key files:
|
||||
There are many other source files. Each has a succinct header comment that
|
||||
describes its purpose and role within the larger system.
|
||||
|
||||
<a name="vauth"></a>
|
||||
## Verifying Code Authenticity
|
||||
|
||||
The `manifest` file at the root directory of the source tree
|
||||
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
|
||||
older files) for every source file in the repository.
|
||||
The SHA3-256 hash of the `manifest`
|
||||
file itself is the official name of the version of the source tree that you
|
||||
have. The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
`manifest` file. If all of the above hash comparisons are correct, then
|
||||
you can be confident that your source tree is authentic and unadulterated.
|
||||
|
||||
The format of the `manifest` file should be mostly self-explanatory, but
|
||||
if you want details, they are available
|
||||
[here](https://fossil-scm.org/fossil/doc/trunk/www/fileformat.wiki#manifest).
|
||||
|
||||
## Contacts
|
||||
|
||||
The main SQLite website 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 backups at
|
||||
[http://www2.sqlite.org/](http://www2.sqlite.org) and
|
||||
[http://www3.sqlite.org/](http://www3.sqlite.org).
|
||||
|
||||
@@ -13,7 +13,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_D
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
pkgconfig_DATA = sqlite3.pc
|
||||
|
||||
|
||||
+6
-27
@@ -73,7 +73,7 @@ API_ARMOR = 0
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -196,7 +196,6 @@ OSTRACE = 0
|
||||
DEBUG = 0
|
||||
!ENDIF
|
||||
|
||||
|
||||
# Enable use of available compiler optimizations? Normally, this should be
|
||||
# non-zero. Setting this to zero, thus disabling all compiler optimizations,
|
||||
# can be useful for testing.
|
||||
@@ -211,12 +210,6 @@ OPTIMIZATIONS = 2
|
||||
SESSION = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for the rbu extension.
|
||||
#
|
||||
!IFNDEF RBU
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -289,8 +282,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -303,13 +295,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
!ENDIF
|
||||
|
||||
# Should the rbu extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
!IF $(RBU)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
||||
!ENDIF
|
||||
|
||||
# These are the "extended" SQLite compilation options used when compiling for
|
||||
# the Windows 10 platform.
|
||||
#
|
||||
@@ -447,9 +432,9 @@ UCRTLIBPATH = $(UCRTLIBPATH:\\=\)
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
BCC = $(NCC) -nologo -W4 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
|
||||
!ELSE
|
||||
BCC = $(NCC) -nologo -W3 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
@@ -822,7 +807,7 @@ BCC = $(BCC) -Zi
|
||||
# Command line prefixes for compiling code, compiling resources,
|
||||
# linking, etc.
|
||||
#
|
||||
LTCOMPILE = $(TCC) -Fo$@ -Fd$*.pdb
|
||||
LTCOMPILE = $(TCC) -Fo$@
|
||||
LTRCOMPILE = $(RCC) -r
|
||||
LTLIB = lib.exe
|
||||
LTLINK = $(TCC) -Fe$@
|
||||
@@ -840,11 +825,6 @@ LTLIBS = $(LTLIBS) rpcrt4.lib
|
||||
!IFDEF PLATFORM
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
!ELSEIF "$(VISUALSTUDIOVERSION)"=="12.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="14.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="15.0"
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:x86
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:x86
|
||||
!ELSE
|
||||
LTLINKOPTS = /NOLOGO
|
||||
LTLIBOPTS = /NOLOGO
|
||||
@@ -957,7 +937,6 @@ LIBRESOBJS =
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -992,7 +971,7 @@ Replace.exe:
|
||||
sqlite3.def: Replace.exe $(LIBOBJ)
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all $(LIBOBJ) \
|
||||
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
||||
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
||||
| sort >> sqlite3.def
|
||||
|
||||
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
|
||||
|
||||
@@ -161,7 +161,7 @@ AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
|
||||
[--enable-rtree], [include rtree support [default=yes]])],
|
||||
[], [enable_rtree=yes])
|
||||
if test x"$enable_rtree" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so you can encode the package version directly into the source files.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite], [3.32.0])
|
||||
AC_INIT([sqlite], [3.7.4])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -153,7 +153,7 @@ Please `cd` to its location first.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
PROJECT = tclsqlite3
|
||||
PROJECT = sqlite3
|
||||
!include "rules.vc"
|
||||
|
||||
# nmakehelp -V <file> <tag> will search the file for tag, skips until a
|
||||
@@ -162,15 +162,18 @@ PROJECT = tclsqlite3
|
||||
|
||||
!if [echo REM = This file is generated from Makefile.vc > versions.vc]
|
||||
!endif
|
||||
# get project version from row "AC_INIT([sqlite], [3.x.y])"
|
||||
# get project version from row "AC_INIT([sqlite], [3.7.14])"
|
||||
!if [echo DOTVERSION = \>> versions.vc] \
|
||||
&& [nmakehlp -V ..\configure.ac AC_INIT >> versions.vc]
|
||||
&& [nmakehlp -V ..\configure.in AC_INIT >> versions.vc]
|
||||
!endif
|
||||
!include "versions.vc"
|
||||
|
||||
VERSION = $(DOTVERSION:.=)
|
||||
STUBPREFIX = $(PROJECT)stub
|
||||
|
||||
DLLOBJS = \
|
||||
$(TMP_DIR)\tclsqlite3.obj
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Target names and paths ( shouldn't need changing )
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -179,7 +182,7 @@ BINROOT = .
|
||||
ROOT = ..
|
||||
|
||||
PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
|
||||
PRJLIBNAME = $(PROJECT).$(EXT)
|
||||
PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT)
|
||||
PRJLIB = $(OUT_DIR)\$(PRJLIBNAME)
|
||||
|
||||
PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib
|
||||
@@ -201,17 +204,6 @@ DOCDIR = $(ROOT)\doc
|
||||
TOOLSDIR = $(ROOT)\tools
|
||||
COMPATDIR = $(ROOT)\compat
|
||||
|
||||
### Figure out where the primary source code file(s) is/are.
|
||||
!if exist("$(ROOT)\..\..\sqlite3.c") && exist("$(ROOT)\..\..\src\tclsqlite.c")
|
||||
SQL_INCLUDES = -I"$(ROOT)\..\.."
|
||||
SQLITE_SRCDIR = $(ROOT)\..\..
|
||||
TCLSQLITE_SRCDIR = $(ROOT)\..\..\src
|
||||
DLLOBJS = $(TMP_DIR)\sqlite3.obj $(TMP_DIR)\tclsqlite.obj
|
||||
!else
|
||||
TCLSQLITE_SRCDIR = $(ROOT)\generic
|
||||
DLLOBJS = $(TMP_DIR)\tclsqlite3.obj
|
||||
!endif
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Compile flags
|
||||
#---------------------------------------------------------------------
|
||||
@@ -231,7 +223,7 @@ cdebug = -Z7 -WX -Od -GZ
|
||||
!endif
|
||||
|
||||
### Declarations common to all compiler options
|
||||
cflags = -nologo -c -W3 -D_CRT_SECURE_NO_WARNINGS -YX -Fp$(TMP_DIR)^\
|
||||
cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
|
||||
|
||||
!if $(MSVCRT)
|
||||
!if $(DEBUG)
|
||||
@@ -247,8 +239,8 @@ crt = -MT
|
||||
!endif
|
||||
!endif
|
||||
|
||||
INCLUDES = $(SQL_INCLUDES) $(TCL_INCLUDES) -I"$(WINDIR)" \
|
||||
-I"$(GENERICDIR)" -I"$(ROOT)\.."
|
||||
INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" \
|
||||
-I"$(ROOT)\.."
|
||||
BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \
|
||||
-DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
|
||||
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
|
||||
@@ -349,17 +341,20 @@ $(PRJSTUBLIB): $(PRJSTUBOBJS)
|
||||
# Implicit rules
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
$(TMP_DIR)\sqlite3.obj: $(SQLITE_SRCDIR)\sqlite3.c
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
||||
-c $(SQLITE_SRCDIR)\sqlite3.c
|
||||
{$(WINDIR)}.c{$(TMP_DIR)}.obj::
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
||||
$<
|
||||
<<
|
||||
|
||||
$(TMP_DIR)\tclsqlite.obj: $(TCLSQLITE_SRCDIR)\tclsqlite.c
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
||||
-c $(TCLSQLITE_SRCDIR)\tclsqlite.c
|
||||
{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
||||
$<
|
||||
<<
|
||||
|
||||
$(TMP_DIR)\tclsqlite3.obj: $(TCLSQLITE_SRCDIR)\tclsqlite3.c
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
||||
-c $(TCLSQLITE_SRCDIR)\tclsqlite3.c
|
||||
{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
|
||||
$(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
||||
$<
|
||||
<<
|
||||
|
||||
{$(WINDIR)}.rc{$(TMP_DIR)}.res:
|
||||
$(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
|
||||
|
||||
Vendored
+609
-733
File diff suppressed because it is too large
Load Diff
Vendored
+1248
-1402
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.33.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.26.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.33.0'
|
||||
PACKAGE_STRING='sqlite 3.33.0'
|
||||
PACKAGE_VERSION='3.26.0'
|
||||
PACKAGE_STRING='sqlite 3.26.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -906,7 +906,6 @@ enable_amalgamation
|
||||
enable_load_extension
|
||||
enable_memsys5
|
||||
enable_memsys3
|
||||
enable_all
|
||||
enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
@@ -1467,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.33.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1532,7 +1531,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.33.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1560,7 +1559,6 @@ Optional Features:
|
||||
Disable loading of external extensions
|
||||
--enable-memsys5 Enable MEMSYS5
|
||||
--enable-memsys3 Enable MEMSYS3
|
||||
--enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
|
||||
--enable-fts3 Enable the FTS3 extension
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
@@ -1659,7 +1657,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.33.0
|
||||
sqlite configure 3.26.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2078,7 +2076,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.33.0, which was
|
||||
It was created by sqlite $as_me 3.26.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3936,13 +3934,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3939: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3937: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3942: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3945: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3943: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5148,7 +5146,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5151 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5149 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6673,11 +6671,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6676: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6674: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6680: \$? = $ac_status" >&5
|
||||
echo "$as_me:6678: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7012,11 +7010,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7015: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7013: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7019: \$? = $ac_status" >&5
|
||||
echo "$as_me:7017: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7117,11 +7115,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7120: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7118: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7124: \$? = $ac_status" >&5
|
||||
echo "$as_me:7122: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7172,11 +7170,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7175: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7173: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7179: \$? = $ac_status" >&5
|
||||
echo "$as_me:7177: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9552,7 +9550,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9555 "configure"
|
||||
#line 9553 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9648,7 +9646,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9651 "configure"
|
||||
#line 9649 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11268,7 +11266,7 @@ if test "${enable_amalgamation+set}" = set; then :
|
||||
enableval=$enable_amalgamation;
|
||||
fi
|
||||
|
||||
if test "${enable_amalgamation}" = "no" ; then
|
||||
if test "${enable_amalgamation}" == "no" ; then
|
||||
USE_AMALGAMATION=0
|
||||
fi
|
||||
|
||||
@@ -11452,15 +11450,6 @@ else
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-extensions argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
# Check whether --enable-all was given.
|
||||
if test "${enable_all+set}" = set; then :
|
||||
enableval=$enable_all;
|
||||
fi
|
||||
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
# Check whether --enable-fts3 was given.
|
||||
@@ -11476,7 +11465,7 @@ if test "${enable_fts4+set}" = set; then :
|
||||
enableval=$enable_fts4;
|
||||
fi
|
||||
|
||||
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
@@ -11540,7 +11529,7 @@ if test "${enable_fts5+set}" = set; then :
|
||||
enableval=$enable_fts5;
|
||||
fi
|
||||
|
||||
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
@@ -11607,7 +11596,7 @@ if test "${enable_json1+set}" = set; then :
|
||||
enableval=$enable_json1;
|
||||
fi
|
||||
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
@@ -11619,7 +11608,7 @@ if test "${enable_update_limit+set}" = set; then :
|
||||
enableval=$enable_update_limit;
|
||||
fi
|
||||
|
||||
if test "${enable_update_limit}" = "yes" ; then
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
@@ -11632,7 +11621,7 @@ else
|
||||
enable_geopoly=no
|
||||
fi
|
||||
|
||||
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_geopoly}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
|
||||
enable_rtree=yes
|
||||
fi
|
||||
@@ -11655,7 +11644,7 @@ if test "${enable_session+set}" = set; then :
|
||||
enableval=$enable_session;
|
||||
fi
|
||||
|
||||
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
@@ -12243,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.33.0, which was
|
||||
This file was extended by sqlite $as_me 3.26.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12309,7 +12298,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.33.0
|
||||
sqlite config.status 3.26.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+7
-13
@@ -569,7 +569,7 @@ AC_SUBST(TARGET_DEBUG)
|
||||
# See whether we should use the amalgamation to build
|
||||
AC_ARG_ENABLE(amalgamation, AC_HELP_STRING([--disable-amalgamation],
|
||||
[Disable the amalgamation and instead build all files separately]))
|
||||
if test "${enable_amalgamation}" = "no" ; then
|
||||
if test "${enable_amalgamation}" == "no" ; then
|
||||
USE_AMALGAMATION=0
|
||||
fi
|
||||
AC_SUBST(USE_AMALGAMATION)
|
||||
@@ -613,12 +613,6 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-extensions argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
|
||||
[Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
||||
@@ -628,13 +622,13 @@ if test "${enable_fts3}" = "yes" ; then
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]))
|
||||
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]))
|
||||
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
@@ -642,7 +636,7 @@ fi
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
@@ -651,7 +645,7 @@ fi
|
||||
# statements.
|
||||
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
|
||||
[Enable the UPDATE/DELETE LIMIT clause]))
|
||||
if test "${enable_update_limit}" = "yes" ; then
|
||||
if test "${enable_udlimit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
fi
|
||||
|
||||
@@ -660,7 +654,7 @@ fi
|
||||
AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly],
|
||||
[Enable the GEOPOLY extension]),
|
||||
[enable_geopoly=yes],[enable_geopoly=no])
|
||||
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_geopoly}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
|
||||
enable_rtree=yes
|
||||
fi
|
||||
@@ -677,7 +671,7 @@ fi
|
||||
# See whether we should enable the SESSION extension
|
||||
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]))
|
||||
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
+15
-35
@@ -104,13 +104,9 @@ Write all output files into <i>directory</i>. Normally, output files
|
||||
are written into the directory that contains the input grammar file.
|
||||
<li><b>-D<i>name</i></b>
|
||||
Define C preprocessor macro <i>name</i>. This macro is usable by
|
||||
"<tt><a href='#pifdef'>%ifdef</a></tt>",
|
||||
"<tt><a href='#pifdef'>%ifndef</a></tt>", and
|
||||
"<tt><a href="#pifdef">%if</a></tt> lines
|
||||
"<tt><a href='#pifdef'>%ifdef</a></tt>" and
|
||||
"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
|
||||
in the grammar file.
|
||||
<li><b>-E</b>
|
||||
Run the "%if" preprocessor step only and print the revised grammar
|
||||
file.
|
||||
<li><b>-g</b>
|
||||
Do not generate a parser. Instead write the input grammar to standard
|
||||
output with all comments, actions, and other extraneous text removed.
|
||||
@@ -127,7 +123,7 @@ Suppress generation of the report file.
|
||||
<li><b>-r</b>
|
||||
Do not sort or renumber the parser states as part of optimization.
|
||||
<li><b>-s</b>
|
||||
Show parser statistics before exiting.
|
||||
Show parser statistics before existing.
|
||||
<li><b>-T<i>file</i></b>
|
||||
Use <i>file</i> as the template for the generated C-code parser implementation.
|
||||
<li><b>-x</b>
|
||||
@@ -492,7 +488,7 @@ is an error.</p>
|
||||
The precedence of a grammar rule is equal to the precedence of the
|
||||
left-most terminal symbol in the rule for which a precedence is
|
||||
defined. This is normally what you want, but in those cases where
|
||||
you want the precedence of a grammar rule to be something different,
|
||||
you want to precedence of a grammar rule to be something different,
|
||||
you can specify an alternative precedence symbol by putting the
|
||||
symbol in square braces after the period at the end of the rule and
|
||||
before any C-code. For example:</p>
|
||||
@@ -559,11 +555,9 @@ other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
|
||||
<li><tt><a href='#default_type'>%default_type</a></tt>
|
||||
<li><tt><a href='#destructor'>%destructor</a></tt>
|
||||
<li><tt><a href='#pifdef'>%else</a></tt>
|
||||
<li><tt><a href='#pifdef'>%endif</a></tt>
|
||||
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
|
||||
<li><tt><a href='#pfallback'>%fallback</a></tt>
|
||||
<li><tt><a href='#pifdef'>%if</a></tt>
|
||||
<li><tt><a href='#pifdef'>%ifdef</a></tt>
|
||||
<li><tt><a href='#pifdef'>%ifndef</a></tt>
|
||||
<li><tt><a href='#pinclude'>%include</a></tt>
|
||||
@@ -695,7 +689,7 @@ on Parse().
|
||||
<a name='extractx'></a>
|
||||
<h4>The <tt>%extra_context</tt> directive</h4>
|
||||
|
||||
The <tt>%extra_context</tt> directive instructs Lemon to add a 2nd parameter
|
||||
The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
|
||||
to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
|
||||
doesn't do anything itself with these extra argument, but it does
|
||||
store the value make it available to C-code action routines, destructors,
|
||||
@@ -705,9 +699,9 @@ and so forth. For example, if the grammar file contains:</p>
|
||||
%extra_context { MyStruct *pAbc }
|
||||
</pre></p>
|
||||
|
||||
<p>Then the ParseAlloc() and ParseInit() functions will have an 2nd parameter
|
||||
<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
|
||||
of type "MyStruct*" and all action routines will have access to
|
||||
a variable named "pAbc" that is the value of that 2nd parameter.</p>
|
||||
a variable named "pAbc" that is the value of that 2th parameter.</p>
|
||||
|
||||
<p>The <tt>%extra_argument</tt> directive works the same except that it
|
||||
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
|
||||
@@ -743,11 +737,10 @@ arguments are tokens which fall back to the token identified by the first
|
||||
argument.</p>
|
||||
|
||||
<a name='pifdef'></a>
|
||||
<h4>The <tt>%if</tt> directive and its friends</h4>
|
||||
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
|
||||
|
||||
<p>The <tt>%if</tt>, <tt>%ifdef</tt>, <tt>%ifndef</tt>, <tt>%else</tt>,
|
||||
and <tt>%endif</tt> directives
|
||||
are similar to #if, #ifdef, #ifndef, #else, and #endif in the C-preprocessor,
|
||||
<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
|
||||
are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
|
||||
just not as general.
|
||||
Each of these directives must begin at the left margin. No whitespace
|
||||
is allowed between the "%" and the directive name.</p>
|
||||
@@ -756,22 +749,12 @@ is allowed between the "%" and the directive name.</p>
|
||||
"<tt>%endif</tt>" is
|
||||
ignored unless the "-DMACRO" command-line option is used. Grammar text
|
||||
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
|
||||
included except when the "-DMACRO" command-line option is used.<p>
|
||||
included except when the "-DMACRO" command-line option is used.</p>
|
||||
|
||||
<p>The text in between "<tt>%if</tt> <i>CONDITIONAL</i>" and its
|
||||
corresponding <tt>%endif</tt> is included only if <i>CONDITIONAL</i>
|
||||
is true. The CONDITION is one or more macro names, optionally connected
|
||||
using the "||" and "&&" binary operators, the "!" unary operator,
|
||||
and grouped using balanced parentheses. Each term is true if the
|
||||
corresponding macro exists, and false if it does not exist.</p>
|
||||
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
|
||||
be a single preprocessor symbol name, not a general expression.
|
||||
There is no "<tt>%else</tt>" directive.</p>
|
||||
|
||||
<p>An optional "<tt>%else</tt>" directive can occur anywhere in between a
|
||||
<tt>%ifdef</tt>, <tt>%ifndef</tt>, or <tt>%if</tt> directive and
|
||||
its corresponding <tt>%endif</tt>.</p>
|
||||
|
||||
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> is
|
||||
intended to be a single preprocessor symbol name, not a general expression.
|
||||
Use the "<tt>%if</tt>" directive for general expressions.</p>
|
||||
|
||||
<a name='pinclude'></a>
|
||||
<h4>The <tt>%include</tt> directive</h4>
|
||||
@@ -794,9 +777,6 @@ For example:</p>
|
||||
<p>This might be needed, for example, if some of the C actions in the
|
||||
grammar call functions that are prototyped in unistd.h.</p>
|
||||
|
||||
<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
|
||||
the end of the generated parser.</p>
|
||||
|
||||
<a name='pleft'></a>
|
||||
<h4>The <tt>%left</tt> directive</h4>
|
||||
|
||||
@@ -1013,7 +993,7 @@ on the parser's stack associated with terminal and non-terminal
|
||||
symbols. The values of all terminal symbols must be of the same
|
||||
type. This turns out to be the same data type as the 3rd parameter
|
||||
to the Parse() function generated by Lemon. Typically, you will
|
||||
make the value of a terminal symbol be a pointer to some kind of
|
||||
make the value of a terminal symbol by a pointer to some kind of
|
||||
token structure. Like this:</p>
|
||||
|
||||
<p><pre>
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
# The new-security-options branch
|
||||
|
||||
## The problem that the [new-security-options](/timeline?r=new-security-options) branch tries to solve
|
||||
|
||||
An attacker might modify the schema of an SQLite database by adding
|
||||
structures that cause code to run when some other application opens and
|
||||
reads the database. For example, the attacker might replace a table
|
||||
definition with a view. Or the attacker might add triggers to tables
|
||||
or views, or add new CHECK constraints or generated columns or indexes
|
||||
with expressions in the index list or in the WHERE clause. If the
|
||||
added features invoke SQL functions or virtual tables with side effects,
|
||||
that might cause harm to the system if run by a high-privilege victim.
|
||||
Or, the added features might exfiltrate information if the database is
|
||||
read by a high-privilege victim.
|
||||
|
||||
The changes in this branch strive to make it easier for high-privilege
|
||||
applications to safely read SQLite database files that might have been
|
||||
maliciously corrupted by an attacker.
|
||||
|
||||
## Overview of changes in [new-security-options](/timeline?r=new-security-options)
|
||||
|
||||
The basic idea is to tag every SQL function and virtual table with one
|
||||
of three risk levels:
|
||||
|
||||
1. Innocuous
|
||||
2. Normal
|
||||
3. Direct-Only
|
||||
|
||||
Innocuous functions/vtabs are safe and can be used at any time.
|
||||
Direct-only elements, in contrast, might have cause side-effects and
|
||||
should only be used from top-level SQL, not from within triggers or views nor
|
||||
in elements of the schema such as CHECK constraint, DEFAULT values,
|
||||
generated columns, index expressions, or in the WHERE clause of a
|
||||
partial index that are potentially under the control of an attacker.
|
||||
Normal elements behave like Innocuous if TRUSTED\_SCHEMA=on
|
||||
and behave like direct-only if TRUSTED\_SCHEMA=off.
|
||||
|
||||
Application-defined functions and virtual tables go in as Normal unless
|
||||
the application takes deliberate steps to change the risk level.
|
||||
|
||||
For backwards compatibility, the default is TRUSTED\_SCHEMA=on. Documentation
|
||||
will be updated to recommend applications turn TRUSTED\_SCHEMA to off.
|
||||
|
||||
An innocuous function or virtual table is one that can only read content
|
||||
from the database file in which it resides, and can only alter the database
|
||||
in which it resides. Most SQL functions are innocuous. For example, there
|
||||
is no harm in an attacker running the abs() function.
|
||||
|
||||
Direct-only elements that have side-effects that go outside the database file
|
||||
in which it lives, or return information from outside of the database file.
|
||||
Examples of direct-only elements include:
|
||||
|
||||
1. The fts3\_tokenizer() function
|
||||
2. The writefile() function
|
||||
3. The readfile() function
|
||||
4. The zipvfs virtual table
|
||||
5. The csv virtual table
|
||||
|
||||
We do not want an attacker to be able to add these kinds of things to
|
||||
the database schema and possibly trick a high-privilege application
|
||||
from performing any of these actions. Therefore, functions and vtabs
|
||||
with side-effects are marked as Direct-Only.
|
||||
|
||||
Legacy applications might add other risky functions or vtabs. Those will
|
||||
go in as "Normal" by default. For optimal security, we want those risky
|
||||
app-defined functions and vtabs to be direct-only, but making that the
|
||||
default might break some legacy applications. Hence, all app-defined
|
||||
functions and vtabs go in as Normal, but the application can switch them
|
||||
over to "Direct-Only" behavior using a single pragma.
|
||||
|
||||
The restrictions on the use of functions and virtual tables do not apply
|
||||
to TEMP. A TEMP VIEW or a TEMP TRIGGER can use any valid SQL function
|
||||
or virtual table. The idea is that TEMP views and triggers must be
|
||||
directly created by the application and are thus under the control of the
|
||||
application. TEMP views and triggers cannot be created by an attacker who
|
||||
corrupts the schema of a persistent database file. Hence TEMP views and
|
||||
triggers are safe.
|
||||
|
||||
## Specific changes
|
||||
|
||||
1. New sqlite3\_db\_config() option SQLITE\_DBCONFIG\_TRUSTED\_SCHEMA for
|
||||
turning TRUSTED\_SCHEMA on and off. It defaults to ON.
|
||||
|
||||
2. Compile-time option -DSQLITE\_TRUSTED\_SCHEMA=0 causes the default
|
||||
TRUSTED\_SCHEMA setting to be off.
|
||||
|
||||
3. New pragma "PRAGMA trusted\_schema=(ON\|OFF);". This provides access
|
||||
to the TRUSTED_SCHEMA setting for application coded using scripting
|
||||
languages or other secondary languages where they are unable to make
|
||||
calls to sqlite3\_db\_config().
|
||||
|
||||
4. New options for the "enc" parameter to sqlite3\_create\_function() and
|
||||
its kin:
|
||||
<ol type="a">
|
||||
<li> _SQLITE\_INNOCUOUS_ → tags the new functions as Innocuous
|
||||
<li> _SQLITE\_DIRECTONLY_ → tags the new functions as Direct-Only
|
||||
</ol>
|
||||
|
||||
5. New options to sqlite3\_vtab\_config():
|
||||
<ol type="a">
|
||||
<li> _SQLITE\_VTAB\_INNOCUOUS_ → tags the vtab as Innocuous
|
||||
<li> _SQLITE\_VTAB\_DIRECTONLY_ → tags the vtab as Direct-Only
|
||||
</ol>
|
||||
|
||||
6. Change many of the functions and virtual tables in the SQLite source
|
||||
tree to use one of the tags above.
|
||||
|
||||
7. Enhanced PRAGMA function\_list and virtual-table "pragma\_function\_list"
|
||||
with additional columns. The columns now are:
|
||||
<ul>
|
||||
<li> _name_ → Name of the function
|
||||
<li> _builtin_ → 1 for built-in functions. 0 otherwise.
|
||||
<li> _type_ → 's'=Scalar, 'a'=Aggregate, 'w'=Window
|
||||
<li> _enc_ → 'utf8', 'utf16le', or 'utf16be'
|
||||
<li> _narg_ → number of argument
|
||||
<li> _flags_ → Bitmask of SQLITE\_INNOCUOUS, SQLITE\_DIRECTONLY,
|
||||
SQLITE\_DETERMINISTIC, SQLITE\_SUBTYPE, and
|
||||
SQLITE\_FUNC\_INTERNAL flags.
|
||||
</ul>
|
||||
<p>The last four columns are new.
|
||||
|
||||
8. The function\_list PRAGMA now also shows all entries for each function.
|
||||
So, for example, if a function can take either 2 or 3 arguments,
|
||||
there are separate rows for the 2-argument and 3-argument versions of
|
||||
the function.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
The function_list enhancements allow the application to query the set
|
||||
of SQL functions that meet various criteria. For example, to see all
|
||||
SQL functions that are never allowed to be used in the schema or in
|
||||
trigger or views:
|
||||
|
||||
~~~
|
||||
SELECT DISTINCT name FROM pragma_function_list
|
||||
WHERE (flags & 0x80000)!=0
|
||||
ORDER BY name;
|
||||
~~~
|
||||
|
||||
Doing the same is not possible for virtual tables, as a virtual table
|
||||
might be Innocuous, Normal, or Direct-Only depending on the arguments
|
||||
passed into the xConnect method.
|
||||
@@ -1,88 +0,0 @@
|
||||
# Wal-Mode Blocking Locks
|
||||
|
||||
On some Unix-like systems, SQLite may be configured to use POSIX blocking locks
|
||||
by:
|
||||
|
||||
* building the library with SQLITE\_ENABLE\_SETLK\_TIMEOUT defined, and
|
||||
* configuring a timeout in ms using the sqlite3\_busy\_timeout() API.
|
||||
|
||||
Blocking locks may be advantageous as (a) waiting database clients do not
|
||||
need to continuously poll the database lock, and (b) using blocking locks
|
||||
facilitates transfer of OS priority between processes when a high priority
|
||||
process is blocked by a lower priority one.
|
||||
|
||||
Only read/write clients use blocking locks. Clients that have read-only access
|
||||
to the \*-shm file nevery use blocking locks.
|
||||
|
||||
Threads or processes that access a single database at a time never deadlock as
|
||||
a result of blocking database locks. But it is of course possible for threads
|
||||
that lock multiple databases simultaneously to do so. In most cases the OS will
|
||||
detect the deadlock and return an error.
|
||||
|
||||
## Wal Recovery
|
||||
|
||||
Wal database "recovery" is a process required when the number of connected
|
||||
database clients changes from zero to one. In this case, a client is
|
||||
considered to connect to the database when it first reads data from it.
|
||||
Before recovery commences, an exclusive WRITER lock is taken.
|
||||
|
||||
Without blocking locks, if two clients attempt recovery simultaneously, one
|
||||
fails to obtain the WRITER lock and either invokes the busy-handler callback or
|
||||
returns SQLITE\_BUSY to the user. With blocking locks configured, the second
|
||||
client blocks on the WRITER lock.
|
||||
|
||||
## Database Readers
|
||||
|
||||
Usually, read-only are not blocked by any other database clients, so they
|
||||
have no need of blocking locks.
|
||||
|
||||
If a read-only transaction is being opened on a snapshot, the CHECKPOINTER
|
||||
lock is required briefly as part of opening the transaction (to check that a
|
||||
checkpointer is not currently overwriting the snapshot being opened). A
|
||||
blocking lock is used to obtain the CHECKPOINTER lock in this case. A snapshot
|
||||
opener may therefore block on and transfer priority to a checkpointer in some
|
||||
cases.
|
||||
|
||||
## Database Writers
|
||||
|
||||
A database writer must obtain the exclusive WRITER lock. It uses a blocking
|
||||
lock to do so if any of the following are true:
|
||||
|
||||
* the transaction is an implicit one consisting of a single DML or DDL
|
||||
statement, or
|
||||
* the transaction is opened using BEGIN IMMEDIATE or BEGIN EXCLUSIVE, or
|
||||
* the first SQL statement executed following the BEGIN command is a DML or
|
||||
DDL statement (not a read-only statement like a SELECT).
|
||||
|
||||
In other words, in all cases except when an open read-transaction is upgraded
|
||||
to a write-transaction. In that case a non-blocking lock is used.
|
||||
|
||||
## Database Checkpointers
|
||||
|
||||
Database checkpointers takes the following locks, in order:
|
||||
|
||||
* The exclusive CHECKPOINTER lock.
|
||||
* The exclusive WRITER lock (FULL, RESTART and TRUNCATE only).
|
||||
* Exclusive lock on read-mark slots 1-N. These are immediately released after being taken.
|
||||
* Exclusive lock on read-mark 0.
|
||||
* Exclusive lock on read-mark slots 1-N again. These are immediately released
|
||||
after being taken (RESTART and TRUNCATE only).
|
||||
|
||||
All of the above use blocking locks.
|
||||
|
||||
## Summary
|
||||
|
||||
With blocking locks configured, the only cases in which clients should see an
|
||||
SQLITE\_BUSY error are:
|
||||
|
||||
* if the OS does not grant a blocking lock before the configured timeout
|
||||
expires, and
|
||||
* when an open read-transaction is upgraded to a write-transaction.
|
||||
|
||||
In all other cases the blocking locks implementation should prevent clients
|
||||
from having to handle SQLITE\_BUSY errors and facilitate appropriate transfer
|
||||
of priorities between competing clients.
|
||||
|
||||
Clients that lock multiple databases simultaneously must be wary of deadlock.
|
||||
|
||||
|
||||
@@ -1704,3 +1704,4 @@ int sqlite3async_control(int op, ...){
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */
|
||||
|
||||
|
||||
@@ -220,3 +220,4 @@ int sqlite3async_control(int op, ...);
|
||||
} /* End of the 'extern "C"' block */
|
||||
#endif
|
||||
#endif /* ifndef __SQLITEASYNC_H_ */
|
||||
|
||||
|
||||
+6
-17
@@ -37,9 +37,6 @@ proc squish {txt} {
|
||||
|
||||
proc do_setup_rec_test {tn setup sql res} {
|
||||
reset_db
|
||||
if {[info exists ::set_main_db_name]} {
|
||||
dbconfig_maindbname_icecube db
|
||||
}
|
||||
db eval $setup
|
||||
uplevel [list do_rec_test $tn $sql $res]
|
||||
}
|
||||
@@ -79,10 +76,6 @@ foreach {tn setup} {
|
||||
}
|
||||
}
|
||||
3 {
|
||||
if {[info commands sqlite3_expert_new]==""} { continue }
|
||||
set ::set_main_db_name 1
|
||||
}
|
||||
4 {
|
||||
if {![file executable $CLI]} { continue }
|
||||
|
||||
proc do_rec_test {tn sql res} {
|
||||
@@ -141,7 +134,6 @@ do_setup_rec_test $tn.5 {
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
|
||||
}
|
||||
|
||||
if 0 {
|
||||
do_setup_rec_test $tn.6 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
} {
|
||||
@@ -150,7 +142,6 @@ do_setup_rec_test $tn.6 {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a);
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
|
||||
}
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.7 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
@@ -252,10 +243,8 @@ do_setup_rec_test $tn.12.1 {
|
||||
CREATE INDEX t7_idx_00000062 ON t7(b);
|
||||
CREATE INDEX t7_idx_00000061 ON t7(a);
|
||||
MULTI-INDEX OR
|
||||
INDEX 1
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
INDEX 2
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
# rowid terms.
|
||||
@@ -343,7 +332,7 @@ proc do_candidates_test {tn sql res} {
|
||||
|
||||
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(c, d);
|
||||
|
||||
@@ -353,7 +342,7 @@ do_execsql_test 5.0 {
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
|
||||
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
|
||||
}
|
||||
do_candidates_test 5.1 {
|
||||
do_candidates_test 4.1 {
|
||||
SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
|
||||
@@ -362,14 +351,14 @@ do_candidates_test 5.1 {
|
||||
CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
|
||||
}
|
||||
|
||||
do_candidates_test 5.2 {
|
||||
do_candidates_test 4.2 {
|
||||
SELECT * FROM t1,t2 WHERE a=? AND b=? AND c=? AND d=?
|
||||
} {
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 17
|
||||
CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
do_execsql_test 4.3 {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 16
|
||||
|
||||
+12
-18
@@ -644,7 +644,6 @@ static int idxRegisterVtab(sqlite3expert *p){
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
};
|
||||
|
||||
return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
|
||||
@@ -1128,19 +1127,14 @@ int idxFindIndexes(
|
||||
/* int iParent = sqlite3_column_int(pExplain, 1); */
|
||||
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
|
||||
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
|
||||
int nDetail;
|
||||
int nDetail = STRLEN(zDetail);
|
||||
int i;
|
||||
|
||||
if( !zDetail ) continue;
|
||||
nDetail = STRLEN(zDetail);
|
||||
|
||||
for(i=0; i<nDetail; i++){
|
||||
const char *zIdx = 0;
|
||||
if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
|
||||
if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
|
||||
zIdx = &zDetail[i+13];
|
||||
}else if( i+22<nDetail
|
||||
&& memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
|
||||
){
|
||||
}else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
|
||||
zIdx = &zDetail[i+22];
|
||||
}
|
||||
if( zIdx ){
|
||||
@@ -1223,7 +1217,7 @@ static int idxProcessOneTrigger(
|
||||
IdxTable *pTab = pWrite->pTab;
|
||||
const char *zTab = pTab->zName;
|
||||
const char *zSql =
|
||||
"SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
|
||||
"SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
|
||||
"WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
|
||||
"ORDER BY type;";
|
||||
sqlite3_stmt *pSelect = 0;
|
||||
@@ -1323,12 +1317,12 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
** 2) Create the equivalent virtual table in dbv.
|
||||
*/
|
||||
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
|
||||
"SELECT type, name, sql, 1 FROM sqlite_schema "
|
||||
"SELECT type, name, sql, 1 FROM sqlite_master "
|
||||
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
|
||||
" UNION ALL "
|
||||
"SELECT type, name, sql, 2 FROM sqlite_schema "
|
||||
"SELECT type, name, sql, 2 FROM sqlite_master "
|
||||
"WHERE type = 'trigger'"
|
||||
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
|
||||
" AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
|
||||
"ORDER BY 4, 1"
|
||||
);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
|
||||
@@ -1498,7 +1492,7 @@ static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
|
||||
int rc = SQLITE_OK;
|
||||
const char *zMax =
|
||||
"SELECT max(i.seqno) FROM "
|
||||
" sqlite_schema AS s, "
|
||||
" sqlite_master AS s, "
|
||||
" pragma_index_list(s.name) AS l, "
|
||||
" pragma_index_info(l.name) AS i "
|
||||
"WHERE s.type = 'table'";
|
||||
@@ -1651,7 +1645,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
|
||||
const char *zAllIndex =
|
||||
"SELECT s.rowid, s.name, l.name FROM "
|
||||
" sqlite_schema AS s, "
|
||||
" sqlite_master AS s, "
|
||||
" pragma_index_list(s.name) AS l "
|
||||
"WHERE s.type = 'table'";
|
||||
const char *zIndexXInfo =
|
||||
@@ -1725,7 +1719,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
sqlite3_free(pCtx);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
|
||||
}
|
||||
|
||||
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
|
||||
@@ -1764,7 +1758,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_stmt *pSql;
|
||||
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
|
||||
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
|
||||
"SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
|
||||
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
|
||||
);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
@@ -1955,4 +1949,4 @@ void sqlite3_expert_destroy(sqlite3expert *p){
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
||||
#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
**
|
||||
*************************************************************************
|
||||
*/
|
||||
#if !defined(SQLITEEXPERT_H)
|
||||
#define SQLITEEXPERT_H 1
|
||||
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
typedef struct sqlite3expert sqlite3expert;
|
||||
@@ -165,4 +165,4 @@ const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
|
||||
*/
|
||||
void sqlite3_expert_destroy(sqlite3expert*);
|
||||
|
||||
#endif /* !defined(SQLITEEXPERT_H) */
|
||||
|
||||
|
||||
@@ -174,3 +174,5 @@ EXTERNAL CONTENT FTS4 TABLES
|
||||
only be useful if the full-text index has somehow become corrupt. It is an
|
||||
error to attempt to rebuild the full-text index maintained by a contentless
|
||||
FTS4 table.
|
||||
|
||||
|
||||
|
||||
@@ -52,10 +52,8 @@
|
||||
|
||||
SECURITY: If the fts3 extension is used in an environment where potentially
|
||||
malicious users may execute arbitrary SQL (i.e. gears), they should be
|
||||
prevented from invoking the fts3_tokenizer() function. The
|
||||
fts3_tokenizer() function is disabled by default. It is only enabled
|
||||
by SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER. Do not enable it in
|
||||
security sensitive environments.
|
||||
prevented from invoking the fts3_tokenizer() function, possibly using the
|
||||
authorisation callback.
|
||||
|
||||
See "Sample code" below for an example of calling the fts3_tokenizer()
|
||||
function from C code.
|
||||
|
||||
+125
-264
@@ -320,14 +320,6 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This variable is set to false when running tests for which the on disk
|
||||
** structures should not be corrupt. Otherwise, true. If it is false, extra
|
||||
** assert() conditions in the fts3 code are activated - conditions that are
|
||||
** only true if it is guaranteed that the fts3 database is not corrupt.
|
||||
*/
|
||||
int sqlite3_fts3_may_be_corrupt = 1;
|
||||
|
||||
/*
|
||||
** Write a 64-bit variable-length integer to memory starting at p[0].
|
||||
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
|
||||
@@ -346,13 +338,18 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
||||
}
|
||||
|
||||
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
|
||||
v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \
|
||||
v = (v & mask1) | ( (*ptr++) << shift ); \
|
||||
if( (v & mask2)==0 ){ var = v; return ret; }
|
||||
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
|
||||
v = (*ptr++); \
|
||||
if( (v & mask2)==0 ){ var = v; return ret; }
|
||||
|
||||
int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
|
||||
/*
|
||||
** Read a 64-bit variable-length integer from memory starting at p[0].
|
||||
** Return the number of bytes read, or 0 on error.
|
||||
** The value is stored in *v.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
const unsigned char *p = (const unsigned char*)pBuf;
|
||||
const unsigned char *pStart = p;
|
||||
u32 a;
|
||||
@@ -374,61 +371,25 @@ int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
|
||||
return (int)(p - pStart);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a 64-bit variable-length integer from memory starting at p[0].
|
||||
** Return the number of bytes read, or 0 on error.
|
||||
** The value is stored in *v.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a 64-bit variable-length integer from memory starting at p[0] and
|
||||
** not extending past pEnd[-1].
|
||||
** Return the number of bytes read, or 0 on error.
|
||||
** The value is stored in *v.
|
||||
*/
|
||||
int sqlite3Fts3GetVarintBounded(
|
||||
const char *pBuf,
|
||||
const char *pEnd,
|
||||
sqlite_int64 *v
|
||||
){
|
||||
const unsigned char *p = (const unsigned char*)pBuf;
|
||||
const unsigned char *pStart = p;
|
||||
const unsigned char *pX = (const unsigned char*)pEnd;
|
||||
u64 b = 0;
|
||||
int shift;
|
||||
for(shift=0; shift<=63; shift+=7){
|
||||
u64 c = p<pX ? *p : 0;
|
||||
p++;
|
||||
b += (c&0x7F) << shift;
|
||||
if( (c & 0x80)==0 ) break;
|
||||
}
|
||||
*v = b;
|
||||
return (int)(p - pStart);
|
||||
}
|
||||
|
||||
/*
|
||||
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
|
||||
** a non-negative 32-bit integer before it is returned.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
||||
const unsigned char *ptr = (const unsigned char*)p;
|
||||
u32 a;
|
||||
|
||||
#ifndef fts3GetVarint32
|
||||
GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1);
|
||||
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
|
||||
#else
|
||||
a = (*ptr++);
|
||||
a = (*p++);
|
||||
assert( a & 0x80 );
|
||||
#endif
|
||||
|
||||
GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2);
|
||||
GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3);
|
||||
GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
||||
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
|
||||
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
||||
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
||||
a = (a & 0x0FFFFFFF );
|
||||
*pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
|
||||
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
|
||||
assert( 0==(a & 0x80000000) );
|
||||
assert( *pi>=0 );
|
||||
return 5;
|
||||
@@ -599,18 +560,13 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
|
||||
sqlite3 *db = p->db; /* Database handle */
|
||||
|
||||
/* Drop the shadow tables */
|
||||
fts3DbExec(&rc, db,
|
||||
"DROP TABLE IF EXISTS %Q.'%q_segments';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_segdir';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_docsize';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_stat';"
|
||||
"%s DROP TABLE IF EXISTS %Q.'%q_content';",
|
||||
zDb, p->zName,
|
||||
zDb, p->zName,
|
||||
zDb, p->zName,
|
||||
zDb, p->zName,
|
||||
(p->zContentTbl ? "--" : ""), zDb,p->zName
|
||||
);
|
||||
if( p->zContentTbl==0 ){
|
||||
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
|
||||
}
|
||||
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
|
||||
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
|
||||
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
|
||||
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
|
||||
|
||||
/* If everything has worked, invoke fts3DisconnectMethod() to free the
|
||||
** memory associated with the Fts3Table structure and return SQLITE_OK.
|
||||
@@ -842,10 +798,10 @@ static void fts3Appendf(
|
||||
** memory.
|
||||
*/
|
||||
static char *fts3QuoteId(char const *zInput){
|
||||
sqlite3_int64 nRet;
|
||||
int nRet;
|
||||
char *zRet;
|
||||
nRet = 2 + (int)strlen(zInput)*2 + 1;
|
||||
zRet = sqlite3_malloc64(nRet);
|
||||
zRet = sqlite3_malloc(nRet);
|
||||
if( zRet ){
|
||||
int i;
|
||||
char *z = zRet;
|
||||
@@ -962,22 +918,6 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
|
||||
return zRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Buffer z contains a positive integer value encoded as utf-8 text.
|
||||
** Decode this value and store it in *pnOut, returning the number of bytes
|
||||
** consumed. If an overflow error occurs return a negative value.
|
||||
*/
|
||||
int sqlite3Fts3ReadInt(const char *z, int *pnOut){
|
||||
u64 iVal = 0;
|
||||
int i;
|
||||
for(i=0; z[i]>='0' && z[i]<='9'; i++){
|
||||
iVal = iVal*10 + (z[i] - '0');
|
||||
if( iVal>0x7FFFFFFF ) return -1;
|
||||
}
|
||||
*pnOut = (int)iVal;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function interprets the string at (*pp) as a non-negative integer
|
||||
** value. It reads the integer and sets *pnOut to the value read, then
|
||||
@@ -993,17 +933,19 @@ int sqlite3Fts3ReadInt(const char *z, int *pnOut){
|
||||
*/
|
||||
static int fts3GobbleInt(const char **pp, int *pnOut){
|
||||
const int MAX_NPREFIX = 10000000;
|
||||
const char *p; /* Iterator pointer */
|
||||
int nInt = 0; /* Output value */
|
||||
int nByte;
|
||||
nByte = sqlite3Fts3ReadInt(*pp, &nInt);
|
||||
if( nInt>MAX_NPREFIX ){
|
||||
nInt = 0;
|
||||
}
|
||||
if( nByte==0 ){
|
||||
return SQLITE_ERROR;
|
||||
|
||||
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
|
||||
nInt = nInt * 10 + (p[0] - '0');
|
||||
if( nInt>MAX_NPREFIX ){
|
||||
nInt = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( p==*pp ) return SQLITE_ERROR;
|
||||
*pnOut = nInt;
|
||||
*pp += nByte;
|
||||
*pp = p;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1040,7 +982,7 @@ static int fts3PrefixParameter(
|
||||
}
|
||||
}
|
||||
|
||||
aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
|
||||
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
|
||||
*apIndex = aIndex;
|
||||
if( !aIndex ){
|
||||
return SQLITE_NOMEM;
|
||||
@@ -1119,7 +1061,7 @@ static int fts3ContentColumns(
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
const char **azCol; /* Output array */
|
||||
sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */
|
||||
int nStr = 0; /* Size of all column names (incl. 0x00) */
|
||||
int nCol; /* Number of table columns */
|
||||
int i; /* Used to iterate through columns */
|
||||
|
||||
@@ -1129,11 +1071,11 @@ static int fts3ContentColumns(
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
for(i=0; i<nCol; i++){
|
||||
const char *zCol = sqlite3_column_name(pStmt, i);
|
||||
nStr += strlen(zCol) + 1;
|
||||
nStr += (int)strlen(zCol) + 1;
|
||||
}
|
||||
|
||||
/* Allocate and populate the array to return. */
|
||||
azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
|
||||
azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
|
||||
if( azCol==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -1181,7 +1123,7 @@ static int fts3InitVtab(
|
||||
Fts3Table *p = 0; /* Pointer to allocated vtab */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* Iterator variable */
|
||||
sqlite3_int64 nByte; /* Size of allocation used for *p */
|
||||
int nByte; /* Size of allocation used for *p */
|
||||
int iCol; /* Column index */
|
||||
int nString = 0; /* Bytes required to hold all column names */
|
||||
int nCol = 0; /* Number of columns in the FTS table */
|
||||
@@ -1215,10 +1157,10 @@ static int fts3InitVtab(
|
||||
nName = (int)strlen(argv[2]) + 1;
|
||||
|
||||
nByte = sizeof(const char *) * (argc-2);
|
||||
aCol = (const char **)sqlite3_malloc64(nByte);
|
||||
aCol = (const char **)sqlite3_malloc(nByte);
|
||||
if( aCol ){
|
||||
memset((void*)aCol, 0, nByte);
|
||||
azNotindexed = (char **)sqlite3_malloc64(nByte);
|
||||
azNotindexed = (char **)sqlite3_malloc(nByte);
|
||||
}
|
||||
if( azNotindexed ){
|
||||
memset(azNotindexed, 0, nByte);
|
||||
@@ -1413,7 +1355,7 @@ static int fts3InitVtab(
|
||||
nName + /* zName */
|
||||
nDb + /* zDb */
|
||||
nString; /* Space for azColumn strings */
|
||||
p = (Fts3Table*)sqlite3_malloc64(nByte);
|
||||
p = (Fts3Table*)sqlite3_malloc(nByte);
|
||||
if( p==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto fts3_init_out;
|
||||
@@ -1518,10 +1460,6 @@ static int fts3InitVtab(
|
||||
fts3DatabasePageSize(&rc, p);
|
||||
p->nNodeSize = p->nPgsz-35;
|
||||
|
||||
#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
|
||||
p->nMergeCount = FTS3_MERGE_COUNT;
|
||||
#endif
|
||||
|
||||
/* Declare the table schema to SQLite. */
|
||||
fts3DeclareVtab(&rc, p);
|
||||
|
||||
@@ -1617,10 +1555,6 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
int iDocidLe = -1; /* Index of docid<=x constraint, if present */
|
||||
int iIdx;
|
||||
|
||||
if( p->bLock ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* By default use a full table scan. This is an expensive option,
|
||||
** so search through the constraints to see if a more efficient
|
||||
** strategy is possible.
|
||||
@@ -1819,11 +1753,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
|
||||
}else{
|
||||
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
|
||||
if( !zSql ) return SQLITE_NOMEM;
|
||||
p->bLock++;
|
||||
rc = sqlite3_prepare_v3(
|
||||
p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
|
||||
);
|
||||
p->bLock--;
|
||||
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
|
||||
@@ -1841,15 +1771,11 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
||||
if( pCsr->isRequireSeek ){
|
||||
rc = fts3CursorSeekStmt(pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
|
||||
pTab->bLock++;
|
||||
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
|
||||
pCsr->isRequireSeek = 0;
|
||||
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
|
||||
pTab->bLock--;
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
pTab->bLock--;
|
||||
rc = sqlite3_reset(pCsr->pStmt);
|
||||
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
|
||||
/* If no row was found and no error has occurred, then the %_content
|
||||
@@ -1895,10 +1821,9 @@ static int fts3ScanInteriorNode(
|
||||
const char *zCsr = zNode; /* Cursor to iterate through node */
|
||||
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
** interior node. Then load the blockid of the left-child of the b-tree
|
||||
@@ -1923,28 +1848,25 @@ static int fts3ScanInteriorNode(
|
||||
int cmp; /* memcmp() result */
|
||||
int nSuffix; /* Size of term suffix */
|
||||
int nPrefix = 0; /* Size of term prefix */
|
||||
int nBuffer; /* Total term size */
|
||||
|
||||
/* Load the next term on the node into zBuffer. Use realloc() to expand
|
||||
** the size of zBuffer if required. */
|
||||
if( !isFirstTerm ){
|
||||
zCsr += fts3GetVarint32(zCsr, &nPrefix);
|
||||
if( nPrefix>nBuffer ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
}
|
||||
isFirstTerm = 0;
|
||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
assert( nPrefix>=0 && nSuffix>=0 );
|
||||
if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){
|
||||
if( &zCsr[nSuffix]>zEnd ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
if( (i64)nPrefix+nSuffix>nAlloc ){
|
||||
if( nPrefix+nSuffix>nAlloc ){
|
||||
char *zNew;
|
||||
nAlloc = ((i64)nPrefix+nSuffix) * 2;
|
||||
zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
|
||||
nAlloc = (nPrefix+nSuffix) * 2;
|
||||
zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
|
||||
if( !zNew ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto finish_scan;
|
||||
@@ -2025,7 +1947,7 @@ static int fts3SelectLeaf(
|
||||
|
||||
fts3GetVarint32(zNode, &iHeight);
|
||||
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
|
||||
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
||||
assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
||||
|
||||
if( rc==SQLITE_OK && iHeight>1 ){
|
||||
char *zBlob = 0; /* Blob read from %_segments table */
|
||||
@@ -2045,13 +1967,7 @@ static int fts3SelectLeaf(
|
||||
rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int iNewHeight = 0;
|
||||
fts3GetVarint32(zBlob, &iNewHeight);
|
||||
if( iNewHeight>=iHeight ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}else{
|
||||
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
|
||||
}
|
||||
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
|
||||
}
|
||||
sqlite3_free(zBlob);
|
||||
}
|
||||
@@ -2068,7 +1984,7 @@ static void fts3PutDeltaVarint(
|
||||
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
|
||||
sqlite3_int64 iVal /* Write this value to the list */
|
||||
){
|
||||
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
|
||||
assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
|
||||
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
|
||||
*piPrev = iVal;
|
||||
}
|
||||
@@ -2156,11 +2072,10 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
|
||||
}
|
||||
|
||||
/*
|
||||
** Value used to signify the end of an position-list. This must be
|
||||
** as large or larger than any value that might appear on the
|
||||
** position-list, even a position list that has been corrupted.
|
||||
** Value used to signify the end of an position-list. This is safe because
|
||||
** it is not possible to have a document with 2^31 terms.
|
||||
*/
|
||||
#define POSITION_LIST_END LARGEST_INT64
|
||||
#define POSITION_LIST_END 0x7fffffff
|
||||
|
||||
/*
|
||||
** This function is used to help parse position-lists. When this function is
|
||||
@@ -2185,9 +2100,7 @@ static void fts3ReadNextPos(
|
||||
sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
|
||||
){
|
||||
if( (**pp)&0xFE ){
|
||||
int iVal;
|
||||
*pp += fts3GetVarint32((*pp), &iVal);
|
||||
*pi += iVal;
|
||||
fts3GetDeltaVarint(pp, pi);
|
||||
*pi -= 2;
|
||||
}else{
|
||||
*pi = POSITION_LIST_END;
|
||||
@@ -2221,7 +2134,7 @@ static int fts3PutColNumber(char **pp, int iCol){
|
||||
** updated appropriately. The caller is responsible for insuring
|
||||
** that there is enough space in *pp to hold the complete output.
|
||||
*/
|
||||
static int fts3PoslistMerge(
|
||||
static void fts3PoslistMerge(
|
||||
char **pp, /* Output buffer */
|
||||
char **pp1, /* Left input list */
|
||||
char **pp2 /* Right input list */
|
||||
@@ -2234,18 +2147,12 @@ static int fts3PoslistMerge(
|
||||
int iCol1; /* The current column index in pp1 */
|
||||
int iCol2; /* The current column index in pp2 */
|
||||
|
||||
if( *p1==POS_COLUMN ){
|
||||
fts3GetVarint32(&p1[1], &iCol1);
|
||||
if( iCol1==0 ) return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
else if( *p1==POS_END ) iCol1 = 0x7fffffff;
|
||||
if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
|
||||
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
|
||||
else iCol1 = 0;
|
||||
|
||||
if( *p2==POS_COLUMN ){
|
||||
fts3GetVarint32(&p2[1], &iCol2);
|
||||
if( iCol2==0 ) return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
else if( *p2==POS_END ) iCol2 = 0x7fffffff;
|
||||
if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
|
||||
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
|
||||
else iCol2 = 0;
|
||||
|
||||
if( iCol1==iCol2 ){
|
||||
@@ -2267,9 +2174,6 @@ static int fts3PoslistMerge(
|
||||
*/
|
||||
fts3GetDeltaVarint(&p1, &i1);
|
||||
fts3GetDeltaVarint(&p2, &i2);
|
||||
if( i1<2 || i2<2 ){
|
||||
break;
|
||||
}
|
||||
do {
|
||||
fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
|
||||
iPrev -= 2;
|
||||
@@ -2295,7 +2199,6 @@ static int fts3PoslistMerge(
|
||||
*pp = p;
|
||||
*pp1 = p1 + 1;
|
||||
*pp2 = p2 + 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2338,7 +2241,7 @@ static int fts3PoslistPhraseMerge(
|
||||
/* Never set both isSaveLeft and isExact for the same invocation. */
|
||||
assert( isSaveLeft==0 || isExact==0 );
|
||||
|
||||
assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 );
|
||||
assert( p!=0 && *p1!=0 && *p2!=0 );
|
||||
if( *p1==POS_COLUMN ){
|
||||
p1++;
|
||||
p1 += fts3GetVarint32(p1, &iCol1);
|
||||
@@ -2360,9 +2263,10 @@ static int fts3PoslistPhraseMerge(
|
||||
p += sqlite3Fts3PutVarint(p, iCol1);
|
||||
}
|
||||
|
||||
assert( *p1!=POS_END && *p1!=POS_COLUMN );
|
||||
assert( *p2!=POS_END && *p2!=POS_COLUMN );
|
||||
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
|
||||
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
|
||||
if( iPos1<0 || iPos2<0 ) break;
|
||||
|
||||
while( 1 ){
|
||||
if( iPos2==iPos1+nToken
|
||||
@@ -2511,12 +2415,12 @@ static void fts3GetDeltaVarint3(
|
||||
if( *pp>=pEnd ){
|
||||
*pp = 0;
|
||||
}else{
|
||||
u64 iVal;
|
||||
*pp += sqlite3Fts3GetVarintU(*pp, &iVal);
|
||||
sqlite3_int64 iVal;
|
||||
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
|
||||
if( bDescIdx ){
|
||||
*pVal = (i64)((u64)*pVal - iVal);
|
||||
*pVal -= iVal;
|
||||
}else{
|
||||
*pVal = (i64)((u64)*pVal + iVal);
|
||||
*pVal += iVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2543,16 +2447,14 @@ static void fts3PutDeltaVarint3(
|
||||
int *pbFirst, /* IN/OUT: True after first int written */
|
||||
sqlite3_int64 iVal /* Write this value to the list */
|
||||
){
|
||||
sqlite3_uint64 iWrite;
|
||||
sqlite3_int64 iWrite;
|
||||
if( bDescIdx==0 || *pbFirst==0 ){
|
||||
assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
|
||||
iWrite = (u64)iVal - (u64)*piPrev;
|
||||
iWrite = iVal - *piPrev;
|
||||
}else{
|
||||
assert_fts3_nc( *piPrev>=iVal );
|
||||
iWrite = (u64)*piPrev - (u64)iVal;
|
||||
iWrite = *piPrev - iVal;
|
||||
}
|
||||
assert( *pbFirst || *piPrev==0 );
|
||||
assert_fts3_nc( *pbFirst==0 || iWrite>0 );
|
||||
assert( *pbFirst==0 || iWrite>0 );
|
||||
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
|
||||
*piPrev = iVal;
|
||||
*pbFirst = 1;
|
||||
@@ -2568,8 +2470,7 @@ static void fts3PutDeltaVarint3(
|
||||
** Using this makes it easier to write code that can merge doclists that are
|
||||
** sorted in either ascending or descending order.
|
||||
*/
|
||||
/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
|
||||
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
|
||||
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
|
||||
|
||||
/*
|
||||
** This function does an "OR" merge of two doclists (output contains all
|
||||
@@ -2591,7 +2492,6 @@ static int fts3DoclistOrMerge(
|
||||
char *a2, int n2, /* Second doclist */
|
||||
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_int64 i1 = 0;
|
||||
sqlite3_int64 i2 = 0;
|
||||
sqlite3_int64 iPrev = 0;
|
||||
@@ -2635,7 +2535,7 @@ static int fts3DoclistOrMerge(
|
||||
** A symetric argument may be made if the doclists are in descending
|
||||
** order.
|
||||
*/
|
||||
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
|
||||
aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
|
||||
if( !aOut ) return SQLITE_NOMEM;
|
||||
|
||||
p = aOut;
|
||||
@@ -2646,8 +2546,7 @@ static int fts3DoclistOrMerge(
|
||||
|
||||
if( p2 && p1 && iDiff==0 ){
|
||||
fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
|
||||
rc = fts3PoslistMerge(&p, &p1, &p2);
|
||||
if( rc ) break;
|
||||
fts3PoslistMerge(&p, &p1, &p2);
|
||||
fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
|
||||
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
|
||||
}else if( !p2 || (p1 && iDiff<0) ){
|
||||
@@ -2659,20 +2558,12 @@ static int fts3DoclistOrMerge(
|
||||
fts3PoslistCopy(&p, &p2);
|
||||
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
|
||||
}
|
||||
|
||||
assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(aOut);
|
||||
p = aOut = 0;
|
||||
}else{
|
||||
assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
|
||||
memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
|
||||
}
|
||||
*paOut = aOut;
|
||||
*pnOut = (int)(p-aOut);
|
||||
return rc;
|
||||
assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2707,7 +2598,7 @@ static int fts3DoclistPhraseMerge(
|
||||
|
||||
assert( nDist>0 );
|
||||
if( bDescDoclist ){
|
||||
aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
|
||||
aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
|
||||
if( aOut==0 ) return SQLITE_NOMEM;
|
||||
}else{
|
||||
aOut = aRight;
|
||||
@@ -2891,7 +2782,6 @@ static int fts3TermSelectMerge(
|
||||
pTS->anOutput[0] = nDoclist;
|
||||
if( pTS->aaOutput[0] ){
|
||||
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
|
||||
memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
|
||||
}else{
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -2943,8 +2833,8 @@ static int fts3SegReaderCursorAppend(
|
||||
){
|
||||
if( (pCsr->nSegment%16)==0 ){
|
||||
Fts3SegReader **apNew;
|
||||
sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
|
||||
apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
|
||||
int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
|
||||
apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
|
||||
if( !apNew ){
|
||||
sqlite3Fts3SegReaderFree(pNew);
|
||||
return SQLITE_NOMEM;
|
||||
@@ -2983,7 +2873,7 @@ static int fts3SegReaderCursor(
|
||||
** Fts3SegReaderPending might segfault, as the data structures used by
|
||||
** fts4aux are not completely populated. So it's easiest to filter these
|
||||
** calls out here. */
|
||||
if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
|
||||
if( iLevel<0 && p->aIndex ){
|
||||
Fts3SegReader *pSeg = 0;
|
||||
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
|
||||
if( rc==SQLITE_OK && pSeg ){
|
||||
@@ -3008,7 +2898,7 @@ static int fts3SegReaderCursor(
|
||||
|
||||
/* If zTerm is not NULL, and this segment is not stored entirely on its
|
||||
** root node, the range of leaves scanned can be reduced. Do this. */
|
||||
if( iStartBlock && zTerm && zRoot ){
|
||||
if( iStartBlock && zTerm ){
|
||||
sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
|
||||
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
@@ -3246,8 +3136,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int rc;
|
||||
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
||||
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
|
||||
Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
|
||||
pTab->bLock++;
|
||||
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
|
||||
pCsr->isEof = 1;
|
||||
rc = sqlite3_reset(pCsr->pStmt);
|
||||
@@ -3255,7 +3143,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
pTab->bLock--;
|
||||
}else{
|
||||
rc = fts3EvalNext((Fts3Cursor *)pCursor);
|
||||
}
|
||||
@@ -3263,6 +3150,18 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following are copied from sqliteInt.h.
|
||||
**
|
||||
** Constants for the largest and smallest possible 64-bit signed integers.
|
||||
** These macros are designed to work correctly on both 32-bit and 64-bit
|
||||
** compilers.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If the numeric type of argument pVal is "integer", then return it
|
||||
** converted to a 64-bit signed integer. Otherwise, return a copy of
|
||||
@@ -3316,10 +3215,6 @@ static int fts3FilterMethod(
|
||||
UNUSED_PARAMETER(idxStr);
|
||||
UNUSED_PARAMETER(nVal);
|
||||
|
||||
if( p->bLock ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
eSearch = (idxNum & 0x0000FFFF);
|
||||
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
|
||||
assert( p->pSegments==0 );
|
||||
@@ -3391,11 +3286,7 @@ static int fts3FilterMethod(
|
||||
);
|
||||
}
|
||||
if( zSql ){
|
||||
p->bLock++;
|
||||
rc = sqlite3_prepare_v3(
|
||||
p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
|
||||
);
|
||||
p->bLock--;
|
||||
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -3479,7 +3370,7 @@ static int fts3ColumnMethod(
|
||||
break;
|
||||
}else{
|
||||
iCol = p->nColumn;
|
||||
/* no break */ deliberate_fall_through
|
||||
/* fall-through */
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -3722,13 +3613,9 @@ static void fts3SnippetFunc(
|
||||
|
||||
switch( nVal ){
|
||||
case 6: nToken = sqlite3_value_int(apVal[5]);
|
||||
/* no break */ deliberate_fall_through
|
||||
case 5: iCol = sqlite3_value_int(apVal[4]);
|
||||
/* no break */ deliberate_fall_through
|
||||
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
|
||||
/* no break */ deliberate_fall_through
|
||||
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
|
||||
/* no break */ deliberate_fall_through
|
||||
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
|
||||
}
|
||||
if( !zEllipsis || !zEnd || !zStart ){
|
||||
@@ -3953,28 +3840,14 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
UNUSED_PARAMETER(iSavepoint);
|
||||
assert( p->inTransaction );
|
||||
assert( p->mxSavepoint >= iSavepoint );
|
||||
TESTONLY( p->mxSavepoint = iSavepoint );
|
||||
sqlite3Fts3PendingTermsClear(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zName is the extension on one of the shadow tables used
|
||||
** by this module.
|
||||
*/
|
||||
static int fts3ShadowName(const char *zName){
|
||||
static const char *azName[] = {
|
||||
"content", "docsize", "segdir", "segments", "stat",
|
||||
};
|
||||
unsigned int i;
|
||||
for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
|
||||
if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const sqlite3_module fts3Module = {
|
||||
/* iVersion */ 3,
|
||||
/* iVersion */ 2,
|
||||
/* xCreate */ fts3CreateMethod,
|
||||
/* xConnect */ fts3ConnectMethod,
|
||||
/* xBestIndex */ fts3BestIndexMethod,
|
||||
@@ -3997,7 +3870,6 @@ static const sqlite3_module fts3Module = {
|
||||
/* xSavepoint */ fts3SavepointMethod,
|
||||
/* xRelease */ fts3ReleaseMethod,
|
||||
/* xRollbackTo */ fts3RollbackToMethod,
|
||||
/* xShadowName */ fts3ShadowName,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4278,7 +4150,6 @@ static int fts3EvalPhraseLoad(
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
/*
|
||||
** This function is called on each phrase after the position lists for
|
||||
** any deferred tokens have been loaded into memory. It updates the phrases
|
||||
@@ -4382,7 +4253,6 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
|
||||
|
||||
/*
|
||||
** Maximum number of tokens a phrase may have to be considered for the
|
||||
@@ -4416,7 +4286,7 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
|
||||
int bIncrOk = (bOptOk
|
||||
&& pCsr->bDesc==pTab->bDescIdx
|
||||
&& p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
#ifdef SQLITE_TEST
|
||||
&& pTab->bNoIncrDoclist==0
|
||||
#endif
|
||||
);
|
||||
@@ -4527,7 +4397,7 @@ void sqlite3Fts3DoclistNext(
|
||||
|
||||
assert( nDoclist>0 );
|
||||
assert( *pbEof==0 );
|
||||
assert_fts3_nc( p || *piDocid==0 );
|
||||
assert( p || *piDocid==0 );
|
||||
assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) );
|
||||
|
||||
if( p==0 ){
|
||||
@@ -4558,16 +4428,15 @@ static void fts3EvalDlPhraseNext(
|
||||
u8 *pbEof
|
||||
){
|
||||
char *pIter; /* Used to iterate through aAll */
|
||||
char *pEnd; /* 1 byte past end of aAll */
|
||||
char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
|
||||
|
||||
if( pDL->pNextDocid ){
|
||||
pIter = pDL->pNextDocid;
|
||||
assert( pDL->aAll!=0 || pIter==0 );
|
||||
}else{
|
||||
pIter = pDL->aAll;
|
||||
}
|
||||
|
||||
if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
|
||||
if( pIter>=pEnd ){
|
||||
/* We have already reached the end of this doclist. EOF. */
|
||||
*pbEof = 1;
|
||||
}else{
|
||||
@@ -4728,10 +4597,9 @@ static int fts3EvalIncrPhraseNext(
|
||||
if( bEof==0 ){
|
||||
int nList = 0;
|
||||
int nByte = a[p->nToken-1].nList;
|
||||
char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
|
||||
char *aDoclist = sqlite3_malloc(nByte+1);
|
||||
if( !aDoclist ) return SQLITE_NOMEM;
|
||||
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
|
||||
memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
|
||||
|
||||
for(i=0; i<(p->nToken-1); i++){
|
||||
if( a[i].bIgnore==0 ){
|
||||
@@ -4939,13 +4807,12 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
a = sqlite3_column_blob(pStmt, 0);
|
||||
testcase( a==0 ); /* If %_stat.value set to X'' */
|
||||
if( a ){
|
||||
pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
|
||||
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
|
||||
while( a<pEnd ){
|
||||
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
|
||||
}
|
||||
assert( a );
|
||||
|
||||
pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
|
||||
a += sqlite3Fts3GetVarint(a, &nDoc);
|
||||
while( a<pEnd ){
|
||||
a += sqlite3Fts3GetVarint(a, &nByte);
|
||||
}
|
||||
if( nDoc==0 || nByte==0 ){
|
||||
sqlite3_reset(pStmt);
|
||||
@@ -5123,7 +4990,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
|
||||
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
|
||||
Fts3TokenAndCost *aTC;
|
||||
Fts3Expr **apOr;
|
||||
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
|
||||
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
|
||||
sizeof(Fts3TokenAndCost) * nToken
|
||||
+ sizeof(Fts3Expr *) * nOr * 2
|
||||
);
|
||||
@@ -5177,7 +5044,7 @@ static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
|
||||
**
|
||||
** Parameter nNear is passed the NEAR distance of the expression (5 in
|
||||
** the example above). When this function is called, *paPoslist points to
|
||||
** the position list, and *pnToken is the number of phrase tokens in the
|
||||
** the position list, and *pnToken is the number of phrase tokens in, the
|
||||
** phrase on the other side of the NEAR operator to pPhrase. For example,
|
||||
** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
|
||||
** the position list associated with phrase "abc".
|
||||
@@ -5212,12 +5079,10 @@ static int fts3EvalNearTrim(
|
||||
);
|
||||
if( res ){
|
||||
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
|
||||
if( nNew>=0 ){
|
||||
assert( pPhrase->doclist.pList[nNew]=='\0' );
|
||||
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
|
||||
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
|
||||
pPhrase->doclist.nList = nNew;
|
||||
}
|
||||
assert( pPhrase->doclist.pList[nNew]=='\0' );
|
||||
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
|
||||
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
|
||||
pPhrase->doclist.nList = nNew;
|
||||
*paPoslist = pPhrase->doclist.pList;
|
||||
*pnToken = pPhrase->nToken;
|
||||
}
|
||||
@@ -5326,7 +5191,6 @@ static void fts3EvalNextRow(
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
}
|
||||
}
|
||||
pRight->bEof = pLeft->bEof = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -5437,7 +5301,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
||||
){
|
||||
Fts3Expr *p;
|
||||
sqlite3_int64 nTmp = 0; /* Bytes of temp space */
|
||||
int nTmp = 0; /* Bytes of temp space */
|
||||
char *aTmp; /* Temp space for PoslistNearMerge() */
|
||||
|
||||
/* Allocate temporary working space. */
|
||||
@@ -5446,7 +5310,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||
}
|
||||
nTmp += p->pPhrase->doclist.nList;
|
||||
aTmp = sqlite3_malloc64(nTmp*2);
|
||||
aTmp = sqlite3_malloc(nTmp*2);
|
||||
if( !aTmp ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
res = 0;
|
||||
@@ -5569,10 +5433,7 @@ static int fts3EvalTestExpr(
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
bHit = (
|
||||
pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId
|
||||
&& pExpr->pPhrase->doclist.nList>0
|
||||
);
|
||||
bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5719,14 +5580,15 @@ static void fts3EvalRestart(
|
||||
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
|
||||
** expression nodes.
|
||||
*/
|
||||
static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
|
||||
static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
|
||||
if( pExpr ){
|
||||
Fts3Phrase *pPhrase = pExpr->pPhrase;
|
||||
if( pPhrase && pPhrase->doclist.pList ){
|
||||
int iCol = 0;
|
||||
char *p = pPhrase->doclist.pList;
|
||||
|
||||
do{
|
||||
assert( *p );
|
||||
while( 1 ){
|
||||
u8 c = 0;
|
||||
int iCnt = 0;
|
||||
while( 0xFE & (*p | c) ){
|
||||
@@ -5742,11 +5604,11 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
|
||||
if( *p==0x00 ) break;
|
||||
p++;
|
||||
p += fts3GetVarint32(p, &iCol);
|
||||
}while( iCol<nCol );
|
||||
}
|
||||
}
|
||||
|
||||
fts3EvalUpdateCounts(pExpr->pLeft, nCol);
|
||||
fts3EvalUpdateCounts(pExpr->pRight, nCol);
|
||||
fts3EvalUpdateCounts(pExpr->pLeft);
|
||||
fts3EvalUpdateCounts(pExpr->pRight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5790,7 +5652,7 @@ static int fts3EvalGatherStats(
|
||||
for(p=pRoot; p; p=p->pLeft){
|
||||
Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
|
||||
assert( pE->aMI==0 );
|
||||
pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
|
||||
pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
|
||||
if( !pE->aMI ) return SQLITE_NOMEM;
|
||||
memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
|
||||
}
|
||||
@@ -5816,7 +5678,7 @@ static int fts3EvalGatherStats(
|
||||
);
|
||||
|
||||
if( rc==SQLITE_OK && pCsr->isEof==0 ){
|
||||
fts3EvalUpdateCounts(pRoot, pTab->nColumn);
|
||||
fts3EvalUpdateCounts(pRoot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5835,8 +5697,7 @@ static int fts3EvalGatherStats(
|
||||
fts3EvalRestart(pCsr, pRoot, &rc);
|
||||
do {
|
||||
fts3EvalNextRow(pCsr, pRoot, &rc);
|
||||
assert_fts3_nc( pRoot->bEof==0 );
|
||||
if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB;
|
||||
assert( pRoot->bEof==0 );
|
||||
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
|
||||
}
|
||||
}
|
||||
|
||||
+1
-34
@@ -95,8 +95,6 @@ SQLITE_EXTENSION_INIT3
|
||||
*/
|
||||
#define FTS3_VARINT_MAX 10
|
||||
|
||||
#define FTS3_BUFFER_PADDING 8
|
||||
|
||||
/*
|
||||
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
|
||||
** in the document set and zero or more prefix indexes. All indexes are stored
|
||||
@@ -129,18 +127,6 @@ SQLITE_EXTENSION_INIT3
|
||||
#define POS_COLUMN (1) /* Column-list terminator */
|
||||
#define POS_END (0) /* Position-list terminator */
|
||||
|
||||
/*
|
||||
** The assert_fts3_nc() macro is similar to the assert() macro, except that it
|
||||
** is used for assert() conditions that are true only if it can be
|
||||
** guranteed that the database is not corrupt.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
extern int sqlite3_fts3_may_be_corrupt;
|
||||
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
|
||||
#else
|
||||
# define assert_fts3_nc(x) assert(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This section provides definitions to allow the
|
||||
** FTS3 extension to be compiled outside of the
|
||||
@@ -196,11 +182,6 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
|
||||
# define TESTONLY(X)
|
||||
#endif
|
||||
|
||||
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
||||
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
||||
|
||||
#define deliberate_fall_through
|
||||
|
||||
#endif /* SQLITE_AMALGAMATION */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -244,7 +225,6 @@ struct Fts3Table {
|
||||
char *zLanguageid; /* languageid=xxx option, or NULL */
|
||||
int nAutoincrmerge; /* Value configured by 'automerge' */
|
||||
u32 nLeafAdd; /* Number of leaf blocks added this trans */
|
||||
int bLock; /* Used to prevent recursive content= tbls */
|
||||
|
||||
/* Precompiled statements used by the implementation. Each of these
|
||||
** statements is run and reset within a single virtual table API call.
|
||||
@@ -303,23 +283,13 @@ struct Fts3Table {
|
||||
int mxSavepoint; /* Largest valid xSavepoint integer */
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
#ifdef SQLITE_TEST
|
||||
/* True to disable the incremental doclist optimization. This is controled
|
||||
** by special insert command 'test-no-incr-doclist'. */
|
||||
int bNoIncrDoclist;
|
||||
|
||||
/* Number of segments in a level */
|
||||
int nMergeCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Macro to find the number of segments to merge */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
# define MergeCount(P) ((P)->nMergeCount)
|
||||
#else
|
||||
# define MergeCount(P) FTS3_MERGE_COUNT
|
||||
#endif
|
||||
|
||||
/*
|
||||
** When the core wants to read from the virtual table, it creates a
|
||||
** virtual table cursor (an instance of the following structure) using
|
||||
@@ -583,8 +553,6 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
|
||||
void sqlite3Fts3ErrMsg(char**,const char*,...);
|
||||
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
|
||||
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
|
||||
int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
|
||||
int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
|
||||
int sqlite3Fts3GetVarint32(const char *, int *);
|
||||
int sqlite3Fts3VarintLen(sqlite3_uint64);
|
||||
void sqlite3Fts3Dequote(char *);
|
||||
@@ -593,7 +561,6 @@ int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
|
||||
int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
|
||||
void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
|
||||
int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
|
||||
int sqlite3Fts3ReadInt(const char *z, int *pnOut);
|
||||
|
||||
/* fts3_tokenizer.c */
|
||||
const char *sqlite3Fts3NextToken(const char *, int *);
|
||||
|
||||
+6
-7
@@ -66,7 +66,7 @@ static int fts3auxConnectMethod(
|
||||
char const *zFts3; /* Name of fts3 table */
|
||||
int nDb; /* Result of strlen(zDb) */
|
||||
int nFts3; /* Result of strlen(zFts3) */
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate here */
|
||||
int nByte; /* Bytes of space to allocate here */
|
||||
int rc; /* value returned by declare_vtab() */
|
||||
Fts3auxTable *p; /* Virtual table object to return */
|
||||
|
||||
@@ -98,7 +98,7 @@ static int fts3auxConnectMethod(
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
|
||||
p = (Fts3auxTable *)sqlite3_malloc64(nByte);
|
||||
p = (Fts3auxTable *)sqlite3_malloc(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, nByte);
|
||||
|
||||
@@ -248,7 +248,7 @@ static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
|
||||
if( nSize>pCsr->nStat ){
|
||||
struct Fts3auxColstats *aNew;
|
||||
aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat,
|
||||
aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
|
||||
sizeof(struct Fts3auxColstats) * nSize
|
||||
);
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
@@ -416,15 +416,15 @@ static int fts3auxFilterMethod(
|
||||
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
|
||||
if( zStr ){
|
||||
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
|
||||
pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
|
||||
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
|
||||
pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
|
||||
}
|
||||
}
|
||||
|
||||
if( iLe>=0 ){
|
||||
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
|
||||
pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
|
||||
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
|
||||
pCsr->nStop = (int)strlen(pCsr->zStop);
|
||||
}
|
||||
|
||||
if( iLangid>=0 ){
|
||||
@@ -539,8 +539,7 @@ int sqlite3Fts3InitAux(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
+12
-8
@@ -122,8 +122,8 @@ static int fts3isspace(char c){
|
||||
** zero the memory before returning a pointer to it. If unsuccessful,
|
||||
** return NULL.
|
||||
*/
|
||||
static void *fts3MallocZero(sqlite3_int64 nByte){
|
||||
void *pRet = sqlite3_malloc64(nByte);
|
||||
static void *fts3MallocZero(int nByte){
|
||||
void *pRet = sqlite3_malloc(nByte);
|
||||
if( pRet ) memset(pRet, 0, nByte);
|
||||
return pRet;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ static int getNextToken(
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zToken;
|
||||
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
|
||||
sqlite3_int64 nByte; /* total space to allocate */
|
||||
int nByte; /* total space to allocate */
|
||||
|
||||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -252,8 +252,8 @@ static int getNextToken(
|
||||
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
|
||||
** then free the old allocation.
|
||||
*/
|
||||
static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
|
||||
void *pRet = sqlite3_realloc64(pOrig, nNew);
|
||||
static void *fts3ReallocOrFree(void *pOrig, int nNew){
|
||||
void *pRet = sqlite3_realloc(pOrig, nNew);
|
||||
if( !pRet ){
|
||||
sqlite3_free(pOrig);
|
||||
}
|
||||
@@ -446,7 +446,10 @@ static int getNextNode(
|
||||
if( pKey->eType==FTSQUERY_NEAR ){
|
||||
assert( nKey==4 );
|
||||
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
||||
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
||||
nNear = 0;
|
||||
for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
|
||||
nNear = nNear * 10 + (zInput[nKey] - '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,6 +497,7 @@ static int getNextNode(
|
||||
int nConsumed = 0;
|
||||
pParse->nNest++;
|
||||
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
|
||||
if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
|
||||
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
|
||||
return rc;
|
||||
}else if( *zInput==')' ){
|
||||
@@ -792,7 +796,7 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
|
||||
Fts3Expr **apLeaf;
|
||||
apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth);
|
||||
apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
|
||||
if( 0==apLeaf ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -1212,7 +1216,7 @@ static void fts3ExprTestCommon(
|
||||
zExpr = (const char *)sqlite3_value_text(argv[1]);
|
||||
nExpr = sqlite3_value_bytes(argv[1]);
|
||||
nCol = argc-2;
|
||||
azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *));
|
||||
azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
|
||||
if( !azCol ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
goto exprtest_out;
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
/*
|
||||
** Malloc and Free functions
|
||||
*/
|
||||
static void *fts3HashMalloc(sqlite3_int64 n){
|
||||
void *p = sqlite3_malloc64(n);
|
||||
static void *fts3HashMalloc(int n){
|
||||
void *p = sqlite3_malloc(n);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
}
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ static int icuCreate(
|
||||
if( argc>0 ){
|
||||
n = strlen(argv[0])+1;
|
||||
}
|
||||
p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
|
||||
p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
|
||||
if( !p ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ static int icuOpen(
|
||||
nInput = strlen(zInput);
|
||||
}
|
||||
nChar = nInput+1;
|
||||
pCsr = (IcuCursor *)sqlite3_malloc64(
|
||||
pCsr = (IcuCursor *)sqlite3_malloc(
|
||||
sizeof(IcuCursor) + /* IcuCursor */
|
||||
((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
|
||||
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
|
||||
|
||||
+47
-89
@@ -128,19 +128,17 @@ struct StrBuffer {
|
||||
/*
|
||||
** Allocate a two-slot MatchinfoBuffer object.
|
||||
*/
|
||||
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){
|
||||
MatchinfoBuffer *pRet;
|
||||
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
|
||||
+ sizeof(MatchinfoBuffer);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer);
|
||||
int nStr = (int)strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3_malloc64(nByte + nStr+1);
|
||||
pRet = sqlite3_malloc(nByte + nStr+1);
|
||||
if( pRet ){
|
||||
memset(pRet, 0, nByte);
|
||||
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
|
||||
+ sizeof(u32)*((int)nElem+1);
|
||||
pRet->nElem = (int)nElem;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1);
|
||||
pRet->nElem = nElem;
|
||||
pRet->zMatchinfo = ((char*)pRet) + nByte;
|
||||
memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
|
||||
pRet->aRef[0] = 1;
|
||||
@@ -180,7 +178,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
|
||||
aOut = &p->aMatchinfo[p->nElem+2];
|
||||
xRet = fts3MIBufferFree;
|
||||
}else{
|
||||
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
|
||||
aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
|
||||
if( aOut ){
|
||||
xRet = sqlite3_free;
|
||||
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
|
||||
@@ -431,12 +429,11 @@ static void fts3SnippetDetails(
|
||||
char *pCsr = pPhrase->pTail;
|
||||
int iCsr = pPhrase->iTail;
|
||||
|
||||
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
|
||||
while( iCsr<(iStart+pIter->nSnippet) ){
|
||||
int j;
|
||||
u64 mPhrase = (u64)1 << (i%64);
|
||||
u64 mPhrase = (u64)1 << i;
|
||||
u64 mPos = (u64)1 << (iCsr - iStart);
|
||||
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
|
||||
assert( i>=0 );
|
||||
assert( iCsr>=iStart );
|
||||
if( (mCover|mCovered)&mPhrase ){
|
||||
iScore++;
|
||||
}else{
|
||||
@@ -478,14 +475,11 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
int iFirst = 0;
|
||||
pPhrase->pList = pCsr;
|
||||
fts3GetDeltaPosition(&pCsr, &iFirst);
|
||||
if( iFirst<0 ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}else{
|
||||
pPhrase->pHead = pCsr;
|
||||
pPhrase->pTail = pCsr;
|
||||
pPhrase->iHead = iFirst;
|
||||
pPhrase->iTail = iFirst;
|
||||
}
|
||||
assert( iFirst>=0 );
|
||||
pPhrase->pHead = pCsr;
|
||||
pPhrase->pTail = pCsr;
|
||||
pPhrase->iHead = iFirst;
|
||||
pPhrase->iTail = iFirst;
|
||||
}else{
|
||||
assert( rc!=SQLITE_OK || (
|
||||
pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
|
||||
@@ -522,7 +516,7 @@ static int fts3BestSnippet(
|
||||
int rc; /* Return Code */
|
||||
int nList; /* Number of phrases in expression */
|
||||
SnippetIter sIter; /* Iterates through snippet candidates */
|
||||
sqlite3_int64 nByte; /* Number of bytes of space to allocate */
|
||||
int nByte; /* Number of bytes of space to allocate */
|
||||
int iBestScore = -1; /* Best snippet score found so far */
|
||||
int i; /* Loop counter */
|
||||
|
||||
@@ -540,7 +534,7 @@ static int fts3BestSnippet(
|
||||
** the required space using malloc().
|
||||
*/
|
||||
nByte = sizeof(SnippetPhrase) * nList;
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
|
||||
if( !sIter.aPhrase ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -560,7 +554,7 @@ static int fts3BestSnippet(
|
||||
/* Set the *pmSeen output variable. */
|
||||
for(i=0; i<nList; i++){
|
||||
if( sIter.aPhrase[i].pHead ){
|
||||
*pmSeen |= (u64)1 << (i%64);
|
||||
*pmSeen |= (u64)1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,8 +604,8 @@ static int fts3StringAppend(
|
||||
** appended data.
|
||||
*/
|
||||
if( pStr->n+nAppend+1>=pStr->nAlloc ){
|
||||
sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
|
||||
char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
|
||||
int nAlloc = pStr->nAlloc+nAppend+100;
|
||||
char *zNew = sqlite3_realloc(pStr->z, nAlloc);
|
||||
if( !zNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -666,7 +660,6 @@ static int fts3SnippetShift(
|
||||
|
||||
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
|
||||
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
|
||||
assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
|
||||
nDesired = (nLeft-nRight)/2;
|
||||
|
||||
/* Ideally, the start of the snippet should be pushed forward in the
|
||||
@@ -859,7 +852,7 @@ static int fts3ColumnlistCount(char **ppCollist){
|
||||
/*
|
||||
** This function gathers 'y' or 'b' data for a single phrase.
|
||||
*/
|
||||
static int fts3ExprLHits(
|
||||
static void fts3ExprLHits(
|
||||
Fts3Expr *pExpr, /* Phrase expression node */
|
||||
MatchInfo *p /* Matchinfo context */
|
||||
){
|
||||
@@ -876,7 +869,7 @@ static int fts3ExprLHits(
|
||||
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
|
||||
}
|
||||
|
||||
if( pIter ) while( 1 ){
|
||||
while( 1 ){
|
||||
int nHit = fts3ColumnlistCount(&pIter);
|
||||
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
|
||||
if( p->flag==FTS3_MATCHINFO_LHITS ){
|
||||
@@ -889,29 +882,25 @@ static int fts3ExprLHits(
|
||||
if( *pIter!=0x01 ) break;
|
||||
pIter++;
|
||||
pIter += fts3GetVarint32(pIter, &iCol);
|
||||
if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Gather the results for matchinfo directives 'y' and 'b'.
|
||||
*/
|
||||
static int fts3ExprLHitGather(
|
||||
static void fts3ExprLHitGather(
|
||||
Fts3Expr *pExpr,
|
||||
MatchInfo *p
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
|
||||
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
|
||||
if( pExpr->pLeft ){
|
||||
rc = fts3ExprLHitGather(pExpr->pLeft, p);
|
||||
if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p);
|
||||
fts3ExprLHitGather(pExpr->pLeft, p);
|
||||
fts3ExprLHitGather(pExpr->pRight, p);
|
||||
}else{
|
||||
rc = fts3ExprLHits(pExpr, p);
|
||||
fts3ExprLHits(pExpr, p);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1001,8 +990,8 @@ static int fts3MatchinfoCheck(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
size_t nVal; /* Number of integers output by cArg */
|
||||
static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
int nVal; /* Number of integers output by cArg */
|
||||
|
||||
switch( cArg ){
|
||||
case FTS3_MATCHINFO_NDOC:
|
||||
@@ -1038,15 +1027,11 @@ static int fts3MatchinfoSelectDoctotal(
|
||||
Fts3Table *pTab,
|
||||
sqlite3_stmt **ppStmt,
|
||||
sqlite3_int64 *pnDoc,
|
||||
const char **paLen,
|
||||
const char **ppEnd
|
||||
const char **paLen
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
const char *a;
|
||||
const char *pEnd;
|
||||
sqlite3_int64 nDoc;
|
||||
int n;
|
||||
|
||||
|
||||
if( !*ppStmt ){
|
||||
int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
|
||||
@@ -1055,20 +1040,12 @@ static int fts3MatchinfoSelectDoctotal(
|
||||
pStmt = *ppStmt;
|
||||
assert( sqlite3_data_count(pStmt)==1 );
|
||||
|
||||
n = sqlite3_column_bytes(pStmt, 0);
|
||||
a = sqlite3_column_blob(pStmt, 0);
|
||||
if( a==0 ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
pEnd = a + n;
|
||||
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
|
||||
if( nDoc<=0 || a>pEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
*pnDoc = nDoc;
|
||||
a += sqlite3Fts3GetVarint(a, &nDoc);
|
||||
if( nDoc==0 ) return FTS_CORRUPT_VTAB;
|
||||
*pnDoc = (u32)nDoc;
|
||||
|
||||
if( paLen ) *paLen = a;
|
||||
if( ppEnd ) *ppEnd = pEnd;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1140,12 +1117,11 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
|
||||
int i;
|
||||
int iCol;
|
||||
int nToken = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* Allocate and populate the array of LcsIterator objects. The array
|
||||
** contains one element for each matchable phrase in the query.
|
||||
**/
|
||||
aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
if( !aIter ) return SQLITE_NOMEM;
|
||||
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
|
||||
@@ -1161,16 +1137,13 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
|
||||
int nLive = 0; /* Number of iterators in aIter not at EOF */
|
||||
|
||||
for(i=0; i<pInfo->nPhrase; i++){
|
||||
int rc;
|
||||
LcsIterator *pIt = &aIter[i];
|
||||
rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
|
||||
if( rc!=SQLITE_OK ) goto matchinfo_lcs_out;
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( pIt->pRead ){
|
||||
pIt->iPos = pIt->iPosOffset;
|
||||
fts3LcsIteratorAdvance(pIt);
|
||||
if( pIt->pRead==0 ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto matchinfo_lcs_out;
|
||||
}
|
||||
fts3LcsIteratorAdvance(&aIter[i]);
|
||||
nLive++;
|
||||
}
|
||||
}
|
||||
@@ -1202,9 +1175,8 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
|
||||
pInfo->aMatchinfo[iCol] = nLcs;
|
||||
}
|
||||
|
||||
matchinfo_lcs_out:
|
||||
sqlite3_free(aIter);
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1249,7 +1221,7 @@ static int fts3MatchinfoValues(
|
||||
case FTS3_MATCHINFO_NDOC:
|
||||
if( bGlobal ){
|
||||
sqlite3_int64 nDoc = 0;
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
|
||||
pInfo->aMatchinfo[0] = (u32)nDoc;
|
||||
}
|
||||
break;
|
||||
@@ -1258,19 +1230,14 @@ static int fts3MatchinfoValues(
|
||||
if( bGlobal ){
|
||||
sqlite3_int64 nDoc; /* Number of rows in table */
|
||||
const char *a; /* Aggregate column length array */
|
||||
const char *pEnd; /* First byte past end of length array */
|
||||
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
|
||||
if( rc==SQLITE_OK ){
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pInfo->nCol; iCol++){
|
||||
u32 iVal;
|
||||
sqlite3_int64 nToken;
|
||||
a += sqlite3Fts3GetVarint(a, &nToken);
|
||||
if( a>pEnd ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
|
||||
pInfo->aMatchinfo[iCol] = iVal;
|
||||
}
|
||||
@@ -1284,14 +1251,9 @@ static int fts3MatchinfoValues(
|
||||
if( rc==SQLITE_OK ){
|
||||
int iCol;
|
||||
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
|
||||
const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
|
||||
for(iCol=0; iCol<pInfo->nCol; iCol++){
|
||||
sqlite3_int64 nToken;
|
||||
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
|
||||
if( a>pEnd ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
a += sqlite3Fts3GetVarint(a, &nToken);
|
||||
pInfo->aMatchinfo[iCol] = (u32)nToken;
|
||||
}
|
||||
}
|
||||
@@ -1308,9 +1270,9 @@ static int fts3MatchinfoValues(
|
||||
|
||||
case FTS3_MATCHINFO_LHITS_BM:
|
||||
case FTS3_MATCHINFO_LHITS: {
|
||||
size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
|
||||
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
|
||||
memset(pInfo->aMatchinfo, 0, nZero);
|
||||
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
|
||||
fts3ExprLHitGather(pCsr->pExpr, pInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1322,7 +1284,7 @@ static int fts3MatchinfoValues(
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
if( bGlobal ){
|
||||
if( pCsr->pDeferred ){
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
|
||||
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
|
||||
@@ -1377,7 +1339,7 @@ static void fts3GetMatchinfo(
|
||||
** initialize those elements that are constant for every row.
|
||||
*/
|
||||
if( pCsr->pMIBuffer==0 ){
|
||||
size_t nMatchinfo = 0; /* Number of u32 elements in match-info */
|
||||
int nMatchinfo = 0; /* Number of u32 elements in match-info */
|
||||
int i; /* Used to iterate through zArg */
|
||||
|
||||
/* Determine the number of phrases in the query */
|
||||
@@ -1462,10 +1424,6 @@ void sqlite3Fts3Snippet(
|
||||
return;
|
||||
}
|
||||
|
||||
/* Limit the snippet length to 64 tokens. */
|
||||
if( nToken<-64 ) nToken = -64;
|
||||
if( nToken>+64 ) nToken = +64;
|
||||
|
||||
for(nSnippet=1; 1; nSnippet++){
|
||||
|
||||
int iSnip; /* Loop counter 0..nSnippet-1 */
|
||||
@@ -1567,7 +1525,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
nTerm = pExpr->pPhrase->nToken;
|
||||
if( pList ){
|
||||
fts3GetDeltaPosition(&pList, &iPos);
|
||||
assert_fts3_nc( iPos>=0 );
|
||||
assert( iPos>=0 );
|
||||
}
|
||||
|
||||
for(iTerm=0; iTerm<nTerm; iTerm++){
|
||||
@@ -1608,7 +1566,7 @@ void sqlite3Fts3Offsets(
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Allocate the array of TermOffset iterators. */
|
||||
sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
|
||||
sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
|
||||
if( 0==sCtx.aTerm ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto offsets_out;
|
||||
@@ -1677,7 +1635,7 @@ void sqlite3Fts3Offsets(
|
||||
/* All offsets for this column have been gathered. */
|
||||
rc = SQLITE_DONE;
|
||||
}else{
|
||||
assert_fts3_nc( iCurrent<=iMinPos );
|
||||
assert( iCurrent<=iMinPos );
|
||||
if( 0==(0xFE&*pTerm->pList) ){
|
||||
pTerm->pList = 0;
|
||||
}else{
|
||||
|
||||
@@ -68,9 +68,9 @@ static int fts3termConnectMethod(
|
||||
char const *zFts3; /* Name of fts3 table */
|
||||
int nDb; /* Result of strlen(zDb) */
|
||||
int nFts3; /* Result of strlen(zFts3) */
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate here */
|
||||
int nByte; /* Bytes of space to allocate here */
|
||||
int rc; /* value returned by declare_vtab() */
|
||||
Fts3termTable *p; /* Virtual table object to return */
|
||||
Fts3termTable *p; /* Virtual table object to return */
|
||||
int iIndex = 0;
|
||||
|
||||
UNUSED_PARAMETER(pCtx);
|
||||
@@ -96,9 +96,9 @@ static int fts3termConnectMethod(
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
|
||||
p = (Fts3termTable *)sqlite3_malloc64(nByte);
|
||||
p = (Fts3termTable *)sqlite3_malloc(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, (size_t)nByte);
|
||||
memset(p, 0, nByte);
|
||||
|
||||
p->pFts3Tab = (Fts3Table *)&p[1];
|
||||
p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
|
||||
@@ -361,8 +361,7 @@ int sqlite3Fts3InitTerm(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
+5
-34
@@ -448,14 +448,14 @@ static int testTokenizerNext(
|
||||
}else{
|
||||
/* Advance to the end of the token */
|
||||
const char *pToken = p;
|
||||
sqlite3_int64 nToken;
|
||||
int nToken;
|
||||
while( p<pEnd && testIsTokenChar(*p) ) p++;
|
||||
nToken = (sqlite3_int64)(p-pToken);
|
||||
nToken = (int)(p-pToken);
|
||||
|
||||
/* Copy the token into the buffer */
|
||||
if( nToken>pCsr->nBuffer ){
|
||||
sqlite3_free(pCsr->aBuffer);
|
||||
pCsr->aBuffer = sqlite3_malloc64(nToken);
|
||||
pCsr->aBuffer = sqlite3_malloc(nToken);
|
||||
}
|
||||
if( pCsr->aBuffer==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -471,7 +471,7 @@ static int testTokenizerNext(
|
||||
pCsr->iInput = (int)(p - pCsr->aInput);
|
||||
|
||||
*ppToken = pCsr->aBuffer;
|
||||
*pnBytes = (int)nToken;
|
||||
*pnBytes = nToken;
|
||||
*piStartOffset = (int)(pToken - pCsr->aInput);
|
||||
*piEndOffset = (int)(p - pCsr->aInput);
|
||||
*piPosition = pCsr->iToken;
|
||||
@@ -574,33 +574,6 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
|
||||
** End of tokenizer code.
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
** sqlite3_fts3_may_be_corrupt BOOLEAN
|
||||
**
|
||||
** Set or clear the global "may-be-corrupt" flag. Return the old value.
|
||||
*/
|
||||
static int SQLITE_TCLAPI fts3_may_be_corrupt(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int bOld = sqlite3_fts3_may_be_corrupt;
|
||||
|
||||
if( objc!=2 && objc!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( objc==2 ){
|
||||
int bNew;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
|
||||
sqlite3_fts3_may_be_corrupt = bNew;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int Sqlitetestfts3_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
|
||||
Tcl_CreateObjCommand(interp,
|
||||
@@ -609,12 +582,10 @@ int Sqlitetestfts3_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0
|
||||
);
|
||||
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "fts3_test_varint", fts3_test_varint_cmd, 0, 0
|
||||
);
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "sqlite3_fts3_may_be_corrupt", fts3_may_be_corrupt, 0, 0
|
||||
);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */
|
||||
|
||||
@@ -122,7 +122,7 @@ static int fts3tokDequoteArray(
|
||||
nByte += (int)(strlen(argv[i]) + 1);
|
||||
}
|
||||
|
||||
*pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
|
||||
*pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
|
||||
if( azDequote==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -188,8 +188,7 @@ static int fts3tokConnectMethod(
|
||||
|
||||
assert( (rc==SQLITE_OK)==(pMod!=0) );
|
||||
if( rc==SQLITE_OK ){
|
||||
const char * const *azArg = 0;
|
||||
if( nDequote>1 ) azArg = (const char * const *)&azDequote[1];
|
||||
const char * const *azArg = (const char * const *)&azDequote[1];
|
||||
rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
|
||||
}
|
||||
|
||||
@@ -347,11 +346,11 @@ static int fts3tokFilterMethod(
|
||||
if( idxNum==1 ){
|
||||
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
|
||||
int nByte = sqlite3_value_bytes(apVal[0]);
|
||||
pCsr->zInput = sqlite3_malloc64(nByte+1);
|
||||
pCsr->zInput = sqlite3_malloc(nByte+1);
|
||||
if( pCsr->zInput==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
|
||||
memcpy(pCsr->zInput, zByte, nByte);
|
||||
pCsr->zInput[nByte] = 0;
|
||||
rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -444,8 +443,7 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ static void fts3TokenizerFunc(
|
||||
nName = sqlite3_value_bytes(argv[0])+1;
|
||||
|
||||
if( argc==2 ){
|
||||
if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){
|
||||
if( fts3TokenizerEnabled(context) ){
|
||||
void *pOld;
|
||||
int n = sqlite3_value_bytes(argv[1]);
|
||||
if( zName==0 || n!=sizeof(pPtr) ){
|
||||
@@ -106,9 +106,7 @@ static void fts3TokenizerFunc(
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){
|
||||
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
|
||||
}
|
||||
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
int sqlite3Fts3IsIdChar(char c){
|
||||
@@ -196,8 +194,8 @@ int sqlite3Fts3InitTokenizer(
|
||||
int iArg = 0;
|
||||
z = &z[n+1];
|
||||
while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
|
||||
sqlite3_int64 nNew = sizeof(char *)*(iArg+1);
|
||||
char const **aNew = (const char **)sqlite3_realloc64((void *)aArg, nNew);
|
||||
int nNew = sizeof(char *)*(iArg+1);
|
||||
char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
|
||||
if( !aNew ){
|
||||
sqlite3_free(zCopy);
|
||||
sqlite3_free((void *)aArg);
|
||||
@@ -390,9 +388,7 @@ int queryTokenizer(
|
||||
|
||||
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB
|
||||
&& sqlite3_column_bytes(pStmt, 0)==sizeof(*pp)
|
||||
){
|
||||
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
||||
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
}
|
||||
}
|
||||
@@ -481,7 +477,7 @@ int sqlite3Fts3InitHashTable(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
void *p = (void *)pHash;
|
||||
const int any = SQLITE_UTF8|SQLITE_DIRECTONLY;
|
||||
const int any = SQLITE_ANY;
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
char *zTest = 0;
|
||||
|
||||
+7
-10
@@ -82,7 +82,7 @@ typedef struct unicode_cursor unicode_cursor;
|
||||
|
||||
struct unicode_tokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
int eRemoveDiacritic;
|
||||
int bRemoveDiacritic;
|
||||
int nException;
|
||||
int *aiException;
|
||||
};
|
||||
@@ -155,7 +155,7 @@ static int unicodeAddExceptions(
|
||||
int *aNew; /* New aiException[] array */
|
||||
int nNew; /* Number of valid entries in array aNew[] */
|
||||
|
||||
aNew = sqlite3_realloc64(p->aiException,(p->nException+nEntry)*sizeof(int));
|
||||
aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
nNew = p->nException;
|
||||
|
||||
@@ -227,20 +227,17 @@ static int unicodeCreate(
|
||||
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
|
||||
if( pNew==NULL ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(unicode_tokenizer));
|
||||
pNew->eRemoveDiacritic = 1;
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i++){
|
||||
const char *z = azArg[i];
|
||||
int n = (int)strlen(z);
|
||||
|
||||
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
|
||||
pNew->eRemoveDiacritic = 1;
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
}
|
||||
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
|
||||
pNew->eRemoveDiacritic = 0;
|
||||
}
|
||||
else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
|
||||
pNew->eRemoveDiacritic = 2;
|
||||
pNew->bRemoveDiacritic = 0;
|
||||
}
|
||||
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
|
||||
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
|
||||
@@ -344,7 +341,7 @@ static int unicodeNext(
|
||||
|
||||
/* Grow the output buffer if required. */
|
||||
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
|
||||
char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
|
||||
char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
|
||||
if( !zNew ) return SQLITE_NOMEM;
|
||||
zOut = &zNew[zOut - pCsr->zToken];
|
||||
pCsr->zToken = zNew;
|
||||
@@ -353,7 +350,7 @@ static int unicodeNext(
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
|
||||
+26
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** 2012-05-25
|
||||
** 2012 May 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
@@ -159,48 +159,32 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int remove_diacritic(int c, int bComplex){
|
||||
static int remove_diacritic(int c){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
|
||||
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
|
||||
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
|
||||
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
|
||||
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
|
||||
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
|
||||
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
|
||||
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
|
||||
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
|
||||
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
|
||||
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
|
||||
63182, 63242, 63274, 63310, 63368, 63390,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
};
|
||||
#define HIBIT ((unsigned char)0x80)
|
||||
unsigned char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n',
|
||||
'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y',
|
||||
'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
|
||||
'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
|
||||
'e', 'i', 'o', 'r', 'u', 's',
|
||||
't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
|
||||
'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b',
|
||||
'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
|
||||
'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
|
||||
'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
|
||||
'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
|
||||
's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
|
||||
'w', 'x', 'y', 'z', 'h', 't',
|
||||
'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
|
||||
'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
|
||||
'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
@@ -217,8 +201,7 @@ static int remove_diacritic(int c, int bComplex){
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,8 +214,8 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
unsigned int mask1 = 0x000361F8;
|
||||
if( c<768 || c>817 ) return 0;
|
||||
return (c < 768+32) ?
|
||||
(mask0 & ((unsigned int)1 << (c-768))) :
|
||||
(mask1 & ((unsigned int)1 << (c-768-32)));
|
||||
(mask0 & (1 << (c-768))) :
|
||||
(mask1 & (1 << (c-768-32)));
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +228,7 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
|
||||
int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
@@ -368,9 +351,7 @@ int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( eRemoveDiacritic ){
|
||||
ret = remove_diacritic(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
|
||||
+120
-229
@@ -23,7 +23,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define FTS_MAX_APPENDABLE_HEIGHT 16
|
||||
|
||||
@@ -67,7 +67,7 @@ int test_fts3_node_chunk_threshold = (4*1024)*4;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The values that may be meaningfully bound to the :1 parameter in
|
||||
** The two values that may be meaningfully bound to the :1 parameter in
|
||||
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
|
||||
*/
|
||||
#define FTS_STAT_DOCTOTAL 0
|
||||
@@ -335,15 +335,13 @@ static int fts3SqlStmt(
|
||||
** returns zero rows. */
|
||||
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
|
||||
" GROUP BY level HAVING cnt>=?"
|
||||
" ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",
|
||||
" ORDER BY (level %% 1024) ASC LIMIT 1",
|
||||
|
||||
/* Estimate the upper limit on the number of leaf nodes in a new segment
|
||||
** created by merging the oldest :2 segments from absolute level :1. See
|
||||
** function sqlite3Fts3Incrmerge() for details. */
|
||||
/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
|
||||
" FROM (SELECT * FROM %Q.'%q_segdir' "
|
||||
" WHERE level = ? ORDER BY idx ASC LIMIT ?"
|
||||
" )",
|
||||
" FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
|
||||
|
||||
/* SQL_DELETE_SEGDIR_ENTRY
|
||||
** Delete the %_segdir entry on absolute level :1 with index :2. */
|
||||
@@ -398,12 +396,10 @@ static int fts3SqlStmt(
|
||||
|
||||
pStmt = p->aStmt[eStmt];
|
||||
if( !pStmt ){
|
||||
int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
|
||||
char *zSql;
|
||||
if( eStmt==SQL_CONTENT_INSERT ){
|
||||
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
|
||||
}else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
|
||||
f &= ~SQLITE_PREPARE_NO_VTAB;
|
||||
zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
|
||||
}else{
|
||||
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
|
||||
@@ -411,7 +407,8 @@ static int fts3SqlStmt(
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
|
||||
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
&pStmt, NULL);
|
||||
sqlite3_free(zSql);
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
p->aStmt[eStmt] = pStmt;
|
||||
@@ -569,7 +566,7 @@ static sqlite3_int64 getAbsoluteLevel(
|
||||
int iLevel /* Level of segments */
|
||||
){
|
||||
sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
|
||||
assert_fts3_nc( iLangid>=0 );
|
||||
assert( iLangid>=0 );
|
||||
assert( p->nIndex>0 );
|
||||
assert( iIndex>=0 && iIndex<p->nIndex );
|
||||
|
||||
@@ -698,7 +695,7 @@ static int fts3PendingListAppend(
|
||||
assert( !p || p->iLastDocid<=iDocid );
|
||||
|
||||
if( !p || p->iLastDocid!=iDocid ){
|
||||
u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
|
||||
sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
|
||||
if( p ){
|
||||
assert( p->nData<p->nSpace );
|
||||
assert( p->aData[p->nData]==0 );
|
||||
@@ -1155,7 +1152,7 @@ static int fts3AllocateSegdirIdx(
|
||||
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
|
||||
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
|
||||
*/
|
||||
if( iNext>=MergeCount(p) ){
|
||||
if( iNext>=FTS3_MERGE_COUNT ){
|
||||
fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
|
||||
rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
|
||||
*piIdx = 0;
|
||||
@@ -1239,8 +1236,6 @@ int sqlite3Fts3ReadBlock(
|
||||
}
|
||||
*paBlob = aByte;
|
||||
}
|
||||
}else if( rc==SQLITE_ERROR ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1352,9 +1347,7 @@ static int fts3SegReaderNext(
|
||||
|
||||
/* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
|
||||
** blocks have already been traversed. */
|
||||
#ifdef CORRUPT_DB
|
||||
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB );
|
||||
#endif
|
||||
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
|
||||
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -1381,19 +1374,15 @@ static int fts3SegReaderNext(
|
||||
** safe (no risk of overread) even if the node data is corrupted. */
|
||||
pNext += fts3GetVarint32(pNext, &nPrefix);
|
||||
pNext += fts3GetVarint32(pNext, &nSuffix);
|
||||
if( nSuffix<=0
|
||||
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
|
||||
|| nPrefix>pReader->nTerm
|
||||
if( nPrefix<0 || nSuffix<=0
|
||||
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
/* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are
|
||||
** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer
|
||||
** overflow - hence the (i64) casts. */
|
||||
if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){
|
||||
i64 nNew = ((i64)nPrefix+nSuffix)*2;
|
||||
char *zNew = sqlite3_realloc64(pReader->zTerm, nNew);
|
||||
if( nPrefix+nSuffix>pReader->nTermAlloc ){
|
||||
int nNew = (nPrefix+nSuffix)*2;
|
||||
char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
|
||||
if( !zNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -1415,9 +1404,8 @@ static int fts3SegReaderNext(
|
||||
** b-tree node. And that the final byte of the doclist is 0x00. If either
|
||||
** of these statements is untrue, then the data structure is corrupt.
|
||||
*/
|
||||
if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|
||||
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|
||||
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
|
||||
|| pReader->nDoclist==0
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -1534,18 +1522,18 @@ static int fts3SegReaderNextDocid(
|
||||
}else{
|
||||
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
|
||||
if( rc==SQLITE_OK ){
|
||||
u64 iDelta;
|
||||
pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
|
||||
sqlite3_int64 iDelta;
|
||||
pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
|
||||
if( pTab->bDescIdx ){
|
||||
pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
|
||||
pReader->iDocid -= iDelta;
|
||||
}else{
|
||||
pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
|
||||
pReader->iDocid += iDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1616,13 +1604,8 @@ int sqlite3Fts3SegReaderNew(
|
||||
Fts3SegReader *pReader; /* Newly allocated SegReader object */
|
||||
int nExtra = 0; /* Bytes to allocate segment root node */
|
||||
|
||||
assert( zRoot!=0 || nRoot==0 );
|
||||
#ifdef CORRUPT_DB
|
||||
assert( zRoot!=0 || CORRUPT_DB );
|
||||
#endif
|
||||
|
||||
assert( iStartLeaf<=iEndLeaf );
|
||||
if( iStartLeaf==0 ){
|
||||
if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
|
||||
nExtra = nRoot + FTS3_NODE_PADDING;
|
||||
}
|
||||
|
||||
@@ -1642,7 +1625,7 @@ int sqlite3Fts3SegReaderNew(
|
||||
pReader->aNode = (char *)&pReader[1];
|
||||
pReader->rootOnly = 1;
|
||||
pReader->nNode = nRoot;
|
||||
if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
|
||||
memcpy(pReader->aNode, zRoot, nRoot);
|
||||
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
|
||||
}else{
|
||||
pReader->iCurrentBlock = iStartLeaf-1;
|
||||
@@ -1757,9 +1740,8 @@ int sqlite3Fts3SegReaderPending(
|
||||
}
|
||||
|
||||
if( nElem>0 ){
|
||||
sqlite3_int64 nByte;
|
||||
nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
|
||||
pReader = (Fts3SegReader *)sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
|
||||
pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
|
||||
if( !pReader ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -2035,11 +2017,6 @@ static int fts3NodeAddTerm(
|
||||
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
|
||||
nSuffix = nTerm-nPrefix;
|
||||
|
||||
/* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
|
||||
** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
|
||||
** compared with BINARY collation. This indicates corruption. */
|
||||
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
|
||||
if( nReq<=p->nNodeSize || !pTree->zTerm ){
|
||||
|
||||
@@ -2268,11 +2245,6 @@ static int fts3SegWriterAdd(
|
||||
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
|
||||
nSuffix = nTerm-nPrefix;
|
||||
|
||||
/* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
|
||||
** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
|
||||
** compared with BINARY collation. This indicates corruption. */
|
||||
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
/* Figure out how many bytes are required by this new entry */
|
||||
nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
|
||||
sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
|
||||
@@ -2284,7 +2256,6 @@ static int fts3SegWriterAdd(
|
||||
int rc;
|
||||
|
||||
/* The current leaf node is full. Write it out to the database. */
|
||||
if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
|
||||
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
p->nLeafAdd++;
|
||||
@@ -2334,11 +2305,9 @@ static int fts3SegWriterAdd(
|
||||
/* Append the prefix-compressed term and doclist to the buffer. */
|
||||
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
|
||||
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
|
||||
assert( nSuffix>0 );
|
||||
memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
|
||||
nData += nSuffix;
|
||||
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
|
||||
assert( nDoclist>0 );
|
||||
memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
|
||||
pWriter->nData = nData + nDoclist;
|
||||
|
||||
@@ -2358,7 +2327,6 @@ static int fts3SegWriterAdd(
|
||||
pWriter->zTerm = zNew;
|
||||
}
|
||||
assert( pWriter->zTerm==pWriter->zMalloc );
|
||||
assert( nTerm>0 );
|
||||
memcpy(pWriter->zTerm, zTerm, nTerm);
|
||||
}else{
|
||||
pWriter->zTerm = (char *)zTerm;
|
||||
@@ -2505,7 +2473,7 @@ static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
|
||||
sqlite3_bind_int64(pStmt, 2,
|
||||
(((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
||||
((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
||||
);
|
||||
|
||||
*pbMax = 0;
|
||||
@@ -2633,14 +2601,14 @@ static void fts3ColumnFilter(
|
||||
|
||||
nList -= (int)(p - pList);
|
||||
pList = p;
|
||||
if( nList<=0 ){
|
||||
if( nList==0 ){
|
||||
break;
|
||||
}
|
||||
p = &pList[1];
|
||||
p += fts3GetVarint32(p, &iCurrent);
|
||||
}
|
||||
|
||||
if( bZero && (pEnd - &pList[nList])>0){
|
||||
if( bZero && &pList[nList]!=pEnd ){
|
||||
memset(&pList[nList], 0, pEnd - &pList[nList]);
|
||||
}
|
||||
*ppList = pList;
|
||||
@@ -2667,7 +2635,6 @@ static int fts3MsrBufferData(
|
||||
pMsr->aBuffer = pNew;
|
||||
}
|
||||
|
||||
assert( nList>0 );
|
||||
memcpy(pMsr->aBuffer, pList, nList);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -2855,19 +2822,6 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
|
||||
if( nReq>pCsr->nBuffer ){
|
||||
char *aNew;
|
||||
pCsr->nBuffer = nReq*2;
|
||||
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
|
||||
if( !aNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pCsr->aBuffer = aNew;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
int sqlite3Fts3SegReaderStep(
|
||||
Fts3Table *p, /* Virtual table handle */
|
||||
@@ -2994,17 +2948,23 @@ int sqlite3Fts3SegReaderStep(
|
||||
** doclist. */
|
||||
sqlite3_int64 iDelta;
|
||||
if( p->bDescIdx && nDoclist>0 ){
|
||||
if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
|
||||
iDelta = (i64)((u64)iPrev - (u64)iDocid);
|
||||
iDelta = iPrev - iDocid;
|
||||
}else{
|
||||
if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
|
||||
iDelta = (i64)((u64)iDocid - (u64)iPrev);
|
||||
iDelta = iDocid - iPrev;
|
||||
}
|
||||
assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
|
||||
assert( nDoclist>0 || iDelta==iDocid );
|
||||
|
||||
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
|
||||
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
|
||||
if( rc ) return rc;
|
||||
if( nDoclist+nByte>pCsr->nBuffer ){
|
||||
char *aNew;
|
||||
pCsr->nBuffer = (nDoclist+nByte)*2;
|
||||
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
|
||||
if( !aNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pCsr->aBuffer = aNew;
|
||||
}
|
||||
|
||||
if( isFirst ){
|
||||
char *a = &pCsr->aBuffer[nDoclist];
|
||||
@@ -3029,9 +2989,6 @@ int sqlite3Fts3SegReaderStep(
|
||||
fts3SegReaderSort(apSegment, nMerge, j, xCmp);
|
||||
}
|
||||
if( nDoclist>0 ){
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
|
||||
if( rc ) return rc;
|
||||
memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
|
||||
pCsr->aDoclist = pCsr->aBuffer;
|
||||
pCsr->nDoclist = nDoclist;
|
||||
rc = SQLITE_ROW;
|
||||
@@ -3081,11 +3038,11 @@ static void fts3ReadEndBlockField(
|
||||
if( zText ){
|
||||
int i;
|
||||
int iMul = 1;
|
||||
u64 iVal = 0;
|
||||
i64 iVal = 0;
|
||||
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*piEndBlock = (i64)iVal;
|
||||
*piEndBlock = iVal;
|
||||
while( zText[i]==' ' ) i++;
|
||||
iVal = 0;
|
||||
if( zText[i]=='-' ){
|
||||
@@ -3095,7 +3052,7 @@ static void fts3ReadEndBlockField(
|
||||
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*pnByte = ((i64)iVal * (i64)iMul);
|
||||
*pnByte = (iVal * (i64)iMul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3261,10 +3218,8 @@ static int fts3SegmentMerge(
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
|
||||
assert( csr.nSegment>0 );
|
||||
assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
|
||||
assert_fts3_nc(
|
||||
iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL)
|
||||
);
|
||||
assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
|
||||
assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
|
||||
|
||||
memset(&filter, 0, sizeof(Fts3SegFilter));
|
||||
filter.flags = FTS3_SEGMENT_REQUIRE_POS;
|
||||
@@ -3278,7 +3233,7 @@ static int fts3SegmentMerge(
|
||||
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
assert_fts3_nc( pWriter || bIgnoreEmpty );
|
||||
assert( pWriter || bIgnoreEmpty );
|
||||
|
||||
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
|
||||
rc = fts3DeleteSegdir(
|
||||
@@ -3363,16 +3318,14 @@ static void fts3DecodeIntArray(
|
||||
const char *zBuf, /* The BLOB containing the varints */
|
||||
int nBuf /* size of the BLOB */
|
||||
){
|
||||
int i = 0;
|
||||
if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
|
||||
int j;
|
||||
for(i=j=0; i<N && j<nBuf; i++){
|
||||
sqlite3_int64 x;
|
||||
j += sqlite3Fts3GetVarint(&zBuf[j], &x);
|
||||
a[i] = (u32)(x & 0xffffffff);
|
||||
}
|
||||
int i, j;
|
||||
UNUSED_PARAMETER(nBuf);
|
||||
for(i=j=0; i<N; i++){
|
||||
sqlite3_int64 x;
|
||||
j += sqlite3Fts3GetVarint(&zBuf[j], &x);
|
||||
assert(j<=nBuf);
|
||||
a[i] = (u32)(x & 0xffffffff);
|
||||
}
|
||||
while( i<N ) a[i++] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3391,7 +3344,7 @@ static void fts3InsertDocsize(
|
||||
int rc; /* Result code from subfunctions */
|
||||
|
||||
if( *pRC ) return;
|
||||
pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn );
|
||||
pBlob = sqlite3_malloc( 10*p->nColumn );
|
||||
if( pBlob==0 ){
|
||||
*pRC = SQLITE_NOMEM;
|
||||
return;
|
||||
@@ -3441,7 +3394,7 @@ static void fts3UpdateDocTotals(
|
||||
const int nStat = p->nColumn+2;
|
||||
|
||||
if( *pRC ) return;
|
||||
a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat );
|
||||
a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
|
||||
if( a==0 ){
|
||||
*pRC = SQLITE_NOMEM;
|
||||
return;
|
||||
@@ -3505,10 +3458,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
|
||||
int rc;
|
||||
sqlite3_stmt *pAllLangid = 0;
|
||||
|
||||
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
||||
}
|
||||
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
int rc2;
|
||||
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
|
||||
@@ -3529,6 +3479,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
|
||||
}
|
||||
|
||||
sqlite3Fts3SegmentsClose(p);
|
||||
sqlite3Fts3PendingTermsClear(p);
|
||||
|
||||
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
|
||||
}
|
||||
@@ -3564,8 +3515,8 @@ static int fts3DoRebuild(Fts3Table *p){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
|
||||
aSz = (u32 *)sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(u32) * (p->nColumn+1)*3;
|
||||
aSz = (u32 *)sqlite3_malloc(nByte);
|
||||
if( aSz==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -3631,12 +3582,12 @@ static int fts3IncrmergeCsr(
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
|
||||
sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */
|
||||
int nByte; /* Bytes allocated at pCsr->apSegment[] */
|
||||
|
||||
/* Allocate space for the Fts3MultiSegReader.aCsr[] array */
|
||||
memset(pCsr, 0, sizeof(*pCsr));
|
||||
nByte = sizeof(Fts3SegReader *) * nSeg;
|
||||
pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte);
|
||||
pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
|
||||
|
||||
if( pCsr->apSegment==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -3779,9 +3730,6 @@ static int nodeReaderNext(NodeReader *p){
|
||||
}
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
|
||||
|
||||
if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
|
||||
@@ -3789,16 +3737,14 @@ static int nodeReaderNext(NodeReader *p){
|
||||
p->iOff += nSuffix;
|
||||
if( p->iChild==0 ){
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
|
||||
if( (p->nNode-p->iOff)<p->nDoclist ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
p->aDoclist = &p->aNode[p->iOff];
|
||||
p->iOff += p->nDoclist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_fts3_nc( p->iOff<=p->nNode );
|
||||
assert( p->iOff<=p->nNode );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3822,14 +3768,14 @@ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
|
||||
p->nNode = nNode;
|
||||
|
||||
/* Figure out if this is a leaf or an internal node. */
|
||||
if( aNode && aNode[0] ){
|
||||
if( p->aNode[0] ){
|
||||
/* An internal node. */
|
||||
p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
|
||||
}else{
|
||||
p->iOff = 1;
|
||||
}
|
||||
|
||||
return aNode ? nodeReaderNext(p) : SQLITE_OK;
|
||||
return nodeReaderNext(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3866,7 +3812,6 @@ static int fts3IncrmergePush(
|
||||
** be added to. */
|
||||
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
|
||||
nSuffix = nTerm - nPrefix;
|
||||
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
nSpace = sqlite3Fts3VarintLen(nPrefix);
|
||||
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
|
||||
|
||||
@@ -3960,14 +3905,13 @@ static int fts3AppendToNode(
|
||||
/* Node must have already been started. There must be a doclist for a
|
||||
** leaf node, and there must not be a doclist for an internal node. */
|
||||
assert( pNode->n>0 );
|
||||
assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) );
|
||||
assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
|
||||
|
||||
blobGrowBuffer(pPrev, nTerm, &rc);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
|
||||
nSuffix = nTerm - nPrefix;
|
||||
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
memcpy(pPrev->a, zTerm, nTerm);
|
||||
pPrev->n = nTerm;
|
||||
|
||||
@@ -4177,7 +4121,7 @@ static int fts3TermCmp(
|
||||
int nCmp = MIN(nLhs, nRhs);
|
||||
int res;
|
||||
|
||||
res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
|
||||
res = memcmp(zLhs, zRhs, nCmp);
|
||||
if( res==0 ) res = nLhs - nRhs;
|
||||
|
||||
return res;
|
||||
@@ -4261,10 +4205,6 @@ static int fts3IncrmergeLoad(
|
||||
pWriter->bNoLeafData = (pWriter->nLeafData==0);
|
||||
nRoot = sqlite3_column_bytes(pSelect, 4);
|
||||
aRoot = sqlite3_column_blob(pSelect, 4);
|
||||
if( aRoot==0 ){
|
||||
sqlite3_reset(pSelect);
|
||||
return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}else{
|
||||
return sqlite3_reset(pSelect);
|
||||
}
|
||||
@@ -4300,10 +4240,6 @@ static int fts3IncrmergeLoad(
|
||||
int i;
|
||||
int nHeight = (int)aRoot[0];
|
||||
NodeWriter *pNode;
|
||||
if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){
|
||||
sqlite3_reset(pSelect);
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
|
||||
pWriter->iStart = iStart;
|
||||
@@ -4317,42 +4253,34 @@ static int fts3IncrmergeLoad(
|
||||
|
||||
pNode = &pWriter->aNodeWriter[nHeight];
|
||||
pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
|
||||
blobGrowBuffer(&pNode->block,
|
||||
MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc
|
||||
);
|
||||
blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->block.a, aRoot, nRoot);
|
||||
pNode->block.n = nRoot;
|
||||
memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING);
|
||||
}
|
||||
|
||||
for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
|
||||
NodeReader reader;
|
||||
pNode = &pWriter->aNodeWriter[i];
|
||||
|
||||
if( pNode->block.a){
|
||||
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
|
||||
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
|
||||
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->key.a, reader.term.a, reader.term.n);
|
||||
pNode->key.n = reader.term.n;
|
||||
if( i>0 ){
|
||||
char *aBlock = 0;
|
||||
int nBlock = 0;
|
||||
pNode = &pWriter->aNodeWriter[i-1];
|
||||
pNode->iBlock = reader.iChild;
|
||||
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
|
||||
blobGrowBuffer(&pNode->block,
|
||||
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->block.a, aBlock, nBlock);
|
||||
pNode->block.n = nBlock;
|
||||
memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING);
|
||||
}
|
||||
sqlite3_free(aBlock);
|
||||
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
|
||||
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
|
||||
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->key.a, reader.term.a, reader.term.n);
|
||||
pNode->key.n = reader.term.n;
|
||||
if( i>0 ){
|
||||
char *aBlock = 0;
|
||||
int nBlock = 0;
|
||||
pNode = &pWriter->aNodeWriter[i-1];
|
||||
pNode->iBlock = reader.iChild;
|
||||
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
|
||||
blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->block.a, aBlock, nBlock);
|
||||
pNode->block.n = nBlock;
|
||||
}
|
||||
sqlite3_free(aBlock);
|
||||
}
|
||||
}
|
||||
nodeReaderRelease(&reader);
|
||||
@@ -4595,10 +4523,7 @@ static int fts3TruncateNode(
|
||||
NodeReader reader; /* Reader object */
|
||||
Blob prev = {0, 0, 0}; /* Previous term written to new node */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int bLeaf; /* True for a leaf node */
|
||||
|
||||
if( nNode<1 ) return FTS_CORRUPT_VTAB;
|
||||
bLeaf = aNode[0]=='\0';
|
||||
int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
|
||||
|
||||
/* Allocate required output space */
|
||||
blobGrowBuffer(pNew, nNode, &rc);
|
||||
@@ -4864,17 +4789,13 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
|
||||
const int nHint = pHint->n;
|
||||
int i;
|
||||
|
||||
i = pHint->n-1;
|
||||
if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
|
||||
i = pHint->n-2;
|
||||
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
|
||||
if( i==0 ) return FTS_CORRUPT_VTAB;
|
||||
i--;
|
||||
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
|
||||
|
||||
pHint->n = i;
|
||||
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
|
||||
i += fts3GetVarint32(&pHint->a[i], pnInput);
|
||||
assert( i<=nHint );
|
||||
if( i!=nHint ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
return SQLITE_OK;
|
||||
@@ -4944,14 +4865,8 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
|
||||
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
|
||||
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
|
||||
/* Based on the scan in the block above, it is known that there
|
||||
** are no levels with a relative level smaller than that of
|
||||
** iAbsLevel with more than nSeg segments, or if nSeg is -1,
|
||||
** no levels with more than nMin segments. Use this to limit the
|
||||
** value of nHintSeg to avoid a large memory allocation in case the
|
||||
** merge-hint is corrupt*/
|
||||
iAbsLevel = iHintAbsLevel;
|
||||
nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
|
||||
nSeg = nHintSeg;
|
||||
bUseHint = 1;
|
||||
bDirtyHint = 1;
|
||||
}else{
|
||||
@@ -4964,13 +4879,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
/* If nSeg is less that zero, then there is no level with at least
|
||||
** nMin segments and no hint in the %_stat table. No work to do.
|
||||
** Exit early in this case. */
|
||||
if( nSeg<=0 ) break;
|
||||
|
||||
assert( nMod<=0x7FFFFFFF );
|
||||
if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
if( nSeg<0 ) break;
|
||||
|
||||
/* Open a cursor to iterate through the contents of the oldest nSeg
|
||||
** indexes of absolute level iAbsLevel. If this cursor is opened using
|
||||
@@ -4998,15 +4907,8 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
}
|
||||
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
|
||||
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
|
||||
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
|
||||
){
|
||||
int bEmpty = 0;
|
||||
rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
bEmpty = 1;
|
||||
}else if( rc!=SQLITE_ROW ){
|
||||
sqlite3Fts3SegReaderFinish(pCsr);
|
||||
break;
|
||||
}
|
||||
if( bUseHint && iIdx>0 ){
|
||||
const char *zKey = pCsr->zTerm;
|
||||
int nKey = pCsr->nTerm;
|
||||
@@ -5017,13 +4919,11 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
|
||||
if( rc==SQLITE_OK && pWriter->nLeafEst ){
|
||||
fts3LogMerge(nSeg, iAbsLevel);
|
||||
if( bEmpty==0 ){
|
||||
do {
|
||||
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
||||
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
|
||||
}while( rc==SQLITE_ROW );
|
||||
}
|
||||
do {
|
||||
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
||||
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
|
||||
}while( rc==SQLITE_ROW );
|
||||
|
||||
/* Update or delete the input segments */
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -5088,7 +4988,7 @@ static int fts3DoIncrmerge(
|
||||
const char *zParam /* Nul-terminated string containing "A,B" */
|
||||
){
|
||||
int rc;
|
||||
int nMin = (MergeCount(p) / 2);
|
||||
int nMin = (FTS3_MERGE_COUNT / 2);
|
||||
int nMerge = 0;
|
||||
const char *z = zParam;
|
||||
|
||||
@@ -5133,7 +5033,7 @@ static int fts3DoAutoincrmerge(
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
p->nAutoincrmerge = fts3Getint(&zParam);
|
||||
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
|
||||
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
|
||||
p->nAutoincrmerge = 8;
|
||||
}
|
||||
if( !p->bHasStat ){
|
||||
@@ -5216,12 +5116,12 @@ static u64 fts3ChecksumIndex(
|
||||
|
||||
i64 iDocid = 0;
|
||||
i64 iCol = 0;
|
||||
u64 iPos = 0;
|
||||
i64 iPos = 0;
|
||||
|
||||
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
|
||||
while( pCsr<pEnd ){
|
||||
u64 iVal = 0;
|
||||
pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
|
||||
i64 iVal = 0;
|
||||
pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
|
||||
if( pCsr<pEnd ){
|
||||
if( iVal==0 || iVal==1 ){
|
||||
iCol = 0;
|
||||
@@ -5229,12 +5129,8 @@ static u64 fts3ChecksumIndex(
|
||||
if( iVal ){
|
||||
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
|
||||
}else{
|
||||
pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
|
||||
if( p->bDescIdx ){
|
||||
iDocid = (i64)((u64)iDocid - iVal);
|
||||
}else{
|
||||
iDocid = (i64)((u64)iDocid + iVal);
|
||||
}
|
||||
pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
|
||||
iDocid += iVal;
|
||||
}
|
||||
}else{
|
||||
iPos += (iVal - 2);
|
||||
@@ -5307,9 +5203,10 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
||||
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
|
||||
if( p->abNotindexed[iCol]==0 ){
|
||||
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
|
||||
int nText = sqlite3_column_bytes(pStmt, iCol+1);
|
||||
sqlite3_tokenizer_cursor *pT = 0;
|
||||
|
||||
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
|
||||
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
|
||||
while( rc==SQLITE_OK ){
|
||||
char const *zToken; /* Buffer containing token */
|
||||
int nToken = 0; /* Number of bytes in token */
|
||||
@@ -5394,7 +5291,7 @@ static int fts3DoIntegrityCheck(
|
||||
** meaningful value to insert is the text 'optimize'.
|
||||
*/
|
||||
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
|
||||
int rc = SQLITE_ERROR; /* Return Code */
|
||||
int rc; /* Return Code */
|
||||
const char *zVal = (const char *)sqlite3_value_text(pVal);
|
||||
int nVal = sqlite3_value_bytes(pVal);
|
||||
|
||||
@@ -5410,27 +5307,21 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
|
||||
rc = fts3DoIncrmerge(p, &zVal[6]);
|
||||
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
|
||||
rc = fts3DoAutoincrmerge(p, &zVal[10]);
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
}else{
|
||||
int v;
|
||||
if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
|
||||
v = atoi(&zVal[9]);
|
||||
if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
|
||||
rc = SQLITE_OK;
|
||||
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
|
||||
v = atoi(&zVal[11]);
|
||||
if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
|
||||
rc = SQLITE_OK;
|
||||
}else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
|
||||
p->bNoIncrDoclist = atoi(&zVal[21]);
|
||||
rc = SQLITE_OK;
|
||||
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
|
||||
v = atoi(&zVal[11]);
|
||||
if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
#ifdef SQLITE_TEST
|
||||
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
|
||||
p->nNodeSize = atoi(&zVal[9]);
|
||||
rc = SQLITE_OK;
|
||||
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
|
||||
p->nMaxPendingData = atoi(&zVal[11]);
|
||||
rc = SQLITE_OK;
|
||||
}else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
|
||||
p->bNoIncrDoclist = atoi(&zVal[21]);
|
||||
rc = SQLITE_OK;
|
||||
#endif
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5671,7 +5562,7 @@ int sqlite3Fts3UpdateMethod(
|
||||
}
|
||||
|
||||
/* Allocate space to hold the change in document sizes */
|
||||
aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2);
|
||||
aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
|
||||
if( aSzDel==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto update_out;
|
||||
|
||||
@@ -93,7 +93,7 @@ static int runSql(sqlite3 *db, const char *zFormat, ...){
|
||||
static void showSchema(sqlite3 *db, const char *zTab){
|
||||
sqlite3_stmt *pStmt;
|
||||
pStmt = prepare(db,
|
||||
"SELECT sql FROM sqlite_schema"
|
||||
"SELECT sql FROM sqlite_master"
|
||||
" WHERE name LIKE '%q%%'"
|
||||
" ORDER BY 1",
|
||||
zTab);
|
||||
@@ -831,7 +831,7 @@ int main(int argc, char **argv){
|
||||
sqlite3_stmt *pStmt;
|
||||
int cnt = 0;
|
||||
pStmt = prepare(db, "SELECT b.sql"
|
||||
" FROM sqlite_schema a, sqlite_schema b"
|
||||
" FROM sqlite_master a, sqlite_master b"
|
||||
" WHERE a.name GLOB '*_segdir'"
|
||||
" AND b.name=substr(a.name,1,length(a.name)-7)"
|
||||
" ORDER BY 1");
|
||||
|
||||
@@ -9,12 +9,11 @@ proc print_rd {map} {
|
||||
set nRange 1
|
||||
set iFirst [lindex $map 0 0]
|
||||
set cPrev [lindex $map 0 1]
|
||||
set fPrev [lindex $map 0 2]
|
||||
|
||||
foreach m [lrange $map 1 end] {
|
||||
foreach {i c f} $m {}
|
||||
foreach {i c} $m {}
|
||||
|
||||
if {$cPrev == $c && $fPrev==$f} {
|
||||
if {$cPrev == $c} {
|
||||
for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
|
||||
if {[info exists tl_lookup_table($j)]==0} break
|
||||
}
|
||||
@@ -30,16 +29,13 @@ proc print_rd {map} {
|
||||
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
lappend aFlag $fPrev
|
||||
|
||||
set iFirst $i
|
||||
set cPrev $c
|
||||
set fPrev $f
|
||||
set nRange 1
|
||||
}
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
lappend aFlag $fPrev
|
||||
|
||||
puts "/*"
|
||||
puts "** If the argument is a codepoint corresponding to a lowercase letter"
|
||||
@@ -49,7 +45,7 @@ proc print_rd {map} {
|
||||
puts "** E\"). The resuls of passing a codepoint that corresponds to an"
|
||||
puts "** uppercase letter are undefined."
|
||||
puts "*/"
|
||||
puts "static int ${::remove_diacritic}(int c, int bComplex)\{"
|
||||
puts "static int ${::remove_diacritic}(int c)\{"
|
||||
puts " unsigned short aDia\[\] = \{"
|
||||
puts -nonewline " 0, "
|
||||
set i 1
|
||||
@@ -63,19 +59,14 @@ proc print_rd {map} {
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
puts "#define HIBIT ((unsigned char)0x80)"
|
||||
puts " unsigned char aChar\[\] = \{"
|
||||
puts -nonewline " '\\0', "
|
||||
puts " char aChar\[\] = \{"
|
||||
puts -nonewline " '\\0', "
|
||||
set i 1
|
||||
foreach c $aChar f $aFlag {
|
||||
if { $f } {
|
||||
set str "'$c'|HIBIT, "
|
||||
} else {
|
||||
set str "'$c', "
|
||||
}
|
||||
if {$c == ""} { set str "'\\0', " }
|
||||
foreach c $aChar {
|
||||
set str "'$c', "
|
||||
if {$c == ""} { set str "'\\0', " }
|
||||
|
||||
if {($i % 6)==0} {puts "" ; puts -nonewline " " }
|
||||
if {($i % 12)==0} {puts "" ; puts -nonewline " " }
|
||||
incr i
|
||||
puts -nonewline "$str"
|
||||
}
|
||||
@@ -96,8 +87,7 @@ proc print_rd {map} {
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);}
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
@@ -105,8 +95,7 @@ proc print_isdiacritic {zFunc map} {
|
||||
|
||||
set lCode [list]
|
||||
foreach m $map {
|
||||
foreach {code char flag} $m {}
|
||||
if {$flag} continue
|
||||
foreach {code char} $m {}
|
||||
if {$code && $char == ""} { lappend lCode $code }
|
||||
}
|
||||
set lCode [lsort -integer $lCode]
|
||||
@@ -135,8 +124,8 @@ proc print_isdiacritic {zFunc map} {
|
||||
|
||||
puts " if( c<$iFirst || c>$iLast ) return 0;"
|
||||
puts " return (c < $iFirst+32) ?"
|
||||
puts " (mask0 & ((unsigned int)1 << (c-$iFirst))) :"
|
||||
puts " (mask1 & ((unsigned int)1 << (c-$iFirst-32)));"
|
||||
puts " (mask0 & (1 << (c-$iFirst))) :"
|
||||
puts " (mask1 & (1 << (c-$iFirst-32)));"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
@@ -483,7 +472,7 @@ proc print_fold {zFunc} {
|
||||
puts "** The results are undefined if the value passed to this function"
|
||||
puts "** is less than zero."
|
||||
puts "*/"
|
||||
puts "int ${zFunc}\(int c, int eRemoveDiacritic)\{"
|
||||
puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
|
||||
|
||||
set liOff [tl_generate_ioff_table $lRecord]
|
||||
tl_print_table_header
|
||||
@@ -527,9 +516,7 @@ proc print_fold {zFunc} {
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( eRemoveDiacritic ){
|
||||
ret = ${::remove_diacritic}(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret);
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -618,6 +605,10 @@ proc print_categories {lMap} {
|
||||
|
||||
set nCat [expr [llength [array names C]] + 1]
|
||||
puts [code {
|
||||
int sqlite3Fts5UnicodeNCat(void) {
|
||||
return $nCat;
|
||||
}
|
||||
|
||||
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
|
||||
aArray[0] = 1;
|
||||
switch( zCat[0] ){
|
||||
@@ -700,7 +691,7 @@ proc print_categories {lMap} {
|
||||
static u16 aFts5UnicodeMap[] = {$aMapArray};
|
||||
static u16 aFts5UnicodeData[] = {$aDataArray};
|
||||
|
||||
int sqlite3Fts5UnicodeCategory(u32 iCode) {
|
||||
int sqlite3Fts5UnicodeCategory(int iCode) {
|
||||
int iRes = -1;
|
||||
int iHi;
|
||||
int iLo;
|
||||
@@ -738,7 +729,7 @@ proc print_categories {lMap} {
|
||||
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
|
||||
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
|
||||
for(; i<128 && i<n; i++){
|
||||
aAscii[i] = (u8)bToken;
|
||||
aAscii[i] = bToken;
|
||||
}
|
||||
iTbl++;
|
||||
}
|
||||
@@ -783,7 +774,7 @@ proc print_test_categories {lMap} {
|
||||
aArray[0] = 1;
|
||||
}
|
||||
|
||||
c = sqlite3Fts5UnicodeCategory((u32)i);
|
||||
c = sqlite3Fts5UnicodeCategory(i);
|
||||
if( aArray[c]==0 ){
|
||||
*piCode = i;
|
||||
return 1;
|
||||
@@ -838,7 +829,7 @@ proc print_fold_test {zFunc mappings} {
|
||||
proc print_fileheader {} {
|
||||
puts [string trim {
|
||||
/*
|
||||
** 2012-05-25
|
||||
** 2012 May 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
|
||||
@@ -7,24 +7,12 @@
|
||||
# character that it should be replaced with, or an empty string if the
|
||||
# codepoint should simply be removed from the input. Examples:
|
||||
#
|
||||
# { 224 a 0 } (replace codepoint 224 to "a")
|
||||
# { 769 "" 0 } (remove codepoint 769 from input)
|
||||
# { 224 a } (replace codepoint 224 to "a")
|
||||
# { 769 "" } (remove codepoint 769 from input)
|
||||
#
|
||||
# Mappings are only returned for non-upper case codepoints. It is assumed
|
||||
# that the input has already been folded to lower case.
|
||||
#
|
||||
# The third value in the list is always either 0 or 1. 0 if the
|
||||
# UnicodeData.txt file maps the codepoint to a single ASCII character and
|
||||
# a diacritic, or 1 if the mapping is indirect. For example, consider the
|
||||
# two entries:
|
||||
#
|
||||
# 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
|
||||
# 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
|
||||
#
|
||||
# The first codepoint is a direct mapping (as 006F is ASCII and 0323 is a
|
||||
# diacritic). The second is an indirect mapping, as it maps to the
|
||||
# first codepoint plus 0302 (a diacritic).
|
||||
#
|
||||
proc rd_load_unicodedata_text {zName} {
|
||||
global tl_lookup_table
|
||||
|
||||
@@ -65,29 +53,18 @@ proc rd_load_unicodedata_text {zName} {
|
||||
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
|
||||
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
|
||||
|
||||
# Filter out upper-case characters, as they will be mapped to their
|
||||
# lower-case equivalents before this data is used.
|
||||
if {[info exists tl_lookup_table($iCode)]} continue
|
||||
|
||||
# Check if this is an indirect mapping. If so, set bIndirect to true
|
||||
# and change $iAscii to the indirectly mappped ASCII character.
|
||||
set bIndirect 0
|
||||
if {[info exists dia($iDia)] && [info exists mapping($iAscii)]} {
|
||||
set iAscii $mapping($iAscii)
|
||||
set bIndirect 1
|
||||
}
|
||||
|
||||
if { ($iAscii >= 97 && $iAscii <= 122)
|
||||
|| ($iAscii >= 65 && $iAscii <= 90)
|
||||
} {
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]] $bIndirect]
|
||||
set mapping($iCode) $iAscii
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
|
||||
set dia($iDia) 1
|
||||
}
|
||||
}
|
||||
|
||||
foreach d [array names dia] {
|
||||
lappend lRet [list $d "" 0]
|
||||
lappend lRet [list $d ""]
|
||||
}
|
||||
set lRet [lsort -integer -index 0 $lRet]
|
||||
|
||||
|
||||
+17
-13
@@ -120,8 +120,12 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** to the column in which it occurs and *piOff the token offset of the
|
||||
** first token of the phrase. Returns SQLITE_OK if successful, or an error
|
||||
** code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
** first token of the phrase. The exception is if the table was created
|
||||
** with the offsets=0 option specified. In this case *piOff is always
|
||||
** set to -1.
|
||||
**
|
||||
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
|
||||
** if an error occurs.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
@@ -159,10 +163,10 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** xSetAuxdata(pFts5, pAux, xDelete)
|
||||
**
|
||||
** Save the pointer passed as the second argument as the extension function's
|
||||
** Save the pointer passed as the second argument as the extension functions
|
||||
** "auxiliary data". The pointer may then be retrieved by the current or any
|
||||
** future invocation of the same fts5 extension function made as part of
|
||||
** the same MATCH query using the xGetAuxdata() API.
|
||||
** of the same MATCH query using the xGetAuxdata() API.
|
||||
**
|
||||
** Each extension function is allocated a single auxiliary data slot for
|
||||
** each FTS query (MATCH expression). If the extension function is invoked
|
||||
@@ -177,7 +181,7 @@ struct Fts5PhraseIter {
|
||||
** The xDelete callback, if one is specified, is also invoked on the
|
||||
** auxiliary data pointer after the FTS5 query has finished.
|
||||
**
|
||||
** If an error (e.g. an OOM condition) occurs within this function,
|
||||
** If an error (e.g. an OOM condition) occurs within this function, an
|
||||
** the auxiliary data is set to NULL and an error code returned. If the
|
||||
** xDelete parameter was not NULL, it is invoked on the auxiliary data
|
||||
** pointer before returning.
|
||||
@@ -401,8 +405,8 @@ struct Fts5ExtensionApi {
|
||||
**
|
||||
** There are several ways to approach this in FTS5:
|
||||
**
|
||||
** <ol><li> By mapping all synonyms to a single token. In this case, using
|
||||
** the above example, this means that the tokenizer returns the
|
||||
** <ol><li> By mapping all synonyms to a single token. In this case, the
|
||||
** In the above example, this means that the tokenizer returns the
|
||||
** same token for inputs "first" and "1st". Say that token is in
|
||||
** fact "first", so that when the user inserts the document "I won
|
||||
** 1st place" entries are added to the index for tokens "i", "won",
|
||||
@@ -410,11 +414,11 @@ struct Fts5ExtensionApi {
|
||||
** the tokenizer substitutes "first" for "1st" and the query works
|
||||
** as expected.
|
||||
**
|
||||
** <li> By querying the index for all synonyms of each query term
|
||||
** separately. In this case, when tokenizing query text, the
|
||||
** tokenizer may provide multiple synonyms for a single term
|
||||
** within the document. FTS5 then queries the index for each
|
||||
** synonym individually. For example, faced with the query:
|
||||
** <li> By adding multiple synonyms for a single term to the FTS index.
|
||||
** In this case, when tokenizing query text, the tokenizer may
|
||||
** provide multiple synonyms for a single term within the document.
|
||||
** FTS5 then queries the index for each synonym individually. For
|
||||
** example, faced with the query:
|
||||
**
|
||||
** <codeblock>
|
||||
** ... MATCH 'first place'</codeblock>
|
||||
@@ -438,7 +442,7 @@ struct Fts5ExtensionApi {
|
||||
** "place".
|
||||
**
|
||||
** This way, even if the tokenizer does not provide synonyms
|
||||
** when tokenizing query text (it should not - to do so would be
|
||||
** when tokenizing query text (it should not - to do would be
|
||||
** inefficient), it doesn't matter if the user queries for
|
||||
** 'first + place' or '1st + place', as there are entries in the
|
||||
** FTS index corresponding to both forms of the first token.
|
||||
|
||||
+6
-37
@@ -61,11 +61,6 @@ typedef sqlite3_uint64 u64;
|
||||
*/
|
||||
#define FTS5_MAX_PREFIX_INDEXES 31
|
||||
|
||||
/*
|
||||
** Maximum segments permitted in a single index
|
||||
*/
|
||||
#define FTS5_MAX_SEGMENT 2000
|
||||
|
||||
#define FTS5_DEFAULT_NEARDIST 10
|
||||
#define FTS5_DEFAULT_RANK "bm25"
|
||||
|
||||
@@ -92,12 +87,6 @@ extern int sqlite3_fts5_may_be_corrupt;
|
||||
# define assert_nc(x) assert(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A version of memcmp() that does not cause asan errors if one of the pointer
|
||||
** parameters is NULL and the number of bytes to compare is zero.
|
||||
*/
|
||||
#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
|
||||
|
||||
/* Mark a function parameter as unused, to suppress nuisance compiler
|
||||
** warnings. */
|
||||
#ifndef UNUSED_PARAM
|
||||
@@ -183,7 +172,6 @@ struct Fts5Config {
|
||||
char *zContentExprlist;
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
int bLock; /* True when table is preparing statement */
|
||||
|
||||
/* Values loaded from the %_config table */
|
||||
int iCookie; /* Incremented when %_config is modified */
|
||||
@@ -286,7 +274,7 @@ void sqlite3Fts5Put32(u8*, int);
|
||||
int sqlite3Fts5Get32(const u8*);
|
||||
|
||||
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
|
||||
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
|
||||
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
|
||||
|
||||
typedef struct Fts5PoslistReader Fts5PoslistReader;
|
||||
struct Fts5PoslistReader {
|
||||
@@ -321,7 +309,7 @@ int sqlite3Fts5PoslistNext64(
|
||||
);
|
||||
|
||||
/* Malloc utility */
|
||||
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte);
|
||||
void *sqlite3Fts5MallocZero(int *pRc, int nByte);
|
||||
char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
|
||||
|
||||
/* Character set tests (like isspace(), isalpha() etc.) */
|
||||
@@ -422,11 +410,6 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
|
||||
*/
|
||||
void sqlite3Fts5IterClose(Fts5IndexIter*);
|
||||
|
||||
/*
|
||||
** Close the reader blob handle, if it is open.
|
||||
*/
|
||||
void sqlite3Fts5IndexCloseReader(Fts5Index*);
|
||||
|
||||
/*
|
||||
** This interface is used by the fts5vocab module.
|
||||
*/
|
||||
@@ -537,19 +520,9 @@ int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_main.c.
|
||||
** Interface to code in fts5.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Virtual-table object.
|
||||
*/
|
||||
typedef struct Fts5Table Fts5Table;
|
||||
struct Fts5Table {
|
||||
sqlite3_vtab base; /* Base class used by SQLite core */
|
||||
Fts5Config *pConfig; /* Virtual table configuration */
|
||||
Fts5Index *pIndex; /* Full-text index */
|
||||
};
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
Fts5Global*,
|
||||
const char **azArg,
|
||||
@@ -559,9 +532,7 @@ int sqlite3Fts5GetTokenizer(
|
||||
char **pzErr
|
||||
);
|
||||
|
||||
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
|
||||
|
||||
int sqlite3Fts5FlushToDisk(Fts5Table*);
|
||||
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5.c.
|
||||
@@ -594,9 +565,8 @@ void sqlite3Fts5HashClear(Fts5Hash*);
|
||||
|
||||
int sqlite3Fts5HashQuery(
|
||||
Fts5Hash*, /* Hash table to query */
|
||||
int nPre,
|
||||
const char *pTerm, int nTerm, /* Query term */
|
||||
void **ppObj, /* OUT: Pointer to doclist for pTerm */
|
||||
const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
|
||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||
);
|
||||
|
||||
@@ -705,7 +675,6 @@ int sqlite3Fts5ExprEof(Fts5Expr*);
|
||||
i64 sqlite3Fts5ExprRowid(Fts5Expr*);
|
||||
|
||||
void sqlite3Fts5ExprFree(Fts5Expr*);
|
||||
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);
|
||||
|
||||
/* Called during startup to register a UDF with SQLite */
|
||||
int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
|
||||
@@ -819,7 +788,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c);
|
||||
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
|
||||
|
||||
int sqlite3Fts5UnicodeCatParse(const char*, u8*);
|
||||
int sqlite3Fts5UnicodeCategory(u32 iCode);
|
||||
int sqlite3Fts5UnicodeCategory(int iCode);
|
||||
void sqlite3Fts5UnicodeAscii(u8*, u8*);
|
||||
/*
|
||||
** End of interface to code in fts5_unicode2.c.
|
||||
|
||||
+11
-13
@@ -136,7 +136,7 @@ static void fts5HighlightAppend(
|
||||
HighlightContext *p,
|
||||
const char *z, int n
|
||||
){
|
||||
if( *pRc==SQLITE_OK && z ){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
if( n<0 ) n = (int)strlen(z);
|
||||
p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
|
||||
if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
|
||||
@@ -268,7 +268,7 @@ static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
|
||||
int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
|
||||
int *aNew;
|
||||
|
||||
aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int));
|
||||
aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
p->aFirst = aNew;
|
||||
p->nFirstAlloc = nNew;
|
||||
@@ -335,12 +335,11 @@ static int fts5SnippetScore(
|
||||
int nInst;
|
||||
int nScore = 0;
|
||||
int iLast = 0;
|
||||
sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken;
|
||||
|
||||
rc = pApi->xInstCount(pFts, &nInst);
|
||||
for(i=0; i<nInst && rc==SQLITE_OK; i++){
|
||||
rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
|
||||
if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<iEnd ){
|
||||
if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
|
||||
nScore += (aSeen[ip] ? 1 : 1000);
|
||||
aSeen[ip] = 1;
|
||||
if( iFirst<0 ) iFirst = iOff;
|
||||
@@ -350,10 +349,10 @@ static int fts5SnippetScore(
|
||||
|
||||
*pnScore = nScore;
|
||||
if( piPos ){
|
||||
sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
|
||||
int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
|
||||
if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
|
||||
if( iAdj<0 ) iAdj = 0;
|
||||
*piPos = (int)iAdj;
|
||||
*piPos = iAdj;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -443,9 +442,7 @@ static void fts5SnippetFunction(
|
||||
int jj;
|
||||
|
||||
rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
|
||||
if( ic!=i ) continue;
|
||||
if( io>nDocsize ) rc = FTS5_CORRUPT;
|
||||
if( rc!=SQLITE_OK ) continue;
|
||||
if( ic!=i || rc!=SQLITE_OK ) continue;
|
||||
memset(aSeen, 0, nPhrase);
|
||||
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
|
||||
io, nToken, &nScore, &iAdj
|
||||
@@ -571,17 +568,17 @@ static int fts5Bm25GetData(
|
||||
int nPhrase; /* Number of phrases in query */
|
||||
sqlite3_int64 nRow = 0; /* Number of rows in table */
|
||||
sqlite3_int64 nToken = 0; /* Number of tokens in table */
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
int i;
|
||||
|
||||
/* Allocate the Fts5Bm25Data object */
|
||||
nPhrase = pApi->xPhraseCount(pFts);
|
||||
nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
|
||||
p = (Fts5Bm25Data*)sqlite3_malloc64(nByte);
|
||||
p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
|
||||
if( p==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(p, 0, (size_t)nByte);
|
||||
memset(p, 0, nByte);
|
||||
p->nPhrase = nPhrase;
|
||||
p->aIDF = (double*)&p[1];
|
||||
p->aFreq = &p->aIDF[nPhrase];
|
||||
@@ -589,7 +586,6 @@ static int fts5Bm25GetData(
|
||||
|
||||
/* Calculate the average document length for this FTS5 table */
|
||||
if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
|
||||
assert( rc!=SQLITE_OK || nRow>0 );
|
||||
if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
|
||||
if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow;
|
||||
|
||||
@@ -714,3 +710,5 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+9
-18
@@ -17,17 +17,17 @@
|
||||
|
||||
int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
|
||||
if( (u32)pBuf->nSpace<nByte ){
|
||||
u64 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
|
||||
u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
|
||||
u8 *pNew;
|
||||
while( nNew<nByte ){
|
||||
nNew = nNew * 2;
|
||||
}
|
||||
pNew = sqlite3_realloc64(pBuf->p, nNew);
|
||||
pNew = sqlite3_realloc(pBuf->p, nNew);
|
||||
if( pNew==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
return 1;
|
||||
}else{
|
||||
pBuf->nSpace = (int)nNew;
|
||||
pBuf->nSpace = nNew;
|
||||
pBuf->p = pNew;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ void sqlite3Fts5Put32(u8 *aBuf, int iVal){
|
||||
}
|
||||
|
||||
int sqlite3Fts5Get32(const u8 *aBuf){
|
||||
return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]);
|
||||
return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,21 +178,12 @@ int sqlite3Fts5PoslistNext64(
|
||||
i64 iOff = *piOff;
|
||||
int iVal;
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal<=1 ){
|
||||
if( iVal==0 ){
|
||||
*pi = i;
|
||||
return 0;
|
||||
}
|
||||
if( iVal==1 ){
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
iOff = ((i64)iVal) << 32;
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal<2 ){
|
||||
/* This is a corrupt record. So stop parsing it here. */
|
||||
*piOff = -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
|
||||
*piOff = iOff + (iVal-2);
|
||||
*pi = i;
|
||||
return 0;
|
||||
}
|
||||
@@ -253,14 +244,14 @@ int sqlite3Fts5PoslistWriterAppend(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){
|
||||
void *sqlite3Fts5MallocZero(int *pRc, int nByte){
|
||||
void *pRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
pRet = sqlite3_malloc64(nByte);
|
||||
pRet = sqlite3_malloc(nByte);
|
||||
if( pRet==0 ){
|
||||
if( nByte>0 ) *pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pRet, 0, (size_t)nByte);
|
||||
memset(pRet, 0, nByte);
|
||||
}
|
||||
}
|
||||
return pRet;
|
||||
|
||||
+10
-11
@@ -23,7 +23,7 @@
|
||||
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
|
||||
|
||||
/* Maximum allowed page size */
|
||||
#define FTS5_MAX_PAGE_SIZE (64*1024)
|
||||
#define FTS5_MAX_PAGE_SIZE (128*1024)
|
||||
|
||||
static int fts5_iswhitespace(char x){
|
||||
return (x==' ');
|
||||
@@ -150,7 +150,7 @@ static int fts5Dequote(char *z){
|
||||
assert( q=='[' || q=='\'' || q=='"' || q=='`' );
|
||||
if( q=='[' ) q = ']';
|
||||
|
||||
while( z[iIn] ){
|
||||
while( ALWAYS(z[iIn]) ){
|
||||
if( z[iIn]==q ){
|
||||
if( z[iIn+1]!=q ){
|
||||
/* Character iIn was the close quote. */
|
||||
@@ -295,7 +295,7 @@ static int fts5ConfigParseSpecial(
|
||||
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
const char *p = (const char*)zArg;
|
||||
sqlite3_int64 nArg = strlen(zArg) + 1;
|
||||
int nArg = (int)strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
|
||||
char *pSpace = pDel;
|
||||
@@ -325,7 +325,7 @@ static int fts5ConfigParseSpecial(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3Fts5GetTokenizer(pGlobal,
|
||||
(const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
|
||||
(const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi,
|
||||
pzErr
|
||||
);
|
||||
}
|
||||
@@ -425,8 +425,8 @@ static const char *fts5ConfigGobbleWord(
|
||||
){
|
||||
const char *zRet = 0;
|
||||
|
||||
sqlite3_int64 nIn = strlen(zIn);
|
||||
char *zOut = sqlite3_malloc64(nIn+1);
|
||||
int nIn = (int)strlen(zIn);
|
||||
char *zOut = sqlite3_malloc(nIn+1);
|
||||
|
||||
assert( *pRc==SQLITE_OK );
|
||||
*pbQuoted = 0;
|
||||
@@ -435,7 +435,7 @@ static const char *fts5ConfigGobbleWord(
|
||||
if( zOut==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memcpy(zOut, zIn, (size_t)(nIn+1));
|
||||
memcpy(zOut, zIn, nIn+1);
|
||||
if( fts5_isopenquote(zOut[0]) ){
|
||||
int ii = fts5Dequote(zOut);
|
||||
zRet = &zIn[ii];
|
||||
@@ -529,7 +529,7 @@ int sqlite3Fts5ConfigParse(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts5Config *pRet; /* New object to return */
|
||||
int i;
|
||||
sqlite3_int64 nByte;
|
||||
int nByte;
|
||||
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
@@ -683,7 +683,7 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){
|
||||
rc = sqlite3_declare_vtab(pConfig->db, zSql);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -828,7 +828,7 @@ int sqlite3Fts5ConfigSetValue(
|
||||
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
|
||||
pgsz = sqlite3_value_int(pVal);
|
||||
}
|
||||
if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){
|
||||
if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
|
||||
*pbBadkey = 1;
|
||||
}else{
|
||||
pConfig->pgsz = pgsz;
|
||||
@@ -881,7 +881,6 @@ int sqlite3Fts5ConfigSetValue(
|
||||
*pbBadkey = 1;
|
||||
}else{
|
||||
if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
|
||||
if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1;
|
||||
pConfig->nCrisisMerge = nCrisisMerge;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-72
@@ -211,7 +211,7 @@ static int fts5ExprGetToken(
|
||||
return tok;
|
||||
}
|
||||
|
||||
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
|
||||
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
|
||||
static void fts5ParseFree(void *p){ sqlite3_free(p); }
|
||||
|
||||
int sqlite3Fts5ExprNew(
|
||||
@@ -309,42 +309,6 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){
|
||||
}
|
||||
}
|
||||
|
||||
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
|
||||
Fts5Parse sParse;
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
|
||||
if( *pp1 ){
|
||||
Fts5Expr *p1 = *pp1;
|
||||
int nPhrase = p1->nPhrase + p2->nPhrase;
|
||||
|
||||
p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0);
|
||||
p2->pRoot = 0;
|
||||
|
||||
if( sParse.rc==SQLITE_OK ){
|
||||
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
|
||||
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
|
||||
);
|
||||
if( ap==0 ){
|
||||
sParse.rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int i;
|
||||
memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*));
|
||||
for(i=0; i<p2->nPhrase; i++){
|
||||
ap[i] = p2->apExprPhrase[i];
|
||||
}
|
||||
p1->nPhrase = nPhrase;
|
||||
p1->apExprPhrase = ap;
|
||||
}
|
||||
}
|
||||
sqlite3_free(p2->apExprPhrase);
|
||||
sqlite3_free(p2);
|
||||
}else{
|
||||
*pp1 = p2;
|
||||
}
|
||||
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument pTerm must be a synonym iterator. Return the current rowid
|
||||
** that it points to.
|
||||
@@ -392,8 +356,8 @@ static int fts5ExprSynonymList(
|
||||
if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
|
||||
if( pIter->nData==0 ) continue;
|
||||
if( nIter==nAlloc ){
|
||||
sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
|
||||
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
|
||||
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
|
||||
if( aNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto synonym_poslist_out;
|
||||
@@ -473,8 +437,8 @@ static int fts5ExprPhraseIsMatch(
|
||||
/* If the aStatic[] array is not large enough, allocate a large array
|
||||
** using sqlite3_malloc(). This approach could be improved upon. */
|
||||
if( pPhrase->nTerm>ArraySize(aStatic) ){
|
||||
sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
|
||||
aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
|
||||
aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
|
||||
if( !aIter ) return SQLITE_NOMEM;
|
||||
}
|
||||
memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
|
||||
@@ -608,7 +572,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
|
||||
/* If the aStatic[] array is not large enough, allocate a large array
|
||||
** using sqlite3_malloc(). This approach could be improved upon. */
|
||||
if( pNear->nPhrase>ArraySize(aStatic) ){
|
||||
sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
|
||||
int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
|
||||
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
}else{
|
||||
memset(aStatic, 0, sizeof(aStatic));
|
||||
@@ -1517,20 +1481,18 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
return pNear;
|
||||
}
|
||||
if( pNear==0 ){
|
||||
sqlite3_int64 nByte;
|
||||
nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
|
||||
pRet = sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
|
||||
pRet = sqlite3_malloc(nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pRet, 0, (size_t)nByte);
|
||||
memset(pRet, 0, nByte);
|
||||
}
|
||||
}else if( (pNear->nPhrase % SZALLOC)==0 ){
|
||||
int nNew = pNear->nPhrase + SZALLOC;
|
||||
sqlite3_int64 nByte;
|
||||
int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
|
||||
|
||||
nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
|
||||
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
|
||||
pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -1594,12 +1556,12 @@ static int fts5ParseTokenize(
|
||||
|
||||
if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
|
||||
Fts5ExprTerm *pSyn;
|
||||
sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
|
||||
pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
|
||||
int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
|
||||
pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
|
||||
if( pSyn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pSyn, 0, (size_t)nByte);
|
||||
memset(pSyn, 0, nByte);
|
||||
pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
|
||||
memcpy(pSyn->zTerm, pToken, nToken);
|
||||
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
|
||||
@@ -1611,7 +1573,7 @@ static int fts5ParseTokenize(
|
||||
Fts5ExprPhrase *pNew;
|
||||
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
|
||||
|
||||
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
|
||||
pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
|
||||
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
|
||||
);
|
||||
if( pNew==0 ){
|
||||
@@ -1697,9 +1659,9 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
|
||||
if( pAppend==0 ){
|
||||
if( (pParse->nPhrase % 8)==0 ){
|
||||
sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
|
||||
int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
|
||||
Fts5ExprPhrase **apNew;
|
||||
apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
|
||||
apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
|
||||
if( apNew==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
fts5ExprPhraseFree(sCtx.pPhrase);
|
||||
@@ -1754,12 +1716,10 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
|
||||
if( pColsetOrig ){
|
||||
sqlite3_int64 nByte;
|
||||
Fts5Colset *pColset;
|
||||
nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
|
||||
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
|
||||
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
if( pColset ){
|
||||
memcpy(pColset, pColsetOrig, (size_t)nByte);
|
||||
memcpy(pColset, pColsetOrig, nByte);
|
||||
}
|
||||
pNew->pRoot->pNear->pColset = pColset;
|
||||
}
|
||||
@@ -1877,7 +1837,7 @@ static Fts5Colset *fts5ParseColset(
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
|
||||
|
||||
pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
|
||||
pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
|
||||
if( pNew==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -1973,10 +1933,10 @@ Fts5Colset *sqlite3Fts5ParseColset(
|
||||
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
|
||||
Fts5Colset *pRet;
|
||||
if( pOrig ){
|
||||
sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
|
||||
int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pRet ){
|
||||
memcpy(pRet, pOrig, (size_t)nByte);
|
||||
memcpy(pRet, pOrig, nByte);
|
||||
}
|
||||
}else{
|
||||
pRet = 0;
|
||||
@@ -2127,7 +2087,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
int nChild = 0; /* Number of children of returned node */
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate for this node */
|
||||
int nByte; /* Bytes of space to allocate for this node */
|
||||
|
||||
assert( (eType!=FTS5_STRING && !pNear)
|
||||
|| (eType==FTS5_STRING && !pLeft && !pRight)
|
||||
@@ -2259,7 +2219,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
}
|
||||
|
||||
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
|
||||
sqlite3_int64 nByte = 0;
|
||||
int nByte = 0;
|
||||
Fts5ExprTerm *p;
|
||||
char *zQuoted;
|
||||
|
||||
@@ -2267,7 +2227,7 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
|
||||
for(p=pTerm; p; p=p->pSynonym){
|
||||
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
|
||||
}
|
||||
zQuoted = sqlite3_malloc64(nByte);
|
||||
zQuoted = sqlite3_malloc(nByte);
|
||||
|
||||
if( zQuoted ){
|
||||
int i = 0;
|
||||
@@ -2507,7 +2467,7 @@ static void fts5ExprFunction(
|
||||
}
|
||||
|
||||
nConfig = 3 + (nArg-iArg);
|
||||
azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig);
|
||||
azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
|
||||
if( azConfig==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return;
|
||||
@@ -2516,12 +2476,10 @@ static void fts5ExprFunction(
|
||||
azConfig[1] = "main";
|
||||
azConfig[2] = "tbl";
|
||||
for(i=3; iArg<nArg; iArg++){
|
||||
const char *z = (const char*)sqlite3_value_text(apVal[iArg]);
|
||||
azConfig[i++] = (z ? z : "");
|
||||
azConfig[i++] = (const char*)sqlite3_value_text(apVal[iArg]);
|
||||
}
|
||||
|
||||
zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
||||
if( zExpr==0 ) zExpr = "";
|
||||
|
||||
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2595,7 +2553,7 @@ static void fts5ExprIsAlnum(
|
||||
sqlite3Fts5UnicodeCatParse("N*", aArr);
|
||||
sqlite3Fts5UnicodeCatParse("Co", aArr);
|
||||
iCode = sqlite3_value_int(apVal[0]);
|
||||
sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]);
|
||||
sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
|
||||
}
|
||||
|
||||
static void fts5ExprFold(
|
||||
@@ -2690,7 +2648,7 @@ struct Fts5PoslistPopulator {
|
||||
|
||||
Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
|
||||
Fts5PoslistPopulator *pRet;
|
||||
pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
|
||||
pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
|
||||
if( pRet ){
|
||||
int i;
|
||||
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
|
||||
@@ -2889,3 +2847,4 @@ int sqlite3Fts5ExprPhraseCollist(
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+31
-54
@@ -90,20 +90,20 @@ int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_int64 nByte;
|
||||
int nByte;
|
||||
memset(pNew, 0, sizeof(Fts5Hash));
|
||||
pNew->pnByte = pnByte;
|
||||
pNew->eDetail = pConfig->eDetail;
|
||||
|
||||
pNew->nSlot = 1024;
|
||||
nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
|
||||
pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte);
|
||||
pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
|
||||
if( pNew->aSlot==0 ){
|
||||
sqlite3_free(pNew);
|
||||
*ppNew = 0;
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pNew->aSlot, 0, (size_t)nByte);
|
||||
memset(pNew->aSlot, 0, nByte);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -165,7 +165,7 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
Fts5HashEntry **apNew;
|
||||
Fts5HashEntry **apOld = pHash->aSlot;
|
||||
|
||||
apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*));
|
||||
apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
|
||||
if( !apNew ) return SQLITE_NOMEM;
|
||||
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
|
||||
|
||||
@@ -187,25 +187,19 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts5HashAddPoslistSize(
|
||||
Fts5Hash *pHash,
|
||||
Fts5HashEntry *p,
|
||||
Fts5HashEntry *p2
|
||||
){
|
||||
int nRet = 0;
|
||||
static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
|
||||
if( p->iSzPoslist ){
|
||||
u8 *pPtr = p2 ? (u8*)p2 : (u8*)p;
|
||||
int nData = p->nData;
|
||||
u8 *pPtr = (u8*)p;
|
||||
if( pHash->eDetail==FTS5_DETAIL_NONE ){
|
||||
assert( nData==p->iSzPoslist );
|
||||
assert( p->nData==p->iSzPoslist );
|
||||
if( p->bDel ){
|
||||
pPtr[nData++] = 0x00;
|
||||
pPtr[p->nData++] = 0x00;
|
||||
if( p->bContent ){
|
||||
pPtr[nData++] = 0x00;
|
||||
pPtr[p->nData++] = 0x00;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int nSz = (nData - p->iSzPoslist - 1); /* Size in bytes */
|
||||
int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
|
||||
int nPos = nSz*2 + p->bDel; /* Value of nPos field */
|
||||
|
||||
assert( p->bDel==0 || p->bDel==1 );
|
||||
@@ -215,19 +209,14 @@ static int fts5HashAddPoslistSize(
|
||||
int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
|
||||
memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
|
||||
sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
|
||||
nData += (nByte-1);
|
||||
p->nData += (nByte-1);
|
||||
}
|
||||
}
|
||||
|
||||
nRet = nData - p->nData;
|
||||
if( p2==0 ){
|
||||
p->iSzPoslist = 0;
|
||||
p->bDel = 0;
|
||||
p->bContent = 0;
|
||||
p->nData = nData;
|
||||
}
|
||||
p->iSzPoslist = 0;
|
||||
p->bDel = 0;
|
||||
p->bContent = 0;
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -270,7 +259,7 @@ int sqlite3Fts5HashWrite(
|
||||
if( p==0 ){
|
||||
/* Figure out how much space to allocate */
|
||||
char *zKey;
|
||||
sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
|
||||
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
|
||||
if( nByte<128 ) nByte = 128;
|
||||
|
||||
/* Grow the Fts5Hash.aSlot[] array if necessary. */
|
||||
@@ -281,10 +270,10 @@ int sqlite3Fts5HashWrite(
|
||||
}
|
||||
|
||||
/* Allocate new Fts5HashEntry and add it to the hash table. */
|
||||
p = (Fts5HashEntry*)sqlite3_malloc64(nByte);
|
||||
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, sizeof(Fts5HashEntry));
|
||||
p->nAlloc = (int)nByte;
|
||||
p->nAlloc = nByte;
|
||||
zKey = fts5EntryKey(p);
|
||||
zKey[0] = bByte;
|
||||
memcpy(&zKey[1], pToken, nToken);
|
||||
@@ -320,12 +309,12 @@ int sqlite3Fts5HashWrite(
|
||||
** + 5 bytes for the new position offset (32-bit max).
|
||||
*/
|
||||
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
|
||||
sqlite3_int64 nNew = p->nAlloc * 2;
|
||||
int nNew = p->nAlloc * 2;
|
||||
Fts5HashEntry *pNew;
|
||||
Fts5HashEntry **pp;
|
||||
pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
|
||||
pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
pNew->nAlloc = (int)nNew;
|
||||
pNew->nAlloc = nNew;
|
||||
for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
|
||||
*pp = pNew;
|
||||
p = pNew;
|
||||
@@ -339,7 +328,7 @@ int sqlite3Fts5HashWrite(
|
||||
/* If this is a new rowid, append the 4-byte size field for the previous
|
||||
** entry, and the new rowid for this entry. */
|
||||
if( iRowid!=p->iRowid ){
|
||||
fts5HashAddPoslistSize(pHash, p, 0);
|
||||
fts5HashAddPoslistSize(pHash, p);
|
||||
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
|
||||
p->iRowid = iRowid;
|
||||
bNew = 1;
|
||||
@@ -449,16 +438,14 @@ static int fts5HashEntrySort(
|
||||
int i;
|
||||
|
||||
*ppSorted = 0;
|
||||
ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot);
|
||||
ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
|
||||
if( !ap ) return SQLITE_NOMEM;
|
||||
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
|
||||
|
||||
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
|
||||
Fts5HashEntry *pIter;
|
||||
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
|
||||
if( pTerm==0
|
||||
|| (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
|
||||
){
|
||||
if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
|
||||
Fts5HashEntry *pEntry = pIter;
|
||||
pEntry->pScanNext = 0;
|
||||
for(i=0; ap[i]; i++){
|
||||
@@ -486,9 +473,8 @@ static int fts5HashEntrySort(
|
||||
*/
|
||||
int sqlite3Fts5HashQuery(
|
||||
Fts5Hash *pHash, /* Hash table to query */
|
||||
int nPre,
|
||||
const char *pTerm, int nTerm, /* Query term */
|
||||
void **ppOut, /* OUT: Pointer to new object */
|
||||
const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
|
||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||
){
|
||||
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
||||
@@ -497,25 +483,15 @@ int sqlite3Fts5HashQuery(
|
||||
|
||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||
zKey = fts5EntryKey(p);
|
||||
assert( p->nKey+1==(int)strlen(zKey) );
|
||||
if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
|
||||
if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
|
||||
}
|
||||
|
||||
if( p ){
|
||||
int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1;
|
||||
int nList = p->nData - nHashPre;
|
||||
u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10));
|
||||
if( pRet ){
|
||||
Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre];
|
||||
memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList);
|
||||
nList += fts5HashAddPoslistSize(pHash, p, pFaux);
|
||||
*pnDoclist = nList;
|
||||
}else{
|
||||
*pnDoclist = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
fts5HashAddPoslistSize(pHash, p);
|
||||
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||
}else{
|
||||
*ppOut = 0;
|
||||
*ppDoclist = 0;
|
||||
*pnDoclist = 0;
|
||||
}
|
||||
|
||||
@@ -548,7 +524,7 @@ void sqlite3Fts5HashScanEntry(
|
||||
if( (p = pHash->pScan) ){
|
||||
char *zKey = fts5EntryKey(p);
|
||||
int nTerm = (int)strlen(zKey);
|
||||
fts5HashAddPoslistSize(pHash, p, 0);
|
||||
fts5HashAddPoslistSize(pHash, p);
|
||||
*pzTerm = zKey;
|
||||
*ppDoclist = (const u8*)&zKey[nTerm+1];
|
||||
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
|
||||
@@ -558,3 +534,4 @@ void sqlite3Fts5HashScanEntry(
|
||||
*pnDoclist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+137
-258
@@ -239,6 +239,11 @@
|
||||
#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
|
||||
#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
|
||||
|
||||
/*
|
||||
** Maximum segments permitted in a single index
|
||||
*/
|
||||
#define FTS5_MAX_SEGMENT 2000
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
|
||||
#endif
|
||||
@@ -507,6 +512,7 @@ struct Fts5Iter {
|
||||
Fts5IndexIter base; /* Base class containing output vars */
|
||||
|
||||
Fts5Index *pIndex; /* Index that owns this iterator */
|
||||
Fts5Structure *pStruct; /* Database structure for this iterator */
|
||||
Fts5Buffer poslist; /* Buffer containing current poslist */
|
||||
Fts5Colset *pColset; /* Restrict matches to these columns */
|
||||
|
||||
@@ -567,7 +573,7 @@ static u16 fts5GetU16(const u8 *aIn){
|
||||
** If an OOM error is encountered, return NULL and set the error code in
|
||||
** the Fts5Index handle passed as the first argument.
|
||||
*/
|
||||
static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
|
||||
static void *fts5IdxMalloc(Fts5Index *p, int nByte){
|
||||
return sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
}
|
||||
|
||||
@@ -601,7 +607,7 @@ static int fts5BufferCompareBlob(
|
||||
*/
|
||||
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
|
||||
int nCmp = MIN(pLeft->n, pRight->n);
|
||||
int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
|
||||
int res = memcmp(pLeft->p, pRight->p, nCmp);
|
||||
return (res==0 ? (pLeft->n - pRight->n) : res);
|
||||
}
|
||||
|
||||
@@ -614,7 +620,7 @@ static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
|
||||
/*
|
||||
** Close the read-only blob handle, if it is open.
|
||||
*/
|
||||
void sqlite3Fts5IndexCloseReader(Fts5Index *p){
|
||||
static void fts5CloseReader(Fts5Index *p){
|
||||
if( p->pReader ){
|
||||
sqlite3_blob *pReader = p->pReader;
|
||||
p->pReader = 0;
|
||||
@@ -643,7 +649,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
assert( p->pReader==0 );
|
||||
p->pReader = pBlob;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Fts5IndexCloseReader(p);
|
||||
fts5CloseReader(p);
|
||||
}
|
||||
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
|
||||
}
|
||||
@@ -667,8 +673,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *aOut = 0; /* Read blob data into this buffer */
|
||||
int nByte = sqlite3_blob_bytes(p->pReader);
|
||||
sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
|
||||
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
|
||||
int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
|
||||
pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
|
||||
if( pRet ){
|
||||
pRet->nn = nByte;
|
||||
aOut = pRet->p = (u8*)&pRet[1];
|
||||
@@ -684,8 +690,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
pRet = 0;
|
||||
}else{
|
||||
/* TODO1: Fix this */
|
||||
pRet->p[nByte] = 0x00;
|
||||
pRet->p[nByte+1] = 0x00;
|
||||
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
|
||||
}
|
||||
}
|
||||
@@ -708,7 +712,7 @@ static void fts5DataRelease(Fts5Data *pData){
|
||||
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
||||
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
||||
if( pRet ){
|
||||
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
|
||||
if( pRet->szLeaf>pRet->nn ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pRet);
|
||||
pRet = 0;
|
||||
@@ -725,8 +729,7 @@ static int fts5IndexPrepareStmt(
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( zSql ){
|
||||
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
|
||||
ppStmt, 0);
|
||||
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
|
||||
}else{
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -767,12 +770,23 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
|
||||
if( p->pDeleter==0 ){
|
||||
int rc;
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?",
|
||||
pConfig->zDb, pConfig->zName
|
||||
);
|
||||
if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return;
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
p->rc = rc;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_bind_int64(p->pDeleter, 1, iFirst);
|
||||
@@ -844,7 +858,7 @@ static int fts5StructureDecode(
|
||||
int iLvl;
|
||||
int nLevel = 0;
|
||||
int nSegment = 0;
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */
|
||||
int nByte; /* Bytes of space to allocate at pRet */
|
||||
Fts5Structure *pRet = 0; /* Structure object to return */
|
||||
|
||||
/* Grab the cookie value */
|
||||
@@ -855,11 +869,6 @@ static int fts5StructureDecode(
|
||||
** structure record. */
|
||||
i += fts5GetVarint32(&pData[i], nLevel);
|
||||
i += fts5GetVarint32(&pData[i], nSegment);
|
||||
if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
|
||||
|| nSegment>FTS5_MAX_SEGMENT || nSegment<0
|
||||
){
|
||||
return FTS5_CORRUPT;
|
||||
}
|
||||
nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
|
||||
@@ -882,35 +891,25 @@ static int fts5StructureDecode(
|
||||
}else{
|
||||
i += fts5GetVarint32(&pData[i], pLvl->nMerge);
|
||||
i += fts5GetVarint32(&pData[i], nTotal);
|
||||
if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
|
||||
assert( nTotal>=pLvl->nMerge );
|
||||
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
|
||||
nTotal * sizeof(Fts5StructureSegment)
|
||||
);
|
||||
nSegment -= nTotal;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pLvl->nSeg = nTotal;
|
||||
for(iSeg=0; iSeg<nTotal; iSeg++){
|
||||
Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
|
||||
if( i>=nData ){
|
||||
rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
i += fts5GetVarint32(&pData[i], pSeg->iSegid);
|
||||
i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
|
||||
i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
|
||||
if( pSeg->pgnoLast<pSeg->pgnoFirst ){
|
||||
rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
|
||||
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
|
||||
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
|
||||
}
|
||||
if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
|
||||
if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
|
||||
}
|
||||
}
|
||||
if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5StructureRelease(pRet);
|
||||
pRet = 0;
|
||||
@@ -928,12 +927,12 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5Structure *pStruct = *ppStruct;
|
||||
int nLevel = pStruct->nLevel;
|
||||
sqlite3_int64 nByte = (
|
||||
int nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
|
||||
);
|
||||
|
||||
pStruct = sqlite3_realloc64(pStruct, nByte);
|
||||
pStruct = sqlite3_realloc(pStruct, nByte);
|
||||
if( pStruct ){
|
||||
memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
|
||||
pStruct->nLevel++;
|
||||
@@ -958,10 +957,10 @@ static void fts5StructureExtendLevel(
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
|
||||
Fts5StructureSegment *aNew;
|
||||
sqlite3_int64 nByte;
|
||||
int nByte;
|
||||
|
||||
nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
|
||||
aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
|
||||
aNew = sqlite3_realloc(pLvl->aSeg, nByte);
|
||||
if( aNew ){
|
||||
if( bInsert==0 ){
|
||||
memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
|
||||
@@ -988,7 +987,7 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){
|
||||
/* TODO: Do we need this if the leaf-index is appended? Probably... */
|
||||
memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
|
||||
p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
|
||||
if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
|
||||
if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){
|
||||
p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
|
||||
}
|
||||
fts5DataRelease(pData);
|
||||
@@ -1475,10 +1474,10 @@ static Fts5DlidxIter *fts5DlidxIterInit(
|
||||
int bDone = 0;
|
||||
|
||||
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
|
||||
sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
|
||||
int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
|
||||
Fts5DlidxIter *pNew;
|
||||
|
||||
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
|
||||
pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
|
||||
if( pNew==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -1648,13 +1647,12 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
|
||||
int nNew; /* Bytes of new data */
|
||||
|
||||
iOff += fts5GetVarint32(&a[iOff], nNew);
|
||||
if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
|
||||
if( iOff+nNew>pIter->pLeaf->nn ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
pIter->term.n = nKeep;
|
||||
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
|
||||
assert( pIter->term.n<=pIter->term.nSpace );
|
||||
iOff += nNew;
|
||||
pIter->iTermLeafOffset = iOff;
|
||||
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
||||
@@ -1719,7 +1717,7 @@ static void fts5SegIterInit(
|
||||
if( p->rc==SQLITE_OK ){
|
||||
pIter->iLeafOffset = 4;
|
||||
assert_nc( pIter->pLeaf->nn>4 );
|
||||
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
|
||||
assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
|
||||
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
|
||||
fts5SegIterLoadTerm(p, pIter, 0);
|
||||
fts5SegIterLoadNPos(p, pIter);
|
||||
@@ -1775,7 +1773,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
/* If necessary, grow the pIter->aRowidOffset[] array. */
|
||||
if( iRowidOffset>=pIter->nRowidOffset ){
|
||||
int nNew = pIter->nRowidOffset + 8;
|
||||
int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
|
||||
int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
|
||||
if( aNew==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
break;
|
||||
@@ -2229,10 +2227,10 @@ static void fts5LeafSeek(
|
||||
int szLeaf = pIter->pLeaf->szLeaf;
|
||||
int n = pIter->pLeaf->nn;
|
||||
|
||||
u32 nMatch = 0;
|
||||
u32 nKeep = 0;
|
||||
u32 nNew = 0;
|
||||
u32 iTermOff;
|
||||
int nMatch = 0;
|
||||
int nKeep = 0;
|
||||
int nNew = 0;
|
||||
int iTermOff;
|
||||
int iPgidx; /* Current offset in pgidx */
|
||||
int bEndOfPage = 0;
|
||||
|
||||
@@ -2256,15 +2254,15 @@ static void fts5LeafSeek(
|
||||
|
||||
assert( nKeep>=nMatch );
|
||||
if( nKeep==nMatch ){
|
||||
u32 nCmp;
|
||||
u32 i;
|
||||
nCmp = (u32)MIN(nNew, nTerm-nMatch);
|
||||
int nCmp;
|
||||
int i;
|
||||
nCmp = MIN(nNew, nTerm-nMatch);
|
||||
for(i=0; i<nCmp; i++){
|
||||
if( a[iOff+i]!=pTerm[nMatch+i] ) break;
|
||||
}
|
||||
nMatch += i;
|
||||
|
||||
if( (u32)nTerm==nMatch ){
|
||||
if( nTerm==nMatch ){
|
||||
if( i==nNew ){
|
||||
goto search_success;
|
||||
}else{
|
||||
@@ -2308,7 +2306,6 @@ static void fts5LeafSeek(
|
||||
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
|
||||
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}else{
|
||||
nKeep = 0;
|
||||
iTermOff = iOff;
|
||||
@@ -2321,10 +2318,7 @@ static void fts5LeafSeek(
|
||||
}
|
||||
|
||||
search_success:
|
||||
if( (i64)iOff+nNew>n || nNew<1 ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
|
||||
pIter->iLeafOffset = iOff + nNew;
|
||||
pIter->iTermLeafOffset = pIter->iLeafOffset;
|
||||
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
||||
@@ -2432,7 +2426,7 @@ static void fts5SegIterSeekInit(
|
||||
** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
|
||||
** to an entry with a term greater than or equal to (pTerm/nTerm).
|
||||
*/
|
||||
assert_nc( p->rc!=SQLITE_OK /* 1 */
|
||||
assert( p->rc!=SQLITE_OK /* 1 */
|
||||
|| pIter->pLeaf==0 /* 2 */
|
||||
|| fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
|
||||
|| (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
|
||||
@@ -2453,40 +2447,31 @@ static void fts5SegIterHashInit(
|
||||
int flags, /* Mask of FTS5INDEX_XXX flags */
|
||||
Fts5SegIter *pIter /* Object to populate */
|
||||
){
|
||||
const u8 *pList = 0;
|
||||
int nList = 0;
|
||||
const u8 *z = 0;
|
||||
int n = 0;
|
||||
Fts5Data *pLeaf = 0;
|
||||
|
||||
assert( p->pHash );
|
||||
assert( p->rc==SQLITE_OK );
|
||||
|
||||
if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
|
||||
const u8 *pList = 0;
|
||||
|
||||
p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
|
||||
sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList);
|
||||
n = (z ? (int)strlen((const char*)z) : 0);
|
||||
if( pList ){
|
||||
pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
|
||||
if( pLeaf ){
|
||||
pLeaf->p = (u8*)pList;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data),
|
||||
(const char*)pTerm, nTerm, (void**)&pLeaf, &nList
|
||||
);
|
||||
if( pLeaf ){
|
||||
pLeaf->p = (u8*)&pLeaf[1];
|
||||
}
|
||||
pIter->flags |= FTS5_SEGITER_ONETERM;
|
||||
sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList);
|
||||
z = pTerm;
|
||||
n = nTerm;
|
||||
pIter->flags |= FTS5_SEGITER_ONETERM;
|
||||
}
|
||||
|
||||
if( pLeaf ){
|
||||
if( pList ){
|
||||
Fts5Data *pLeaf;
|
||||
sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z);
|
||||
pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
|
||||
if( pLeaf==0 ) return;
|
||||
pLeaf->p = (u8*)pList;
|
||||
pLeaf->nn = pLeaf->szLeaf = nList;
|
||||
pIter->pLeaf = pLeaf;
|
||||
pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
|
||||
@@ -2539,7 +2524,7 @@ static void fts5AssertComparisonResult(
|
||||
assert( pRes->iFirst==i1 );
|
||||
}else{
|
||||
int nMin = MIN(p1->term.n, p2->term.n);
|
||||
int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
|
||||
int res = memcmp(p1->term.p, p2->term.p, nMin);
|
||||
if( res==0 ) res = p1->term.n - p2->term.n;
|
||||
|
||||
if( res==0 ){
|
||||
@@ -2639,8 +2624,8 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){
|
||||
}else{
|
||||
int res = fts5BufferCompare(&p1->term, &p2->term);
|
||||
if( res==0 ){
|
||||
assert_nc( i2>i1 );
|
||||
assert_nc( i2!=0 );
|
||||
assert( i2>i1 );
|
||||
assert( i2!=0 );
|
||||
pRes->bTermEq = 1;
|
||||
if( p1->iRowid==p2->iRowid ){
|
||||
p1->bDel = p2->bDel;
|
||||
@@ -2762,6 +2747,7 @@ static void fts5MultiIterFree(Fts5Iter *pIter){
|
||||
for(i=0; i<pIter->nSeg; i++){
|
||||
fts5SegIterClear(&pIter->aSeg[i]);
|
||||
}
|
||||
fts5StructureRelease(pIter->pStruct);
|
||||
fts5BufferFree(&pIter->poslist);
|
||||
sqlite3_free(pIter);
|
||||
}
|
||||
@@ -3109,8 +3095,7 @@ static void fts5SegiterPoslist(
|
||||
Fts5Colset *pColset,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
|
||||
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
|
||||
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
|
||||
if( pColset==0 ){
|
||||
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
|
||||
}else{
|
||||
@@ -3408,7 +3393,9 @@ static void fts5MultiIterNew(
|
||||
if( pNew==0 ) return;
|
||||
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
|
||||
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
|
||||
pNew->pStruct = pStruct;
|
||||
pNew->pColset = pColset;
|
||||
fts5StructureRef(pStruct);
|
||||
if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
|
||||
fts5IterSetOutputCb(&p->rc, pNew);
|
||||
}
|
||||
@@ -3586,24 +3573,24 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
|
||||
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
|
||||
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
|
||||
int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
|
||||
if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
|
||||
aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
|
||||
if( iId<=FTS5_MAX_SEGMENT ){
|
||||
aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; aUsed[i]==0xFFFFFFFF; i++);
|
||||
mask = aUsed[i];
|
||||
for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
|
||||
for(iSegid=0; mask & (1 << iSegid); iSegid++);
|
||||
iSegid += 1 + i*32;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
|
||||
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
|
||||
assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
|
||||
assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
|
||||
}
|
||||
}
|
||||
assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
|
||||
assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
|
||||
|
||||
{
|
||||
sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
|
||||
@@ -3611,7 +3598,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
|
||||
u8 aBlob[2] = {0xff, 0xff};
|
||||
sqlite3_bind_int(pIdxSelect, 1, iSegid);
|
||||
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
|
||||
assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
|
||||
assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
|
||||
p->rc = sqlite3_reset(pIdxSelect);
|
||||
sqlite3_bind_null(pIdxSelect, 2);
|
||||
}
|
||||
@@ -3681,13 +3668,13 @@ static int fts5WriteDlidxGrow(
|
||||
int nLvl
|
||||
){
|
||||
if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
|
||||
Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
|
||||
Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
|
||||
pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
|
||||
);
|
||||
if( aDlidx==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
size_t nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
|
||||
int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
|
||||
memset(&aDlidx[pWriter->nDlidx], 0, nByte);
|
||||
pWriter->aDlidx = aDlidx;
|
||||
pWriter->nDlidx = nLvl;
|
||||
@@ -3760,10 +3747,8 @@ static void fts5WriteBtreeTerm(
|
||||
int nTerm, const u8 *pTerm /* First term on new page */
|
||||
){
|
||||
fts5WriteFlushBtree(p, pWriter);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
|
||||
pWriter->iBtPage = pWriter->writer.pgno;
|
||||
}
|
||||
fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
|
||||
pWriter->iBtPage = pWriter->writer.pgno;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3914,7 +3899,6 @@ static void fts5WriteAppendTerm(
|
||||
int nPrefix; /* Bytes of prefix compression for term */
|
||||
Fts5PageWriter *pPage = &pWriter->writer;
|
||||
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
|
||||
int nMin = MIN(pPage->term.n, nTerm);
|
||||
|
||||
assert( p->rc==SQLITE_OK );
|
||||
assert( pPage->buf.n>=4 );
|
||||
@@ -3924,7 +3908,6 @@ static void fts5WriteAppendTerm(
|
||||
if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
|
||||
if( pPage->buf.n>4 ){
|
||||
fts5WriteFlushLeaf(p, pWriter);
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
}
|
||||
fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
|
||||
}
|
||||
@@ -3957,14 +3940,13 @@ static void fts5WriteAppendTerm(
|
||||
** inefficient, but still correct. */
|
||||
int n = nTerm;
|
||||
if( pPage->term.n ){
|
||||
n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
|
||||
n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
|
||||
}
|
||||
fts5WriteBtreeTerm(p, pWriter, n, pTerm);
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
pPage = &pWriter->writer;
|
||||
}
|
||||
}else{
|
||||
nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
|
||||
nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
|
||||
}
|
||||
|
||||
@@ -4011,7 +3993,7 @@ static void fts5WriteAppendRowid(
|
||||
if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
|
||||
}else{
|
||||
assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
|
||||
assert( p->rc || iRowid>pWriter->iPrevRowid );
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
|
||||
}
|
||||
pWriter->iPrevRowid = iRowid;
|
||||
@@ -4133,7 +4115,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
|
||||
int i;
|
||||
Fts5Buffer buf;
|
||||
memset(&buf, 0, sizeof(Fts5Buffer));
|
||||
for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
|
||||
for(i=0; i<pIter->nSeg; i++){
|
||||
Fts5SegIter *pSeg = &pIter->aSeg[i];
|
||||
if( pSeg->pSeg==0 ){
|
||||
/* no-op */
|
||||
@@ -4151,44 +4133,35 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
|
||||
u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
|
||||
pData = fts5LeafRead(p, iLeafRowid);
|
||||
pData = fts5DataRead(p, iLeafRowid);
|
||||
if( pData ){
|
||||
if( iOff>pData->szLeaf ){
|
||||
/* This can occur if the pages that the segments occupy overlap - if
|
||||
** a single page has been assigned to more than one segment. In
|
||||
** this case a prior iteration of this loop may have corrupted the
|
||||
** segment currently being trimmed. */
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
fts5BufferZero(&buf);
|
||||
fts5BufferGrow(&p->rc, &buf, pData->nn);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
|
||||
fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
/* Set the szLeaf field */
|
||||
fts5PutU16(&buf.p[2], (u16)buf.n);
|
||||
}
|
||||
|
||||
/* Set up the new page-index array */
|
||||
fts5BufferAppendVarint(&p->rc, &buf, 4);
|
||||
if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
|
||||
&& pSeg->iEndofDoclist<pData->szLeaf
|
||||
&& pSeg->iPgidxOff<=pData->nn
|
||||
){
|
||||
int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
|
||||
fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
|
||||
fts5BufferAppendBlob(&p->rc, &buf,
|
||||
pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
|
||||
);
|
||||
}
|
||||
|
||||
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
|
||||
fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
|
||||
fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
|
||||
fts5BufferZero(&buf);
|
||||
fts5BufferGrow(&p->rc, &buf, pData->nn);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
|
||||
fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
|
||||
fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
/* Set the szLeaf field */
|
||||
fts5PutU16(&buf.p[2], (u16)buf.n);
|
||||
}
|
||||
|
||||
/* Set up the new page-index array */
|
||||
fts5BufferAppendVarint(&p->rc, &buf, 4);
|
||||
if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
|
||||
&& pSeg->iEndofDoclist<pData->szLeaf
|
||||
){
|
||||
int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
|
||||
fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
|
||||
fts5BufferAppendBlob(&p->rc, &buf,
|
||||
pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
|
||||
);
|
||||
}
|
||||
|
||||
fts5DataRelease(pData);
|
||||
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
|
||||
fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
|
||||
fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4280,7 +4253,7 @@ static void fts5IndexMergeLevel(
|
||||
const u8 *pTerm;
|
||||
|
||||
pTerm = fts5MultiIterTerm(pIter, &nTerm);
|
||||
if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
|
||||
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
|
||||
if( pnRem && writer.nLeafWritten>nRem ){
|
||||
break;
|
||||
}
|
||||
@@ -4535,7 +4508,6 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
/* Write the term for this entry to disk. */
|
||||
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
|
||||
fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
|
||||
if( p->rc!=SQLITE_OK ) break;
|
||||
|
||||
assert( writer.bFirstRowidInPage==0 );
|
||||
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
|
||||
@@ -4558,7 +4530,6 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
|
||||
writer.bFirstRowidInPage = 0;
|
||||
fts5WriteDlidxAppend(p, &writer, iRowid);
|
||||
if( p->rc!=SQLITE_OK ) break;
|
||||
}else{
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
|
||||
}
|
||||
@@ -4616,7 +4587,7 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
/* TODO2: Doclist terminator written here. */
|
||||
/* pBuf->p[pBuf->n++] = '\0'; */
|
||||
assert( pBuf->n<=pBuf->nSpace );
|
||||
if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
|
||||
sqlite3Fts5HashScanNext(pHash);
|
||||
}
|
||||
sqlite3Fts5HashClear(pHash);
|
||||
fts5WriteFinish(p, &writer, &pgnoLast);
|
||||
@@ -4660,7 +4631,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
Fts5Structure *pStruct
|
||||
){
|
||||
Fts5Structure *pNew = 0;
|
||||
sqlite3_int64 nByte = sizeof(Fts5Structure);
|
||||
int nByte = sizeof(Fts5Structure);
|
||||
int nSeg = pStruct->nSegment;
|
||||
int i;
|
||||
|
||||
@@ -4790,13 +4761,11 @@ static void fts5AppendPoslist(
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
int nData = pMulti->base.nData;
|
||||
int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
|
||||
assert( nData>0 );
|
||||
if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
|
||||
if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
|
||||
fts5BufferSafeAppendVarint(pBuf, iDelta);
|
||||
fts5BufferSafeAppendVarint(pBuf, nData*2);
|
||||
fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
|
||||
memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4949,14 +4918,8 @@ static void fts5MergePrefixLists(
|
||||
** first rowid in one input is a large negative number, and the first in
|
||||
** the other a non-negative number, the delta for the non-negative
|
||||
** number will be larger on disk than the literal integer value
|
||||
** was.
|
||||
**
|
||||
** Or, if the input position-lists are corrupt, then the output might
|
||||
** include up to 2 extra 10-byte positions created by interpreting -1
|
||||
** (the value PoslistNext64() uses for EOF) as a position and appending
|
||||
** it to the output. This can happen at most once for each input
|
||||
** position-list, hence two 10 byte paddings. */
|
||||
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9+10+10) ) return;
|
||||
** was. */
|
||||
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return;
|
||||
fts5DoclistIterInit(p1, &i1);
|
||||
fts5DoclistIterInit(p2, &i2);
|
||||
|
||||
@@ -4967,7 +4930,6 @@ static void fts5MergePrefixLists(
|
||||
fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
|
||||
fts5DoclistIterNext(&i1);
|
||||
if( i1.aPoslist==0 ) break;
|
||||
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
|
||||
}
|
||||
else if( i2.iRowid!=i1.iRowid ){
|
||||
/* Copy entry from i2 */
|
||||
@@ -4975,7 +4937,6 @@ static void fts5MergePrefixLists(
|
||||
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
|
||||
fts5DoclistIterNext(&i2);
|
||||
if( i2.aPoslist==0 ) break;
|
||||
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
|
||||
}
|
||||
else{
|
||||
/* Merge the two position lists. */
|
||||
@@ -4985,24 +4946,19 @@ static void fts5MergePrefixLists(
|
||||
int iOff2 = 0;
|
||||
u8 *a1 = &i1.aPoslist[i1.nSize];
|
||||
u8 *a2 = &i2.aPoslist[i2.nSize];
|
||||
int nCopy;
|
||||
u8 *aCopy;
|
||||
|
||||
i64 iPrev = 0;
|
||||
Fts5PoslistWriter writer;
|
||||
memset(&writer, 0, sizeof(writer));
|
||||
|
||||
/* See the earlier comment in this function for an explanation of why
|
||||
** corrupt input position lists might cause the output to consume
|
||||
** at most 20 bytes of unexpected space. */
|
||||
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
|
||||
fts5BufferZero(&tmp);
|
||||
sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
|
||||
sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
|
||||
if( p->rc ) break;
|
||||
|
||||
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
|
||||
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
|
||||
assert_nc( iPos1>=0 && iPos2>=0 );
|
||||
assert( iPos1>=0 && iPos2>=0 );
|
||||
|
||||
if( iPos1<iPos2 ){
|
||||
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
|
||||
@@ -5011,6 +4967,7 @@ static void fts5MergePrefixLists(
|
||||
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
|
||||
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
|
||||
}
|
||||
|
||||
if( iPos1>=0 && iPos2>=0 ){
|
||||
while( 1 ){
|
||||
if( iPos1<iPos2 ){
|
||||
@@ -5020,7 +4977,7 @@ static void fts5MergePrefixLists(
|
||||
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
|
||||
if( iPos1<0 ) break;
|
||||
}else{
|
||||
assert_nc( iPos2!=iPrev );
|
||||
assert( iPos2!=iPrev );
|
||||
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
|
||||
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
|
||||
if( iPos2<0 ) break;
|
||||
@@ -5032,32 +4989,19 @@ static void fts5MergePrefixLists(
|
||||
if( iPos1!=iPrev ){
|
||||
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
|
||||
}
|
||||
aCopy = &a1[iOff1];
|
||||
nCopy = i1.nPoslist - iOff1;
|
||||
fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
|
||||
}else{
|
||||
assert_nc( iPos2>=0 && iPos2!=iPrev );
|
||||
assert( iPos2>=0 && iPos2!=iPrev );
|
||||
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
|
||||
aCopy = &a2[iOff2];
|
||||
nCopy = i2.nPoslist - iOff2;
|
||||
}
|
||||
if( nCopy>0 ){
|
||||
fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
|
||||
fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
|
||||
}
|
||||
|
||||
/* WRITEPOSLISTSIZE */
|
||||
assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
|
||||
assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
|
||||
if( tmp.n>i1.nPoslist+i2.nPoslist ){
|
||||
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
|
||||
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
|
||||
fts5DoclistIterNext(&i1);
|
||||
fts5DoclistIterNext(&i2);
|
||||
assert_nc( out.n<=(p1->n+p2->n+9) );
|
||||
if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
|
||||
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5069,7 +5013,7 @@ static void fts5MergePrefixLists(
|
||||
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
|
||||
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
|
||||
}
|
||||
assert_nc( out.n<=(p1->n+p2->n+9) );
|
||||
assert( out.n<=(p1->n+p2->n+9) );
|
||||
|
||||
fts5BufferSet(&p->rc, p1, out.n, out.p);
|
||||
fts5BufferFree(&tmp);
|
||||
@@ -5158,7 +5102,7 @@ static void fts5SetupPrefixIter(
|
||||
}
|
||||
fts5MultiIterFree(p1);
|
||||
|
||||
pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING);
|
||||
pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
|
||||
if( pData ){
|
||||
pData->p = (u8*)&pData[1];
|
||||
pData->nn = pData->szLeaf = doclist.n;
|
||||
@@ -5204,7 +5148,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
|
||||
int sqlite3Fts5IndexSync(Fts5Index *p){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
fts5IndexFlush(p);
|
||||
sqlite3Fts5IndexCloseReader(p);
|
||||
fts5CloseReader(p);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -5215,7 +5159,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p){
|
||||
** records must be invalidated.
|
||||
*/
|
||||
int sqlite3Fts5IndexRollback(Fts5Index *p){
|
||||
sqlite3Fts5IndexCloseReader(p);
|
||||
fts5CloseReader(p);
|
||||
fts5IndexDiscardData(p);
|
||||
fts5StructureInvalidate(p);
|
||||
/* assert( p->rc==SQLITE_OK ); */
|
||||
@@ -5230,7 +5174,6 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){
|
||||
int sqlite3Fts5IndexReinit(Fts5Index *p){
|
||||
Fts5Structure s;
|
||||
fts5StructureInvalidate(p);
|
||||
fts5IndexDiscardData(p);
|
||||
memset(&s, 0, sizeof(Fts5Structure));
|
||||
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
|
||||
fts5StructureWrite(p, &s);
|
||||
@@ -5318,13 +5261,9 @@ int sqlite3Fts5IndexCharlenToBytelen(
|
||||
for(i=0; i<nChar; i++){
|
||||
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
|
||||
if( (unsigned char)p[n++]>=0xc0 ){
|
||||
if( n>=nByte ) return 0;
|
||||
while( (p[n] & 0xc0)==0x80 ){
|
||||
n++;
|
||||
if( n>=nByte ){
|
||||
if( i+1==nChar ) break;
|
||||
return 0;
|
||||
}
|
||||
if( n>=nByte ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5460,10 +5399,10 @@ int sqlite3Fts5IndexQuery(
|
||||
if( p->rc ){
|
||||
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
|
||||
pRet = 0;
|
||||
sqlite3Fts5IndexCloseReader(p);
|
||||
fts5CloseReader(p);
|
||||
}
|
||||
|
||||
*ppIter = (Fts5IndexIter*)pRet;
|
||||
*ppIter = &pRet->base;
|
||||
sqlite3Fts5BufferFree(&buf);
|
||||
}
|
||||
return fts5IndexReturn(p);
|
||||
@@ -5533,7 +5472,7 @@ void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
|
||||
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
|
||||
Fts5Index *pIndex = pIter->pIndex;
|
||||
fts5MultiIterFree(pIter);
|
||||
sqlite3Fts5IndexCloseReader(pIndex);
|
||||
fts5CloseReader(pIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5726,37 +5665,6 @@ static int fts5QueryCksum(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if buffer z[], size n bytes, contains as series of valid utf-8
|
||||
** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
|
||||
** contain valid utf-8, return non-zero.
|
||||
*/
|
||||
static int fts5TestUtf8(const char *z, int n){
|
||||
int i = 0;
|
||||
assert_nc( n>0 );
|
||||
while( i<n ){
|
||||
if( (z[i] & 0x80)==0x00 ){
|
||||
i++;
|
||||
}else
|
||||
if( (z[i] & 0xE0)==0xC0 ){
|
||||
if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
|
||||
i += 2;
|
||||
}else
|
||||
if( (z[i] & 0xF0)==0xE0 ){
|
||||
if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
|
||||
i += 3;
|
||||
}else
|
||||
if( (z[i] & 0xF8)==0xF0 ){
|
||||
if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
|
||||
if( (z[i+2] & 0xC0)!=0x80 ) return 1;
|
||||
i += 3;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is also purely an internal test. It does not contribute to
|
||||
@@ -5797,14 +5705,8 @@ static void fts5TestTerm(
|
||||
** This check may only be performed if the hash table is empty. This
|
||||
** is because the hash table only supports a single scan query at
|
||||
** a time, and the multi-iter loop from which this function is called
|
||||
** is already performing such a scan.
|
||||
**
|
||||
** Also only do this if buffer zTerm contains nTerm bytes of valid
|
||||
** utf-8. Otherwise, the last part of the buffer contents might contain
|
||||
** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
|
||||
** character stored in the main fts index, which will cause the
|
||||
** test to fail. */
|
||||
if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
|
||||
** is already performing such a scan. */
|
||||
if( p->nPendingData==0 ){
|
||||
if( iIdx>0 && rc==SQLITE_OK ){
|
||||
int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
|
||||
ck2 = 0;
|
||||
@@ -5927,8 +5829,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
if( pSeg->pgnoFirst==0 ) return;
|
||||
|
||||
fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
|
||||
"SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
|
||||
"ORDER BY 1, 2",
|
||||
"SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
|
||||
pConfig->zDb, pConfig->zName, pSeg->iSegid
|
||||
));
|
||||
|
||||
@@ -5937,8 +5838,8 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
i64 iRow; /* Rowid for this leaf */
|
||||
Fts5Data *pLeaf; /* Data for this leaf */
|
||||
|
||||
const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
|
||||
int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
|
||||
const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
int iIdxLeaf = sqlite3_column_int(pStmt, 2);
|
||||
int bIdxDlidx = sqlite3_column_int(pStmt, 3);
|
||||
|
||||
@@ -5963,11 +5864,11 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
|
||||
iOff = fts5LeafFirstTermOff(pLeaf);
|
||||
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
|
||||
if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
|
||||
if( iRowidOff>=iOff ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
|
||||
res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
|
||||
res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
|
||||
if( res==0 ) res = nTerm - nIdxTerm;
|
||||
if( res<0 ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
@@ -6362,7 +6263,7 @@ static void fts5DecodeFunction(
|
||||
u8 *a = 0;
|
||||
Fts5Buffer s; /* Build up text to return here */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
sqlite3_int64 nSpace = 0;
|
||||
int nSpace = 0;
|
||||
int eDetailNone = (sqlite3_user_data(pCtx)!=0);
|
||||
|
||||
assert( nArg==2 );
|
||||
@@ -6378,7 +6279,8 @@ static void fts5DecodeFunction(
|
||||
nSpace = n + FTS5_DATA_ZERO_PADDING;
|
||||
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
|
||||
if( a==0 ) goto decode_out;
|
||||
if( n>0 ) memcpy(a, aBlob, n);
|
||||
memcpy(a, aBlob, n);
|
||||
|
||||
|
||||
fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);
|
||||
|
||||
@@ -6473,9 +6375,6 @@ static void fts5DecodeFunction(
|
||||
iPgidxOff = szLeaf = fts5GetU16(&a[2]);
|
||||
if( iPgidxOff<n ){
|
||||
fts5GetVarint32(&a[iPgidxOff], iTermOff);
|
||||
}else if( iPgidxOff>n ){
|
||||
rc = FTS5_CORRUPT;
|
||||
goto decode_out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6487,22 +6386,14 @@ static void fts5DecodeFunction(
|
||||
}else{
|
||||
iOff = szLeaf;
|
||||
}
|
||||
if( iOff>n ){
|
||||
rc = FTS5_CORRUPT;
|
||||
goto decode_out;
|
||||
}
|
||||
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
|
||||
|
||||
/* Decode any more doclist data that appears on the page before the
|
||||
** first term. */
|
||||
nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
|
||||
if( nDoclist+iOff>n ){
|
||||
rc = FTS5_CORRUPT;
|
||||
goto decode_out;
|
||||
}
|
||||
fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
|
||||
|
||||
while( iPgidxOff<n && rc==SQLITE_OK ){
|
||||
while( iPgidxOff<n ){
|
||||
int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
|
||||
int nByte; /* Bytes of data */
|
||||
int iEnd;
|
||||
@@ -6517,24 +6408,12 @@ static void fts5DecodeFunction(
|
||||
}else{
|
||||
iEnd = szLeaf;
|
||||
}
|
||||
if( iEnd>szLeaf ){
|
||||
rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
if( bFirst==0 ){
|
||||
iOff += fts5GetVarint32(&a[iOff], nByte);
|
||||
if( nByte>term.n ){
|
||||
rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
term.n = nByte;
|
||||
}
|
||||
iOff += fts5GetVarint32(&a[iOff], nByte);
|
||||
if( iOff+nByte>n ){
|
||||
rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
|
||||
iOff += nByte;
|
||||
|
||||
|
||||
+270
-386
File diff suppressed because it is too large
Load Diff
+15
-31
@@ -115,7 +115,7 @@ static int fts5StorageGetStmt(
|
||||
char *zBind;
|
||||
int i;
|
||||
|
||||
zBind = sqlite3_malloc64(1 + nCol*2);
|
||||
zBind = sqlite3_malloc(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
@@ -136,11 +136,8 @@ static int fts5StorageGetStmt(
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int f = SQLITE_PREPARE_PERSISTENT;
|
||||
if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
|
||||
p->pConfig->bLock++;
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
|
||||
p->pConfig->bLock--;
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
@@ -284,14 +281,14 @@ int sqlite3Fts5StorageOpen(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
Fts5Storage *p; /* New object */
|
||||
sqlite3_int64 nByte; /* Bytes of space to allocate */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
|
||||
nByte = sizeof(Fts5Storage) /* Fts5Storage object */
|
||||
+ pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
|
||||
*pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
|
||||
*pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
|
||||
memset(p, 0, (size_t)nByte);
|
||||
memset(p, 0, nByte);
|
||||
p->aTotalSize = (i64*)&p[1];
|
||||
p->pConfig = pConfig;
|
||||
p->pIndex = pIndex;
|
||||
@@ -299,7 +296,7 @@ int sqlite3Fts5StorageOpen(
|
||||
if( bCreate ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
int nDefn = 32 + pConfig->nCol*10;
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
|
||||
char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -560,8 +557,6 @@ int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc;
|
||||
|
||||
p->bTotalsValid = 0;
|
||||
|
||||
/* Delete the contents of the %_data and %_docsize tables. */
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DELETE FROM %Q.'%q_data';"
|
||||
@@ -592,7 +587,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
sqlite3_stmt *pScan = 0;
|
||||
Fts5InsertCtx ctx;
|
||||
int rc, rc2;
|
||||
int rc;
|
||||
|
||||
memset(&ctx, 0, sizeof(Fts5InsertCtx));
|
||||
ctx.pStorage = p;
|
||||
@@ -613,11 +608,10 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
|
||||
int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(const char*)sqlite3_column_text(pScan, ctx.iCol+1),
|
||||
sqlite3_column_bytes(pScan, ctx.iCol+1),
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
@@ -632,8 +626,6 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
}
|
||||
}
|
||||
sqlite3_free(buf.p);
|
||||
rc2 = sqlite3_reset(pScan);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
|
||||
/* Write the averages record */
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -739,11 +731,10 @@ int sqlite3Fts5StorageIndexInsert(
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
|
||||
int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
|
||||
sqlite3_value_bytes(apVal[ctx.iCol+2]),
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
@@ -884,7 +875,7 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
|
||||
|
||||
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
|
||||
ctx.pConfig = p->pConfig;
|
||||
aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
|
||||
aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
|
||||
if( !aTotalSize ) return SQLITE_NOMEM;
|
||||
aColSize = (int*)&aTotalSize[pConfig->nCol];
|
||||
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
|
||||
@@ -912,11 +903,10 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
|
||||
int nText = sqlite3_column_bytes(pScan, i+1);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(const char*)sqlite3_column_text(pScan, i+1),
|
||||
sqlite3_column_bytes(pScan, i+1),
|
||||
(void*)&ctx,
|
||||
fts5StorageIntegrityCallback
|
||||
);
|
||||
@@ -1085,13 +1075,7 @@ int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
|
||||
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
|
||||
int rc = fts5StorageLoadTotals(p, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* nTotalRow being zero does not necessarily indicate a corrupt
|
||||
** database - it might be that the FTS5 table really does contain zero
|
||||
** rows. However this function is only called from the xRowCount() API,
|
||||
** and there is no way for that API to be invoked if the table contains
|
||||
** no rows. Hence the FTS5_CORRUPT return. */
|
||||
*pnRow = p->nTotalRow;
|
||||
if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
|
||||
int nPhrase;
|
||||
int i;
|
||||
int nInt;
|
||||
sqlite3_int64 nByte;
|
||||
int nByte;
|
||||
int rc;
|
||||
|
||||
nCol = pApi->xColumnCount(pFts);
|
||||
@@ -330,7 +330,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
|
||||
nByte = sizeof(Fts5MatchinfoCtx) /* The struct itself */
|
||||
+ sizeof(u32) * nInt /* The p->aRet[] array */
|
||||
+ (i+1); /* The p->zArg string */
|
||||
p = (Fts5MatchinfoCtx*)sqlite3_malloc64(nByte);
|
||||
p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte);
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return 0;
|
||||
|
||||
@@ -137,7 +137,7 @@ static int fts5tokDequoteArray(
|
||||
nByte += (int)(strlen(argv[i]) + 1);
|
||||
}
|
||||
|
||||
*pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
|
||||
*pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
|
||||
if( azDequote==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -335,7 +335,7 @@ static int fts5tokCb(
|
||||
if( (pCsr->nRow & (pCsr->nRow-1))==0 ){
|
||||
int nNew = pCsr->nRow ? pCsr->nRow*2 : 32;
|
||||
Fts5tokRow *aNew;
|
||||
aNew = (Fts5tokRow*)sqlite3_realloc64(pCsr->aRow, nNew*sizeof(Fts5tokRow));
|
||||
aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow));
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow));
|
||||
pCsr->aRow = aNew;
|
||||
@@ -378,7 +378,7 @@ static int fts5tokFilterMethod(
|
||||
if( pCsr->zInput==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
|
||||
memcpy(pCsr->zInput, zByte, nByte);
|
||||
pCsr->zInput[nByte] = 0;
|
||||
rc = pTab->tok.xTokenize(
|
||||
pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb
|
||||
@@ -471,8 +471,7 @@ int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
+15
-24
@@ -152,7 +152,7 @@ static int fts5AsciiTokenize(
|
||||
nByte = ie-is;
|
||||
if( nByte>nFold ){
|
||||
if( pFold!=aFold ) sqlite3_free(pFold);
|
||||
pFold = sqlite3_malloc64((sqlite3_int64)nByte*2);
|
||||
pFold = sqlite3_malloc(nByte*2);
|
||||
if( pFold==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
@@ -234,18 +234,13 @@ struct Unicode61Tokenizer {
|
||||
unsigned char aTokenChar[128]; /* ASCII range token characters */
|
||||
char *aFold; /* Buffer to fold text into */
|
||||
int nFold; /* Size of aFold[] in bytes */
|
||||
int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
|
||||
int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
|
||||
int nException;
|
||||
int *aiException;
|
||||
|
||||
unsigned char aCategory[32]; /* True for token char categories */
|
||||
};
|
||||
|
||||
/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */
|
||||
#define FTS5_REMOVE_DIACRITICS_NONE 0
|
||||
#define FTS5_REMOVE_DIACRITICS_SIMPLE 1
|
||||
#define FTS5_REMOVE_DIACRITICS_COMPLEX 2
|
||||
|
||||
static int fts5UnicodeAddExceptions(
|
||||
Unicode61Tokenizer *p, /* Tokenizer object */
|
||||
const char *z, /* Characters to treat as exceptions */
|
||||
@@ -256,14 +251,13 @@ static int fts5UnicodeAddExceptions(
|
||||
int *aNew;
|
||||
|
||||
if( n>0 ){
|
||||
aNew = (int*)sqlite3_realloc64(p->aiException,
|
||||
(n+p->nException)*sizeof(int));
|
||||
aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
|
||||
if( aNew ){
|
||||
int nNew = p->nException;
|
||||
const unsigned char *zCsr = (const unsigned char*)z;
|
||||
const unsigned char *zTerm = (const unsigned char*)&z[n];
|
||||
while( zCsr<zTerm ){
|
||||
u32 iCode;
|
||||
int iCode;
|
||||
int bToken;
|
||||
READ_UTF8(zCsr, zTerm, iCode);
|
||||
if( iCode<128 ){
|
||||
@@ -275,7 +269,7 @@ static int fts5UnicodeAddExceptions(
|
||||
if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
|
||||
int i;
|
||||
for(i=0; i<nNew; i++){
|
||||
if( (u32)aNew[i]>iCode ) break;
|
||||
if( aNew[i]>iCode ) break;
|
||||
}
|
||||
memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
|
||||
aNew[i] = iCode;
|
||||
@@ -367,9 +361,9 @@ static int fts5UnicodeCreate(
|
||||
int i;
|
||||
memset(p, 0, sizeof(Unicode61Tokenizer));
|
||||
|
||||
p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
|
||||
p->bRemoveDiacritic = 1;
|
||||
p->nFold = 64;
|
||||
p->aFold = sqlite3_malloc64(p->nFold * sizeof(char));
|
||||
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
|
||||
if( p->aFold==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -388,15 +382,10 @@ static int fts5UnicodeCreate(
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p->eRemoveDiacritic = (zArg[0] - '0');
|
||||
assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE
|
||||
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE
|
||||
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX
|
||||
);
|
||||
}
|
||||
p->bRemoveDiacritic = (zArg[0]=='1');
|
||||
}else
|
||||
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
|
||||
rc = fts5UnicodeAddExceptions(p, zArg, 1);
|
||||
@@ -430,7 +419,7 @@ static int fts5UnicodeCreate(
|
||||
*/
|
||||
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
|
||||
return (
|
||||
p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)]
|
||||
p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
|
||||
^ fts5UnicodeIsException(p, iCode)
|
||||
);
|
||||
}
|
||||
@@ -459,7 +448,7 @@ static int fts5UnicodeTokenize(
|
||||
/* Each iteration of this loop gobbles up a contiguous run of separators,
|
||||
** then the next token. */
|
||||
while( rc==SQLITE_OK ){
|
||||
u32 iCode; /* non-ASCII codepoint read from input */
|
||||
int iCode; /* non-ASCII codepoint read from input */
|
||||
char *zOut = aFold;
|
||||
int is;
|
||||
int ie;
|
||||
@@ -491,7 +480,7 @@ static int fts5UnicodeTokenize(
|
||||
/* Grow the output buffer so that there is sufficient space to fit the
|
||||
** largest possible utf-8 character. */
|
||||
if( zOut>pEnd ){
|
||||
aFold = sqlite3_malloc64((sqlite3_int64)nFold*2);
|
||||
aFold = sqlite3_malloc(nFold*2);
|
||||
if( aFold==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto tokenize_done;
|
||||
@@ -510,7 +499,7 @@ static int fts5UnicodeTokenize(
|
||||
READ_UTF8(zCsr, zTerm, iCode);
|
||||
if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
|
||||
non_ascii_tokenchar:
|
||||
iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic);
|
||||
iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
|
||||
if( iCode ) WRITE_UTF8(zOut, iCode);
|
||||
}else{
|
||||
break;
|
||||
@@ -1285,3 +1274,5 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+34
-46
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** 2012-05-25
|
||||
** 2012 May 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
@@ -28,48 +28,32 @@
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int fts5_remove_diacritic(int c, int bComplex){
|
||||
static int fts5_remove_diacritic(int c){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
|
||||
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
|
||||
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
|
||||
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
|
||||
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
|
||||
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
|
||||
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
|
||||
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
|
||||
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
|
||||
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
|
||||
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
|
||||
63182, 63242, 63274, 63310, 63368, 63390,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
};
|
||||
#define HIBIT ((unsigned char)0x80)
|
||||
unsigned char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n',
|
||||
'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y',
|
||||
'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
|
||||
'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
|
||||
'e', 'i', 'o', 'r', 'u', 's',
|
||||
't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
|
||||
'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b',
|
||||
'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
|
||||
'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
|
||||
'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
|
||||
'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
|
||||
's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
|
||||
'w', 'x', 'y', 'z', 'h', 't',
|
||||
'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
|
||||
'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
|
||||
'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
@@ -86,8 +70,7 @@ static int fts5_remove_diacritic(int c, int bComplex){
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,8 +83,8 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
|
||||
unsigned int mask1 = 0x000361F8;
|
||||
if( c<768 || c>817 ) return 0;
|
||||
return (c < 768+32) ?
|
||||
(mask0 & ((unsigned int)1 << (c-768))) :
|
||||
(mask1 & ((unsigned int)1 << (c-768-32)));
|
||||
(mask0 & (1 << (c-768))) :
|
||||
(mask1 & (1 << (c-768-32)));
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +97,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
|
||||
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
@@ -237,9 +220,7 @@ int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( eRemoveDiacritic ){
|
||||
ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
@@ -250,6 +231,12 @@ int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int sqlite3Fts5UnicodeNCat(void) {
|
||||
return 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
|
||||
aArray[0] = 1;
|
||||
switch( zCat[0] ){
|
||||
@@ -731,7 +718,7 @@ static u16 aFts5UnicodeData[] = {
|
||||
34, 3074, 7692, 63, 63,
|
||||
};
|
||||
|
||||
int sqlite3Fts5UnicodeCategory(u32 iCode) {
|
||||
int sqlite3Fts5UnicodeCategory(int iCode) {
|
||||
int iRes = -1;
|
||||
int iHi;
|
||||
int iLo;
|
||||
@@ -774,3 +761,4 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
|
||||
iTbl++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
|
||||
u8 n;
|
||||
p -= 2;
|
||||
n = sqlite3Fts5GetVarint(p, &v64);
|
||||
*v = ((u32)v64) & 0x7FFFFFFF;
|
||||
*v = (u32)v64;
|
||||
assert( n>3 && n<=9 );
|
||||
return n;
|
||||
}
|
||||
@@ -342,3 +342,4 @@ int sqlite3Fts5GetVarintLen(u32 iVal){
|
||||
if( iVal<(1 << 28) ) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
+35
-54
@@ -50,13 +50,12 @@ struct Fts5VocabTable {
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* FTS5 global object for this database */
|
||||
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
|
||||
unsigned bBusy; /* True if busy */
|
||||
};
|
||||
|
||||
struct Fts5VocabCursor {
|
||||
sqlite3_vtab_cursor base;
|
||||
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
|
||||
Fts5Table *pFts5; /* Associated FTS5 table */
|
||||
Fts5Index *pIndex; /* Associated FTS5 index */
|
||||
|
||||
int bEof; /* True if this cursor is at EOF */
|
||||
Fts5IndexIter *pIter; /* Term/rowid iterator object */
|
||||
@@ -65,6 +64,7 @@ struct Fts5VocabCursor {
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
|
||||
/* These are used by 'col' tables only */
|
||||
Fts5Config *pConfig; /* Fts5 table configuration */
|
||||
int iCol;
|
||||
i64 *aCnt;
|
||||
i64 *aDoc;
|
||||
@@ -327,18 +327,13 @@ static int fts5VocabOpenMethod(
|
||||
sqlite3_vtab_cursor **ppCsr
|
||||
){
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
|
||||
Fts5Table *pFts5 = 0;
|
||||
Fts5Index *pIndex = 0;
|
||||
Fts5Config *pConfig = 0;
|
||||
Fts5VocabCursor *pCsr = 0;
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *zSql = 0;
|
||||
|
||||
if( pTab->bBusy ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
zSql = sqlite3Fts5Mprintf(&rc,
|
||||
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
||||
pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
|
||||
@@ -350,38 +345,33 @@ static int fts5VocabOpenMethod(
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
|
||||
|
||||
pTab->bBusy = 1;
|
||||
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
i64 iId = sqlite3_column_int64(pStmt, 0);
|
||||
pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
|
||||
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
|
||||
}
|
||||
pTab->bBusy = 0;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pFts5==0 ){
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}else{
|
||||
rc = sqlite3Fts5FlushToDisk(pFts5);
|
||||
if( rc==SQLITE_OK && pIndex==0 ){
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
|
||||
int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
|
||||
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
}
|
||||
|
||||
if( pCsr ){
|
||||
pCsr->pFts5 = pFts5;
|
||||
pCsr->pIndex = pIndex;
|
||||
pCsr->pStmt = pStmt;
|
||||
pCsr->pConfig = pConfig;
|
||||
pCsr->aCnt = (i64*)&pCsr[1];
|
||||
pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
|
||||
pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
|
||||
}else{
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
@@ -397,7 +387,6 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
||||
sqlite3_free(pCsr->zLeTerm);
|
||||
pCsr->nLeTerm = -1;
|
||||
pCsr->zLeTerm = 0;
|
||||
pCsr->bEof = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -436,14 +425,12 @@ static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
|
||||
}
|
||||
|
||||
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
|
||||
int eDetail = pCsr->pFts5->pConfig->eDetail;
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
int rc = SQLITE_OK;
|
||||
Fts5IndexIter *pIter = pCsr->pIter;
|
||||
i64 *pp = &pCsr->iInstPos;
|
||||
int *po = &pCsr->iInstOff;
|
||||
|
||||
assert( sqlite3Fts5IterEof(pIter)==0 );
|
||||
assert( pCsr->bEof==0 );
|
||||
while( eDetail==FTS5_DETAIL_NONE
|
||||
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
|
||||
){
|
||||
@@ -453,7 +440,7 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
|
||||
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5VocabInstanceNewTerm(pCsr);
|
||||
if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break;
|
||||
if( eDetail==FTS5_DETAIL_NONE ) break;
|
||||
}
|
||||
if( rc ){
|
||||
pCsr->bEof = 1;
|
||||
@@ -471,7 +458,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
int nCol = pCsr->pFts5->pConfig->nCol;
|
||||
int nCol = pCsr->pConfig->nCol;
|
||||
|
||||
pCsr->rowid++;
|
||||
|
||||
@@ -493,7 +480,6 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int nTerm;
|
||||
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
assert( nTerm>=0 );
|
||||
if( pCsr->nLeTerm>=0 ){
|
||||
int nCmp = MIN(nTerm, pCsr->nLeTerm);
|
||||
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
|
||||
@@ -510,7 +496,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
|
||||
while( rc==SQLITE_OK ){
|
||||
int eDetail = pCsr->pFts5->pConfig->eDetail;
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
const u8 *pPos; int nPos; /* Position list */
|
||||
i64 iPos = 0; /* 64-bit position read from poslist */
|
||||
int iOff = 0; /* Current offset within position list */
|
||||
@@ -533,6 +519,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int iCol = -1;
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
int ii = FTS5_POS2COLUMN(iPos);
|
||||
pCsr->aCnt[ii]++;
|
||||
if( iCol!=ii ){
|
||||
if( ii>=nCol ){
|
||||
rc = FTS5_CORRUPT;
|
||||
@@ -541,7 +528,6 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
pCsr->aDoc[ii]++;
|
||||
iCol = ii;
|
||||
}
|
||||
pCsr->aCnt[ii]++;
|
||||
}
|
||||
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
|
||||
@@ -570,9 +556,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
if( nTerm!=pCsr->term.n
|
||||
|| (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm))
|
||||
){
|
||||
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
|
||||
break;
|
||||
}
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
|
||||
@@ -582,10 +566,8 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
|
||||
for(/* noop */; pCsr->iCol<nCol && pCsr->aDoc[pCsr->iCol]==0; pCsr->iCol++);
|
||||
if( pCsr->iCol==nCol ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
|
||||
assert( pCsr->iCol<pCsr->pConfig->nCol );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -632,7 +614,6 @@ static int fts5VocabFilterMethod(
|
||||
}
|
||||
if( pLe ){
|
||||
const char *zCopy = (const char *)sqlite3_value_text(pLe);
|
||||
if( zCopy==0 ) zCopy = "";
|
||||
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
|
||||
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
|
||||
if( pCsr->zLeTerm==0 ){
|
||||
@@ -644,15 +625,14 @@ static int fts5VocabFilterMethod(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5Index *pIndex = pCsr->pFts5->pIndex;
|
||||
rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
}
|
||||
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
|
||||
rc = fts5VocabInstanceNewTerm(pCsr);
|
||||
}
|
||||
if( rc==SQLITE_OK && !pCsr->bEof
|
||||
&& (eType!=FTS5_VOCAB_INSTANCE
|
||||
|| pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
|
||||
if( rc==SQLITE_OK
|
||||
&& !pCsr->bEof
|
||||
&& (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
|
||||
){
|
||||
rc = fts5VocabNextMethod(pCursor);
|
||||
}
|
||||
@@ -675,7 +655,7 @@ static int fts5VocabColumnMethod(
|
||||
int iCol /* Index of column to read value from */
|
||||
){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
int eDetail = pCsr->pFts5->pConfig->eDetail;
|
||||
int eDetail = pCsr->pConfig->eDetail;
|
||||
int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
|
||||
i64 iVal = 0;
|
||||
|
||||
@@ -687,7 +667,7 @@ static int fts5VocabColumnMethod(
|
||||
assert( iCol==1 || iCol==2 || iCol==3 );
|
||||
if( iCol==1 ){
|
||||
if( eDetail!=FTS5_DETAIL_NONE ){
|
||||
const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
|
||||
const char *z = pCsr->pConfig->azCol[pCsr->iCol];
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
|
||||
}
|
||||
}else if( iCol==2 ){
|
||||
@@ -715,8 +695,8 @@ static int fts5VocabColumnMethod(
|
||||
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
ii = (int)pCsr->iInstPos;
|
||||
}
|
||||
if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
|
||||
const char *z = pCsr->pFts5->pConfig->azCol[ii];
|
||||
if( ii>=0 && ii<pCsr->pConfig->nCol ){
|
||||
const char *z = pCsr->pConfig->azCol[ii];
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
|
||||
}
|
||||
break;
|
||||
@@ -775,9 +755,10 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
};
|
||||
void *p = (void*)pGlobal;
|
||||
|
||||
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ do_execsql_test 1.0 {
|
||||
do_execsql_test 1.1 {
|
||||
DROP TABLE t1;
|
||||
SELECT name, sql FROM sqlite_master;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -408,7 +409,6 @@ do_test 14.3 {
|
||||
do_execsql_test 15.0 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 15.1 {
|
||||
UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1;
|
||||
}
|
||||
@@ -427,7 +427,7 @@ proc funk {} {
|
||||
db eval { UPDATE n1_config SET v=50 WHERE k='version' }
|
||||
set fd [db incrblob main n1_data block 10]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
# puts -nonewline $fd "\x44\x45"
|
||||
puts -nonewline $fd "\x44\x45"
|
||||
close $fd
|
||||
}
|
||||
db func funk funk
|
||||
@@ -603,38 +603,6 @@ do_execsql_test 23.2 {
|
||||
SELECT * FROM t11, t10 WHERE t10.rowid IS NULL;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 24.0 {
|
||||
CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL%);
|
||||
INSERT INTO t12 VALUES('aaaa');
|
||||
}
|
||||
do_execsql_test 24.1 {
|
||||
BEGIN;
|
||||
DELETE FROM t12 WHERE rowid=1;
|
||||
SELECT * FROM t12('aaaa');
|
||||
INSERT INTO t12 VALUES('aaaa');
|
||||
END;
|
||||
}
|
||||
do_execsql_test 24.2 {
|
||||
INSERT INTO t12(t12) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 24.3 {
|
||||
SELECT * FROM t12('aaaa');
|
||||
} {aaaa}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 25.0 {
|
||||
CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL%);
|
||||
}
|
||||
do_execsql_test 25.1 {
|
||||
BEGIN;
|
||||
INSERT INTO t13 VALUES('AAAA');
|
||||
SELECT * FROM t13('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*');
|
||||
|
||||
END;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
expand_all_sql db
|
||||
|
||||
@@ -51,12 +51,6 @@ do_execsql_test 1.1 {
|
||||
do_execsql_test 1.2 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SAVEPOINT one;
|
||||
INSERT INTO t1 VALUES('v w x');
|
||||
ROLLBACK TO one;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -144,14 +144,6 @@ do_execsql_test 3.1 {
|
||||
{[a b c d e]}
|
||||
}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT highlight(ft, 0, NULL, NULL) FROM ft WHERE ft MATCH 'a+b+c AND c+d+e';
|
||||
} {
|
||||
{a b c x c d e}
|
||||
{a b c c d e}
|
||||
{a b c d e}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -275,37 +275,6 @@ do_execsql_test 9.3 {
|
||||
9 10
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that aux. functions may not be used in aggregate queries.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 10.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, y, z);
|
||||
INSERT INTO t1 VALUES('a', 'one two', 1);
|
||||
INSERT INTO t1 VALUES('b', 'two three', 2);
|
||||
INSERT INTO t1 VALUES('c', 'three four', 1);
|
||||
INSERT INTO t1 VALUES('d', 'four five', 2);
|
||||
INSERT INTO t1 VALUES('e', 'five six', 1);
|
||||
INSERT INTO t1 VALUES('f', 'six seven', 2);
|
||||
}
|
||||
|
||||
proc firstcol {cmd} { $cmd xColumnText 0 }
|
||||
sqlite3_fts5_create_function db firstcol firstcol
|
||||
|
||||
do_execsql_test 10.1.1 {
|
||||
SELECT firstcol(t1) FROM t1
|
||||
} {a b c d e f}
|
||||
do_execsql_test 10.1.2 {
|
||||
SELECT group_concat(x, '.') FROM t1
|
||||
} {a.b.c.d.e.f}
|
||||
|
||||
do_catchsql_test 10.1.3 {
|
||||
SELECT group_concat(firstcol(t1), '.') FROM t1
|
||||
} {1 {unable to use function firstcol in the requested context}}
|
||||
|
||||
do_catchsql_test 10.1.4 {
|
||||
SELECT group_concat(firstcol(t1), '.') FROM t1 GROUP BY rowid
|
||||
} {1 {unable to use function firstcol in the requested context}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# 2018 Dec 22
|
||||
#
|
||||
# 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 fts5circref
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE tt USING fts5(a);
|
||||
SELECT name FROM sqlite_master ORDER BY 1;
|
||||
} {
|
||||
tt tt_config tt_content tt_data tt_docsize tt_idx
|
||||
}
|
||||
db_save_and_close
|
||||
|
||||
foreach {tn schema sql} {
|
||||
1 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_config BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(tt, rank) VALUES('usermerge', 4);
|
||||
}
|
||||
|
||||
2 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_docsize BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
3 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_content BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
4 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_data BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
5 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_idx BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 1.1.$tn.1 $schema
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
|
||||
db close
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -244,3 +244,4 @@ foreach {tn sql res} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -253,45 +253,5 @@ do_execsql_test 6.2 {
|
||||
SELECT name FROM sqlite_master;
|
||||
} {}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Check that an fts5 table cannot be its own content table.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.1.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, c=t1 );
|
||||
INSERT INTO t1( a ) VALUES('abc');
|
||||
}
|
||||
do_catchsql_test 7.1.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.1.3 {
|
||||
SELECT * FROM t1('abc');
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.1.4 {
|
||||
SELECT count(*) FROM t1;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.1.5 {
|
||||
SELECT * FROM t1('abc') ORDER BY rank;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 7.2.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, c=t2 );
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(a, c=t1 );
|
||||
INSERT INTO t1( a ) VALUES('abc');
|
||||
}
|
||||
do_catchsql_test 7.2.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.2.3 {
|
||||
SELECT * FROM t1('abc');
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.2.4 {
|
||||
SELECT count(*) FROM t1;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
do_catchsql_test 7.2.5 {
|
||||
SELECT * FROM t1('abc') ORDER BY rank;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ db_save
|
||||
do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
set segid [lindex [fts5_level_segids t1] 0]
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_test 1.3 {
|
||||
execsql {
|
||||
DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4);
|
||||
@@ -51,7 +50,6 @@ do_test 1.3 {
|
||||
|
||||
do_test 1.4 {
|
||||
db_restore_and_reopen
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
execsql {
|
||||
UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE
|
||||
rowid = fts5_rowid('segment', $segid, 4);
|
||||
@@ -91,7 +89,7 @@ do_execsql_test 3.0 {
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o'
|
||||
} {{one o} {three o} {five o}}
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
DELETE FROM t3_content WHERE rowid = 3;
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o';
|
||||
|
||||
@@ -99,7 +99,6 @@ foreach {tno stmt} {
|
||||
set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}]
|
||||
set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}]
|
||||
set all [db eval {SELECT rowid FROM t1}]
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
|
||||
do_execsql_test 2.$i.1 {
|
||||
BEGIN;
|
||||
@@ -249,7 +248,6 @@ foreach {tn hdr} {
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
reset_db
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 6.1 {
|
||||
CREATE VIRTUAL TABLE x5 USING fts5(tt);
|
||||
INSERT INTO x5 VALUES('a');
|
||||
|
||||
+4
-9922
File diff suppressed because one or more lines are too long
@@ -1,61 +0,0 @@
|
||||
# 2019 May 16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ttt USING fts5(a, b);
|
||||
INSERT INTO ttt
|
||||
VALUES('e ee eee e ee eee e ee eee', 'eee ee e e e ee eee ee ee');
|
||||
INSERT INTO ttt SELECT a||a, b||b FROM ttt;
|
||||
INSERT INTO ttt SELECT a||a, b||b FROM ttt;
|
||||
}
|
||||
|
||||
proc mutate {blob i} {
|
||||
set o [expr {$i % [string length $blob]}]
|
||||
set a [string range $blob 0 $o-1]
|
||||
set b [string range $blob $o+1 end]
|
||||
set v [expr int(rand()*255) - 127]
|
||||
return "$a[binary format c $v]$b"
|
||||
}
|
||||
db func mutate mutate
|
||||
|
||||
for {set j 1000} {$j <= 5000} {incr j 1000} {
|
||||
do_test 1.$j {
|
||||
for {set i 0} {$i < 1000} {incr i} {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE ttt_data SET block = mutate(block, $i) WHERE id>10;
|
||||
}
|
||||
foreach sql {
|
||||
{SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e*')}
|
||||
{SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e* NOT ee*')}
|
||||
} {
|
||||
catch { execsql $sql }
|
||||
}
|
||||
execsql ROLLBACK
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -59,27 +59,10 @@ do_catchsql_test 2.1 {
|
||||
SELECT fts5_expr()
|
||||
} {1 {wrong number of arguments to function fts5_expr}}
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT fts5_expr_tcl()
|
||||
} {1 {wrong number of arguments to function fts5_expr_tcl}}
|
||||
|
||||
do_catchsql_test 2.3 {
|
||||
SELECT fts5_expr('')
|
||||
} {1 {fts5: syntax error near ""}}
|
||||
|
||||
do_catchsql_test 2.4 {
|
||||
SELECT fts5_expr(NULL)
|
||||
} {1 {fts5: syntax error near ""}}
|
||||
|
||||
do_catchsql_test 2.5 {
|
||||
SELECT fts5_expr(NULL, NULL)
|
||||
} {1 {parse error in ""}}
|
||||
|
||||
for {set i 0} {$i < 255} {incr i} {
|
||||
do_test 2.6.$i {
|
||||
lindex [catchsql {sELECT fts5_expr(NULL, char($i));}] 0
|
||||
} 1
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
|
||||
|
||||
@@ -147,27 +147,5 @@ do_faultsim_test 5.1 -faults oom* -body {
|
||||
faultsim_test_result {0 {1 4}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test OOM injection in a query with two MATCH expressions
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
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 6.1 -faults oom* -body {
|
||||
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 2 3 4}}
|
||||
}
|
||||
do_faultsim_test 6.2 -faults oom* -body {
|
||||
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 2 3 4}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -93,3 +93,4 @@ do_catchsql_test 3.3 {
|
||||
SELECT * FROM x2('^a');
|
||||
} {1 {fts5: phrase queries are not supported (detail!=full)}}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ do_test 1.1 {
|
||||
execsql { INSERT INTO x8 VALUES( rnddoc(5) ); }
|
||||
}
|
||||
} msg] $msg
|
||||
} {0 {}}
|
||||
} {1 {database or disk is full}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -71,7 +71,6 @@ do_execsql_test 4.1 {
|
||||
INSERT INTO aa(aa) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_catchsql_test 4.2 {
|
||||
BEGIN;
|
||||
UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3;
|
||||
@@ -210,76 +209,4 @@ foreach {tn pgsz} {
|
||||
} {1000}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
PRAGMA encoding = 'UTF-16';
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
INSERT INTO vt0 VALUES (x'46f0');
|
||||
SELECT quote(c0) FROM vt0;
|
||||
} {X'46F0'}
|
||||
do_execsql_test 7.1 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('rebuild');
|
||||
}
|
||||
do_execsql_test 7.3 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 7.4 {
|
||||
UPDATE vt0 SET c0='';
|
||||
}
|
||||
do_execsql_test 7.5 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket 7a458c2a5f4
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
PRAGMA journal_mode = PERSIST;
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
} {exclusive persist}
|
||||
do_execsql_test 8.1 {
|
||||
PRAGMA data_version
|
||||
} {1}
|
||||
do_execsql_test 8.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
PRAGMA data_version;
|
||||
} {1}
|
||||
do_execsql_test 8.1 {
|
||||
INSERT INTO vt0(vt0, rank) VALUES('usermerge', 2);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket [771fe617]
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 9.0 {
|
||||
PRAGMA encoding = 'UTF16';
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
}
|
||||
|
||||
#explain_i { SELECT quote(SUBSTR(x'37', 0)); }
|
||||
#execsql { PRAGMA vdbe_trace = 1 }
|
||||
do_execsql_test 9.1.1 {
|
||||
SELECT quote(SUBSTR(x'37', 0));
|
||||
} {X'37'}
|
||||
do_execsql_test 9.1.2 {
|
||||
SELECT quote(x'37');
|
||||
} {X'37'}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 9.2 {
|
||||
INSERT INTO vt0 VALUES (SUBSTR(x'37', 0));
|
||||
-- INSERT INTO vt0 VALUES (x'37');
|
||||
}
|
||||
do_execsql_test 9.3 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
# 2019 Jan 4
|
||||
#
|
||||
# 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 fts5interrupt
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
|
||||
}
|
||||
db_save_and_close
|
||||
|
||||
proc progress_handler {args} {
|
||||
incr ::progress_handler_delay -1
|
||||
if {$::progress_handler_delay<=0} { return 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1 { INSERT INTO t1(rowid, a) VALUES(0, 'z z z z') }
|
||||
2 { COMMIT }
|
||||
} {
|
||||
set bDone 0
|
||||
for {set i 1} {$bDone==0} {incr i} {
|
||||
do_test 1.$tn.$i {
|
||||
db_restore_and_reopen
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t1(rowid, a) VALUES(1, 'a b c d');
|
||||
INSERT INTO t1(rowid, a) VALUES(2, 'd e f g');
|
||||
INSERT INTO t1(rowid, a) VALUES(3, 'h i j k');
|
||||
INSERT INTO t1(rowid, a) VALUES(4, 'l m n o');
|
||||
}
|
||||
|
||||
set ::progress_handler_delay $i
|
||||
db progress 1 progress_handler
|
||||
set res [catchsql $sql]
|
||||
db close
|
||||
if {$res=="0 {}"} {
|
||||
set bDone 1
|
||||
} else {
|
||||
if {$res!="1 interrupted"} { error "got: $res" }
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -491,33 +491,4 @@ do_catchsql_test 14.2 {
|
||||
SELECT matchinfo(x1, 'd') FROM x1('a b c');
|
||||
} {1 {unrecognized matchinfo flag: d}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test using matchinfo() and similar on a non-full-text query
|
||||
#
|
||||
do_execsql_test 15.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, y);
|
||||
INSERT INTO t1 VALUES('a', 'b');
|
||||
INSERT INTO t1 VALUES('c', 'd');
|
||||
}
|
||||
|
||||
if {$tcl_platform(byteOrder)=="littleEndian"} {
|
||||
set res {X'02000000'}
|
||||
} else {
|
||||
set res {X'00000002'}
|
||||
}
|
||||
do_execsql_test 15.1 {
|
||||
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
|
||||
} $res
|
||||
do_execsql_test 15.2 {
|
||||
DELETE FROM t1_content WHERE rowid=1;
|
||||
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
|
||||
} $res
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 15.3 {
|
||||
SELECT fts5_test_all(t1) FROM t1 LIMIT 1;
|
||||
} {
|
||||
{columnsize {0 0} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
# 2019 September 02
|
||||
#
|
||||
# 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 fts5misc
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
}
|
||||
|
||||
do_catchsql_test 1.1.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*');
|
||||
} {1 {unknown special query: }}
|
||||
do_catchsql_test 1.1.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*'));
|
||||
} {1 {unknown special query: }}
|
||||
|
||||
do_catchsql_test 1.2.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id');
|
||||
} {0 {{}}}
|
||||
|
||||
do_catchsql_test 1.2.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id'));
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 1.3.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
|
||||
} {1 {no such cursor: 1}}
|
||||
|
||||
do_catchsql_test 1.3.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.3.3 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t0(c0);
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
}
|
||||
do_execsql_test 2.1.1 {
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO vt0(c0) VALUES ('xyz');
|
||||
}
|
||||
do_execsql_test 2.1.2 {
|
||||
ALTER TABLE t0 ADD COLUMN c5;
|
||||
}
|
||||
do_execsql_test 2.1.3 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 2.1.4 {
|
||||
INSERT INTO vt0(c0) VALUES ('abc');
|
||||
COMMIT
|
||||
}
|
||||
do_execsql_test 2.1.5 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.2.1 {
|
||||
CREATE TABLE t0(c0);
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO vt0(c0) VALUES ('xyz');
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 2.2.2 {
|
||||
ALTER TABLE t0 RENAME TO t1;
|
||||
}
|
||||
do_execsql_test 2.2.3 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
do_execsql_test 2.2.4 {
|
||||
INSERT INTO vt0(c0) VALUES ('abc');
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 2.2.5 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(a);
|
||||
PRAGMA reverse_unordered_selects = true;
|
||||
INSERT INTO vt0 VALUES('365062398'), (0), (0);
|
||||
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '38');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
UPDATE vt0 SET a = 399905135; -- unexpected: database disk image is malformed
|
||||
}
|
||||
do_execsql_test 3.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
INSERT INTO vt0(c0) VALUES ('xyz');
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
BEGIN;
|
||||
INSERT INTO vt0(c0) VALUES ('abc');
|
||||
INSERT INTO vt0(vt0) VALUES('rebuild');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
BEGIN;
|
||||
INSERT INTO vt0(vt0) VALUES('rebuild');
|
||||
INSERT INTO vt0(vt0) VALUES('rebuild');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 4.4 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket [81a7f7b9].
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
|
||||
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65536');
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1236
|
||||
)
|
||||
INSERT INTO vt0(c0) SELECT '0' FROM s;
|
||||
} {}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
UPDATE vt0 SET c1 = 'T,D&p^y/7#3*v<b<4j7|f';
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_catchsql_test 5.3 {
|
||||
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65537');
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket [d392017c].
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
|
||||
)
|
||||
INSERT INTO vt0(c0) SELECT '0' FROM s;
|
||||
INSERT INTO vt0(vt0, rank) VALUES('crisismerge', 2000);
|
||||
INSERT INTO vt0(vt0, rank) VALUES('automerge', 0);
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO vt0(vt0) VALUES('rebuild');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
INSERT INTO t1(rowid, x) VALUES(1, 'hello world');
|
||||
INSERT INTO t1(rowid, x) VALUES(2, 'well said');
|
||||
INSERT INTO t1(rowid, x) VALUES(3, 'hello said');
|
||||
INSERT INTO t1(rowid, x) VALUES(4, 'well world');
|
||||
|
||||
CREATE TABLE t2 (a, b);
|
||||
INSERT INTO t2 VALUES(1, 'hello');
|
||||
INSERT INTO t2 VALUES(2, 'world');
|
||||
INSERT INTO t2 VALUES(3, 'said');
|
||||
INSERT INTO t2 VALUES(4, 'hello');
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
SELECT rowid FROM t1 WHERE (rowid, x) IN (SELECT a, b FROM t2);
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
SELECT rowid FROM t1 WHERE rowid=2 AND t1 = 'hello';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0, tokenize = "ascii", prefix = 1);
|
||||
INSERT INTO vt0(c0) VALUES (x'd1');
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 9.0 {
|
||||
CREATE VIRTUAL TABLE t1 using FTS5(mailcontent);
|
||||
insert into t1(rowid, mailcontent) values
|
||||
(-4764623217061966105, 'we are going to upgrade'),
|
||||
(8324454597464624651, 'we are going to upgrade');
|
||||
}
|
||||
|
||||
do_execsql_test 9.1 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
SELECT rowid FROM t1('upgrade');
|
||||
} {
|
||||
-4764623217061966105 8324454597464624651
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 10.0 {
|
||||
CREATE VIRTUAL TABLE vt1 USING fts5(c1, c2, prefix = 1, tokenize = "ascii");
|
||||
INSERT INTO vt1 VALUES (x'e4', '䔬');
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT quote(CAST(c1 AS blob)), quote(CAST(c2 AS blob)) FROM vt1
|
||||
} {X'E4' X'E494AC'}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
INSERT INTO vt1(vt1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(
|
||||
c0, prefix = 71, tokenize = "porter ascii", prefix = 9
|
||||
);
|
||||
} {}
|
||||
do_execsql_test 11.1 {
|
||||
BEGIN;
|
||||
INSERT INTO vt0(c0) VALUES (x'e8');
|
||||
}
|
||||
do_execsql_test 11.2 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket [752fdbf6]
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 11.0 {
|
||||
PRAGMA encoding = 'UTF-16';
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
|
||||
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '37');
|
||||
INSERT INTO vt0(c0, c1) VALUES (0.66077, 1957391816);
|
||||
}
|
||||
do_execsql_test 11.1 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket [7c0e06b16]
|
||||
#
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE t1(a, b, rank);
|
||||
INSERT INTO t1 VALUES('a', 'hello', '');
|
||||
INSERT INTO t1 VALUES('b', 'world', '');
|
||||
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a);
|
||||
INSERT INTO ft VALUES('b');
|
||||
INSERT INTO ft VALUES('y');
|
||||
|
||||
CREATE TABLE t2(x, y, ft);
|
||||
INSERT INTO t2 VALUES(1, 2, 'x');
|
||||
INSERT INTO t2 VALUES(3, 4, 'b');
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
SELECT * FROM t1 NATURAL JOIN ft WHERE ft MATCH('b')
|
||||
} {b world {}}
|
||||
do_execsql_test 12.2 {
|
||||
SELECT * FROM ft NATURAL JOIN t1 WHERE ft MATCH('b')
|
||||
} {b world {}}
|
||||
do_execsql_test 12.3 {
|
||||
SELECT * FROM t2 JOIN ft USING (ft)
|
||||
} {3 4 b b}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
# 2014 September 13
|
||||
#
|
||||
# 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 fts5multi
|
||||
|
||||
# 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(a, b, c);
|
||||
INSERT INTO t1 VALUES('gg bb bb' ,'gg ff gg' ,'ii ii');
|
||||
INSERT INTO t1 VALUES('dd dd hh kk','jj' ,'aa');
|
||||
INSERT INTO t1 VALUES('kk gg ee' ,'hh cc' ,'hh jj aa cc');
|
||||
INSERT INTO t1 VALUES('hh' ,'bb jj cc' ,'kk ii');
|
||||
INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa' ,'ee');
|
||||
INSERT INTO t1 VALUES('ee' ,'ff gg kk aa','ee ff ee');
|
||||
INSERT INTO t1 VALUES('ff jj' ,'gg ee' ,'kk ee gg kk');
|
||||
INSERT INTO t1 VALUES('ff ee dd hh','kk ee' ,'gg dd');
|
||||
INSERT INTO t1 VALUES('bb' ,'aa' ,'bb aa');
|
||||
INSERT INTO t1 VALUES('hh cc bb' ,'ff bb' ,'cc');
|
||||
INSERT INTO t1 VALUES('jj' ,'ff dd bb aa','dd dd ff ff');
|
||||
INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc');
|
||||
INSERT INTO t1 VALUES('ff aa cc jj','kk' ,'ii dd');
|
||||
INSERT INTO t1 VALUES('jj dd' ,'cc' ,'ii hh ee aa');
|
||||
INSERT INTO t1 VALUES('ff ii hh' ,'dd' ,'gg');
|
||||
INSERT INTO t1 VALUES('ff dd gg hh','hh' ,'ff dd');
|
||||
INSERT INTO t1 VALUES('cc cc' ,'ff dd ff' ,'bb');
|
||||
INSERT INTO t1 VALUES('ii' ,'bb ii' ,'jj kk');
|
||||
INSERT INTO t1 VALUES('ff hh' ,'hh bb' ,'bb dd ee');
|
||||
INSERT INTO t1 VALUES('jj kk' ,'jj' ,'gg ff cc');
|
||||
INSERT INTO t1 VALUES('dd kk' ,'ii gg' ,'dd');
|
||||
INSERT INTO t1 VALUES('cc' ,'aa ff' ,'ii');
|
||||
INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd');
|
||||
INSERT INTO t1 VALUES('aa' ,'ee bb jj jj','dd');
|
||||
INSERT INTO t1 VALUES('kk dd cc' ,'aa jj' ,'ee aa ff');
|
||||
INSERT INTO t1 VALUES('aa gg aa' ,'jj' ,'ii kk hh gg');
|
||||
INSERT INTO t1 VALUES('ff hh aa' ,'jj ii' ,'hh dd bb jj');
|
||||
INSERT INTO t1 VALUES('hh' ,'aa gg kk' ,'bb ee');
|
||||
INSERT INTO t1 VALUES('bb' ,'ee' ,'gg');
|
||||
INSERT INTO t1 VALUES('dd kk' ,'kk bb aa' ,'ee');
|
||||
}
|
||||
|
||||
foreach {tn c1 e1 c2 e2} {
|
||||
1 t1 aa t1 bb
|
||||
2 a aa b bb
|
||||
3 a "aa OR bb OR cc" b "jj OR ii OR hh"
|
||||
4 t1 "aa AND bb" t1 "cc"
|
||||
5 c "kk" b "aa OR bb OR cc OR dd OR ee"
|
||||
} {
|
||||
if {$c1=="t1"} {
|
||||
set lhs "( $e1 )"
|
||||
} else {
|
||||
set lhs "$c1 : ( $e1 )"
|
||||
}
|
||||
if {$c2=="t1"} {
|
||||
set rhs "( $e2 )"
|
||||
} else {
|
||||
set rhs "$c2 : ( $e2 )"
|
||||
}
|
||||
|
||||
set q1 "t1 MATCH '($lhs) AND ($rhs)'"
|
||||
set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'"
|
||||
|
||||
set ret [execsql "SELECT rowid FROM t1 WHERE $q1"]
|
||||
set N [llength $ret]
|
||||
do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret
|
||||
|
||||
set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"]
|
||||
do_execsql_test 1.$tn.2.($N) "
|
||||
SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2
|
||||
" $ret
|
||||
}
|
||||
|
||||
do_catchsql_test 2.1.1 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb';
|
||||
} {1 {fts5: syntax error near "NOT"}}
|
||||
do_catchsql_test 2.1.2 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT';
|
||||
} {1 {fts5: syntax error near "NOT"}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -31,7 +31,7 @@ do_eqp_test 1.1 {
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
|
||||
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
@@ -46,7 +46,7 @@ do_eqp_test 1.3 {
|
||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
@@ -60,6 +60,6 @@ do_eqp_test 1.4 {
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM f1 WHERE rank MATCH ?
|
||||
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
|
||||
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -162,22 +162,5 @@ do_execsql_test 5.1 {
|
||||
SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank;
|
||||
} {30 31 32 33 34 35 36 37 38 39 40}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE "My.Table" USING fts5(Text);
|
||||
|
||||
INSERT INTO "My.Table" VALUES ('hello this is a test');
|
||||
INSERT INTO "My.Table" VALUES ('of trying to order by');
|
||||
INSERT INTO "My.Table" VALUES ('rank on an fts5 table');
|
||||
INSERT INTO "My.Table" VALUES ('that have periods in');
|
||||
INSERT INTO "My.Table" VALUES ('the table names.');
|
||||
INSERT INTO "My.Table" VALUES ('table table table');
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
SELECT * FROM "My.Table" WHERE Text MATCH 'table' ORDER BY rank;
|
||||
} {
|
||||
{table table table} {the table names.} {rank on an fts5 table}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ do_execsql_test 1.4 {
|
||||
INSERT INTO f1(f1) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 1.5 {
|
||||
DELETE FROM f1_data;
|
||||
} {}
|
||||
|
||||
@@ -70,7 +70,6 @@ set res [db one {SELECT count(*) FROM x1_data}]
|
||||
do_execsql_test 2.3 {
|
||||
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
|
||||
} $res
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 2.4 {
|
||||
UPDATE x1_data SET block = X'';
|
||||
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# 2019 Dec 26
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5savepoint
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(c);
|
||||
BEGIN;
|
||||
SAVEPOINT one;
|
||||
INSERT INTO ft VALUES('a');
|
||||
SAVEPOINT two;
|
||||
INSERT INTO ft VALUES('b');
|
||||
RELEASE two;
|
||||
SAVEPOINT four;
|
||||
INSERT INTO ft VALUES('c');
|
||||
RELEASE four;
|
||||
SAVEPOINT three;
|
||||
INSERT INTO ft VALUES('d');
|
||||
ROLLBACK TO three;
|
||||
COMMIT;
|
||||
SELECT * FROM ft
|
||||
} {a b c}
|
||||
|
||||
reset_db
|
||||
do_catchsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(c);
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(c);
|
||||
DROP TABLE ft2_idx;
|
||||
BEGIN;
|
||||
INSERT INTO ft2 VALUES('a');
|
||||
INSERT INTO ft1 VALUES('a');
|
||||
SAVEPOINT two;
|
||||
INSERT INTO ft1 VALUES('b');
|
||||
COMMIT;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
reset_db
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
CREATE VIRTUAL TABLE vt1 USING fts4(c0);
|
||||
INSERT INTO vt1(c0) VALUES(0);
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
BEGIN;
|
||||
UPDATE vt1 SET c0 = 0;
|
||||
INSERT INTO vt1(c0) VALUES (0), (0);
|
||||
UPDATE vt0 SET c0 = 0;
|
||||
INSERT INTO vt1(c0) VALUES (0);
|
||||
UPDATE vt1 SET c0 = 0;
|
||||
INSERT INTO vt1(vt1) VALUES('automerge=1');
|
||||
UPDATE vt1 SET c0 = 0;
|
||||
}
|
||||
|
||||
do_catchsql_test 3.2 {
|
||||
DROP TABLE vt1;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SAVEPOINT x;
|
||||
INSERT INTO vt0 VALUES('x');
|
||||
COMMIT;
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -467,17 +467,4 @@ do_execsql_test 21.3 {
|
||||
SELECT rowid FROM x1($doc);
|
||||
} {11112}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 22.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
INSERT INTO x1(x) VALUES('a b c');
|
||||
INSERT INTO x1(x) VALUES('x y z');
|
||||
INSERT INTO x1(x) VALUES('c b a');
|
||||
INSERT INTO x1(x) VALUES('z y x');
|
||||
}
|
||||
|
||||
do_catchsql_test 22.1 {SELECT * FROM x1('')} {1 {fts5: syntax error near ""}}
|
||||
do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -189,7 +189,7 @@ do_catchsql_test 6.2 {
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.3 {
|
||||
CREATE VIRTUAL TABLE a3 USING fts5(
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 3'
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 2'
|
||||
);
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.4 {
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# 2014 June 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5umlaut
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(
|
||||
x,
|
||||
tokenize="unicode61 remove_diacritics 2"
|
||||
);
|
||||
}
|
||||
|
||||
foreach {tn q res1 res2} {
|
||||
1 "Hà Nội" 0 1
|
||||
2 "Hà Noi" 1 1
|
||||
3 "Ha Noi" 1 1
|
||||
4 "Ha N\u1ed9i" 0 1
|
||||
5 "Ha N\u006fi" 1 1
|
||||
6 "Ha N\u006f\u0302i" 1 1
|
||||
7 "Ha N\u006f\u0323\u0302i" 1 1
|
||||
} {
|
||||
do_execsql_test 1.$tn.1 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t1($q)
|
||||
} $res1
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t1('Ha Noi')
|
||||
} $res1
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t2($q)
|
||||
} $res2
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t2('Ha Noi')
|
||||
} $res2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -21,7 +21,7 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
proc fts3_unicode_path {file} {
|
||||
file join .. [file dirname [info script]] .. .. fts3 unicode $file
|
||||
file join [file dirname [info script]] .. .. fts3 unicode $file
|
||||
}
|
||||
|
||||
source [fts3_unicode_path parseunicode.tcl]
|
||||
@@ -36,26 +36,24 @@ foreach x [an_load_unicodedata_text $UD] {
|
||||
}
|
||||
|
||||
foreach {y} [rd_load_unicodedata_text $UD] {
|
||||
foreach {code ascii f} $y {}
|
||||
foreach {code ascii} $y {}
|
||||
if {$ascii==""} {
|
||||
set int 0
|
||||
} else {
|
||||
binary scan $ascii c int
|
||||
}
|
||||
set aDiacritic($code,$f) $int
|
||||
if {$f==0} { set aDiacritic($code,1) $int }
|
||||
set aDiacritic($code) $int
|
||||
}
|
||||
|
||||
proc tcl_fold {i {bRemoveDiacritic 0}} {
|
||||
global tl_lookup_table
|
||||
global aDiacritic
|
||||
set f [expr $bRemoveDiacritic==2]
|
||||
|
||||
if {[info exists tl_lookup_table($i)]} {
|
||||
set i $tl_lookup_table($i)
|
||||
}
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i,$f)]} {
|
||||
set i $aDiacritic($i,$f)
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i)]} {
|
||||
set i $aDiacritic($i)
|
||||
}
|
||||
expr $i
|
||||
}
|
||||
@@ -87,7 +85,7 @@ do_execsql_test 1.1 {
|
||||
SELECT count(*), min(i) FROM ii WHERE fts5_fold(i)!=CAST(tcl_fold(i) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2.1 {
|
||||
do_execsql_test 1.2 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
@@ -97,16 +95,6 @@ do_execsql_test 1.2.1 {
|
||||
WHERE fts5_fold(i,1)!=CAST(tcl_fold(i,1) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2.2 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
SELECT i+1 FROM ii WHERE i<100000
|
||||
)
|
||||
SELECT count(*), min(i) FROM ii
|
||||
WHERE fts5_fold(i,2)!=CAST(tcl_fold(i,2) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
|
||||
@@ -115,43 +115,5 @@ do_execsql_test 2.2.integrity {
|
||||
INSERT INTO x2(x2) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE x3 USING fts5(x, detail=%DETAIL%);
|
||||
INSERT INTO x3 VALUES('one');
|
||||
INSERT INTO x3 VALUES('two');
|
||||
INSERT INTO x3 VALUES('one');
|
||||
INSERT INTO x3 VALUES('two');
|
||||
INSERT INTO x3 VALUES('one');
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
db eval { SELECT * FROM x3('one') } {
|
||||
db eval {
|
||||
INSERT INTO x3(x3) VALUES('optimize');
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x4 USING fts5(a, detail=%DETAIL%);
|
||||
INSERT INTO x4 VALUES('one two three');
|
||||
INSERT INTO x4(rowid, a) VALUES('2', 'one two three');
|
||||
INSERT INTO x4(rowid, a) VALUES('3.0', 'one two three');
|
||||
}
|
||||
do_catchsql_test 4.1 {
|
||||
INSERT INTO x4(rowid, a) VALUES('four', 'one two three');
|
||||
} {1 {datatype mismatch}}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
UPDATE x4 SET rowid = 'four' WHERE rowid=1;
|
||||
} {1 {datatype mismatch}}
|
||||
|
||||
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_catchsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); } {0 {}}
|
||||
do_catchsql_test 4.1 { DELETE FROM t1 WHERE t1 MATCH 'f*'; } {0 {}}
|
||||
finish_test
|
||||
|
||||
@@ -36,10 +36,9 @@ do_execsql_test 1.3 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'a';
|
||||
} {1}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 1.4 {
|
||||
UPDATE t1_config set v=5 WHERE k='version';
|
||||
}
|
||||
}
|
||||
|
||||
do_test 1.5 {
|
||||
db close
|
||||
@@ -54,7 +53,6 @@ do_test 1.6 {
|
||||
} {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}}
|
||||
|
||||
do_test 1.7 {
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
execsql { DELETE FROM t1_config WHERE k='version' }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
@@ -79,8 +79,8 @@ do_execsql_test 1.1.2 {
|
||||
3 cnt {} 0 {} 0
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.1 { SELECT * FROM v1 } {}
|
||||
do_execsql_test 1.2.2 { SELECT * FROM v2 } {}
|
||||
do_execsql_test 1.2.1 { SELECT * FROM v1 } { }
|
||||
do_execsql_test 1.2.2 { SELECT * FROM v2 } { }
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
INSERT INTO t1 VALUES('x y z');
|
||||
@@ -420,7 +420,6 @@ if {[detail_is_none]} { set resc [row_to_col $resr] }
|
||||
do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr
|
||||
do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 8.2 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master
|
||||
@@ -479,79 +478,7 @@ do_test 9.6 {
|
||||
expr [lsearch $e2 SorterSort]<0
|
||||
} 0
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 10.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, c);
|
||||
CREATE VIRTUAL TABLE t2 USING fts5vocab('ft','row');
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab('ft','row');
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
BEGIN;
|
||||
INSERT INTO ft(b) VALUES('x y');
|
||||
}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT t2.term FROM t2;
|
||||
} {x y}
|
||||
|
||||
do_execsql_test 10.3 {
|
||||
SELECT t2.term, t3.term FROM t2, t3;
|
||||
} {x x x y y x y y}
|
||||
|
||||
do_execsql_test 10.4 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 10.5 {
|
||||
BEGIN;
|
||||
INSERT INTO ft(a) VALUES('1 2 3');
|
||||
INSERT INTO ft(a) VALUES('4 5 6');
|
||||
INSERT INTO ft(a) VALUES('1 2 3');
|
||||
INSERT INTO ft(a) VALUES('4 5 6');
|
||||
INSERT INTO ft(a) VALUES('1 2 3');
|
||||
INSERT INTO ft(a) VALUES('4 5 6');
|
||||
}
|
||||
|
||||
do_test 10.6 {
|
||||
set res [list]
|
||||
db eval { SELECT rowid FROM ft('4') } x {
|
||||
db eval { SELECT * FROM t2 }
|
||||
lappend res $x(rowid)
|
||||
}
|
||||
db eval COMMIT
|
||||
set res
|
||||
} {3 5 7}
|
||||
|
||||
do_execsql_test 10.6.1 {
|
||||
SELECT * FROM t2 WHERE term<NULL;
|
||||
}
|
||||
do_execsql_test 10.6.2 {
|
||||
SELECT * FROM t2 WHERE term>NULL;
|
||||
}
|
||||
do_execsql_test 10.6.3 {
|
||||
SELECT * FROM t2 WHERE term=NULL;
|
||||
}
|
||||
do_execsql_test 10.7.1 {
|
||||
SELECT * FROM t2 WHERE term<?;
|
||||
}
|
||||
do_execsql_test 10.7.2 {
|
||||
SELECT * FROM t2 WHERE term>?;
|
||||
}
|
||||
do_execsql_test 10.7.3 {
|
||||
SELECT * FROM t2 WHERE term=?;
|
||||
}
|
||||
|
||||
# 2020-02-16 Detect recursively define fts5vocab() tables.
|
||||
# Error found by dbsqlfuzz.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 11.100 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab(rowid , 'col');
|
||||
CREATE VIRTUAL TABLE rowid USING fts5vocab(rowid , 'instance');
|
||||
} {}
|
||||
do_catchsql_test 11.110 {
|
||||
SELECT rowid+1,rowid, * FROM t3 WHERE null>rowid ;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5vocab2
|
||||
set testprefix fts5vocab
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
@@ -80,7 +80,8 @@ do_execsql_test 1.4 {
|
||||
do_execsql_test 1.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -142,7 +143,8 @@ do_execsql_test 2.4 {
|
||||
do_execsql_test 2.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -200,38 +202,8 @@ do_execsql_test 3.4 {
|
||||
do_execsql_test 3.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE v1 USING fts5vocab(nosuchtable, col);
|
||||
}
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM v1 WHERE term=='nosuchterm';
|
||||
} {1 {no such fts5 table: main.nosuchtable}}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
CREATE TABLE nosuchtable(nosuchtable, y, z);
|
||||
}
|
||||
do_catchsql_test 4.2.2 {
|
||||
SELECT * FROM v1 WHERE term=='nosuchterm';
|
||||
} {1 {no such fts5 table: main.nosuchtable}}
|
||||
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 4.3.1 {
|
||||
DROP TABLE nosuchtable;
|
||||
CREATE VIRTUAL TABLE nosuchtable USING fts3(a, b);
|
||||
} {}
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM v1 WHERE term=='nosuchterm';
|
||||
} {1 {no such fts5 table: main.nosuchtable}}
|
||||
do_catchsql_test 4.3.3 {
|
||||
INSERT INTO nosuchtable VALUES('id', '*id');
|
||||
SELECT * FROM v1 WHERE term=='nosuchterm';
|
||||
} {1 {no such fts5 table: main.nosuchtable}}
|
||||
} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+1
-2
@@ -116,8 +116,7 @@ SQLite. Documentation follows.
|
||||
and use it as a dynamically loadable SQLite extension. To do this
|
||||
using gcc on *nix:
|
||||
|
||||
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-uc icu-io` \
|
||||
-o libSqliteIcu.so
|
||||
gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
|
||||
|
||||
You may need to add "-I" flags so that gcc can find sqlite3ext.h
|
||||
and sqlite3.h. The resulting shared lib, libSqliteIcu.so, may be
|
||||
|
||||
+16
-17
@@ -143,7 +143,7 @@ static int icuLikeCompare(
|
||||
** 3. uPattern is an unescaped escape character, or
|
||||
** 4. uPattern is to be handled as an ordinary character
|
||||
*/
|
||||
if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
||||
if( !prevEscape && uPattern==MATCH_ALL ){
|
||||
/* Case 1. */
|
||||
uint8_t c;
|
||||
|
||||
@@ -169,12 +169,12 @@ static int icuLikeCompare(
|
||||
}
|
||||
return 0;
|
||||
|
||||
}else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
||||
}else if( !prevEscape && uPattern==MATCH_ONE ){
|
||||
/* Case 2. */
|
||||
if( *zString==0 ) return 0;
|
||||
SQLITE_ICU_SKIP_UTF8(zString);
|
||||
|
||||
}else if( uPattern==(uint32_t)uEsc && !prevEscape ){
|
||||
}else if( !prevEscape && uPattern==(uint32_t)uEsc){
|
||||
/* Case 3. */
|
||||
prevEscape = 1;
|
||||
|
||||
@@ -499,27 +499,26 @@ static void icuLoadCollation(
|
||||
** Register the ICU extension functions with database db.
|
||||
*/
|
||||
int sqlite3IcuInit(sqlite3 *db){
|
||||
# define SQLITEICU_EXTRAFLAGS (SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
|
||||
static const struct IcuScalar {
|
||||
const char *zName; /* Function name */
|
||||
unsigned char nArg; /* Number of arguments */
|
||||
unsigned int enc; /* Optimal text encoding */
|
||||
unsigned short enc; /* Optimal text encoding */
|
||||
unsigned char iContext; /* sqlite3_user_data() context */
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} scalars[] = {
|
||||
{"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
||||
{"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
|
||||
{"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
|
||||
{"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
{"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
{"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
||||
{"upper", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
||||
{"lower", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
{"lower", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
||||
{"upper", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
||||
{"upper", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
||||
{"like", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
|
||||
{"like", 3, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
|
||||
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
|
||||
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
||||
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
||||
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
||||
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
||||
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
||||
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
||||
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
||||
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
||||
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
||||
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
|
||||
};
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
@@ -24,3 +24,4 @@ int sqlite3IcuInit(sqlite3 *db);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
+2
-2
@@ -43,10 +43,10 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \
|
||||
|
||||
# all: lsm.so
|
||||
|
||||
LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
|
||||
LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
|
||||
|
||||
lsm.so: $(LSMOBJ)
|
||||
$(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ)
|
||||
$(TCCX) -shared -o lsm.so $(LSMOBJ)
|
||||
|
||||
%.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h
|
||||
$(TCCX) $(LSMOPTS) -c $<
|
||||
|
||||
@@ -654,3 +654,5 @@ void test_data_3(
|
||||
testFree(zName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -322,3 +322,5 @@ void do_writer_crash_test(const char *zPattern, int *pRc){
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -138,3 +138,6 @@ void test_data_4(
|
||||
testFree(zName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,3 +69,7 @@ int do_bt(int nArg, char **azArg){
|
||||
sqlite4_buffer_clear(&buf.output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ static int sql_begin(TestDb *pTestDb, int iLevel){
|
||||
/* If there are no transactions at all open, open a read transaction. */
|
||||
if( pDb->nOpenTrans==0 ){
|
||||
int rc = sqlite3_exec(pDb->db,
|
||||
"BEGIN; SELECT * FROM sqlite_schema LIMIT 1;" , 0, 0, 0
|
||||
"BEGIN; SELECT * FROM sqlite_master LIMIT 1;" , 0, 0, 0
|
||||
);
|
||||
if( rc!=0 ) return rc;
|
||||
pDb->nOpenTrans = 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user