Compare commits

..

8 Commits

Author SHA1 Message Date
drh 8477f7f79c Reduce the size of Expr to 64-bytes. This works somewhat, but there are
test failures.  More importantly, the size reduction from 80- to 64-bytes has
not lowered the schema memory usage, but it has made the code a little bigger
and a little slower.  So the initial evidence is that this Expr refactoring
experiment is not working...

FossilOrigin-Name: 24b0f66ac611e26f55ffeaff459b0d7ab53e6fa8d72765bea77c3b50634357e8
2018-09-19 20:14:48 +00:00
drh ee9d4d7fed Fix an issue in virtual table handling associated with the new Expr.x.pRight
field.

FossilOrigin-Name: 8487f84af00a8afde4ae24c4925e0f8ac9f38e86ea8b453dccedb3ee10f7f667
2018-09-19 17:24:00 +00:00
drh 53872e7259 Make sure Expr.eX changes back to EX_None after Expr.x.pRight is set to NULL
due to an OOM.

FossilOrigin-Name: e4129cd3a04bff314d2318f33d7ca02c05de35d35f6c650dddb5cabc7c430017
2018-09-19 16:35:38 +00:00
drh 3d6bedf14f Reduce the size of Expr from 80 to 72 bytes moving the pRight field inside the
"x" union.  This is an incremental check-in that still has issues.

FossilOrigin-Name: 147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f
2018-09-19 14:54:38 +00:00
drh 12b0fabde2 Make sure temporary Expr objects are fully initialized prior to sending them
into sqlite3ExprCodeTemp().

FossilOrigin-Name: de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
2018-09-19 11:59:15 +00:00
drh 3b3c86ade2 In the Expr object, the Expr.eX field determines what value is stored in the
Expr.x union.  This mostly works, but there are issues identified by valgrind.

FossilOrigin-Name: 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
2018-09-18 21:35:31 +00:00
drh 110e3afd11 Merge all recent trunk enhancements.
FossilOrigin-Name: 655f065404e08083ad5eb9b22a036f410b46eb5eb2bcfb0fbc953b4e152c95e7
2018-09-18 18:08:01 +00:00
drh 35284b6c48 Add assert() statements to sqlite3ExprDelete() that prove various symmetry
properties of the Expr object that might be exploited to make the Expr object
smaller and faster.

FossilOrigin-Name: 81f25d5c84e4d2d0cd3c6a7c105c7c93d310218feeea4e023dbc32e7e96b2a52
2018-07-28 01:30:43 +00:00
737 changed files with 18429 additions and 122660 deletions
-6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+13 -37
View File
@@ -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).
+1 -1
View File
@@ -1 +1 @@
3.33.0
3.26.0
+1 -1
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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
#-----------------------------------------------------------------------
+1 -1
View File
@@ -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.
+22 -27
View File
@@ -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__ \
+609 -733
View File
File diff suppressed because it is too large Load Diff
Vendored
+1248 -1402
View File
File diff suppressed because it is too large Load Diff
Vendored
+30 -41
View File
@@ -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
View File
@@ -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
View File
@@ -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 "&amp;&amp;" 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>
-142
View File
@@ -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_ &rarr; tags the new functions as Innocuous
<li> _SQLITE\_DIRECTONLY_ &rarr; tags the new functions as Direct-Only
</ol>
5. New options to sqlite3\_vtab\_config():
<ol type="a">
<li> _SQLITE\_VTAB\_INNOCUOUS_ &rarr; tags the vtab as Innocuous
<li> _SQLITE\_VTAB\_DIRECTONLY_ &rarr; 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_ &rarr; Name of the function
<li> _builtin_ &rarr; 1 for built-in functions. 0 otherwise.
<li> _type_ &rarr; 's'=Scalar, 'a'=Aggregate, 'w'=Window
<li> _enc_ &rarr; 'utf8', 'utf16le', or 'utf16be'
<li> _narg_ &rarr; number of argument
<li> _flags_ &rarr; 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.
-88
View File
@@ -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.
+1
View File
@@ -1704,3 +1704,4 @@ int sqlite3async_control(int op, ...){
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */
+1
View File
@@ -220,3 +220,4 @@ int sqlite3async_control(int op, ...);
} /* End of the 'extern "C"' block */
#endif
#endif /* ifndef __SQLITEASYNC_H_ */
+6 -17
View File
@@ -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
View File
@@ -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 */
+3 -3
View File
@@ -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) */
+2
View File
@@ -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.
+2 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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{
+5 -6
View File
@@ -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
View File
@@ -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 */
+5 -7
View File
@@ -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 */
+6 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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");
+23 -32
View File
@@ -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:
+4 -27
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+15 -31
View File
@@ -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;
}
+2 -2
View File
@@ -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;
+4 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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++;
}
}
+2 -1
View File
@@ -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
View File
@@ -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);
}
+3 -35
View File
@@ -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
-6
View File
@@ -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;
}
}
-8
View File
@@ -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
-31
View File
@@ -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
-80
View File
@@ -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
+1
View File
@@ -244,3 +244,4 @@ foreach {tn sql res} {
}
finish_test
-40
View File
@@ -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
+1 -3
View File
@@ -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';
-2
View File
@@ -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');
File diff suppressed because one or more lines are too long
-61
View File
@@ -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
+1 -18
View File
@@ -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');
-22
View File
@@ -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
+1
View File
@@ -93,3 +93,4 @@ do_catchsql_test 3.3 {
SELECT * FROM x2('^a');
} {1 {fts5: phrase queries are not supported (detail!=full)}}
finish_test
+1 -1
View File
@@ -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
-73
View File
@@ -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
-67
View File
@@ -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
-29
View File
@@ -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
-327
View File
@@ -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
-99
View File
@@ -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
+3 -3
View File
@@ -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
+1 -18
View File
@@ -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
-1
View File
@@ -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;
} {}
-1
View File
@@ -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;
-85
View File
@@ -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
-13
View File
@@ -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
+1 -1
View File
@@ -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 {
-65
View File
@@ -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
+6 -18
View File
@@ -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
-38
View File
@@ -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
+1 -3
View File
@@ -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
+3 -76
View File
@@ -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
+7 -35
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -24,3 +24,4 @@ int sqlite3IcuInit(sqlite3 *db);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
+2 -2
View File
@@ -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 $<
+2
View File
@@ -654,3 +654,5 @@ void test_data_3(
testFree(zName);
}
}
+2
View File
@@ -322,3 +322,5 @@ void do_writer_crash_test(const char *zPattern, int *pRc){
}
}
+3
View File
@@ -138,3 +138,6 @@ void test_data_4(
testFree(zName);
}
}
+4
View File
@@ -69,3 +69,7 @@ int do_bt(int nArg, char **azArg){
sqlite4_buffer_clear(&buf.output);
return 0;
}
+1 -1
View File
@@ -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