Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9e5f5cd21 |
+23
-67
@@ -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,7 +187,7 @@ 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 wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
window.lo utf.lo vtab.lo
|
||||
@@ -356,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
|
||||
@@ -429,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
|
||||
#
|
||||
@@ -459,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
|
||||
#
|
||||
@@ -476,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 \
|
||||
@@ -513,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.
|
||||
#
|
||||
@@ -566,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
|
||||
#
|
||||
@@ -587,8 +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/fuzzdata6.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@@ -605,14 +596,13 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_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_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.
|
||||
@@ -669,28 +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_RTREE \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_EANBLE_FTS5
|
||||
|
||||
dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
|
||||
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
|
||||
-fsanitize=fuzzer,undefined,address -o dbfuzz2 \
|
||||
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
|
||||
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)"
|
||||
@@ -1126,10 +1099,7 @@ 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
|
||||
|
||||
sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
|
||||
|
||||
userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
@@ -1157,7 +1127,7 @@ FTS5_SRC = \
|
||||
$(TOP)/ext/fts5/fts5_varint.c \
|
||||
$(TOP)/ext/fts5/fts5_vocab.c \
|
||||
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
cp $(TOP)/ext/fts5/fts5parse.y .
|
||||
rm -f fts5parse.h
|
||||
./lemon$(BEXE) $(OPTS) fts5parse.y
|
||||
@@ -1184,13 +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_DESERIALIZE
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||
TESTFIXTURE_SRC1 = sqlite3.c
|
||||
@@ -1201,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)
|
||||
@@ -1264,7 +1229,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
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
|
||||
@@ -1293,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)
|
||||
|
||||
@@ -1311,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) -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)
|
||||
|
||||
@@ -1340,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
|
||||
@@ -1368,7 +1324,7 @@ snapshot-tarball: sqlite3.c
|
||||
# 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 \
|
||||
@@ -1382,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
|
||||
@@ -1390,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)
|
||||
@@ -1408,7 +1364,7 @@ tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
|
||||
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
|
||||
|
||||
+1
-21
@@ -345,7 +345,6 @@ 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_INTROSPECTION_PRAGMAS=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -1624,8 +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\fuzzdata6.db
|
||||
# <</mark>>
|
||||
|
||||
# Additional compiler options for the shell. These are only effective
|
||||
@@ -1635,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>>
|
||||
@@ -2298,7 +2295,6 @@ 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_JSON1=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||
@@ -2339,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)
|
||||
@@ -2426,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)
|
||||
@@ -2448,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)
|
||||
|
||||
@@ -283,7 +283,6 @@ 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_INTROSPECTION_PRAGMAS=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -938,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
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.27.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.27.0'
|
||||
PACKAGE_STRING='sqlite 3.27.0'
|
||||
PACKAGE_VERSION='3.26.0'
|
||||
PACKAGE_STRING='sqlite 3.26.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1466,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.27.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]...
|
||||
|
||||
@@ -1531,7 +1531,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.27.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1657,7 +1657,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.27.0
|
||||
sqlite configure 3.26.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2076,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.27.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 $@
|
||||
@@ -12232,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.27.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
|
||||
@@ -12298,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.27.0
|
||||
sqlite config.status 3.26.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -777,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>
|
||||
|
||||
|
||||
@@ -243,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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
+13
-32
@@ -338,7 +338,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
||||
}
|
||||
|
||||
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
|
||||
v = (v & mask1) | ( (*(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++); \
|
||||
@@ -376,21 +376,20 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
** 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;
|
||||
@@ -1822,7 +1821,7 @@ 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 */
|
||||
|
||||
@@ -1860,14 +1859,14 @@ static int fts3ScanInteriorNode(
|
||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
assert( nPrefix>=0 && nSuffix>=0 );
|
||||
if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
|
||||
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;
|
||||
@@ -3847,23 +3846,8 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
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,
|
||||
@@ -3886,7 +3870,6 @@ static const sqlite3_module fts3Module = {
|
||||
/* xSavepoint */ fts3SavepointMethod,
|
||||
/* xRelease */ fts3ReleaseMethod,
|
||||
/* xRollbackTo */ fts3RollbackToMethod,
|
||||
/* xShadowName */ fts3ShadowName,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4167,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
|
||||
@@ -4271,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
|
||||
|
||||
+1
-2
@@ -539,8 +539,7 @@ int sqlite3Fts3InitAux(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
@@ -361,8 +361,7 @@ int sqlite3Fts3InitTerm(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
|
||||
@@ -443,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 */
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef struct unicode_cursor unicode_cursor;
|
||||
|
||||
struct unicode_tokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
int eRemoveDiacritic;
|
||||
int bRemoveDiacritic;
|
||||
int nException;
|
||||
int *aiException;
|
||||
};
|
||||
@@ -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);
|
||||
@@ -353,7 +350,7 @@ static int unicodeNext(
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
|
||||
+26
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** 2012-05-25
|
||||
** 2012 May 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
@@ -159,48 +159,32 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int remove_diacritic(int c, int bComplex){
|
||||
static int remove_diacritic(int c){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
|
||||
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
|
||||
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
|
||||
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
|
||||
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
|
||||
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
|
||||
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
|
||||
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
|
||||
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
|
||||
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
|
||||
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
|
||||
63182, 63242, 63274, 63310, 63368, 63390,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
};
|
||||
#define HIBIT ((unsigned char)0x80)
|
||||
unsigned char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n',
|
||||
'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y',
|
||||
'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
|
||||
'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
|
||||
'e', 'i', 'o', 'r', 'u', 's',
|
||||
't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
|
||||
'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b',
|
||||
'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
|
||||
'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
|
||||
'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
|
||||
'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
|
||||
's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
|
||||
'w', 'x', 'y', 'z', 'h', 't',
|
||||
'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
|
||||
'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
|
||||
'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
@@ -217,8 +201,7 @@ static int remove_diacritic(int c, int bComplex){
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,8 +214,8 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
unsigned int mask1 = 0x000361F8;
|
||||
if( c<768 || c>817 ) return 0;
|
||||
return (c < 768+32) ?
|
||||
(mask0 & ((unsigned int)1 << (c-768))) :
|
||||
(mask1 & ((unsigned int)1 << (c-768-32)));
|
||||
(mask0 & (1 << (c-768))) :
|
||||
(mask1 & (1 << (c-768-32)));
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +228,7 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
|
||||
int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
@@ -368,9 +351,7 @@ int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( eRemoveDiacritic ){
|
||||
ret = remove_diacritic(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
|
||||
+11
-25
@@ -396,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);
|
||||
@@ -409,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;
|
||||
@@ -1375,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->nTermAlloc
|
||||
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;
|
||||
}
|
||||
@@ -1409,7 +1404,7 @@ 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])
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
@@ -1609,11 +1604,7 @@ 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 ){
|
||||
nExtra = nRoot + FTS3_NODE_PADDING;
|
||||
}
|
||||
@@ -1634,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;
|
||||
@@ -3739,9 +3730,6 @@ static int nodeReaderNext(NodeReader *p){
|
||||
}
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
|
||||
|
||||
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
|
||||
@@ -3749,9 +3737,6 @@ 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 SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
p->aDoclist = &p->aNode[p->iOff];
|
||||
p->iOff += p->nDoclist;
|
||||
}
|
||||
@@ -3759,6 +3744,7 @@ static int nodeReaderNext(NodeReader *p){
|
||||
}
|
||||
|
||||
assert( p->iOff<=p->nNode );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -783,7 +774,7 @@ proc print_test_categories {lMap} {
|
||||
aArray[0] = 1;
|
||||
}
|
||||
|
||||
c = sqlite3Fts5UnicodeCategory((u32)i);
|
||||
c = sqlite3Fts5UnicodeCategory(i);
|
||||
if( aArray[c]==0 ){
|
||||
*piCode = i;
|
||||
return 1;
|
||||
@@ -838,7 +829,7 @@ proc print_fold_test {zFunc mappings} {
|
||||
proc print_fileheader {} {
|
||||
puts [string trim {
|
||||
/*
|
||||
** 2012-05-25
|
||||
** 2012 May 25
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
|
||||
@@ -7,24 +7,12 @@
|
||||
# character that it should be replaced with, or an empty string if the
|
||||
# codepoint should simply be removed from the input. Examples:
|
||||
#
|
||||
# { 224 a 0 } (replace codepoint 224 to "a")
|
||||
# { 769 "" 0 } (remove codepoint 769 from input)
|
||||
# { 224 a } (replace codepoint 224 to "a")
|
||||
# { 769 "" } (remove codepoint 769 from input)
|
||||
#
|
||||
# Mappings are only returned for non-upper case codepoints. It is assumed
|
||||
# that the input has already been folded to lower case.
|
||||
#
|
||||
# The third value in the list is always either 0 or 1. 0 if the
|
||||
# UnicodeData.txt file maps the codepoint to a single ASCII character and
|
||||
# a diacritic, or 1 if the mapping is indirect. For example, consider the
|
||||
# two entries:
|
||||
#
|
||||
# 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
|
||||
# 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
|
||||
#
|
||||
# The first codepoint is a direct mapping (as 006F is ASCII and 0323 is a
|
||||
# diacritic). The second is an indirect mapping, as it maps to the
|
||||
# first codepoint plus 0302 (a diacritic).
|
||||
#
|
||||
proc rd_load_unicodedata_text {zName} {
|
||||
global tl_lookup_table
|
||||
|
||||
@@ -65,29 +53,18 @@ proc rd_load_unicodedata_text {zName} {
|
||||
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
|
||||
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
|
||||
|
||||
# Filter out upper-case characters, as they will be mapped to their
|
||||
# lower-case equivalents before this data is used.
|
||||
if {[info exists tl_lookup_table($iCode)]} continue
|
||||
|
||||
# Check if this is an indirect mapping. If so, set bIndirect to true
|
||||
# and change $iAscii to the indirectly mappped ASCII character.
|
||||
set bIndirect 0
|
||||
if {[info exists dia($iDia)] && [info exists mapping($iAscii)]} {
|
||||
set iAscii $mapping($iAscii)
|
||||
set bIndirect 1
|
||||
}
|
||||
|
||||
if { ($iAscii >= 97 && $iAscii <= 122)
|
||||
|| ($iAscii >= 65 && $iAscii <= 90)
|
||||
} {
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]] $bIndirect]
|
||||
set mapping($iCode) $iAscii
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
|
||||
set dia($iDia) 1
|
||||
}
|
||||
}
|
||||
|
||||
foreach d [array names dia] {
|
||||
lappend lRet [list $d "" 0]
|
||||
lappend lRet [list $d ""]
|
||||
}
|
||||
set lRet [lsort -integer -index 0 $lRet]
|
||||
|
||||
|
||||
+6
-6
@@ -414,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>
|
||||
@@ -442,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.
|
||||
|
||||
+1
-1
@@ -788,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.
|
||||
|
||||
@@ -2553,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(
|
||||
|
||||
+36
-52
@@ -690,7 +690,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
pRet = 0;
|
||||
}else{
|
||||
/* TODO1: Fix this */
|
||||
pRet->p[nByte] = 0x00;
|
||||
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
|
||||
}
|
||||
}
|
||||
@@ -730,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;
|
||||
}
|
||||
@@ -772,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);
|
||||
@@ -860,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 */
|
||||
@@ -887,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;
|
||||
@@ -1653,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->nn || nKeep>pIter->term.n ){
|
||||
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;
|
||||
@@ -1724,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);
|
||||
@@ -2313,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;
|
||||
@@ -2326,11 +2318,8 @@ static void fts5LeafSeek(
|
||||
}
|
||||
|
||||
search_success:
|
||||
|
||||
pIter->iLeafOffset = iOff + nNew;
|
||||
if( pIter->iLeafOffset>n ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
pIter->iTermLeafOffset = pIter->iLeafOffset;
|
||||
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
||||
|
||||
@@ -2437,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 */
|
||||
@@ -3585,23 +3574,23 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
|
||||
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
|
||||
int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
|
||||
if( iId<=FTS5_MAX_SEGMENT ){
|
||||
aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
|
||||
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);
|
||||
@@ -3609,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);
|
||||
}
|
||||
@@ -3758,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3912,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 );
|
||||
@@ -3922,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);
|
||||
}
|
||||
@@ -3955,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);
|
||||
}
|
||||
|
||||
@@ -4009,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;
|
||||
@@ -4524,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) ){
|
||||
@@ -4604,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);
|
||||
@@ -5419,7 +5402,7 @@ int sqlite3Fts5IndexQuery(
|
||||
fts5CloseReader(p);
|
||||
}
|
||||
|
||||
*ppIter = (Fts5IndexIter*)pRet;
|
||||
*ppIter = &pRet->base;
|
||||
sqlite3Fts5BufferFree(&buf);
|
||||
}
|
||||
return fts5IndexReturn(p);
|
||||
@@ -5881,7 +5864,7 @@ 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);
|
||||
@@ -6296,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);
|
||||
|
||||
|
||||
+1
-17
@@ -2645,24 +2645,9 @@ static void fts5SourceIdFunc(
|
||||
sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zName is the extension on one of the shadow tables used
|
||||
** by this module.
|
||||
*/
|
||||
static int fts5ShadowName(const char *zName){
|
||||
static const char *azName[] = {
|
||||
"config", "content", "data", "docsize", "idx"
|
||||
};
|
||||
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 int fts5Init(sqlite3 *db){
|
||||
static const sqlite3_module fts5Mod = {
|
||||
/* iVersion */ 3,
|
||||
/* iVersion */ 2,
|
||||
/* xCreate */ fts5CreateMethod,
|
||||
/* xConnect */ fts5ConnectMethod,
|
||||
/* xBestIndex */ fts5BestIndexMethod,
|
||||
@@ -2685,7 +2670,6 @@ static int fts5Init(sqlite3 *db){
|
||||
/* xSavepoint */ fts5SavepointMethod,
|
||||
/* xRelease */ fts5ReleaseMethod,
|
||||
/* xRollbackTo */ fts5RollbackToMethod,
|
||||
/* xShadowName */ fts5ShadowName
|
||||
};
|
||||
|
||||
int rc;
|
||||
|
||||
@@ -136,9 +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;
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
|
||||
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
@@ -588,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;
|
||||
@@ -627,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 ){
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
+11
-19
@@ -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 */
|
||||
@@ -262,7 +257,7 @@ static int fts5UnicodeAddExceptions(
|
||||
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 ){
|
||||
@@ -274,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;
|
||||
@@ -366,7 +361,7 @@ 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_malloc(p->nFold * sizeof(char));
|
||||
if( p->aFold==0 ){
|
||||
@@ -387,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);
|
||||
@@ -429,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)
|
||||
);
|
||||
}
|
||||
@@ -458,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;
|
||||
@@ -509,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;
|
||||
@@ -1284,3 +1274,5 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+34
-47
@@ -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;
|
||||
@@ -769,7 +756,7 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
|
||||
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
|
||||
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
|
||||
for(; i<128 && i<n; i++){
|
||||
aAscii[i] = bToken;
|
||||
aAscii[i] = (u8)bToken;
|
||||
}
|
||||
iTbl++;
|
||||
}
|
||||
|
||||
@@ -431,8 +431,6 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
|
||||
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)
|
||||
){
|
||||
@@ -442,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;
|
||||
@@ -757,9 +755,10 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
};
|
||||
void *p = (void*)pGlobal;
|
||||
|
||||
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ do_execsql_test 1.0 {
|
||||
do_execsql_test 1.1 {
|
||||
DROP TABLE t1;
|
||||
SELECT name, sql FROM sqlite_master;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -408,7 +409,6 @@ do_test 14.3 {
|
||||
do_execsql_test 15.0 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 15.1 {
|
||||
UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1;
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# 2018 Dec 22
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5circref
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE tt USING fts5(a);
|
||||
SELECT name FROM sqlite_master ORDER BY 1;
|
||||
} {
|
||||
tt tt_config tt_content tt_data tt_docsize tt_idx
|
||||
}
|
||||
db_save_and_close
|
||||
|
||||
foreach {tn schema sql} {
|
||||
1 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_config BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(tt, rank) VALUES('usermerge', 4);
|
||||
}
|
||||
|
||||
2 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_docsize BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
3 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_content BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
4 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_data BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
|
||||
5 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON tt_idx BEGIN
|
||||
SELECT * FROM tt;
|
||||
END;
|
||||
} {
|
||||
INSERT INTO tt(a) VALUES('one two three');
|
||||
}
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 1.1.$tn.1 $schema
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
|
||||
db close
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -244,3 +244,4 @@ foreach {tn sql res} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ db_save
|
||||
do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
set segid [lindex [fts5_level_segids t1] 0]
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_test 1.3 {
|
||||
execsql {
|
||||
DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4);
|
||||
@@ -51,7 +50,6 @@ do_test 1.3 {
|
||||
|
||||
do_test 1.4 {
|
||||
db_restore_and_reopen
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
execsql {
|
||||
UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE
|
||||
rowid = fts5_rowid('segment', $segid, 4);
|
||||
@@ -91,7 +89,7 @@ do_execsql_test 3.0 {
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o'
|
||||
} {{one o} {three o} {five o}}
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
DELETE FROM t3_content WHERE rowid = 3;
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o';
|
||||
|
||||
@@ -99,7 +99,6 @@ foreach {tno stmt} {
|
||||
set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}]
|
||||
set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}]
|
||||
set all [db eval {SELECT rowid FROM t1}]
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
|
||||
do_execsql_test 2.$i.1 {
|
||||
BEGIN;
|
||||
@@ -249,7 +248,6 @@ foreach {tn hdr} {
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
reset_db
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 6.1 {
|
||||
CREATE VIRTUAL TABLE x5 USING fts5(tt);
|
||||
INSERT INTO x5 VALUES('a');
|
||||
|
||||
+4
-2122
File diff suppressed because it is too large
Load Diff
@@ -93,3 +93,4 @@ do_catchsql_test 3.3 {
|
||||
SELECT * FROM x2('^a');
|
||||
} {1 {fts5: phrase queries are not supported (detail!=full)}}
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ do_execsql_test 4.1 {
|
||||
INSERT INTO aa(aa) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_catchsql_test 4.2 {
|
||||
BEGIN;
|
||||
UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -163,3 +163,4 @@ do_execsql_test 5.1 {
|
||||
} {30 31 32 33 34 35 36 37 38 39 40}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ do_execsql_test 1.4 {
|
||||
INSERT INTO f1(f1) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 1.5 {
|
||||
DELETE FROM f1_data;
|
||||
} {}
|
||||
|
||||
@@ -70,7 +70,6 @@ set res [db one {SELECT count(*) FROM x1_data}]
|
||||
do_execsql_test 2.3 {
|
||||
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
|
||||
} $res
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 2.4 {
|
||||
UPDATE x1_data SET block = X'';
|
||||
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
|
||||
|
||||
@@ -189,7 +189,7 @@ do_catchsql_test 6.2 {
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.3 {
|
||||
CREATE VIRTUAL TABLE a3 USING fts5(
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 3'
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 2'
|
||||
);
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.4 {
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# 2014 June 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5umlaut
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(
|
||||
x,
|
||||
tokenize="unicode61 remove_diacritics 2"
|
||||
);
|
||||
}
|
||||
|
||||
foreach {tn q res1 res2} {
|
||||
1 "Hà Nội" 0 1
|
||||
2 "Hà Noi" 1 1
|
||||
3 "Ha Noi" 1 1
|
||||
4 "Ha N\u1ed9i" 0 1
|
||||
5 "Ha N\u006fi" 1 1
|
||||
6 "Ha N\u006f\u0302i" 1 1
|
||||
7 "Ha N\u006f\u0323\u0302i" 1 1
|
||||
} {
|
||||
do_execsql_test 1.$tn.1 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t1($q)
|
||||
} $res1
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t1('Ha Noi')
|
||||
} $res1
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t2($q)
|
||||
} $res2
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t2('Ha Noi')
|
||||
} $res2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -21,7 +21,7 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
proc fts3_unicode_path {file} {
|
||||
file join .. [file dirname [info script]] .. .. fts3 unicode $file
|
||||
file join [file dirname [info script]] .. .. fts3 unicode $file
|
||||
}
|
||||
|
||||
source [fts3_unicode_path parseunicode.tcl]
|
||||
@@ -36,26 +36,24 @@ foreach x [an_load_unicodedata_text $UD] {
|
||||
}
|
||||
|
||||
foreach {y} [rd_load_unicodedata_text $UD] {
|
||||
foreach {code ascii f} $y {}
|
||||
foreach {code ascii} $y {}
|
||||
if {$ascii==""} {
|
||||
set int 0
|
||||
} else {
|
||||
binary scan $ascii c int
|
||||
}
|
||||
set aDiacritic($code,$f) $int
|
||||
if {$f==0} { set aDiacritic($code,1) $int }
|
||||
set aDiacritic($code) $int
|
||||
}
|
||||
|
||||
proc tcl_fold {i {bRemoveDiacritic 0}} {
|
||||
global tl_lookup_table
|
||||
global aDiacritic
|
||||
set f [expr $bRemoveDiacritic==2]
|
||||
|
||||
if {[info exists tl_lookup_table($i)]} {
|
||||
set i $tl_lookup_table($i)
|
||||
}
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i,$f)]} {
|
||||
set i $aDiacritic($i,$f)
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i)]} {
|
||||
set i $aDiacritic($i)
|
||||
}
|
||||
expr $i
|
||||
}
|
||||
@@ -87,7 +85,7 @@ do_execsql_test 1.1 {
|
||||
SELECT count(*), min(i) FROM ii WHERE fts5_fold(i)!=CAST(tcl_fold(i) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2.1 {
|
||||
do_execsql_test 1.2 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
@@ -97,16 +95,6 @@ do_execsql_test 1.2.1 {
|
||||
WHERE fts5_fold(i,1)!=CAST(tcl_fold(i,1) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2.2 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
SELECT i+1 FROM ii WHERE i<100000
|
||||
)
|
||||
SELECT count(*), min(i) FROM ii
|
||||
WHERE fts5_fold(i,2)!=CAST(tcl_fold(i,2) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
|
||||
@@ -36,10 +36,9 @@ do_execsql_test 1.3 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'a';
|
||||
} {1}
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 1.4 {
|
||||
UPDATE t1_config set v=5 WHERE k='version';
|
||||
}
|
||||
}
|
||||
|
||||
do_test 1.5 {
|
||||
db close
|
||||
@@ -54,7 +53,6 @@ do_test 1.6 {
|
||||
} {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}}
|
||||
|
||||
do_test 1.7 {
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
execsql { DELETE FROM t1_config WHERE k='version' }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
@@ -79,8 +79,8 @@ do_execsql_test 1.1.2 {
|
||||
3 cnt {} 0 {} 0
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.1 { SELECT * FROM v1 } {}
|
||||
do_execsql_test 1.2.2 { SELECT * FROM v2 } {}
|
||||
do_execsql_test 1.2.1 { SELECT * FROM v1 } { }
|
||||
do_execsql_test 1.2.2 { SELECT * FROM v2 } { }
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
INSERT INTO t1 VALUES('x y z');
|
||||
@@ -420,7 +420,6 @@ if {[detail_is_none]} { set resc [row_to_col $resr] }
|
||||
do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr
|
||||
do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc
|
||||
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 8.2 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master
|
||||
@@ -482,3 +481,4 @@ do_test 9.6 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5vocab2
|
||||
set testprefix fts5vocab
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
@@ -80,7 +80,8 @@ do_execsql_test 1.4 {
|
||||
do_execsql_test 1.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -142,7 +143,8 @@ do_execsql_test 2.4 {
|
||||
do_execsql_test 2.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -200,6 +202,8 @@ do_execsql_test 3.4 {
|
||||
do_execsql_test 3.5 {
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} {}
|
||||
} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+1
-2
@@ -1473,8 +1473,7 @@ static sqlite3_module amatchModule = {
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -411,7 +411,6 @@ int sqlite3BinfoRegister(sqlite3 *db){
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
};
|
||||
return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0);
|
||||
}
|
||||
|
||||
+1
-2
@@ -938,8 +938,7 @@ static sqlite3_module closureModule = {
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -468,8 +468,7 @@ static sqlite3_module completionModule = {
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
+35
-96
@@ -19,9 +19,9 @@
|
||||
** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME);
|
||||
** SELECT * FROM csv;
|
||||
**
|
||||
** The columns are named "c1", "c2", "c3", ... by default. Or the
|
||||
** application can define its own CREATE TABLE statement using the
|
||||
** schema= parameter, like this:
|
||||
** The columns are named "c1", "c2", "c3", ... by default. But the
|
||||
** application can define its own CREATE TABLE statement as an additional
|
||||
** parameter. For example:
|
||||
**
|
||||
** CREATE VIRTUAL TABLE temp.csv2 USING csv(
|
||||
** filename = "../http.log",
|
||||
@@ -32,9 +32,9 @@
|
||||
** the data= parameter.
|
||||
**
|
||||
** If the columns=N parameter is supplied, then the CSV file is assumed to have
|
||||
** N columns. If both the columns= and schema= parameters are omitted, then
|
||||
** the number and names of the columns is determined by the first line of
|
||||
** the CSV input.
|
||||
** N columns. If the columns parameter is omitted, the CSV file is opened
|
||||
** as soon as the virtual table is constructed and the first row of the CSV
|
||||
** is read in order to count the tables.
|
||||
**
|
||||
** Some extra debugging features (used for testing virtual tables) are available
|
||||
** if this module is compiled with -DSQLITE_TEST.
|
||||
@@ -436,34 +436,6 @@ static int csv_boolean(const char *z){
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check to see if the string is of the form: "TAG = BOOLEAN" or just "TAG".
|
||||
** If it is, set *pValue to be the value of the boolean ("true" if there is
|
||||
** not "= BOOLEAN" component) and return non-zero. If the input string
|
||||
** does not begin with TAG, return zero.
|
||||
*/
|
||||
static int csv_boolean_parameter(
|
||||
const char *zTag, /* Tag we are looking for */
|
||||
int nTag, /* Size of the tag in bytes */
|
||||
const char *z, /* Input parameter */
|
||||
int *pValue /* Write boolean value here */
|
||||
){
|
||||
int b;
|
||||
z = csv_skip_whitespace(z);
|
||||
if( strncmp(zTag, z, nTag)!=0 ) return 0;
|
||||
z = csv_skip_whitespace(z + nTag);
|
||||
if( z[0]==0 ){
|
||||
*pValue = 1;
|
||||
return 1;
|
||||
}
|
||||
if( z[0]!='=' ) return 0;
|
||||
z = csv_skip_whitespace(z+1);
|
||||
b = csv_boolean(z);
|
||||
if( b>=0 ){
|
||||
*pValue = b;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameters:
|
||||
@@ -497,7 +469,6 @@ static int csvtabConnect(
|
||||
#ifdef SQLITE_TEST
|
||||
int tstFlags = 0; /* Value for testflags=N parameter */
|
||||
#endif
|
||||
int b; /* Value of a boolean parameter */
|
||||
int nCol = -99; /* Value of the columns= parameter */
|
||||
CsvReader sRdr; /* A CSV file reader used to store an error
|
||||
** message and/or to count the number of columns */
|
||||
@@ -522,12 +493,21 @@ static int csvtabConnect(
|
||||
if( j<sizeof(azParam)/sizeof(azParam[0]) ){
|
||||
if( sRdr.zErr[0] ) goto csvtab_connect_error;
|
||||
}else
|
||||
if( csv_boolean_parameter("header",6,z,&b) ){
|
||||
if( (zValue = csv_parameter("header",6,z))!=0 ){
|
||||
int x;
|
||||
if( bHeader>=0 ){
|
||||
csv_errmsg(&sRdr, "more than one 'header' parameter");
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
bHeader = b;
|
||||
x = csv_boolean(zValue);
|
||||
if( x==1 ){
|
||||
bHeader = 1;
|
||||
}else if( x==0 ){
|
||||
bHeader = 0;
|
||||
}else{
|
||||
csv_errmsg(&sRdr, "unrecognized argument to 'header': %s", zValue);
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
}else
|
||||
#ifdef SQLITE_TEST
|
||||
if( (zValue = csv_parameter("testflags",9,z))!=0 ){
|
||||
@@ -541,94 +521,53 @@ static int csvtabConnect(
|
||||
}
|
||||
nCol = atoi(zValue);
|
||||
if( nCol<=0 ){
|
||||
csv_errmsg(&sRdr, "column= value must be positive");
|
||||
csv_errmsg(&sRdr, "must have at least one column");
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
}else
|
||||
{
|
||||
csv_errmsg(&sRdr, "bad parameter: '%s'", z);
|
||||
csv_errmsg(&sRdr, "unrecognized parameter '%s'", z);
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
}
|
||||
if( (CSV_FILENAME==0)==(CSV_DATA==0) ){
|
||||
csv_errmsg(&sRdr, "must specify either filename= or data= but not both");
|
||||
csv_errmsg(&sRdr, "must either filename= or data= but not both");
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
|
||||
if( (nCol<=0 || bHeader==1)
|
||||
&& csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA)
|
||||
){
|
||||
if( nCol<=0 && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) ){
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) goto csvtab_connect_oom;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
if( CSV_SCHEMA==0 ){
|
||||
sqlite3_str *pStr = sqlite3_str_new(0);
|
||||
char *zSep = "";
|
||||
int iCol = 0;
|
||||
sqlite3_str_appendf(pStr, "CREATE TABLE x(");
|
||||
if( nCol<0 && bHeader<1 ){
|
||||
nCol = 0;
|
||||
do{
|
||||
csv_read_one_field(&sRdr);
|
||||
nCol++;
|
||||
}while( sRdr.cTerm==',' );
|
||||
}
|
||||
if( nCol>0 && bHeader<1 ){
|
||||
for(iCol=0; iCol<nCol; iCol++){
|
||||
sqlite3_str_appendf(pStr, "%sc%d TEXT", zSep, iCol);
|
||||
zSep = ",";
|
||||
}
|
||||
}else{
|
||||
do{
|
||||
char *z = csv_read_one_field(&sRdr);
|
||||
if( (nCol>0 && iCol<nCol) || (nCol<0 && bHeader) ){
|
||||
sqlite3_str_appendf(pStr,"%s\"%w\" TEXT", zSep, z);
|
||||
zSep = ",";
|
||||
iCol++;
|
||||
}
|
||||
}while( sRdr.cTerm==',' );
|
||||
if( nCol<0 ){
|
||||
nCol = iCol;
|
||||
}else{
|
||||
while( iCol<nCol ){
|
||||
sqlite3_str_appendf(pStr,"%sc%d TEXT", zSep, ++iCol);
|
||||
zSep = ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
if( nCol>0 ){
|
||||
pNew->nCol = nCol;
|
||||
sqlite3_str_appendf(pStr, ")");
|
||||
CSV_SCHEMA = sqlite3_str_finish(pStr);
|
||||
if( CSV_SCHEMA==0 ) goto csvtab_connect_oom;
|
||||
}else if( nCol<0 ){
|
||||
}else{
|
||||
do{
|
||||
csv_read_one_field(&sRdr);
|
||||
pNew->nCol++;
|
||||
}while( sRdr.cTerm==',' );
|
||||
}else{
|
||||
pNew->nCol = nCol;
|
||||
}
|
||||
pNew->zFilename = CSV_FILENAME; CSV_FILENAME = 0;
|
||||
pNew->zData = CSV_DATA; CSV_DATA = 0;
|
||||
#ifdef SQLITE_TEST
|
||||
pNew->tstFlags = tstFlags;
|
||||
#endif
|
||||
if( bHeader!=1 ){
|
||||
pNew->iStart = 0;
|
||||
}else if( pNew->zData ){
|
||||
pNew->iStart = (int)sRdr.iIn;
|
||||
}else{
|
||||
pNew->iStart = (int)(ftell(sRdr.in) - sRdr.nIn + sRdr.iIn);
|
||||
}
|
||||
pNew->iStart = bHeader==1 ? ftell(sRdr.in) : 0;
|
||||
csv_reader_reset(&sRdr);
|
||||
rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
|
||||
if( rc ){
|
||||
csv_errmsg(&sRdr, "bad schema: '%s' - %s", CSV_SCHEMA, sqlite3_errmsg(db));
|
||||
goto csvtab_connect_error;
|
||||
if( CSV_SCHEMA==0 ){
|
||||
char *zSep = "";
|
||||
CSV_SCHEMA = sqlite3_mprintf("CREATE TABLE x(");
|
||||
if( CSV_SCHEMA==0 ) goto csvtab_connect_oom;
|
||||
for(i=0; i<pNew->nCol; i++){
|
||||
CSV_SCHEMA = sqlite3_mprintf("%z%sc%d TEXT",CSV_SCHEMA, zSep, i);
|
||||
zSep = ",";
|
||||
}
|
||||
CSV_SCHEMA = sqlite3_mprintf("%z);", CSV_SCHEMA);
|
||||
}
|
||||
rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
|
||||
if( rc ) goto csvtab_connect_error;
|
||||
for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){
|
||||
sqlite3_free(azPValue[i]);
|
||||
}
|
||||
|
||||
+11
-24
@@ -18,10 +18,6 @@
|
||||
** .load ./explain
|
||||
** SELECT p2 FROM explain('SELECT * FROM sqlite_master')
|
||||
** WHERE opcode='OpenRead';
|
||||
**
|
||||
** This module was originally written to help simplify SQLite testing,
|
||||
** by providing an easier means of verifying certain patterns in the
|
||||
** generated bytecode.
|
||||
*/
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
@@ -236,31 +232,23 @@ static int explainBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i; /* Loop counter */
|
||||
int idx = -1; /* Index of a usable == constraint against SQL */
|
||||
int unusable = 0; /* True if there are unusable constraints on SQL */
|
||||
int i;
|
||||
|
||||
pIdxInfo->estimatedCost = (double)1000000;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
|
||||
if( p->iColumn!=EXPLN_COLUMN_SQL ) continue;
|
||||
if( !p->usable ){
|
||||
unusable = 1;
|
||||
}else if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
idx = i;
|
||||
if( p->usable
|
||||
&& p->iColumn==EXPLN_COLUMN_SQL
|
||||
&& p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
pIdxInfo->estimatedCost = 10.0;
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( idx>=0 ){
|
||||
/* There exists a usable == constraint against the SQL column */
|
||||
pIdxInfo->estimatedCost = 10.0;
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[idx].omit = 1;
|
||||
}else if( unusable ){
|
||||
/* There are unusable constraints against the SQL column. Do not allow
|
||||
** this plan to continue forward. */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -292,7 +280,6 @@ static sqlite3_module explainModule = {
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
+22
-66
@@ -106,18 +106,7 @@ SQLITE_EXTENSION_INIT1
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
** Structure of the fsdir() table-valued function
|
||||
*/
|
||||
/* 0 1 2 3 4 5 */
|
||||
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
|
||||
#define FSDIR_COLUMN_NAME 0 /* Name of the file */
|
||||
#define FSDIR_COLUMN_MODE 1 /* Access mode */
|
||||
#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
|
||||
#define FSDIR_COLUMN_DATA 3 /* File content */
|
||||
#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
|
||||
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
|
||||
|
||||
|
||||
/*
|
||||
** Set the result stored by context ctx to a blob containing the
|
||||
@@ -706,20 +695,20 @@ static int fsdirColumn(
|
||||
){
|
||||
fsdir_cursor *pCur = (fsdir_cursor*)cur;
|
||||
switch( i ){
|
||||
case FSDIR_COLUMN_NAME: {
|
||||
case 0: { /* name */
|
||||
sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
|
||||
case FSDIR_COLUMN_MODE:
|
||||
case 1: /* mode */
|
||||
sqlite3_result_int64(ctx, pCur->sStat.st_mode);
|
||||
break;
|
||||
|
||||
case FSDIR_COLUMN_MTIME:
|
||||
case 2: /* mtime */
|
||||
sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
|
||||
break;
|
||||
|
||||
case FSDIR_COLUMN_DATA: {
|
||||
case 3: { /* data */
|
||||
mode_t m = pCur->sStat.st_mode;
|
||||
if( S_ISDIR(m) ){
|
||||
sqlite3_result_null(ctx);
|
||||
@@ -749,12 +738,6 @@ static int fsdirColumn(
|
||||
readFileContents(ctx, pCur->zPath);
|
||||
}
|
||||
}
|
||||
case FSDIR_COLUMN_PATH:
|
||||
default: {
|
||||
/* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
|
||||
** always return their values as NULL */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -781,9 +764,6 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
|
||||
|
||||
/*
|
||||
** xFilter callback.
|
||||
**
|
||||
** idxNum==1 PATH parameter only
|
||||
** idxNum==2 Both PATH and DIR supplied
|
||||
*/
|
||||
static int fsdirFilter(
|
||||
sqlite3_vtab_cursor *cur,
|
||||
@@ -836,63 +816,40 @@ static int fsdirFilter(
|
||||
** In this implementation idxNum is used to represent the
|
||||
** query plan. idxStr is unused.
|
||||
**
|
||||
** The query plan is represented by values of idxNum:
|
||||
** The query plan is represented by bits in idxNum:
|
||||
**
|
||||
** (1) The path value is supplied by argv[0]
|
||||
** (2) Path is in argv[0] and dir is in argv[1]
|
||||
** (1) start = $value -- constraint exists
|
||||
** (2) stop = $value -- constraint exists
|
||||
** (4) step = $value -- constraint exists
|
||||
** (8) output in descending order
|
||||
*/
|
||||
static int fsdirBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i; /* Loop over constraints */
|
||||
int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
|
||||
int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
|
||||
int seenPath = 0; /* True if an unusable PATH= constraint is seen */
|
||||
int seenDir = 0; /* True if an unusable DIR= constraint is seen */
|
||||
int idx4 = -1;
|
||||
int idx5 = -1;
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
(void)tab;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
switch( pConstraint->iColumn ){
|
||||
case FSDIR_COLUMN_PATH: {
|
||||
if( pConstraint->usable ){
|
||||
idxPath = i;
|
||||
seenPath = 0;
|
||||
}else if( idxPath<0 ){
|
||||
seenPath = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSDIR_COLUMN_DIR: {
|
||||
if( pConstraint->usable ){
|
||||
idxDir = i;
|
||||
seenDir = 0;
|
||||
}else if( idxDir<0 ){
|
||||
seenDir = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( seenPath || seenDir ){
|
||||
/* If input parameters are unusable, disallow this plan */
|
||||
return SQLITE_CONSTRAINT;
|
||||
if( pConstraint->iColumn==4 ) idx4 = i;
|
||||
if( pConstraint->iColumn==5 ) idx5 = i;
|
||||
}
|
||||
|
||||
if( idxPath<0 ){
|
||||
if( idx4<0 ){
|
||||
pIdxInfo->idxNum = 0;
|
||||
/* The pIdxInfo->estimatedCost should have been initialized to a huge
|
||||
** number. Leave it unchanged. */
|
||||
pIdxInfo->estimatedRows = 0x7fffffff;
|
||||
pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
|
||||
}else{
|
||||
pIdxInfo->aConstraintUsage[idxPath].omit = 1;
|
||||
pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
|
||||
if( idxDir>=0 ){
|
||||
pIdxInfo->aConstraintUsage[idxDir].omit = 1;
|
||||
pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[idx4].omit = 1;
|
||||
pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
|
||||
if( idx5>=0 ){
|
||||
pIdxInfo->aConstraintUsage[idx5].omit = 1;
|
||||
pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
|
||||
pIdxInfo->idxNum = 2;
|
||||
pIdxInfo->estimatedCost = 10.0;
|
||||
}else{
|
||||
@@ -931,8 +888,7 @@ static int fsdirRegister(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
|
||||
|
||||
+20
-44
@@ -1994,9 +1994,6 @@ static int jsonEachConnect(
|
||||
#define JEACH_PARENT 5
|
||||
#define JEACH_FULLKEY 6
|
||||
#define JEACH_PATH 7
|
||||
/* The xBestIndex method assumes that the JSON and ROOT columns are
|
||||
** the last two columns in the table. Should this ever changes, be
|
||||
** sure to update the xBestIndex method. */
|
||||
#define JEACH_JSON 8
|
||||
#define JEACH_ROOT 9
|
||||
|
||||
@@ -2254,54 +2251,35 @@ static int jsonEachBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i; /* Loop counter or computed array index */
|
||||
int aIdx[2]; /* Index of constraints for JSON and ROOT */
|
||||
int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */
|
||||
int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */
|
||||
int i;
|
||||
int jsonIdx = -1;
|
||||
int rootIdx = -1;
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
/* This implementation assumes that JSON and ROOT are the last two
|
||||
** columns in the table */
|
||||
assert( JEACH_ROOT == JEACH_JSON+1 );
|
||||
UNUSED_PARAM(tab);
|
||||
aIdx[0] = aIdx[1] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
int iCol;
|
||||
int iMask;
|
||||
if( pConstraint->iColumn < JEACH_JSON ) continue;
|
||||
iCol = pConstraint->iColumn - JEACH_JSON;
|
||||
assert( iCol==0 || iCol==1 );
|
||||
iMask = 1 << iCol;
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
aIdx[iCol] = i;
|
||||
idxMask |= iMask;
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
switch( pConstraint->iColumn ){
|
||||
case JEACH_JSON: jsonIdx = i; break;
|
||||
case JEACH_ROOT: rootIdx = i; break;
|
||||
default: /* no-op */ break;
|
||||
}
|
||||
}
|
||||
if( (unusableMask & ~idxMask)!=0 ){
|
||||
/* If there are any unusable constraints on JSON or ROOT, then reject
|
||||
** this entire plan */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
if( aIdx[0]<0 ){
|
||||
/* No JSON input. Leave estimatedCost at the huge value that it was
|
||||
** initialized to to discourage the query planner from selecting this
|
||||
** plan. */
|
||||
if( jsonIdx<0 ){
|
||||
pIdxInfo->idxNum = 0;
|
||||
pIdxInfo->estimatedCost = 1e99;
|
||||
}else{
|
||||
pIdxInfo->estimatedCost = 1.0;
|
||||
i = aIdx[0];
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
if( aIdx[1]<0 ){
|
||||
pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */
|
||||
pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
|
||||
if( rootIdx<0 ){
|
||||
pIdxInfo->idxNum = 1;
|
||||
}else{
|
||||
i = aIdx[1];
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */
|
||||
pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
|
||||
pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
|
||||
pIdxInfo->idxNum = 3;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
@@ -2410,8 +2388,7 @@ static sqlite3_module jsonEachModule = {
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
/* The methods of the json_tree virtual table. */
|
||||
@@ -2438,8 +2415,7 @@ static sqlite3_module jsonTreeModule = {
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
|
||||
+1
-2
@@ -235,7 +235,7 @@ static int memstatNext(sqlite3_vtab_cursor *cur){
|
||||
assert( pCur->iRowid<=MSV_NROW );
|
||||
while(1){
|
||||
i = (int)pCur->iRowid - 1;
|
||||
if( i<0 || (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
|
||||
if( (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
|
||||
pCur->iRowid++;
|
||||
if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
|
||||
pCur->iDb = 0;
|
||||
@@ -395,7 +395,6 @@ static sqlite3_module memstatModule = {
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
+31
-31
@@ -313,45 +313,44 @@ static int seriesBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i, j; /* Loop over constraints */
|
||||
int i; /* Loop over constraints */
|
||||
int idxNum = 0; /* The query plan bitmask */
|
||||
int unusableMask = 0; /* Mask of unusable constraints */
|
||||
int startIdx = -1; /* Index of the start= constraint, or -1 if none */
|
||||
int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */
|
||||
int stepIdx = -1; /* Index of the step= constraint, or -1 if none */
|
||||
int nArg = 0; /* Number of arguments that seriesFilter() expects */
|
||||
int aIdx[3]; /* Constraints on start, stop, and step */
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
|
||||
/* This implementation assumes that the start, stop, and step columns
|
||||
** are the last three columns in the virtual table. */
|
||||
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
|
||||
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = -1;
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
int iCol; /* 0 for start, 1 for stop, 2 for step */
|
||||
int iMask; /* bitmask for those column */
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
|
||||
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
|
||||
assert( iCol>=0 && iCol<=2 );
|
||||
iMask = 1 << iCol;
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
continue;
|
||||
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
idxNum |= iMask;
|
||||
aIdx[iCol] = i;
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
switch( pConstraint->iColumn ){
|
||||
case SERIES_COLUMN_START:
|
||||
startIdx = i;
|
||||
idxNum |= 1;
|
||||
break;
|
||||
case SERIES_COLUMN_STOP:
|
||||
stopIdx = i;
|
||||
idxNum |= 2;
|
||||
break;
|
||||
case SERIES_COLUMN_STEP:
|
||||
stepIdx = i;
|
||||
idxNum |= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i=0; i<3; i++){
|
||||
if( (j = aIdx[i])>=0 ){
|
||||
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
}
|
||||
if( startIdx>=0 ){
|
||||
pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
}
|
||||
if( (unusableMask & ~idxNum)!=0 ){
|
||||
/* The start, stop, and step columns are inputs. Therefore if there
|
||||
** are unusable constraints on any of start, stop, or step then
|
||||
** this plan is unusable */
|
||||
return SQLITE_CONSTRAINT;
|
||||
if( stopIdx>=0 ){
|
||||
pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
}
|
||||
if( stepIdx>=0 ){
|
||||
pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
|
||||
pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
}
|
||||
if( (idxNum & 3)==3 ){
|
||||
/* Both start= and stop= boundaries are available. This is the
|
||||
@@ -366,6 +365,7 @@ static int seriesBestIndex(
|
||||
/* If either boundary is missing, we have to generate a huge span
|
||||
** of numbers. Make this case very expensive so that the query
|
||||
** planner will work hard to avoid it. */
|
||||
pIdxInfo->estimatedCost = (double)2147483647;
|
||||
pIdxInfo->estimatedRows = 2147483647;
|
||||
}
|
||||
pIdxInfo->idxNum = idxNum;
|
||||
|
||||
@@ -266,7 +266,6 @@ static sqlite3_module stmtModule = {
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -248,8 +248,7 @@ static sqlite3_module templatevtabModule = {
|
||||
/* xRename */ 0,
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
/* xRollbackTo */ 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1350,8 +1350,7 @@ static int createUnionVtab(sqlite3 *db){
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0 /* xShadowName */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
int rc;
|
||||
|
||||
|
||||
@@ -492,7 +492,6 @@ static sqlite3_module vtablogModule = {
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
+11
-12
@@ -1296,26 +1296,25 @@ static int zipfileBestIndex(
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i;
|
||||
int idx = -1;
|
||||
int unusable = 0;
|
||||
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
|
||||
if( pCons->usable==0 ) continue;
|
||||
if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
|
||||
if( pCons->usable==0 ){
|
||||
unusable = 1;
|
||||
}else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
idx = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( idx>=0 ){
|
||||
pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[idx].omit = 1;
|
||||
|
||||
if( i<pIdxInfo->nConstraint ){
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
pIdxInfo->estimatedCost = 1000.0;
|
||||
pIdxInfo->idxNum = 1;
|
||||
}else if( unusable ){
|
||||
return SQLITE_CONSTRAINT;
|
||||
}else{
|
||||
pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
|
||||
pIdxInfo->idxNum = 0;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -670,3 +670,4 @@ foreach {tn3 create_vfs destroy_vfs} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -185,3 +185,4 @@ do_test 4.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -195,3 +195,4 @@ do_test 4.7.2 {
|
||||
} {1 {SQLITE_ERROR - rbu_state mismatch error}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -232,3 +232,4 @@ do_multiclient_test tn {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -62,3 +62,4 @@ do_execsql_test 1.4 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -92,3 +92,4 @@ foreach {tn schema} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -203,3 +203,5 @@ do_test 5.3 {
|
||||
do_test 6.1 { sqlite3rbu_internal_test } {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -300,3 +300,7 @@ foreach {tn idx} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -100,3 +100,4 @@ for {set nStep 8} {$nStep < 20} {incr nStep} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -106,3 +106,5 @@ foreach {tn tbl} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -72,3 +72,4 @@ integrity_check 1.3.3
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -125,3 +125,4 @@ foreach {tn idx} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -80,3 +80,4 @@ do_test 2.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -59,3 +59,4 @@ sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -139,3 +139,4 @@ foreach {tn schema} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -86,13 +86,12 @@ proc step_rbu_legacy {target rbu} {
|
||||
set rc
|
||||
}
|
||||
|
||||
proc do_rbu_vacuum_test {tn step {statedb state.db}} {
|
||||
forcedelete $statedb
|
||||
if {$statedb=="" && $step==1} breakpoint
|
||||
uplevel [list do_test $tn.1 [string map [list %state% $statedb] {
|
||||
if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
|
||||
proc do_rbu_vacuum_test {tn step} {
|
||||
forcedelete state.db
|
||||
uplevel [list do_test $tn.1 {
|
||||
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
|
||||
while 1 {
|
||||
if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
|
||||
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
|
||||
set state [rbu state]
|
||||
check_prestep_state test.db $state
|
||||
set rc [rbu step]
|
||||
@@ -101,7 +100,7 @@ proc do_rbu_vacuum_test {tn step {statedb state.db}} {
|
||||
if {$step==1} { rbu close }
|
||||
}
|
||||
rbu close
|
||||
}] {SQLITE_DONE}]
|
||||
} {SQLITE_DONE}]
|
||||
|
||||
uplevel [list do_execsql_test $tn.2 {
|
||||
PRAGMA integrity_check
|
||||
|
||||
@@ -60,3 +60,4 @@ do_test 1.2 {
|
||||
|
||||
#forcedelete testrbu.db
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -145,3 +145,4 @@ for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -103,3 +103,4 @@ for {set x 1} {$x < 2} {incr x} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -300,3 +300,4 @@ tablE t1 USING FTs5(c);
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -56,3 +56,4 @@ do_execsql_test 1.4 {
|
||||
} [list 1 $bigA 2 $bigB]
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -234,3 +234,4 @@ foreach {tn2 setup sql expect} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,3 +55,4 @@ do_faultsim_test 1 -faults oom* -prep {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -95,3 +95,4 @@ foreach {fault errlist} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -63,3 +63,4 @@ for {set tn 1} {1} {incr tn} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -131,3 +131,4 @@ do_test 3.3 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -172,3 +172,4 @@ for {set i 0} {$i<=3} {incr i} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -416,3 +416,4 @@ foreach {bReopen} { 0 1 } {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -251,3 +251,4 @@ for {set n 1} {$n < 5000} {incr n} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -102,3 +102,4 @@ do_execsql_test 1.5 {
|
||||
} {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -92,3 +92,4 @@ foreach {tn cmd} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -126,3 +126,4 @@ do_test 1.6.1 {
|
||||
do_test 1.6.2 { info commands rbu } {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -397,3 +397,4 @@ do_test 3.5 {
|
||||
|
||||
catch { db close }
|
||||
finish_test
|
||||
|
||||
|
||||
+10
-18
@@ -16,11 +16,8 @@
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
|
||||
foreach {step} {0 1} {
|
||||
foreach {ttt state} {
|
||||
s state.db t test.db-vacuum n {}
|
||||
} {
|
||||
set ::testprefix rbuvacuum2-$step$ttt
|
||||
foreach step {0 1} {
|
||||
set ::testprefix rbuvacuum2-$step
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a database that contains fts3 tables can be vacuumed.
|
||||
@@ -32,7 +29,7 @@ foreach {ttt state} {
|
||||
INSERT INTO t1 VALUES('fix this issue', 'at some point');
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 1.2 $step $state
|
||||
do_rbu_vacuum_test 1.2 $step
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT * FROM t1;
|
||||
@@ -49,7 +46,7 @@ foreach {ttt state} {
|
||||
INSERT INTO t1 VALUES('a b c', 'x y z');
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 1.6 $step $state
|
||||
do_rbu_vacuum_test 1.6 $step
|
||||
do_execsql_test 1.7 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
SELECT * FROM t1;
|
||||
@@ -70,7 +67,7 @@ foreach {ttt state} {
|
||||
INSERT INTO t1 VALUES('fix this issue', 'at some point');
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 2.2 $step $state
|
||||
do_rbu_vacuum_test 2.2 $step
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT * FROM t1;
|
||||
@@ -87,7 +84,7 @@ foreach {ttt state} {
|
||||
INSERT INTO t1 VALUES('a b c', 'x y z');
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 2.6 $step $state
|
||||
do_rbu_vacuum_test 2.6 $step
|
||||
do_execsql_test 2.7 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
SELECT * FROM t1;
|
||||
@@ -110,7 +107,7 @@ foreach {ttt state} {
|
||||
INSERT INTO rt VALUES(3, 55, 65);
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 3.2 $step $state
|
||||
do_rbu_vacuum_test 3.2 $step
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM rt;
|
||||
@@ -123,7 +120,7 @@ foreach {ttt state} {
|
||||
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
|
||||
} {2 3}
|
||||
|
||||
do_rbu_vacuum_test 3.5 $step $state
|
||||
do_rbu_vacuum_test 3.5 $step
|
||||
|
||||
do_execsql_test 3.6.1 {
|
||||
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
|
||||
@@ -150,7 +147,7 @@ foreach {ttt state} {
|
||||
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
|
||||
}
|
||||
|
||||
do_rbu_vacuum_test 4.3 $step $state
|
||||
do_rbu_vacuum_test 4.3 $step
|
||||
do_execsql_test 4.4 {
|
||||
SELECT * FROM sqlite_master;
|
||||
} {
|
||||
@@ -160,7 +157,6 @@ foreach {ttt state} {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that passing a NULL value as the second argument to
|
||||
@@ -235,9 +231,5 @@ do_test 6.3 {
|
||||
execsql { PRAGMA integrity_check }
|
||||
} {ok}
|
||||
|
||||
do_test 6.4 {
|
||||
sqlite3rbu_vacuum rbu test.db test.db-vactmp
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# 2019 Jan 3
|
||||
#
|
||||
# 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 contains tests for the RBU module. More specifically, it
|
||||
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
|
||||
# expected.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set testprefix rbuvacuum3
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1b ON t1(b);
|
||||
CREATE INDEX i1c ON t1(c);
|
||||
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
|
||||
)
|
||||
INSERT INTO t1 SELECT i, randomblob(100), randomblob(100) FROM s;
|
||||
}
|
||||
|
||||
forcedelete state.db
|
||||
do_test 1.1 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
while {1} {
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
rbu savestate
|
||||
}
|
||||
rbu close
|
||||
} {SQLITE_DONE}
|
||||
|
||||
do_test 1.2 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
while {1} {
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
rbu savestate
|
||||
}
|
||||
rbu close
|
||||
} {SQLITE_DONE}
|
||||
|
||||
do_test 1.3 {
|
||||
while {1} {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
rbu savestate
|
||||
rbu close
|
||||
}
|
||||
rbu close
|
||||
} {SQLITE_DONE}
|
||||
|
||||
finish_test
|
||||
+2
-11
@@ -2477,7 +2477,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
|
||||
if( *zExtra=='\0' ) zExtra = 0;
|
||||
}
|
||||
|
||||
zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s",
|
||||
zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
|
||||
sqlite3_db_filename(p->dbRbu, "main"),
|
||||
(zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
|
||||
);
|
||||
@@ -3743,12 +3743,6 @@ sqlite3rbu *sqlite3rbu_vacuum(
|
||||
const char *zState
|
||||
){
|
||||
if( zTarget==0 ){ return rbuMisuseError(); }
|
||||
if( zState ){
|
||||
int n = strlen(zState);
|
||||
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
|
||||
return rbuMisuseError();
|
||||
}
|
||||
}
|
||||
/* TODO: Check that both arguments are non-NULL */
|
||||
return openRbuHandle(0, zTarget, zState);
|
||||
}
|
||||
@@ -3945,10 +3939,7 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
|
||||
if( p->eStage==RBU_STAGE_OAL ){
|
||||
assert( rc!=SQLITE_DONE );
|
||||
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE";
|
||||
rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
|
||||
}
|
||||
|
||||
|
||||
@@ -333,11 +333,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
|
||||
** name of the state database is "<database>-vacuum", where <database>
|
||||
** is the name of the target database file. In this case, on UNIX, if the
|
||||
** state database is not already present in the file-system, it is created
|
||||
** with the same permissions as the target db is made.
|
||||
**
|
||||
** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the
|
||||
** state database ends with "-vactmp". This name is reserved for internal
|
||||
** use.
|
||||
** with the same permissions as the target db is made.
|
||||
**
|
||||
** This function does not delete the state database after an RBU vacuum
|
||||
** is completed, even if it created it. However, if the call to
|
||||
|
||||
@@ -273,7 +273,6 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
|
||||
zCmd = Tcl_GetString(objv[1]);
|
||||
zTarget = Tcl_GetString(objv[2]);
|
||||
if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
|
||||
if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;
|
||||
|
||||
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
|
||||
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
|
||||
|
||||
@@ -347,3 +347,5 @@ do_index_check_test 7.3 t7i3 {
|
||||
do_index_check_test 7.4 t7i4 {
|
||||
{} 1,1 {} 3,3
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-82
@@ -106,24 +106,14 @@ typedef float GeoCoord;
|
||||
**
|
||||
** encoding (1 byte) 0=big-endian, 1=little-endian
|
||||
** nvertex (3 bytes) Number of vertexes as a big-endian integer
|
||||
**
|
||||
** Enough space is allocated for 4 coordinates, to work around over-zealous
|
||||
** warnings coming from some compiler (notably, clang). In reality, the size
|
||||
** of each GeoPoly memory allocate is adjusted as necessary so that the
|
||||
** GeoPoly.a[] array at the end is the appropriate size.
|
||||
*/
|
||||
typedef struct GeoPoly GeoPoly;
|
||||
struct GeoPoly {
|
||||
int nVertex; /* Number of vertexes */
|
||||
unsigned char hdr[4]; /* Header for on-disk representation */
|
||||
GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */
|
||||
GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
|
||||
};
|
||||
|
||||
/* The size of a memory allocation needed for a GeoPoly object sufficient
|
||||
** to hold N coordinate pairs.
|
||||
*/
|
||||
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
|
||||
|
||||
/*
|
||||
** State of a parse of a GeoJSON input.
|
||||
*/
|
||||
@@ -258,10 +248,12 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
|
||||
&& s.a[1]==s.a[s.nVertex*2-1]
|
||||
&& (s.z++, geopolySkipSpace(&s)==0)
|
||||
){
|
||||
int nByte;
|
||||
GeoPoly *pOut;
|
||||
int x = 1;
|
||||
s.nVertex--; /* Remove the redundant vertex at the end */
|
||||
pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
|
||||
nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
|
||||
pOut = sqlite3_malloc64( nByte );
|
||||
x = 1;
|
||||
if( pOut==0 ) goto parse_json_err;
|
||||
pOut->nVertex = s.nVertex;
|
||||
@@ -395,9 +387,7 @@ static void geopolySvgFunc(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
GeoPoly *p;
|
||||
if( argc<1 ) return;
|
||||
p = geopolyFuncParam(context, argv[0], 0);
|
||||
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
|
||||
if( p ){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
sqlite3_str *x = sqlite3_str_new(db);
|
||||
@@ -466,27 +456,6 @@ static void geopolyXformFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the area enclosed by the polygon.
|
||||
**
|
||||
** This routine can also be used to detect polygons that rotate in
|
||||
** the wrong direction. Polygons are suppose to be counter-clockwise (CCW).
|
||||
** This routine returns a negative value for clockwise (CW) polygons.
|
||||
*/
|
||||
static double geopolyArea(GeoPoly *p){
|
||||
double rArea = 0.0;
|
||||
int ii;
|
||||
for(ii=0; ii<p->nVertex-1; ii++){
|
||||
rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
|
||||
* (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
|
||||
* 0.5;
|
||||
}
|
||||
rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
|
||||
* (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
|
||||
* 0.5;
|
||||
return rArea;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the geopoly_area(X) function.
|
||||
**
|
||||
@@ -502,59 +471,32 @@ static void geopolyAreaFunc(
|
||||
){
|
||||
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
|
||||
if( p ){
|
||||
sqlite3_result_double(context, geopolyArea(p));
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the geopoly_ccw(X) function.
|
||||
**
|
||||
** If the rotation of polygon X is clockwise (incorrect) instead of
|
||||
** counter-clockwise (the correct winding order according to RFC7946)
|
||||
** then reverse the order of the vertexes in polygon X.
|
||||
**
|
||||
** In other words, this routine returns a CCW polygon regardless of the
|
||||
** winding order of its input.
|
||||
**
|
||||
** Use this routine to sanitize historical inputs that that sometimes
|
||||
** contain polygons that wind in the wrong direction.
|
||||
*/
|
||||
static void geopolyCcwFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
|
||||
if( p ){
|
||||
if( geopolyArea(p)<0.0 ){
|
||||
int ii, jj;
|
||||
for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
|
||||
GeoCoord t = p->a[ii];
|
||||
p->a[ii] = p->a[jj];
|
||||
p->a[jj] = t;
|
||||
t = p->a[ii+1];
|
||||
p->a[ii+1] = p->a[jj+1];
|
||||
p->a[jj+1] = t;
|
||||
}
|
||||
double rArea = 0.0;
|
||||
int ii;
|
||||
for(ii=0; ii<p->nVertex-1; ii++){
|
||||
rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
|
||||
* (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
|
||||
* 0.5;
|
||||
}
|
||||
sqlite3_result_blob(context, p->hdr,
|
||||
4+8*p->nVertex, SQLITE_TRANSIENT);
|
||||
rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
|
||||
* (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
|
||||
* 0.5;
|
||||
sqlite3_result_double(context, rArea);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
#define GEOPOLY_PI 3.1415926535897932385
|
||||
|
||||
/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi
|
||||
/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi
|
||||
*/
|
||||
static double geopolySine(double r){
|
||||
static double geopolyCosine(double r){
|
||||
assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
|
||||
if( r>=1.5*GEOPOLY_PI ){
|
||||
r -= 2.0*GEOPOLY_PI;
|
||||
}
|
||||
if( r>=0.5*GEOPOLY_PI ){
|
||||
return -geopolySine(r-GEOPOLY_PI);
|
||||
return -geopolyCosine(r-GEOPOLY_PI);
|
||||
}else{
|
||||
double r2 = r*r;
|
||||
double r3 = r2*r;
|
||||
@@ -595,8 +537,8 @@ static void geopolyRegularFunc(
|
||||
p->hdr[3] = n&0xff;
|
||||
for(i=0; i<n; i++){
|
||||
double rAngle = 2.0*GEOPOLY_PI*i/n;
|
||||
p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
|
||||
p->a[i*2+1] = y + r*geopolySine(rAngle);
|
||||
p->a[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI);
|
||||
p->a[i*2+1] = y + r*geopolyCosine(rAngle);
|
||||
}
|
||||
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
|
||||
sqlite3_free(p);
|
||||
@@ -646,7 +588,7 @@ static GeoPoly *geopolyBBox(
|
||||
if( pRc ) *pRc = SQLITE_OK;
|
||||
if( aCoord==0 ){
|
||||
geopolyBboxFill:
|
||||
pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
|
||||
pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
|
||||
if( pOut==0 ){
|
||||
sqlite3_free(p);
|
||||
if( context ) sqlite3_result_error_nomem(context);
|
||||
@@ -1727,7 +1669,7 @@ static int geopolyFindFunction(
|
||||
|
||||
|
||||
static sqlite3_module geopolyModule = {
|
||||
3, /* iVersion */
|
||||
2, /* iVersion */
|
||||
geopolyCreate, /* xCreate - create a table */
|
||||
geopolyConnect, /* xConnect - connect to an existing table */
|
||||
geopolyBestIndex, /* xBestIndex - Determine search strategy */
|
||||
@@ -1750,7 +1692,6 @@ static sqlite3_module geopolyModule = {
|
||||
rtreeSavepoint, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
rtreeShadowName /* xShadowName */
|
||||
};
|
||||
|
||||
static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
@@ -1772,7 +1713,6 @@ static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
{ geopolyBBoxFunc, 1, 1, "geopoly_bbox" },
|
||||
{ geopolyXformFunc, 7, 1, "geopoly_xform" },
|
||||
{ geopolyRegularFunc, 4, 1, "geopoly_regular" },
|
||||
{ geopolyCcwFunc, 1, 1, "geopoly_ccw" },
|
||||
};
|
||||
static const struct {
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user