Compare commits
186 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5596eb3020 | |||
| e8e6657fa7 | |||
| 9fb13abc6e | |||
| 4a6beac28b | |||
| dbf6773e88 | |||
| 6fa255fd5c | |||
| 9109b7f8e1 | |||
| 36c33aa633 | |||
| 24b8457911 | |||
| 1bbbd85bd2 | |||
| f7854c7329 | |||
| 2853c688ad | |||
| c5dc3dcd6e | |||
| 0691191d26 | |||
| ad61c46409 | |||
| 3d541a5b8c | |||
| 433d5aaed1 | |||
| 6b513640c0 | |||
| 4dd83a22f2 | |||
| 46e6ea0282 | |||
| 56d90be183 | |||
| fb785b2c2b | |||
| 2b4e95226c | |||
| fd261ec67e | |||
| 7ef855f156 | |||
| 16158eeb49 | |||
| 1dfaa5c4b2 | |||
| 99b25309d0 | |||
| f2c9995dbe | |||
| 5c22e82a17 | |||
| 6d7734c27d | |||
| 219f4d48a2 | |||
| 9cc4ae6f2a | |||
| 3f9bfa740f | |||
| 8789fbb2bd | |||
| 5e5b454cd8 | |||
| 3c060c2aef | |||
| 0206920e27 | |||
| 05903e6a87 | |||
| b0df963465 | |||
| 0030aaad67 | |||
| f170ea44d4 | |||
| 04ce31fafe | |||
| a649776664 | |||
| 0b086403b4 | |||
| 1cfc44392c | |||
| 49472655d4 | |||
| b9e8f59b63 | |||
| be37c12423 | |||
| faf3727904 | |||
| 95fa606616 | |||
| 848a3326f7 | |||
| c24658b5d7 | |||
| c6ce388301 | |||
| ce78bc6e7e | |||
| fed7ac6f04 | |||
| 9eef8c6934 | |||
| 59a052359d | |||
| 039ca6ab59 | |||
| b02392e6f0 | |||
| 9676c48199 | |||
| 8873996b7b | |||
| 460cd9ccfd | |||
| 5f93ccd7fc | |||
| cdabd7bd50 | |||
| 99f4647ef5 | |||
| fdefc36792 | |||
| 78e3f61f22 | |||
| 501b402c65 | |||
| 021643560b | |||
| 8d32e8042c | |||
| b43b711587 | |||
| f4f968443b | |||
| cec7dec006 | |||
| f2c26ed17b | |||
| df705d8185 | |||
| 58a8a9236e | |||
| fcbe99ae38 | |||
| cf9fb7eb1c | |||
| bfad7be78a | |||
| 2906490b71 | |||
| d12b636330 | |||
| 5b66350ac7 | |||
| 48310f8c51 | |||
| 72724da95a | |||
| c5971cc859 | |||
| 728e0f91bb | |||
| 9a4718ff73 | |||
| ba461cac7b | |||
| 946ef60ad0 | |||
| cc7304888f | |||
| a0882fad7c | |||
| dfff1ffec6 | |||
| 8deb4b8b17 | |||
| 6cac258245 | |||
| 80372ae248 | |||
| 2572751be8 | |||
| 8381be4ace | |||
| c4e6d1775e | |||
| b5c8d27c7d | |||
| 64db184efa | |||
| ce1d9f546b | |||
| 0008ce7cc5 | |||
| 45fac88951 | |||
| c306e08ad5 | |||
| d3b90a2e41 | |||
| 23fda8242c | |||
| 56eac26897 | |||
| 351ccb3825 | |||
| 056d7acf25 | |||
| 50065656f7 | |||
| b2682eb14b | |||
| d7fd6aa4ba | |||
| 98e713bb8d | |||
| 08114efde4 | |||
| 22c7cca21f | |||
| 1dcc97cd3a | |||
| d46cc33131 | |||
| 48cc9a31e1 | |||
| 60a15a48c5 | |||
| 7651e0a439 | |||
| 92099b0753 | |||
| 6418ffab82 | |||
| 6bd7456edd | |||
| b15393b8d5 | |||
| ee38148785 | |||
| 91a3ecb0ad | |||
| 8b0cf38a12 | |||
| a2507137f3 | |||
| 9f1ef45f6a | |||
| 8d9837acd5 | |||
| 6f832d3dff | |||
| f24bebe37a | |||
| 2c1023df09 | |||
| a0f197b842 | |||
| 06f8c635ef | |||
| bca189d5d8 | |||
| 5171e911f2 | |||
| 105865acf9 | |||
| 9b5351d439 | |||
| e755e10a78 | |||
| d95bb39c52 | |||
| 4b92f98ccc | |||
| e60856980a | |||
| 65c4f591be | |||
| e2b7d7a0a1 | |||
| c149f18f4d | |||
| 94f26a1e22 | |||
| 4ad0971919 | |||
| 91742c45a9 | |||
| b3deb4ea64 | |||
| 354474ad6d | |||
| 0f40037eee | |||
| a722821eb5 | |||
| d943b27596 | |||
| 076e0f9674 | |||
| 3169713be0 | |||
| 63c85a7a66 | |||
| 2f20e13b83 | |||
| 32498f1321 | |||
| c4cdb29a0e | |||
| 539482b76a | |||
| 17db155fed | |||
| 2ea31b1286 | |||
| 68391acd5f | |||
| ae1a015c87 | |||
| 81966bea22 | |||
| 163c29c5f3 | |||
| 4970d4032e | |||
| c1bd84124b | |||
| bcf40a7f12 | |||
| b413a5467a | |||
| a67a31624d | |||
| 0403cb3012 | |||
| 1eb6eeb829 | |||
| 2f2b02785a | |||
| 0df57012da | |||
| fe66352d17 | |||
| ffc648cfa9 | |||
| f7e369070e | |||
| 07194bff0e | |||
| bec2476afc | |||
| 91d3a61f8a | |||
| 159c1a18db | |||
| 5b88bc4bec | |||
| 28935364ef |
@@ -1,138 +0,0 @@
|
||||
#!/usr/make
|
||||
#
|
||||
# Makefile for SQLITE
|
||||
#
|
||||
# This is a template makefile for SQLite. Most people prefer to
|
||||
# use the autoconf generated "configure" script to generate the
|
||||
# makefile automatically. But that does not work for everybody
|
||||
# and in every situation. If you are having problems with the
|
||||
# "configure" script, you might want to try this makefile as an
|
||||
# alternative. Create a copy of this file, edit the parameters
|
||||
# below and type "make".
|
||||
#
|
||||
|
||||
#### The directory where to find the mingw32ce tools
|
||||
MINGW32CE = /opt/mingw32ce/bin
|
||||
|
||||
#### The target prefix of the mingw32ce tools
|
||||
TARGET = arm-wince-mingw32ce
|
||||
|
||||
#### The toplevel directory of the source tree. This is the directory
|
||||
# that contains this "Makefile.in" and the "configure.in" script.
|
||||
#
|
||||
TOP = ../sqlite
|
||||
|
||||
#### C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
BCC = gcc -g -O2
|
||||
#BCC = /opt/ancic/bin/c89 -0
|
||||
|
||||
#### If the target operating system supports the "usleep()" system
|
||||
# call, then define the HAVE_USLEEP macro for all C modules.
|
||||
#
|
||||
USLEEP =
|
||||
#USLEEP = -DHAVE_USLEEP=1
|
||||
|
||||
#### If you want the SQLite library to be safe for use within a
|
||||
# multi-threaded program, then define the following macro
|
||||
# appropriately:
|
||||
#
|
||||
THREADSAFE = -DTHREADSAFE=1
|
||||
#THREADSAFE = -DTHREADSAFE=0
|
||||
|
||||
#### Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
#THREADLIB = -lpthread
|
||||
THREADLIB =
|
||||
|
||||
#### Specify any extra libraries needed to access required functions.
|
||||
#
|
||||
#TLIBS = -lrt # fdatasync on Solaris 8
|
||||
TLIBS =
|
||||
|
||||
#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1
|
||||
# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all
|
||||
# malloc()s and free()s in order to track down memory leaks.
|
||||
#
|
||||
# SQLite uses some expensive assert() statements in the inner loop.
|
||||
# You can make the library go almost twice as fast if you compile
|
||||
# with -DNDEBUG=1
|
||||
#
|
||||
#OPTS = -DSQLITE_DEBUG=2
|
||||
#OPTS = -DSQLITE_DEBUG=1
|
||||
#OPTS =
|
||||
OPTS = -DNDEBUG=1 -DSQLITE_OS_WIN=1 -D_WIN32_WCE=1
|
||||
#OPTS += -DHAVE_FDATASYNC=1
|
||||
|
||||
#### The suffix to add to executable files. ".exe" for windows.
|
||||
# Nothing for unix.
|
||||
#
|
||||
EXE = .exe
|
||||
#EXE =
|
||||
|
||||
#### C Compile and options for use in building executables that
|
||||
# will run on the target platform. This is usually the same
|
||||
# as BCC, unless you are cross-compiling.
|
||||
#
|
||||
#TCC = gcc -O6
|
||||
#TCC = gcc -g -O0 -Wall
|
||||
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
|
||||
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
|
||||
TCC = $(MINGW32CE)/$(TARGET)-gcc -O2
|
||||
#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive
|
||||
|
||||
#### Tools used to build a static library.
|
||||
#
|
||||
#AR = ar cr
|
||||
#AR = /opt/mingw/bin/i386-mingw32-ar cr
|
||||
AR = $(MINGW32CE)/$(TARGET)-ar cr
|
||||
#RANLIB = ranlib
|
||||
#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib
|
||||
RANLIB = $(MINGW32CE)/$(TARGET)-ranlib
|
||||
|
||||
#MKSHLIB = gcc -shared
|
||||
#SO = so
|
||||
#SHPREFIX = lib
|
||||
MKSHLIB = $(MINGW32CE)/$(TARGET)-gcc -shared
|
||||
SO = dll
|
||||
SHPREFIX =
|
||||
|
||||
#### Extra compiler options needed for programs that use the TCL library.
|
||||
#
|
||||
#TCL_FLAGS =
|
||||
#TCL_FLAGS = -DSTATIC_BUILD=1
|
||||
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
|
||||
|
||||
#### Linker options needed to link against the TCL library.
|
||||
#
|
||||
#LIBTCL = -ltcl -lm -ldl
|
||||
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
|
||||
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
|
||||
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
|
||||
|
||||
#### Additional objects for SQLite library when TCL support is enabled.
|
||||
TCLOBJ =
|
||||
#TCLOBJ = tclsqlite.o
|
||||
|
||||
#### Compiler options needed for programs that use the readline() library.
|
||||
#
|
||||
READLINE_FLAGS =
|
||||
#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
|
||||
|
||||
#### Linker options needed by programs using readline() must link against.
|
||||
#
|
||||
LIBREADLINE =
|
||||
#LIBREADLINE = -static -lreadline -ltermcap
|
||||
|
||||
#### Which "awk" program provides nawk compatibilty
|
||||
#
|
||||
# NAWK = nawk
|
||||
NAWK = awk
|
||||
|
||||
# You should not have to change anything below this line
|
||||
###############################################################################
|
||||
include $(TOP)/main.mk
|
||||
+35
-29
@@ -65,7 +65,7 @@ TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
|
||||
|
||||
# Any target libraries which libsqlite must be linked against
|
||||
#
|
||||
TLIBS = @LIBS@
|
||||
TLIBS = @LIBS@ $(LIBS)
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
@@ -155,9 +155,6 @@ LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) $(LTCOMPILE_EXTRAS)
|
||||
LTLINK = $(LIBTOOL) --mode=link $(TCC) $(LTCOMPILE_EXTRAS) @LDFLAGS@ $(LTLINK_EXTRAS)
|
||||
LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
|
||||
|
||||
# nawk compatible awk.
|
||||
NAWK = @AWK@
|
||||
|
||||
# You should not have to change anything below this line
|
||||
###############################################################################
|
||||
|
||||
@@ -175,7 +172,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
fts5.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo journal.lo legacy.lo loadext.lo \
|
||||
icu.lo insert.lo journal.lo json1.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
@@ -272,8 +269,8 @@ SRC = \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/threads.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/treeview.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
@@ -347,6 +344,9 @@ SRC += \
|
||||
SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c
|
||||
|
||||
|
||||
|
||||
# Generated source code files
|
||||
@@ -417,7 +417,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||
$(TOP)/ext/fts5/fts5_test_mi.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
@@ -541,16 +540,16 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db
|
||||
|
||||
# Extra arguments for including json1 in the build of tools
|
||||
#
|
||||
JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
|
||||
JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
|
||||
JSON1_SRC = $(TOP)/ext/misc/json1.c
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
TESTOPTS = --verbose=file --output=test-out.txt
|
||||
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
#
|
||||
@@ -573,20 +572,20 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
|
||||
-version-info "8:6:8" \
|
||||
-avoid-version
|
||||
|
||||
sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(JSON1_DEP)
|
||||
$(LTLINK) $(READLINE_FLAGS) $(JSON1_OPT) -o $@ \
|
||||
$(TOP)/src/shell.c $(JSON1_SRC) libsqlite3.la \
|
||||
sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
|
||||
$(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
|
||||
$(TOP)/src/shell.c libsqlite3.la \
|
||||
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
|
||||
|
||||
fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
$(LTLINK) -o $@ $(JSON1_OPT) \
|
||||
$(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c $(TLIBS)
|
||||
fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
|
||||
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
||||
|
||||
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
$(LTLINK) -o $@ $(JSON1_OPT) $(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS)
|
||||
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
|
||||
|
||||
mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
@@ -612,19 +611,23 @@ mptest: mptester$(TEXE)
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl
|
||||
.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
|
||||
rm -rf tsrc
|
||||
mkdir tsrc
|
||||
cp -f $(SRC) tsrc
|
||||
rm tsrc/sqlite.h.in tsrc/parse.y
|
||||
$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
|
||||
mv vdbe.new tsrc/vdbe.c
|
||||
cp fts5.c fts5.h tsrc
|
||||
touch .target_source
|
||||
|
||||
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
|
||||
cp tsrc/shell.c tsrc/sqlite3ext.h .
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
cp tsrc/sqlite3ext.h .
|
||||
|
||||
tclsqlite3.c: sqlite3.c
|
||||
echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
|
||||
cat sqlite3.c >>tclsqlite3.c
|
||||
@@ -896,22 +899,22 @@ tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
|
||||
$(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
|
||||
opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
|
||||
cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
|
||||
cat parse.h $(TOP)/src/vdbe.c | $(TCLSH_CMD) $(TOP)/tool/mkopcodeh.tcl >opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk
|
||||
parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
|
||||
cp $(TOP)/src/parse.y .
|
||||
rm -f parse.h
|
||||
./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
mv parse.h parse.h.temp
|
||||
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
|
||||
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
|
||||
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
|
||||
@@ -987,6 +990,9 @@ 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
|
||||
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
# FTS5 things
|
||||
#
|
||||
FTS5_SRC = \
|
||||
@@ -1093,7 +1099,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
|
||||
echo "static const char *tclsh_main_loop(void){" >> $@
|
||||
echo "static const char *zMainloop = " >> $@
|
||||
$(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
|
||||
$(TCLSH_CMD) $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
|
||||
echo "; return zMainloop; }" >> $@
|
||||
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
|
||||
@@ -118,11 +118,6 @@ READLINE_FLAGS =
|
||||
LIBREADLINE =
|
||||
#LIBREADLINE = -static -lreadline -ltermcap
|
||||
|
||||
#### Which "awk" program provides nawk compatibilty
|
||||
#
|
||||
# NAWK = nawk
|
||||
NAWK = awk
|
||||
|
||||
# You should not have to change anything below this line
|
||||
###############################################################################
|
||||
include $(TOP)/main.mk
|
||||
|
||||
+69
-56
@@ -292,9 +292,9 @@ NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
BCC = $(NCC) -nologo -W4
|
||||
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
|
||||
!ELSE
|
||||
BCC = $(NCC) -nologo -W3
|
||||
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
@@ -322,13 +322,13 @@ NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
|
||||
# same unless your are cross-compiling.)
|
||||
#
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1
|
||||
TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
|
||||
!ELSE
|
||||
TCC = $(CC) -nologo -W3
|
||||
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
|
||||
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||
|
||||
# Check if we want to use the "stdcall" calling convention when compiling.
|
||||
# This is not supported by the compilers for non-x86 platforms. It should
|
||||
@@ -390,9 +390,9 @@ CORE_LINK_OPTS = /DEF:sqlite3.def
|
||||
#
|
||||
!IFNDEF SHELL_COMPILE_OPTS
|
||||
!IF $(DYNAMIC_SHELL)!=0
|
||||
SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
|
||||
SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
|
||||
!ELSE
|
||||
SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS)
|
||||
SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS)
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -569,6 +569,14 @@ TCLLIBDIR = c:\tcl\lib
|
||||
LIBTCL = tcl85.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLSTUB
|
||||
LIBTCLSTUB = tclstub85.lib
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLPATH
|
||||
LIBTCLPATH = c:\tcl\bin
|
||||
!ENDIF
|
||||
|
||||
# The locations of the ICU header and library files. These variables
|
||||
# (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment
|
||||
# prior to running nmake in order to match the actual installed location on
|
||||
@@ -792,7 +800,9 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
|
||||
LDFLAGS = /DEBUG
|
||||
LDFLAGS = /DEBUG $(LDOPTS)
|
||||
!ELSE
|
||||
LDFLAGS = $(LDOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Start with the Tcl related linker options.
|
||||
@@ -809,12 +819,6 @@ LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
|
||||
LTLIBS = $(LTLIBS) $(LIBICU)
|
||||
!ENDIF
|
||||
|
||||
# nawk compatible awk.
|
||||
#
|
||||
!IFNDEF NAWK
|
||||
NAWK = gawk.exe
|
||||
!ENDIF
|
||||
|
||||
# You should not have to change anything below this line
|
||||
###############################################################################
|
||||
|
||||
@@ -1008,7 +1012,8 @@ SRC4 = \
|
||||
$(TOP)\ext\rtree\rtree.h \
|
||||
$(TOP)\ext\rtree\rtree.c \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.h \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||
$(TOP)\ext\misc\json1.c
|
||||
|
||||
|
||||
# Generated source code files
|
||||
@@ -1079,11 +1084,9 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\eval.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\fuzzer.c \
|
||||
fts5.c \
|
||||
$(TOP)\ext\fts5\fts5_tcl.c \
|
||||
$(TOP)\ext\fts5\fts5_test_mi.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\json1.c \
|
||||
$(TOP)\ext\misc\nextchar.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
@@ -1210,11 +1213,11 @@ FUZZDATA = \
|
||||
$(TOP)\test\fuzzdata3.db \
|
||||
$(TOP)\test\fuzzdata4.db
|
||||
|
||||
# Extra arguments for including json1 in the build of tools
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
JSON1_DEP = sqlite3ext.h $(TOP)\ext\misc\json1.c
|
||||
JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
|
||||
JSON1_SRC = $(TOP)\ext\misc\json1.c
|
||||
SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@@ -1229,25 +1232,25 @@ libsqlite3.lib: $(LIBOBJ)
|
||||
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
|
||||
|
||||
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS)
|
||||
|
||||
sqlite3.exe: $(TOP)\src\shell.c $(JSON1_DEP) $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(JSON1_OPT) $(READLINE_FLAGS) $(TOP)\src\shell.c $(JSON1_SRC) \
|
||||
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \
|
||||
/link /pdb:sqlite3sh.pdb $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
$(LTLINK) $(NO_WARN) $(JSON1_OPT) \
|
||||
$(TOP)\tool\fuzzershell.c $(JSON1_SRC) sqlite3.c
|
||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) \
|
||||
$(TOP)\tool\fuzzershell.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
$(LTLINK) $(NO_WARN) $(JSON1_OPT) $(TOP)\test\fuzzcheck.c $(JSON1_SRC) sqlite3.c
|
||||
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c sqlite3.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
|
||||
MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
|
||||
@@ -1269,7 +1272,7 @@ mptest: mptester.exe
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c
|
||||
-rmdir /Q/S tsrc 2>NUL
|
||||
-mkdir tsrc
|
||||
for %i in ($(SRC1)) do copy /Y %i tsrc
|
||||
@@ -1277,6 +1280,8 @@ mptest: mptester.exe
|
||||
for %i in ($(SRC3)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC4)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC5)) do copy /Y %i tsrc
|
||||
copy /Y fts5.c tsrc
|
||||
copy /Y fts5.h tsrc
|
||||
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
|
||||
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
|
||||
move vdbe.new tsrc\vdbe.c
|
||||
@@ -1310,7 +1315,7 @@ lempar.c: $(TOP)\src\lempar.c
|
||||
|
||||
lemon.exe: $(TOP)\tool\lemon.c lempar.c
|
||||
$(BCC) $(NO_WARN) -Daccess=_access \
|
||||
-Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
# Rules to build individual *.lo files from generated *.c files. This
|
||||
# applies to:
|
||||
@@ -1331,7 +1336,7 @@ $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR)
|
||||
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
|
||||
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
|
||||
echo #define SQLITE_RESOURCE_VERSION %%V \
|
||||
| $(NAWK) "/.*/ { gsub(/[.]/,\",\");print }" >> sqlite3rc.h \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \
|
||||
)
|
||||
echo #endif >> sqlite3rc.h
|
||||
$(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc
|
||||
@@ -1568,26 +1573,26 @@ tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
||||
|
||||
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(LIBRESOBJS)
|
||||
$(LTLINK) $(SQLITE3C) /link $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
opcodes.c: opcodes.h $(TOP)\mkopcodec.awk
|
||||
$(NAWK) -f $(TOP)\mkopcodec.awk opcodes.h > opcodes.c
|
||||
opcodes.c: opcodes.h $(TOP)\tool\mkopcodec.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkopcodec.tcl opcodes.h > opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk
|
||||
type parse.h $(TOP)\src\vdbe.c | $(NAWK) -f $(TOP)\mkopcodeh.awk > opcodes.h
|
||||
opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl
|
||||
type parse.h $(TOP)\src\vdbe.c | $(TCLSH_CMD) $(TOP)\tool\mkopcodeh.tcl > opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
|
||||
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
|
||||
del /Q parse.y parse.h parse.h.temp 2>NUL
|
||||
copy $(TOP)\src\parse.y .
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
|
||||
move parse.h parse.h.temp
|
||||
$(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h
|
||||
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
|
||||
|
||||
sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
|
||||
@@ -1597,7 +1602,7 @@ sqlite3ext.h: .target_source
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \
|
||||
$(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
|
||||
|
||||
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
.\mkkeywordhash.exe > keywordhash.h
|
||||
@@ -1731,21 +1736,26 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) \
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
extensiontest: testfixture.exe testloadext.dll
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
|
||||
|
||||
fulltest: $(TESTPROGS) fuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
|
||||
|
||||
soaktest: $(TESTPROGS)
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)
|
||||
|
||||
fulltestonly: $(TESTPROGS) fuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\full.test
|
||||
|
||||
queryplantest: testfixture.exe sqlite3.exe
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
|
||||
|
||||
fuzztest: fuzzcheck.exe
|
||||
@@ -1757,15 +1767,18 @@ fastfuzztest: fuzzcheck.exe
|
||||
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||
#
|
||||
quicktest: testfixture.exe
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS)
|
||||
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: $(TESTPROGS) fastfuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
|
||||
|
||||
smoketest: $(TESTPROGS)
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||
@@ -1774,12 +1787,12 @@ sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
|
||||
echo static const char *tclsh_main_loop(void){ >> $@
|
||||
echo static const char *zMainloop = >> $@
|
||||
$(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
|
||||
$(TCLSH_CMD) $(TOP)\tool\tostr.tcl $(TOP)\tool\spaceanal.tcl >> $@
|
||||
echo ; return zMainloop; } >> $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
||||
@@ -1789,38 +1802,38 @@ testloadext.dll: testloadext.lo
|
||||
|
||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showstat4.c $(SQLITE3C)
|
||||
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showjournal.c $(SQLITE3C)
|
||||
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showwal.c $(SQLITE3C)
|
||||
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C)
|
||||
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\rollback-test.c $(SQLITE3C)
|
||||
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
LogEst.exe: $(TOP)\tool\logest.c sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c
|
||||
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\wordcount.c $(SQLITE3C)
|
||||
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\speedtest1.c $(SQLITE3C)
|
||||
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
@@ -1858,7 +1871,7 @@ dll: sqlite3.dll
|
||||
sqlite3.def: libsqlite3.lib
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all libsqlite3.lib \
|
||||
| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \
|
||||
| sort >> sqlite3.def
|
||||
|
||||
sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
|
||||
@@ -1,673 +0,0 @@
|
||||
#!/usr/make
|
||||
#
|
||||
# Makefile for SQLITE on VxWorks
|
||||
|
||||
ifeq ($(FORCPU),)
|
||||
FORCPU = SH32gnule
|
||||
endif
|
||||
|
||||
TOOL_FAMILY = gnu
|
||||
|
||||
include $(WIND_USR)/tool/gnu/make.$(FORCPU)
|
||||
|
||||
#### The toplevel directory of the source tree. This is the directory
|
||||
# that contains this "Makefile.in" and the "configure.in" script.
|
||||
#
|
||||
TOP = .
|
||||
|
||||
#### C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
BCC = gcc -g -O2
|
||||
#BCC = /opt/ancic/bin/c89 -0
|
||||
|
||||
#### If the target operating system supports the "usleep()" system
|
||||
# call, then define the HAVE_USLEEP macro for all C modules.
|
||||
#
|
||||
USLEEP =
|
||||
#USLEEP = -DHAVE_USLEEP=1
|
||||
|
||||
#### If you want the SQLite library to be safe for use within a
|
||||
# multi-threaded program, then define the following macro
|
||||
# appropriately:
|
||||
#
|
||||
THREADSAFE = -DSQLITE_THREADSAFE=1
|
||||
#THREADSAFE = -DSQLITE_THREADSAFE=0
|
||||
|
||||
#### Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
#THREADLIB = -lpthread
|
||||
THREADLIB =
|
||||
|
||||
#### Specify any extra libraries needed to access required functions.
|
||||
#
|
||||
ifeq ($(CPU),SH32)
|
||||
# for SH4 shared library
|
||||
TLIBS_SHARED += -L$(WIND_USR)/lib/sh/SH32/commonle/PIC
|
||||
else
|
||||
# for all other CPUs shared library
|
||||
TLIBS_SHARED += $(LD_LINK_PATH_ATEND) $(LD_PARTIAL_LAST_FLAGS)
|
||||
endif
|
||||
# for static library
|
||||
TLIBS += $(LD_LINK_PATH_ATEND) $(LD_PARTIAL_LAST_FLAGS)
|
||||
|
||||
#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1
|
||||
# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all
|
||||
# malloc()s and free()s in order to track down memory leaks.
|
||||
#
|
||||
# SQLite uses some expensive assert() statements in the inner loop.
|
||||
# You can make the library go almost twice as fast if you compile
|
||||
# with -DNDEBUG=1
|
||||
#
|
||||
#OPTS = -DSQLITE_DEBUG=2
|
||||
#OPTS = -DSQLITE_DEBUG=1
|
||||
#OPTS =
|
||||
OPTS = -DNDEBUG=1 -DSQLITE_OS_UNIX=1 $(THREADSAFE)
|
||||
OPTS += -DSQLITE_OMIT_LOAD_EXTENSION=1
|
||||
OPTS += -DSQLITE_ENABLE_LOCKING_STYLE=1
|
||||
OPTS += -DSQLITE_THREAD_OVERRIDE_LOCK=0
|
||||
OPTS += -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
OPTS += -DHAVE_FDATASYNC=1
|
||||
|
||||
#### The suffix to add to executable files. ".exe" for windows.
|
||||
# Nothing for unix.
|
||||
#
|
||||
EXE = .vxe
|
||||
#EXE =
|
||||
|
||||
#### C Compile and options for use in building executables that
|
||||
# will run on the target platform. This is usually the same
|
||||
# as BCC, unless you are cross-compiling.
|
||||
#
|
||||
#TCC = gcc -O6
|
||||
#TCC = gcc -g -O0 -Wall
|
||||
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
|
||||
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
|
||||
TCC = $(CC) $(DEFINE_CC) -O2 -g -mrtp $(CC_ARCH_SPEC) -D_REENTRANT=1 -D_VX_CPU=_VX_$(CPU) -D_VX_TOOL_FAMILY=$(TOOL_FAMILY) -D_VX_TOOL=$(TOOL)
|
||||
TCC += -I$(WIND_USR)/h -I$(WIND_USR)/h/wrn/coreip
|
||||
#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive
|
||||
|
||||
#TCC_SHARED = $(TCC) -fPIC
|
||||
TCC_SHARED = $(TCC)
|
||||
|
||||
#### Tools used to build a static library.
|
||||
#
|
||||
#ARX = ar cr
|
||||
#ARX = /opt/mingw/bin/i386-mingw32-ar cr
|
||||
AR += cr
|
||||
#RANLIB = ranlib
|
||||
#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib
|
||||
|
||||
#MKSHLIB = gcc -shared
|
||||
#SO = so
|
||||
#SHPREFIX = lib
|
||||
MKSHLIB = $(CC) $(DEFINE_CC) -mrtp -shared $(CC_ARCH_SPEC) -D_VX_CPU=_VX_$(CPU) -D_VX_TOOL_FAMILY=$(TOOL_FAMILY) -D_VX_TOOL=$(TOOL)
|
||||
SO = so
|
||||
SHPREFIX = lib
|
||||
|
||||
#### Extra compiler options needed for programs that use the TCL library.
|
||||
#
|
||||
#TCL_FLAGS =
|
||||
#TCL_FLAGS = -DSTATIC_BUILD=1
|
||||
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
|
||||
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
|
||||
|
||||
#### Linker options needed to link against the TCL library.
|
||||
#
|
||||
#LIBTCL = -ltcl -lm -ldl
|
||||
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
|
||||
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
|
||||
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
|
||||
|
||||
#### Additional objects for SQLite library when TCL support is enabled.
|
||||
TCLOBJ =
|
||||
#TCLOBJ = tclsqlite.o
|
||||
|
||||
#### Compiler options needed for programs that use the readline() library.
|
||||
#
|
||||
READLINE_FLAGS =
|
||||
#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
|
||||
|
||||
#### Linker options needed by programs using readline() must link against.
|
||||
#
|
||||
LIBREADLINE =
|
||||
#LIBREADLINE = -static -lreadline -ltermcap
|
||||
|
||||
#### Which "awk" program provides nawk compatibilty
|
||||
#
|
||||
# NAWK = nawk
|
||||
NAWK = awk
|
||||
|
||||
|
||||
#### Pasted and adapted main.mk file
|
||||
###############################################################################
|
||||
# The following macros should be defined before this script is
|
||||
# invoked:
|
||||
#
|
||||
# TOP The toplevel directory of the source tree. This is the
|
||||
# directory that contains this "Makefile.in" and the
|
||||
# "configure.in" script.
|
||||
#
|
||||
# BCC C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
# THREADLIB Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
# OPTS Extra compiler command-line options.
|
||||
#
|
||||
# EXE The suffix to add to executable files. ".exe" for windows
|
||||
# and "" for Unix.
|
||||
#
|
||||
# TCC C Compiler and options for use in building executables that
|
||||
# will run on the target platform. This is usually the same
|
||||
# as BCC, unless you are cross-compiling.
|
||||
#
|
||||
# AR Tools used to build a static library.
|
||||
# RANLIB
|
||||
#
|
||||
# TCL_FLAGS Extra compiler options needed for programs that use the
|
||||
# TCL library.
|
||||
#
|
||||
# LIBTCL Linker options needed to link against the TCL library.
|
||||
#
|
||||
# READLINE_FLAGS Compiler options needed for programs that use the
|
||||
# readline() library.
|
||||
#
|
||||
# LIBREADLINE Linker options needed by programs using readline() must
|
||||
# link against.
|
||||
#
|
||||
# NAWK Nawk compatible awk program. Older (obsolete?) solaris
|
||||
# systems need this to avoid using the original AT&T AWK.
|
||||
#
|
||||
# Once the macros above are defined, the rest of this make script will
|
||||
# build the SQLite library and testing tools.
|
||||
################################################################################
|
||||
|
||||
# This is how we compile
|
||||
#
|
||||
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
|
||||
TCCX_SHARED = $(TCC_SHARED) $(OPTS) -I. -I$(TOP)/src -I$(TOP) \
|
||||
-I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3 \
|
||||
-I$(TOP)/ext/async
|
||||
|
||||
# Object files for the SQLite library.
|
||||
#
|
||||
LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
||||
backup.o bitvec.o btmutex.o btree.o build.o \
|
||||
callback.o complete.o date.o delete.o expr.o fault.o \
|
||||
fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
|
||||
fts3_tokenizer.o fts3_tokenizer1.o \
|
||||
func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
notify.o opcodes.o os.o os_unix.o os_win.o \
|
||||
pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
|
||||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \
|
||||
walker.o where.o utf.o vtab.o
|
||||
|
||||
|
||||
|
||||
# All of the source code files.
|
||||
#
|
||||
SRC = \
|
||||
$(TOP)/src/alter.c \
|
||||
$(TOP)/src/analyze.c \
|
||||
$(TOP)/src/attach.c \
|
||||
$(TOP)/src/auth.c \
|
||||
$(TOP)/src/backup.c \
|
||||
$(TOP)/src/bitvec.c \
|
||||
$(TOP)/src/btmutex.c \
|
||||
$(TOP)/src/btree.c \
|
||||
$(TOP)/src/btree.h \
|
||||
$(TOP)/src/btreeInt.h \
|
||||
$(TOP)/src/build.c \
|
||||
$(TOP)/src/callback.c \
|
||||
$(TOP)/src/complete.c \
|
||||
$(TOP)/src/ctime.c \
|
||||
$(TOP)/src/date.c \
|
||||
$(TOP)/src/delete.c \
|
||||
$(TOP)/src/expr.c \
|
||||
$(TOP)/src/fault.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/global.c \
|
||||
$(TOP)/src/hash.c \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/journal.c \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/malloc.c \
|
||||
$(TOP)/src/mem0.c \
|
||||
$(TOP)/src/mem1.c \
|
||||
$(TOP)/src/mem2.c \
|
||||
$(TOP)/src/mem3.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
$(TOP)/src/mutex_unix.c \
|
||||
$(TOP)/src/mutex_w32.c \
|
||||
$(TOP)/src/notify.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/parse.y \
|
||||
$(TOP)/src/pcache.c \
|
||||
$(TOP)/src/pcache.h \
|
||||
$(TOP)/src/pcache1.c \
|
||||
$(TOP)/src/pragma.c \
|
||||
$(TOP)/src/prepare.c \
|
||||
$(TOP)/src/printf.c \
|
||||
$(TOP)/src/random.c \
|
||||
$(TOP)/src/resolve.c \
|
||||
$(TOP)/src/rowset.c \
|
||||
$(TOP)/src/select.c \
|
||||
$(TOP)/src/status.c \
|
||||
$(TOP)/src/shell.c \
|
||||
$(TOP)/src/sqlite.h.in \
|
||||
$(TOP)/src/sqlite3ext.h \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/table.c \
|
||||
$(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/trigger.c \
|
||||
$(TOP)/src/utf.c \
|
||||
$(TOP)/src/update.c \
|
||||
$(TOP)/src/util.c \
|
||||
$(TOP)/src/vacuum.c \
|
||||
$(TOP)/src/vdbe.c \
|
||||
$(TOP)/src/vdbe.h \
|
||||
$(TOP)/src/vdbeapi.c \
|
||||
$(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbeblob.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/walker.c \
|
||||
$(TOP)/src/where.c
|
||||
|
||||
# Source code for extensions
|
||||
#
|
||||
SRC += \
|
||||
$(TOP)/ext/fts1/fts1.c \
|
||||
$(TOP)/ext/fts1/fts1.h \
|
||||
$(TOP)/ext/fts1/fts1_hash.c \
|
||||
$(TOP)/ext/fts1/fts1_hash.h \
|
||||
$(TOP)/ext/fts1/fts1_porter.c \
|
||||
$(TOP)/ext/fts1/fts1_tokenizer.h \
|
||||
$(TOP)/ext/fts1/fts1_tokenizer1.c
|
||||
SRC += \
|
||||
$(TOP)/ext/fts2/fts2.c \
|
||||
$(TOP)/ext/fts2/fts2.h \
|
||||
$(TOP)/ext/fts2/fts2_hash.c \
|
||||
$(TOP)/ext/fts2/fts2_hash.h \
|
||||
$(TOP)/ext/fts2/fts2_icu.c \
|
||||
$(TOP)/ext/fts2/fts2_porter.c \
|
||||
$(TOP)/ext/fts2/fts2_tokenizer.h \
|
||||
$(TOP)/ext/fts2/fts2_tokenizer.c \
|
||||
$(TOP)/ext/fts2/fts2_tokenizer1.c
|
||||
SRC += \
|
||||
$(TOP)/ext/fts3/fts3.c \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.c \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_icu.c \
|
||||
$(TOP)/ext/fts3/fts3_porter.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
$(TOP)/ext/icu/icu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/rtree/rtree.h \
|
||||
$(TOP)/ext/rtree/rtree.c
|
||||
|
||||
|
||||
# Generated source code files
|
||||
#
|
||||
SRC += \
|
||||
keywordhash.h \
|
||||
opcodes.c \
|
||||
opcodes.h \
|
||||
parse.c \
|
||||
parse.h \
|
||||
sqlite3.h
|
||||
|
||||
|
||||
# Source code to the test files.
|
||||
#
|
||||
TESTSRC = \
|
||||
$(TOP)/src/test1.c \
|
||||
$(TOP)/src/test2.c \
|
||||
$(TOP)/src/test3.c \
|
||||
$(TOP)/src/test4.c \
|
||||
$(TOP)/src/test5.c \
|
||||
$(TOP)/src/test6.c \
|
||||
$(TOP)/src/test7.c \
|
||||
$(TOP)/src/test8.c \
|
||||
$(TOP)/src/test9.c \
|
||||
$(TOP)/src/test_autoext.c \
|
||||
$(TOP)/src/test_async.c \
|
||||
$(TOP)/src/test_backup.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_devsym.c \
|
||||
$(TOP)/src/test_func.c \
|
||||
$(TOP)/src/test_hexio.c \
|
||||
$(TOP)/src/test_journal.c \
|
||||
$(TOP)/src/test_malloc.c \
|
||||
$(TOP)/src/test_md5.c \
|
||||
$(TOP)/src/test_mutex.c \
|
||||
$(TOP)/src/test_onefile.c \
|
||||
$(TOP)/src/test_osinst.c \
|
||||
$(TOP)/src/test_pcache.c \
|
||||
$(TOP)/src/test_schema.c \
|
||||
$(TOP)/src/test_server.c \
|
||||
$(TOP)/src/test_tclvar.c \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_wsd.c \
|
||||
|
||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||
#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c
|
||||
|
||||
TESTSRC2 = \
|
||||
$(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \
|
||||
$(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \
|
||||
$(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \
|
||||
$(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
|
||||
$(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \
|
||||
$(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \
|
||||
$(TOP)/src/pcache1.c $(TOP)/src/select.c $(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c \
|
||||
$(TOP)/ext/fts3/fts3.c $(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/async/sqlite3async.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
HDR = \
|
||||
$(TOP)/src/btree.h \
|
||||
$(TOP)/src/btreeInt.h \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
keywordhash.h \
|
||||
$(TOP)/src/msvc.h \
|
||||
$(TOP)/src/mutex.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
$(TOP)/src/os_common.h \
|
||||
$(TOP)/src/os_setup.h \
|
||||
$(TOP)/src/os_win.h \
|
||||
$(TOP)/src/pager.h \
|
||||
$(TOP)/src/pcache.h \
|
||||
parse.h \
|
||||
sqlite3.h \
|
||||
$(TOP)/src/sqlite3ext.h \
|
||||
$(TOP)/src/sqliteInt.h \
|
||||
$(TOP)/src/sqliteLimit.h \
|
||||
$(TOP)/src/vdbe.h \
|
||||
$(TOP)/src/vdbeInt.h
|
||||
|
||||
# Header files used by extensions
|
||||
#
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/fts1/fts1.h \
|
||||
$(TOP)/ext/fts1/fts1_hash.h \
|
||||
$(TOP)/ext/fts1/fts1_tokenizer.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/fts2/fts2.h \
|
||||
$(TOP)/ext/fts2/fts2_hash.h \
|
||||
$(TOP)/ext/fts2/fts2_tokenizer.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/rtree/rtree.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/icu/sqliteicu.h
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
#
|
||||
all: sqlite3.h libsqlite3.a sqlite3$(EXE)
|
||||
|
||||
libsqlite3.a: $(LIBOBJ)
|
||||
$(AR) libsqlite3.a $(LIBOBJ)
|
||||
$(RANLIB) libsqlite3.a
|
||||
|
||||
$(SHPREFIX)sqlite3.$(SO): $(LIBOBJ)
|
||||
$(MKSHLIB) -o $(SHPREFIX)sqlite3.$(SO) $(LIBOBJ) $(TLIBS_SHARED)
|
||||
|
||||
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
|
||||
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \
|
||||
$(TOP)/src/shell.c \
|
||||
$(LIBREADLINE) $(TLIBS) $(THREADLIB) -L. -lsqlite3
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
# build on the target system. Some of the C source code and header
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
target_source: $(SRC)
|
||||
rm -rf tsrc
|
||||
mkdir tsrc
|
||||
cp -f $(SRC) tsrc
|
||||
rm tsrc/sqlite.h.in tsrc/parse.y
|
||||
touch target_source
|
||||
|
||||
sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
tclsh $(TOP)/tool/mksqlite3c.tcl
|
||||
cp sqlite3.c tclsqlite3.c
|
||||
cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
|
||||
|
||||
fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl
|
||||
tclsh $(TOP)/ext/fts2/mkfts2amal.tcl
|
||||
|
||||
fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl
|
||||
tclsh $(TOP)/ext/fts3/mkfts3amal.tcl
|
||||
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lemon: $(TOP)/tool/lemon.c $(TOP)/src/lempar.c
|
||||
$(BCC) -o lemon $(TOP)/tool/lemon.c
|
||||
cp $(TOP)/src/lempar.c .
|
||||
|
||||
# Rules to build individual *.o files from generated *.c files. This
|
||||
# applies to:
|
||||
#
|
||||
# parse.o
|
||||
# opcodes.o
|
||||
#
|
||||
%.o: %.c $(HDR)
|
||||
$(TCCX_SHARED) -c $<
|
||||
|
||||
# Rules to build individual *.o files from files in the src directory.
|
||||
#
|
||||
%.o: $(TOP)/src/%.c $(HDR)
|
||||
$(TCCX_SHARED) -c $<
|
||||
|
||||
tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
$(TCCX_SHARED) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
|
||||
|
||||
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
|
||||
$(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
|
||||
cat parse.h $(TOP)/src/vdbe.c | \
|
||||
$(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
|
||||
cp $(TOP)/src/parse.y .
|
||||
rm -f parse.h
|
||||
./lemon $(OPTS) parse.y
|
||||
mv parse.h parse.h.temp
|
||||
awk -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
|
||||
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in
|
||||
sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
|
||||
-e s/--VERSION-NUMBER--/`cat ${TOP}/VERSION | sed 's/[^0-9]/ /g' | $(NAWK) '{printf "%d%03d%03d",$$1,$$2,$$3}'`/ \
|
||||
$(TOP)/src/sqlite.h.in >sqlite3.h
|
||||
|
||||
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
$(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
|
||||
./mkkeywordhash >keywordhash.h
|
||||
|
||||
|
||||
|
||||
# Rules to build the extension objects.
|
||||
#
|
||||
icu.o: $(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c
|
||||
|
||||
fts2.o: $(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c
|
||||
|
||||
fts2_hash.o: $(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c
|
||||
|
||||
fts2_icu.o: $(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c
|
||||
|
||||
fts2_porter.o: $(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c
|
||||
|
||||
fts2_tokenizer.o: $(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||
|
||||
fts2_tokenizer1.o: $(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c
|
||||
|
||||
fts3.o: $(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c
|
||||
|
||||
fts3_expr.o: $(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_expr.c
|
||||
|
||||
fts3_hash.o: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_hash.c
|
||||
|
||||
fts3_icu.o: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c
|
||||
|
||||
fts3_porter.o: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
|
||||
|
||||
fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
|
||||
|
||||
fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
|
||||
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
|
||||
# Rules for building test programs and for running tests
|
||||
#
|
||||
tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a
|
||||
$(TCCX_SHARED) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
|
||||
$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
|
||||
|
||||
|
||||
# Rules to build the 'testfixture' application.
|
||||
#
|
||||
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
|
||||
|
||||
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
|
||||
$(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB) libsqlite3.a
|
||||
|
||||
amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||
|
||||
fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
|
||||
-DSQLITE_ENABLE_FTS3=1 \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||
|
||||
fulltest: testfixture$(EXE) sqlite3$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/all.test
|
||||
|
||||
soaktest: testfixture$(EXE) sqlite3$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/all.test -soak=1
|
||||
|
||||
fulltestonly: testfixture$(EXE) sqlite3$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/full.test
|
||||
|
||||
test: testfixture$(EXE) sqlite3$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/veryquick.test
|
||||
|
||||
sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \
|
||||
$(TOP)/tool/spaceanal.tcl
|
||||
sed \
|
||||
-e '/^#/d' \
|
||||
-e 's,\\,\\\\,g' \
|
||||
-e 's,",\\",g' \
|
||||
-e 's,^,",' \
|
||||
-e 's,$$,\\n",' \
|
||||
$(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
|
||||
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
|
||||
-DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_DEBUG=1 -DSQLITE_PRIVATE="" \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
|
||||
-o sqlite3_analyzer$(EXE) \
|
||||
$(LIBTCL) $(THREADLIB)
|
||||
|
||||
TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO)
|
||||
$(TEST_EXTENSION): $(TOP)/src/test_loadext.c
|
||||
$(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION)
|
||||
|
||||
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
|
||||
./testfixture$(EXE) $(TOP)/test/loadext.test
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(EXE) libsqlite3.a sqlite3.h opcodes.*
|
||||
rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf quota2a quota2b quota2c
|
||||
rm -rf tsrc target_source
|
||||
rm -f testloadext.dll libtestloadext.so
|
||||
rm -f sqlite3.c fts?amal.c tclsqlite3.c
|
||||
rm -f sqlite3rc.h
|
||||
rm -f shell.c sqlite3ext.h
|
||||
rm -f $(SHPREFIX)sqlite3.$(SO)
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/usr/bin/awk
|
||||
#
|
||||
# This script appends additional token codes to the end of the
|
||||
# parse.h file that lemon generates. These extra token codes are
|
||||
# not used by the parser. But they are used by the tokenizer and/or
|
||||
# the code generator.
|
||||
#
|
||||
#
|
||||
BEGIN {
|
||||
max = 0
|
||||
}
|
||||
/^#define TK_/ {
|
||||
print $0
|
||||
if( max<$3 ) max = $3
|
||||
}
|
||||
END {
|
||||
printf "#define TK_%-29s %4d\n", "TO_TEXT", ++max
|
||||
printf "#define TK_%-29s %4d\n", "TO_BLOB", ++max
|
||||
printf "#define TK_%-29s %4d\n", "TO_NUMERIC", ++max
|
||||
printf "#define TK_%-29s %4d\n", "TO_INT", ++max
|
||||
printf "#define TK_%-29s %4d\n", "TO_REAL", ++max
|
||||
printf "#define TK_%-29s %4d\n", "ISNOT", ++max
|
||||
printf "#define TK_%-29s %4d\n", "END_OF_FILE", ++max
|
||||
printf "#define TK_%-29s %4d\n", "ILLEGAL", ++max
|
||||
printf "#define TK_%-29s %4d\n", "SPACE", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UNCLOSED_STRING", ++max
|
||||
printf "#define TK_%-29s %4d\n", "FUNCTION", ++max
|
||||
printf "#define TK_%-29s %4d\n", "COLUMN", ++max
|
||||
printf "#define TK_%-29s %4d\n", "AGG_FUNCTION", ++max
|
||||
printf "#define TK_%-29s %4d\n", "AGG_COLUMN", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UMINUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UPLUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "REGISTER", ++max
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
|
||||
@@ -78,6 +78,31 @@ AC_MSG_RESULT($enable_dynamic_extensions)
|
||||
AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts5
|
||||
#
|
||||
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
|
||||
[--enable-fts5], [include fts5 support [default=no]])],
|
||||
[], [enable_fts5=no])
|
||||
if test x"$enable_fts5" == "xyes"; then
|
||||
AC_SEARCH_LIBS(log, m)
|
||||
FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
|
||||
fi
|
||||
AC_SUBST(FTS5_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-json1
|
||||
#
|
||||
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
|
||||
[--enable-json1], [include json1 support [default=no]])],
|
||||
[], [enable_json1=no])
|
||||
if test x"$enable_json1" == "xyes"; then
|
||||
JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
|
||||
fi
|
||||
AC_SUBST(JSON1_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNCS(posix_fallocate)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.8.12.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.9.1.
|
||||
#
|
||||
#
|
||||
# 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.8.12'
|
||||
PACKAGE_STRING='sqlite 3.8.12'
|
||||
PACKAGE_VERSION='3.9.1'
|
||||
PACKAGE_STRING='sqlite 3.9.1'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -803,7 +803,6 @@ VERSION
|
||||
program_prefix
|
||||
TCLLIBDIR
|
||||
TCLSH_CMD
|
||||
AWK
|
||||
INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
INSTALL_PROGRAM
|
||||
@@ -902,6 +901,11 @@ with_readline_inc
|
||||
enable_debug
|
||||
enable_amalgamation
|
||||
enable_load_extension
|
||||
enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_rtree
|
||||
enable_gcov
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@@ -1454,7 +1458,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.8.12 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.9.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1519,7 +1523,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.12:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.9.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1544,6 +1548,11 @@ Optional Features:
|
||||
separately
|
||||
--disable-load-extension
|
||||
Disable loading of external extensions
|
||||
--enable-fts3 Enable the FTS3 extension
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-rtree Enable the RTREE extension
|
||||
--enable-gcov Enable coverage testing using gcov
|
||||
|
||||
Optional Packages:
|
||||
@@ -1634,7 +1643,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.8.12
|
||||
sqlite configure 3.9.1
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2053,7 +2062,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.8.12, which was
|
||||
It was created by sqlite $as_me 3.9.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3911,13 +3920,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3914: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3923: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3917: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3926: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3920: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3929: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5123,7 +5132,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5126 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5135 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6648,11 +6657,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6651: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6660: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6655: \$? = $ac_status" >&5
|
||||
echo "$as_me:6664: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -6987,11 +6996,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6990: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6999: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6994: \$? = $ac_status" >&5
|
||||
echo "$as_me:7003: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7092,11 +7101,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7095: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7104: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7099: \$? = $ac_status" >&5
|
||||
echo "$as_me:7108: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7147,11 +7156,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7150: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7159: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7154: \$? = $ac_status" >&5
|
||||
echo "$as_me:7163: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9527,7 +9536,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9530 "configure"
|
||||
#line 9539 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9623,7 +9632,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9626 "configure"
|
||||
#line 9635 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9943,48 +9952,6 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
|
||||
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
|
||||
for ac_prog in gawk mawk nawk awk
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_AWK+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$AWK"; then
|
||||
ac_cv_prog_AWK="$AWK" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_AWK="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
AWK=$ac_cv_prog_AWK
|
||||
if test -n "$AWK"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
|
||||
$as_echo "$AWK" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$AWK" && break
|
||||
done
|
||||
|
||||
|
||||
#########
|
||||
# Enable large file support (if special flags are necessary)
|
||||
@@ -11223,6 +11190,177 @@ else
|
||||
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
# Check whether --enable-fts3 was given.
|
||||
if test "${enable_fts3+set}" = set; then :
|
||||
enableval=$enable_fts3; enable_fts3=yes
|
||||
else
|
||||
enable_fts3=no
|
||||
fi
|
||||
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
# Check whether --enable-fts4 was given.
|
||||
if test "${enable_fts4+set}" = set; then :
|
||||
enableval=$enable_fts4; enable_fts4=yes
|
||||
else
|
||||
enable_fts4=no
|
||||
fi
|
||||
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char log ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return log ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' m; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_log=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_log=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
|
||||
$as_echo "$ac_cv_search_log" >&6; }
|
||||
ac_res=$ac_cv_search_log
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
# Check whether --enable-fts5 was given.
|
||||
if test "${enable_fts5+set}" = set; then :
|
||||
enableval=$enable_fts5; enable_fts5=yes
|
||||
else
|
||||
enable_fts5=no
|
||||
fi
|
||||
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char log ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return log ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' m; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_log=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_log=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
|
||||
$as_echo "$ac_cv_search_log" >&6; }
|
||||
ac_res=$ac_cv_search_log
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
# Check whether --enable-json1 was given.
|
||||
if test "${enable_json1+set}" = set; then :
|
||||
enableval=$enable_json1; enable_json1=yes
|
||||
else
|
||||
enable_json1=no
|
||||
fi
|
||||
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
# Check whether --enable-rtree was given.
|
||||
if test "${enable_rtree+set}" = set; then :
|
||||
enableval=$enable_rtree; enable_rtree=yes
|
||||
else
|
||||
enable_rtree=no
|
||||
fi
|
||||
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
@@ -11808,7 +11946,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.8.12, which was
|
||||
This file was extended by sqlite $as_me 3.9.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -11874,7 +12012,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.8.12
|
||||
sqlite config.status 3.9.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
@@ -11885,7 +12023,6 @@ gives unlimited permission to copy, distribute and modify it."
|
||||
ac_pwd='$ac_pwd'
|
||||
srcdir='$srcdir'
|
||||
INSTALL='$INSTALL'
|
||||
AWK='$AWK'
|
||||
test -n "\$AWK" || AWK=awk
|
||||
_ACEOF
|
||||
|
||||
|
||||
+41
-1
@@ -90,7 +90,6 @@ fi
|
||||
#
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_AWK
|
||||
|
||||
#########
|
||||
# Enable large file support (if special flags are necessary)
|
||||
@@ -560,6 +559,47 @@ else
|
||||
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
||||
[Enable the FTS3 extension]),
|
||||
[enable_fts3=yes],[enable_fts3=no])
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]),
|
||||
[enable_fts4=yes],[enable_fts4=no])
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]),
|
||||
[enable_fts5=yes],[enable_fts5=no])
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
|
||||
[Enable the JSON1 extension]),
|
||||
[enable_json1=yes],[enable_json1=no])
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
[Enable the RTREE extension]),
|
||||
[enable_rtree=yes],[enable_rtree=no])
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
|
||||
@@ -1517,6 +1517,19 @@ static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
|
||||
** extension is currently being used by a version of SQLite too old to
|
||||
** support index-info flags. In that case this function is a no-op.
|
||||
*/
|
||||
static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
||||
#if SQLITE_VERSION_NUMBER>=3008012
|
||||
if( sqlite3_libversion_number()>=3008012 ){
|
||||
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the xBestIndex method for FTS3 tables. There
|
||||
** are three possible strategies, in order of preference:
|
||||
@@ -1607,6 +1620,9 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
}
|
||||
}
|
||||
|
||||
/* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */
|
||||
if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo);
|
||||
|
||||
iIdx = 1;
|
||||
if( iCons>=0 ){
|
||||
pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
|
||||
|
||||
@@ -264,6 +264,7 @@ struct Fts3Table {
|
||||
int nPendingData; /* Current bytes of pending data */
|
||||
sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
|
||||
int iPrevLangid; /* Langid of recently inserted document */
|
||||
int bPrevDelete; /* True if last operation was a delete */
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
/* State variables used for validating that the transaction control
|
||||
|
||||
+126
-100
@@ -793,125 +793,151 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
|
||||
Fts3Expr **apLeaf;
|
||||
apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
|
||||
if( 0==apLeaf ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int i;
|
||||
Fts3Expr *p;
|
||||
|
||||
/* Set $p to point to the left-most leaf in the tree of eType nodes. */
|
||||
for(p=pRoot; p->eType==eType; p=p->pLeft){
|
||||
assert( p->pParent==0 || p->pParent->pLeft==p );
|
||||
assert( p->pLeft && p->pRight );
|
||||
}
|
||||
|
||||
/* This loop runs once for each leaf in the tree of eType nodes. */
|
||||
while( 1 ){
|
||||
int iLvl;
|
||||
Fts3Expr *pParent = p->pParent; /* Current parent of p */
|
||||
|
||||
assert( pParent==0 || pParent->pLeft==p );
|
||||
p->pParent = 0;
|
||||
if( pParent ){
|
||||
pParent->pLeft = 0;
|
||||
}else{
|
||||
pRoot = 0;
|
||||
}
|
||||
rc = fts3ExprBalance(&p, nMaxDepth-1);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
|
||||
for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
|
||||
if( apLeaf[iLvl]==0 ){
|
||||
apLeaf[iLvl] = p;
|
||||
p = 0;
|
||||
}else{
|
||||
assert( pFree );
|
||||
pFree->pLeft = apLeaf[iLvl];
|
||||
pFree->pRight = p;
|
||||
pFree->pLeft->pParent = pFree;
|
||||
pFree->pRight->pParent = pFree;
|
||||
|
||||
p = pFree;
|
||||
pFree = pFree->pParent;
|
||||
p->pParent = 0;
|
||||
apLeaf[iLvl] = 0;
|
||||
}
|
||||
}
|
||||
if( p ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_TOOBIG;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If that was the last leaf node, break out of the loop */
|
||||
if( pParent==0 ) break;
|
||||
|
||||
/* Set $p to point to the next leaf in the tree of eType nodes */
|
||||
for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
|
||||
|
||||
/* Remove pParent from the original tree. */
|
||||
assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
|
||||
pParent->pRight->pParent = pParent->pParent;
|
||||
if( pParent->pParent ){
|
||||
pParent->pParent->pLeft = pParent->pRight;
|
||||
}else{
|
||||
assert( pParent==pRoot );
|
||||
pRoot = pParent->pRight;
|
||||
}
|
||||
|
||||
/* Link pParent into the free node list. It will be used as an
|
||||
** internal node of the new tree. */
|
||||
pParent->pParent = pFree;
|
||||
pFree = pParent;
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
|
||||
Fts3Expr **apLeaf;
|
||||
apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
|
||||
if( 0==apLeaf ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
p = 0;
|
||||
for(i=0; i<nMaxDepth; i++){
|
||||
if( apLeaf[i] ){
|
||||
if( p==0 ){
|
||||
p = apLeaf[i];
|
||||
p->pParent = 0;
|
||||
int i;
|
||||
Fts3Expr *p;
|
||||
|
||||
/* Set $p to point to the left-most leaf in the tree of eType nodes. */
|
||||
for(p=pRoot; p->eType==eType; p=p->pLeft){
|
||||
assert( p->pParent==0 || p->pParent->pLeft==p );
|
||||
assert( p->pLeft && p->pRight );
|
||||
}
|
||||
|
||||
/* This loop runs once for each leaf in the tree of eType nodes. */
|
||||
while( 1 ){
|
||||
int iLvl;
|
||||
Fts3Expr *pParent = p->pParent; /* Current parent of p */
|
||||
|
||||
assert( pParent==0 || pParent->pLeft==p );
|
||||
p->pParent = 0;
|
||||
if( pParent ){
|
||||
pParent->pLeft = 0;
|
||||
}else{
|
||||
pRoot = 0;
|
||||
}
|
||||
rc = fts3ExprBalance(&p, nMaxDepth-1);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
|
||||
for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
|
||||
if( apLeaf[iLvl]==0 ){
|
||||
apLeaf[iLvl] = p;
|
||||
p = 0;
|
||||
}else{
|
||||
assert( pFree!=0 );
|
||||
assert( pFree );
|
||||
pFree->pLeft = apLeaf[iLvl];
|
||||
pFree->pRight = p;
|
||||
pFree->pLeft = apLeaf[i];
|
||||
pFree->pLeft->pParent = pFree;
|
||||
pFree->pRight->pParent = pFree;
|
||||
|
||||
p = pFree;
|
||||
pFree = pFree->pParent;
|
||||
p->pParent = 0;
|
||||
apLeaf[iLvl] = 0;
|
||||
}
|
||||
}
|
||||
if( p ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_TOOBIG;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If that was the last leaf node, break out of the loop */
|
||||
if( pParent==0 ) break;
|
||||
|
||||
/* Set $p to point to the next leaf in the tree of eType nodes */
|
||||
for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
|
||||
|
||||
/* Remove pParent from the original tree. */
|
||||
assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
|
||||
pParent->pRight->pParent = pParent->pParent;
|
||||
if( pParent->pParent ){
|
||||
pParent->pParent->pLeft = pParent->pRight;
|
||||
}else{
|
||||
assert( pParent==pRoot );
|
||||
pRoot = pParent->pRight;
|
||||
}
|
||||
|
||||
/* Link pParent into the free node list. It will be used as an
|
||||
** internal node of the new tree. */
|
||||
pParent->pParent = pFree;
|
||||
pFree = pParent;
|
||||
}
|
||||
pRoot = p;
|
||||
}else{
|
||||
/* An error occurred. Delete the contents of the apLeaf[] array
|
||||
** and pFree list. Everything else is cleaned up by the call to
|
||||
** sqlite3Fts3ExprFree(pRoot) below. */
|
||||
Fts3Expr *pDel;
|
||||
for(i=0; i<nMaxDepth; i++){
|
||||
sqlite3Fts3ExprFree(apLeaf[i]);
|
||||
}
|
||||
while( (pDel=pFree)!=0 ){
|
||||
pFree = pDel->pParent;
|
||||
sqlite3_free(pDel);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
p = 0;
|
||||
for(i=0; i<nMaxDepth; i++){
|
||||
if( apLeaf[i] ){
|
||||
if( p==0 ){
|
||||
p = apLeaf[i];
|
||||
p->pParent = 0;
|
||||
}else{
|
||||
assert( pFree!=0 );
|
||||
pFree->pRight = p;
|
||||
pFree->pLeft = apLeaf[i];
|
||||
pFree->pLeft->pParent = pFree;
|
||||
pFree->pRight->pParent = pFree;
|
||||
|
||||
p = pFree;
|
||||
pFree = pFree->pParent;
|
||||
p->pParent = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
pRoot = p;
|
||||
}else{
|
||||
/* An error occurred. Delete the contents of the apLeaf[] array
|
||||
** and pFree list. Everything else is cleaned up by the call to
|
||||
** sqlite3Fts3ExprFree(pRoot) below. */
|
||||
Fts3Expr *pDel;
|
||||
for(i=0; i<nMaxDepth; i++){
|
||||
sqlite3Fts3ExprFree(apLeaf[i]);
|
||||
}
|
||||
while( (pDel=pFree)!=0 ){
|
||||
pFree = pDel->pParent;
|
||||
sqlite3_free(pDel);
|
||||
}
|
||||
}
|
||||
|
||||
assert( pFree==0 );
|
||||
sqlite3_free( apLeaf );
|
||||
}
|
||||
}else if( eType==FTSQUERY_NOT ){
|
||||
Fts3Expr *pLeft = pRoot->pLeft;
|
||||
Fts3Expr *pRight = pRoot->pRight;
|
||||
|
||||
pRoot->pLeft = 0;
|
||||
pRoot->pRight = 0;
|
||||
pLeft->pParent = 0;
|
||||
pRight->pParent = 0;
|
||||
|
||||
rc = fts3ExprBalance(&pLeft, nMaxDepth-1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts3ExprBalance(&pRight, nMaxDepth-1);
|
||||
}
|
||||
|
||||
assert( pFree==0 );
|
||||
sqlite3_free( apLeaf );
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Fts3ExprFree(pRight);
|
||||
sqlite3Fts3ExprFree(pLeft);
|
||||
}else{
|
||||
assert( pLeft && pRight );
|
||||
pRoot->pLeft = pLeft;
|
||||
pLeft->pParent = pRoot;
|
||||
pRoot->pRight = pRight;
|
||||
pRight->pParent = pRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Fts3ExprFree(pRoot);
|
||||
pRoot = 0;
|
||||
|
||||
+24
-12
@@ -860,10 +860,12 @@ static int fts3PendingTermsAdd(
|
||||
*/
|
||||
static int fts3PendingTermsDocid(
|
||||
Fts3Table *p, /* Full-text table handle */
|
||||
int bDelete, /* True if this op is a delete */
|
||||
int iLangid, /* Language id of row being written */
|
||||
sqlite_int64 iDocid /* Docid of row being written */
|
||||
){
|
||||
assert( iLangid>=0 );
|
||||
assert( bDelete==1 || bDelete==0 );
|
||||
|
||||
/* TODO(shess) Explore whether partially flushing the buffer on
|
||||
** forced-flush would provide better performance. I suspect that if
|
||||
@@ -871,7 +873,8 @@ static int fts3PendingTermsDocid(
|
||||
** buffer was half empty, that would let the less frequent terms
|
||||
** generate longer doclists.
|
||||
*/
|
||||
if( iDocid<=p->iPrevDocid
|
||||
if( iDocid<p->iPrevDocid
|
||||
|| (iDocid==p->iPrevDocid && p->bPrevDelete==0)
|
||||
|| p->iPrevLangid!=iLangid
|
||||
|| p->nPendingData>p->nMaxPendingData
|
||||
){
|
||||
@@ -880,6 +883,7 @@ static int fts3PendingTermsDocid(
|
||||
}
|
||||
p->iPrevDocid = iDocid;
|
||||
p->iPrevLangid = iLangid;
|
||||
p->bPrevDelete = bDelete;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1069,7 +1073,8 @@ static void fts3DeleteTerms(
|
||||
if( SQLITE_ROW==sqlite3_step(pSelect) ){
|
||||
int i;
|
||||
int iLangid = langidFromSelect(p, pSelect);
|
||||
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
|
||||
i64 iDocid = sqlite3_column_int64(pSelect, 0);
|
||||
rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid);
|
||||
for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
|
||||
int iCol = i-1;
|
||||
if( p->abNotindexed[iCol]==0 ){
|
||||
@@ -1317,14 +1322,19 @@ static int fts3SegReaderNext(
|
||||
|
||||
if( fts3SegReaderIsPending(pReader) ){
|
||||
Fts3HashElem *pElem = *(pReader->ppNextElem);
|
||||
if( pElem==0 ){
|
||||
pReader->aNode = 0;
|
||||
}else{
|
||||
sqlite3_free(pReader->aNode);
|
||||
pReader->aNode = 0;
|
||||
if( pElem ){
|
||||
char *aCopy;
|
||||
PendingList *pList = (PendingList *)fts3HashData(pElem);
|
||||
int nCopy = pList->nData+1;
|
||||
pReader->zTerm = (char *)fts3HashKey(pElem);
|
||||
pReader->nTerm = fts3HashKeysize(pElem);
|
||||
pReader->nNode = pReader->nDoclist = pList->nData + 1;
|
||||
pReader->aNode = pReader->aDoclist = pList->aData;
|
||||
aCopy = (char*)sqlite3_malloc(nCopy);
|
||||
if( !aCopy ) return SQLITE_NOMEM;
|
||||
memcpy(aCopy, pList->aData, nCopy);
|
||||
pReader->nNode = pReader->nDoclist = nCopy;
|
||||
pReader->aNode = pReader->aDoclist = aCopy;
|
||||
pReader->ppNextElem++;
|
||||
assert( pReader->aNode );
|
||||
}
|
||||
@@ -1564,12 +1574,14 @@ int sqlite3Fts3MsrOvfl(
|
||||
** second argument.
|
||||
*/
|
||||
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
|
||||
if( pReader && !fts3SegReaderIsPending(pReader) ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
if( pReader ){
|
||||
if( !fts3SegReaderIsPending(pReader) ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
}
|
||||
if( !fts3SegReaderIsRootOnly(pReader) ){
|
||||
sqlite3_free(pReader->aNode);
|
||||
sqlite3_blob_close(pReader->pBlob);
|
||||
}
|
||||
sqlite3_blob_close(pReader->pBlob);
|
||||
}
|
||||
sqlite3_free(pReader);
|
||||
}
|
||||
@@ -3512,7 +3524,7 @@ static int fts3DoRebuild(Fts3Table *p){
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int iCol;
|
||||
int iLangid = langidFromSelect(p, pStmt);
|
||||
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
|
||||
rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0));
|
||||
memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
|
||||
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
|
||||
if( p->abNotindexed[iCol]==0 ){
|
||||
@@ -5617,7 +5629,7 @@ int sqlite3Fts3UpdateMethod(
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
|
||||
rc = fts3PendingTermsDocid(p, iLangid, *pRowid);
|
||||
rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p->iPrevDocid==*pRowid );
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
** CUSTOM AUXILIARY FUNCTIONS
|
||||
**
|
||||
@@ -508,5 +512,9 @@ struct fts5_api {
|
||||
** END OF REGISTRATION API
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
#endif
|
||||
|
||||
#endif /* _FTS5_H */
|
||||
|
||||
|
||||
+40
-15
@@ -81,6 +81,20 @@ extern int sqlite3_fts5_may_be_corrupt;
|
||||
#endif
|
||||
|
||||
typedef struct Fts5Global Fts5Global;
|
||||
typedef struct Fts5Colset Fts5Colset;
|
||||
|
||||
/* If a NEAR() clump or phrase may only match a specific set of columns,
|
||||
** then an object of the following type is used to record the set of columns.
|
||||
** Each entry in the aiCol[] array is a column that may be matched.
|
||||
**
|
||||
** This object is used by fts5_expr.c and fts5_index.c.
|
||||
*/
|
||||
struct Fts5Colset {
|
||||
int nCol;
|
||||
int aiCol[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_config.c. fts5_config.c contains contains code
|
||||
@@ -210,7 +224,7 @@ struct Fts5Buffer {
|
||||
int nSpace;
|
||||
};
|
||||
|
||||
int sqlite3Fts5BufferGrow(int*, Fts5Buffer*, int);
|
||||
int sqlite3Fts5BufferSize(int*, Fts5Buffer*, int);
|
||||
void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64);
|
||||
void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, int, const u8*);
|
||||
void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*);
|
||||
@@ -218,17 +232,19 @@ void sqlite3Fts5BufferFree(Fts5Buffer*);
|
||||
void sqlite3Fts5BufferZero(Fts5Buffer*);
|
||||
void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*);
|
||||
void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
|
||||
void sqlite3Fts5BufferAppend32(int*, Fts5Buffer*, int);
|
||||
|
||||
char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
|
||||
|
||||
#define fts5BufferZero(x) sqlite3Fts5BufferZero(x)
|
||||
#define fts5BufferGrow(a,b,c) sqlite3Fts5BufferGrow(a,b,c)
|
||||
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
|
||||
#define fts5BufferFree(a) sqlite3Fts5BufferFree(a)
|
||||
#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
|
||||
#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d)
|
||||
#define fts5BufferAppend32(a,b,c) sqlite3Fts5BufferAppend32(a,b,c)
|
||||
|
||||
#define fts5BufferGrow(pRc,pBuf,nn) ( \
|
||||
(pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \
|
||||
sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \
|
||||
)
|
||||
|
||||
/* Write and decode big-endian 32-bit integer values */
|
||||
void sqlite3Fts5Put32(u8*, int);
|
||||
@@ -240,7 +256,6 @@ int sqlite3Fts5Get32(const u8*);
|
||||
typedef struct Fts5PoslistReader Fts5PoslistReader;
|
||||
struct Fts5PoslistReader {
|
||||
/* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */
|
||||
int iCol; /* If (iCol>=0), this column only */
|
||||
const u8 *a; /* Position list to iterate through */
|
||||
int n; /* Size of buffer at a[] in bytes */
|
||||
int i; /* Current offset in a[] */
|
||||
@@ -252,7 +267,6 @@ struct Fts5PoslistReader {
|
||||
i64 iPos; /* (iCol<<32) + iPos */
|
||||
};
|
||||
int sqlite3Fts5PoslistReaderInit(
|
||||
int iCol, /* If (iCol>=0), this column only */
|
||||
const u8 *a, int n, /* Poslist buffer to iterate through */
|
||||
Fts5PoslistReader *pIter /* Iterator object to initialize */
|
||||
);
|
||||
@@ -305,7 +319,7 @@ int sqlite3Fts5IndexClose(Fts5Index *p);
|
||||
|
||||
/*
|
||||
** for(
|
||||
** pIter = sqlite3Fts5IndexQuery(p, "token", 5, 0);
|
||||
** sqlite3Fts5IndexQuery(p, "token", 5, 0, 0, &pIter);
|
||||
** 0==sqlite3Fts5IterEof(pIter);
|
||||
** sqlite3Fts5IterNext(pIter)
|
||||
** ){
|
||||
@@ -321,7 +335,8 @@ int sqlite3Fts5IndexQuery(
|
||||
Fts5Index *p, /* FTS index to query */
|
||||
const char *pToken, int nToken, /* Token (or prefix) to query for */
|
||||
int flags, /* Mask of FTS5INDEX_QUERY_X flags */
|
||||
Fts5IndexIter **ppIter
|
||||
Fts5Colset *pColset, /* Match these columns only */
|
||||
Fts5IndexIter **ppIter /* OUT: New iterator object */
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -332,7 +347,7 @@ int sqlite3Fts5IterEof(Fts5IndexIter*);
|
||||
int sqlite3Fts5IterNext(Fts5IndexIter*);
|
||||
int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
|
||||
i64 sqlite3Fts5IterRowid(Fts5IndexIter*);
|
||||
int sqlite3Fts5IterPoslist(Fts5IndexIter*, const u8 **pp, int *pn, i64 *pi);
|
||||
int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*);
|
||||
int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf);
|
||||
|
||||
/*
|
||||
@@ -370,6 +385,7 @@ int sqlite3Fts5IndexWrite(
|
||||
*/
|
||||
int sqlite3Fts5IndexBeginWrite(
|
||||
Fts5Index *p, /* Index to write to */
|
||||
int bDelete, /* True if current operation is a delete */
|
||||
i64 iDocid /* Docid to add or remove data from */
|
||||
);
|
||||
|
||||
@@ -434,6 +450,15 @@ int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
|
||||
#define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b)
|
||||
#define fts5GetVarint sqlite3Fts5GetVarint
|
||||
|
||||
#define fts5FastGetVarint32(a, iOff, nVal) { \
|
||||
nVal = (a)[iOff++]; \
|
||||
if( nVal & 0x80 ){ \
|
||||
iOff--; \
|
||||
iOff += fts5GetVarint32(&(a)[iOff], nVal); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_varint.c.
|
||||
**************************************************************************/
|
||||
@@ -452,7 +477,7 @@ int sqlite3Fts5GetTokenizer(
|
||||
char **pzErr
|
||||
);
|
||||
|
||||
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, int*);
|
||||
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5.c.
|
||||
@@ -526,7 +551,8 @@ int sqlite3Fts5DropAll(Fts5Config*);
|
||||
int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
|
||||
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64);
|
||||
int sqlite3Fts5StorageInsert(Fts5Storage *p, sqlite3_value **apVal, int, i64*);
|
||||
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
|
||||
int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
|
||||
|
||||
int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
|
||||
|
||||
@@ -565,7 +591,6 @@ typedef struct Fts5Parse Fts5Parse;
|
||||
typedef struct Fts5Token Fts5Token;
|
||||
typedef struct Fts5ExprPhrase Fts5ExprPhrase;
|
||||
typedef struct Fts5ExprNearset Fts5ExprNearset;
|
||||
typedef struct Fts5ExprColset Fts5ExprColset;
|
||||
|
||||
struct Fts5Token {
|
||||
const char *p; /* Token text (not NULL terminated) */
|
||||
@@ -633,9 +658,9 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
Fts5ExprPhrase*
|
||||
);
|
||||
|
||||
Fts5ExprColset *sqlite3Fts5ParseColset(
|
||||
Fts5Colset *sqlite3Fts5ParseColset(
|
||||
Fts5Parse*,
|
||||
Fts5ExprColset*,
|
||||
Fts5Colset*,
|
||||
Fts5Token *
|
||||
);
|
||||
|
||||
@@ -644,7 +669,7 @@ void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
|
||||
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
|
||||
|
||||
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
|
||||
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5ExprColset*);
|
||||
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
|
||||
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
|
||||
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
|
||||
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
#include "fts5Int.h"
|
||||
#include <math.h>
|
||||
#include <math.h> /* amalgamator: keep */
|
||||
|
||||
/*
|
||||
** Object used to iterate through all "coalesced phrase instances" in
|
||||
@@ -137,7 +137,7 @@ static void fts5HighlightAppend(
|
||||
const char *z, int n
|
||||
){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
if( n<0 ) n = strlen(z);
|
||||
if( n<0 ) n = (int)strlen(z);
|
||||
p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
|
||||
if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
+33
-48
@@ -15,36 +15,30 @@
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
int sqlite3Fts5BufferGrow(int *pRc, Fts5Buffer *pBuf, int nByte){
|
||||
|
||||
if( (pBuf->n + nByte) > pBuf->nSpace ){
|
||||
u8 *pNew;
|
||||
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
|
||||
|
||||
/* A no-op if an error has already occurred */
|
||||
if( *pRc ) return 1;
|
||||
|
||||
while( nNew<(pBuf->n + nByte) ){
|
||||
nNew = nNew * 2;
|
||||
}
|
||||
pNew = sqlite3_realloc(pBuf->p, nNew);
|
||||
if( pNew==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
return 1;
|
||||
}else{
|
||||
pBuf->nSpace = nNew;
|
||||
pBuf->p = pNew;
|
||||
}
|
||||
int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, int nByte){
|
||||
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
|
||||
u8 *pNew;
|
||||
while( nNew<nByte ){
|
||||
nNew = nNew * 2;
|
||||
}
|
||||
pNew = sqlite3_realloc(pBuf->p, nNew);
|
||||
if( pNew==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
return 1;
|
||||
}else{
|
||||
pBuf->nSpace = nNew;
|
||||
pBuf->p = pNew;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Encode value iVal as an SQLite varint and append it to the buffer object
|
||||
** pBuf. If an OOM error occurs, set the error code in p.
|
||||
*/
|
||||
void sqlite3Fts5BufferAppendVarint(int *pRc, Fts5Buffer *pBuf, i64 iVal){
|
||||
if( sqlite3Fts5BufferGrow(pRc, pBuf, 9) ) return;
|
||||
if( fts5BufferGrow(pRc, pBuf, 9) ) return;
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iVal);
|
||||
}
|
||||
|
||||
@@ -59,12 +53,6 @@ int sqlite3Fts5Get32(const u8 *aBuf){
|
||||
return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
|
||||
}
|
||||
|
||||
void sqlite3Fts5BufferAppend32(int *pRc, Fts5Buffer *pBuf, int iVal){
|
||||
if( sqlite3Fts5BufferGrow(pRc, pBuf, 4) ) return;
|
||||
sqlite3Fts5Put32(&pBuf->p[pBuf->n], iVal);
|
||||
pBuf->n += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set
|
||||
** the error code in p. If an error has already occurred when this function
|
||||
@@ -77,7 +65,7 @@ void sqlite3Fts5BufferAppendBlob(
|
||||
const u8 *pData
|
||||
){
|
||||
assert( *pRc || nData>=0 );
|
||||
if( sqlite3Fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||
pBuf->n += nData;
|
||||
}
|
||||
@@ -92,7 +80,7 @@ void sqlite3Fts5BufferAppendString(
|
||||
Fts5Buffer *pBuf,
|
||||
const char *zStr
|
||||
){
|
||||
int nStr = strlen(zStr);
|
||||
int nStr = (int)strlen(zStr);
|
||||
sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr);
|
||||
pBuf->n--;
|
||||
}
|
||||
@@ -185,11 +173,11 @@ int sqlite3Fts5PoslistNext64(
|
||||
}else{
|
||||
i64 iOff = *piOff;
|
||||
int iVal;
|
||||
i += fts5GetVarint32(&a[i], iVal);
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal==1 ){
|
||||
i += fts5GetVarint32(&a[i], iVal);
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
iOff = ((i64)iVal) << 32;
|
||||
i += fts5GetVarint32(&a[i], iVal);
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
}
|
||||
*piOff = iOff + (iVal-2);
|
||||
*pi = i;
|
||||
@@ -203,26 +191,20 @@ int sqlite3Fts5PoslistNext64(
|
||||
** if the iterator reaches EOF, or false otherwise.
|
||||
*/
|
||||
int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){
|
||||
if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos)
|
||||
|| (pIter->iCol>=0 && (pIter->iPos >> 32) > pIter->iCol)
|
||||
){
|
||||
if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){
|
||||
pIter->bEof = 1;
|
||||
}
|
||||
return pIter->bEof;
|
||||
}
|
||||
|
||||
int sqlite3Fts5PoslistReaderInit(
|
||||
int iCol, /* If (iCol>=0), this column only */
|
||||
const u8 *a, int n, /* Poslist buffer to iterate through */
|
||||
Fts5PoslistReader *pIter /* Iterator object to initialize */
|
||||
){
|
||||
memset(pIter, 0, sizeof(*pIter));
|
||||
pIter->a = a;
|
||||
pIter->n = n;
|
||||
pIter->iCol = iCol;
|
||||
do {
|
||||
sqlite3Fts5PoslistReaderNext(pIter);
|
||||
}while( pIter->bEof==0 && (pIter->iPos >> 32)<iCol );
|
||||
sqlite3Fts5PoslistReaderNext(pIter);
|
||||
return pIter->bEof;
|
||||
}
|
||||
|
||||
@@ -233,13 +215,15 @@ int sqlite3Fts5PoslistWriterAppend(
|
||||
){
|
||||
static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
|
||||
int rc = SQLITE_OK;
|
||||
if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
|
||||
fts5BufferAppendVarint(&rc, pBuf, 1);
|
||||
fts5BufferAppendVarint(&rc, pBuf, (iPos >> 32));
|
||||
pWriter->iPrev = (iPos & colmask);
|
||||
if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){
|
||||
if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
|
||||
pBuf->p[pBuf->n++] = 1;
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
|
||||
pWriter->iPrev = (iPos & colmask);
|
||||
}
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2);
|
||||
pWriter->iPrev = iPos;
|
||||
}
|
||||
fts5BufferAppendVarint(&rc, pBuf, (iPos - pWriter->iPrev) + 2);
|
||||
pWriter->iPrev = iPos;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -268,7 +252,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
char *zRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
if( nIn<0 ){
|
||||
nIn = strlen(pIn);
|
||||
nIn = (int)strlen(pIn);
|
||||
}
|
||||
zRet = (char*)sqlite3_malloc(nIn+1);
|
||||
if( zRet ){
|
||||
@@ -290,11 +274,12 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
** * The 52 upper and lower case ASCII characters, and
|
||||
** * The 10 integer ASCII characters.
|
||||
** * The underscore character "_" (0x5F).
|
||||
** * The unicode "subsitute" character (0x1A).
|
||||
*/
|
||||
int sqlite3Fts5IsBareword(char t){
|
||||
u8 aBareword[128] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 .. 0x2F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30 .. 0x3F */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 .. 0x4F */
|
||||
|
||||
@@ -211,7 +211,7 @@ static int fts5ConfigParseSpecial(
|
||||
char **pzErr /* OUT: Error message */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nCmd = strlen(zCmd);
|
||||
int nCmd = (int)strlen(zCmd);
|
||||
if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
|
||||
const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
|
||||
const char *p;
|
||||
@@ -248,7 +248,7 @@ static int fts5ConfigParseSpecial(
|
||||
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
const char *p = (const char*)zArg;
|
||||
int nArg = strlen(zArg) + 1;
|
||||
int nArg = (int)strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
|
||||
char *pSpace = pDel;
|
||||
@@ -364,7 +364,7 @@ static const char *fts5ConfigGobbleWord(
|
||||
){
|
||||
const char *zRet = 0;
|
||||
|
||||
int nIn = strlen(zIn);
|
||||
int nIn = (int)strlen(zIn);
|
||||
char *zOut = sqlite3_malloc(nIn+1);
|
||||
|
||||
assert( *pRc==SQLITE_OK );
|
||||
|
||||
+42
-128
@@ -32,6 +32,11 @@ typedef struct Fts5ExprTerm Fts5ExprTerm;
|
||||
void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(u64));
|
||||
void sqlite3Fts5ParserFree(void*, void (*freeProc)(void*));
|
||||
void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*);
|
||||
#ifndef NDEBUG
|
||||
#include <stdio.h>
|
||||
void sqlite3Fts5ParserTrace(FILE*, char*);
|
||||
#endif
|
||||
|
||||
|
||||
struct Fts5Expr {
|
||||
Fts5Index *pIndex;
|
||||
@@ -89,23 +94,13 @@ struct Fts5ExprPhrase {
|
||||
Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
|
||||
};
|
||||
|
||||
/*
|
||||
** If a NEAR() clump may only match a specific set of columns, then
|
||||
** Fts5ExprNearset.pColset points to an object of the following type.
|
||||
** Each entry in the aiCol[] array
|
||||
*/
|
||||
struct Fts5ExprColset {
|
||||
int nCol;
|
||||
int aiCol[1];
|
||||
};
|
||||
|
||||
/*
|
||||
** One or more phrases that must appear within a certain token distance of
|
||||
** each other within each matching document.
|
||||
*/
|
||||
struct Fts5ExprNearset {
|
||||
int nNear; /* NEAR parameter */
|
||||
Fts5ExprColset *pColset; /* Columns to search (NULL -> all columns) */
|
||||
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
|
||||
int nPhrase; /* Number of entries in aPhrase[] array */
|
||||
Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
|
||||
};
|
||||
@@ -276,14 +271,6 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){
|
||||
}
|
||||
}
|
||||
|
||||
static int fts5ExprColsetTest(Fts5ExprColset *pColset, int iCol){
|
||||
int i;
|
||||
for(i=0; i<pColset->nCol; i++){
|
||||
if( pColset->aiCol[i]==iCol ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument pTerm must be a synonym iterator. Return the current rowid
|
||||
** that it points to.
|
||||
@@ -314,6 +301,7 @@ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
|
||||
*/
|
||||
static int fts5ExprSynonymPoslist(
|
||||
Fts5ExprTerm *pTerm,
|
||||
Fts5Colset *pColset,
|
||||
i64 iRowid,
|
||||
int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */
|
||||
u8 **pa, int *pn
|
||||
@@ -332,7 +320,7 @@ static int fts5ExprSynonymPoslist(
|
||||
const u8 *a;
|
||||
int n;
|
||||
i64 dummy;
|
||||
rc = sqlite3Fts5IterPoslist(pIter, &a, &n, &dummy);
|
||||
rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
|
||||
if( rc!=SQLITE_OK ) goto synonym_poslist_out;
|
||||
if( nIter==nAlloc ){
|
||||
int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
|
||||
@@ -346,7 +334,7 @@ static int fts5ExprSynonymPoslist(
|
||||
if( aIter!=aStatic ) sqlite3_free(aIter);
|
||||
aIter = aNew;
|
||||
}
|
||||
sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[nIter]);
|
||||
sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]);
|
||||
assert( aIter[nIter].bEof==0 );
|
||||
nIter++;
|
||||
}
|
||||
@@ -405,7 +393,7 @@ static int fts5ExprSynonymPoslist(
|
||||
*/
|
||||
static int fts5ExprPhraseIsMatch(
|
||||
Fts5ExprNode *pNode, /* Node pPhrase belongs to */
|
||||
Fts5ExprColset *pColset, /* Restrict matches to these columns */
|
||||
Fts5Colset *pColset, /* Restrict matches to these columns */
|
||||
Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */
|
||||
int *pbMatch /* OUT: Set to true if really a match */
|
||||
){
|
||||
@@ -414,13 +402,7 @@ static int fts5ExprPhraseIsMatch(
|
||||
Fts5PoslistReader *aIter = aStatic;
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
int iCol = -1;
|
||||
|
||||
if( pColset && pColset->nCol==1 ){
|
||||
iCol = pColset->aiCol[0];
|
||||
pColset = 0;
|
||||
}
|
||||
|
||||
fts5BufferZero(&pPhrase->poslist);
|
||||
|
||||
/* If the aStatic[] array is not large enough, allocate a large array
|
||||
@@ -440,12 +422,14 @@ static int fts5ExprPhraseIsMatch(
|
||||
int bFlag = 0;
|
||||
const u8 *a = 0;
|
||||
if( pTerm->pSynonym ){
|
||||
rc = fts5ExprSynonymPoslist(pTerm, pNode->iRowid, &bFlag, (u8**)&a, &n);
|
||||
rc = fts5ExprSynonymPoslist(
|
||||
pTerm, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n
|
||||
);
|
||||
}else{
|
||||
rc = sqlite3Fts5IterPoslist(pTerm->pIter, &a, &n, &dummy);
|
||||
rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
sqlite3Fts5PoslistReaderInit(iCol, a, n, &aIter[i]);
|
||||
sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
|
||||
aIter[i].bFlag = bFlag;
|
||||
if( aIter[i].bEof ) goto ismatch_out;
|
||||
}
|
||||
@@ -468,11 +452,9 @@ static int fts5ExprPhraseIsMatch(
|
||||
}
|
||||
}while( bMatch==0 );
|
||||
|
||||
if( pColset==0 || fts5ExprColsetTest(pColset, FTS5_POS2COLUMN(iPos)) ){
|
||||
/* Append position iPos to the output */
|
||||
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
}
|
||||
/* Append position iPos to the output */
|
||||
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
|
||||
for(i=0; i<pPhrase->nTerm; i++){
|
||||
if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out;
|
||||
@@ -767,61 +749,6 @@ static int fts5ExprSynonymAdvanceto(
|
||||
return bEof;
|
||||
}
|
||||
|
||||
/*
|
||||
** IN/OUT parameter (*pa) points to a position list n bytes in size. If
|
||||
** the position list contains entries for column iCol, then (*pa) is set
|
||||
** to point to the sub-position-list for that column and the number of
|
||||
** bytes in it returned. Or, if the argument position list does not
|
||||
** contain any entries for column iCol, return 0.
|
||||
*/
|
||||
static int fts5ExprExtractCol(
|
||||
const u8 **pa, /* IN/OUT: Pointer to poslist */
|
||||
int n, /* IN: Size of poslist in bytes */
|
||||
int iCol /* Column to extract from poslist */
|
||||
){
|
||||
int iCurrent = 0;
|
||||
const u8 *p = *pa;
|
||||
const u8 *pEnd = &p[n]; /* One byte past end of position list */
|
||||
u8 prev = 0;
|
||||
|
||||
while( iCol!=iCurrent ){
|
||||
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
|
||||
** not part of a varint */
|
||||
while( (prev & 0x80) || *p!=0x01 ){
|
||||
prev = *p++;
|
||||
if( p==pEnd ) return 0;
|
||||
}
|
||||
*pa = p++;
|
||||
p += fts5GetVarint32(p, iCurrent);
|
||||
}
|
||||
|
||||
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
|
||||
** not part of a varint */
|
||||
assert( (prev & 0x80)==0 );
|
||||
while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){
|
||||
prev = *p++;
|
||||
}
|
||||
return p - (*pa);
|
||||
}
|
||||
|
||||
static int fts5ExprExtractColset (
|
||||
Fts5ExprColset *pColset, /* Colset to filter on */
|
||||
const u8 *pPos, int nPos, /* Position list */
|
||||
Fts5Buffer *pBuf /* Output buffer */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
|
||||
fts5BufferZero(pBuf);
|
||||
for(i=0; i<pColset->nCol; i++){
|
||||
const u8 *pSub = pPos;
|
||||
int nSub = fts5ExprExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
||||
if( nSub ){
|
||||
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5ExprNearTest(
|
||||
int *pRc,
|
||||
@@ -868,35 +795,16 @@ static int fts5ExprTokenTest(
|
||||
Fts5ExprNearset *pNear = pNode->pNear;
|
||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
|
||||
Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
|
||||
Fts5ExprColset *pColset = pNear->pColset;
|
||||
const u8 *pPos;
|
||||
int nPos;
|
||||
Fts5Colset *pColset = pNear->pColset;
|
||||
int rc;
|
||||
|
||||
assert( pNode->eType==FTS5_TERM );
|
||||
assert( pNear->nPhrase==1 && pPhrase->nTerm==1 );
|
||||
assert( pPhrase->aTerm[0].pSynonym==0 );
|
||||
|
||||
rc = sqlite3Fts5IterPoslist(pIter, &pPos, &nPos, &pNode->iRowid);
|
||||
|
||||
/* If the term may match any column, then this must be a match.
|
||||
** Return immediately in this case. Otherwise, try to find the
|
||||
** part of the poslist that corresponds to the required column.
|
||||
** If it can be found, return. If it cannot, the next iteration
|
||||
** of the loop will test the next rowid in the database for this
|
||||
** term. */
|
||||
if( pColset==0 ){
|
||||
assert( pPhrase->poslist.nSpace==0 );
|
||||
pPhrase->poslist.p = (u8*)pPos;
|
||||
pPhrase->poslist.n = nPos;
|
||||
}else if( pColset->nCol==1 ){
|
||||
assert( pPhrase->poslist.nSpace==0 );
|
||||
pPhrase->poslist.n = fts5ExprExtractCol(&pPos, nPos, pColset->aiCol[0]);
|
||||
pPhrase->poslist.p = (u8*)pPos;
|
||||
}else if( rc==SQLITE_OK ){
|
||||
rc = fts5ExprExtractColset(pColset, pPos, nPos, &pPhrase->poslist);
|
||||
}
|
||||
|
||||
rc = sqlite3Fts5IterPoslist(pIter, pColset,
|
||||
(const u8**)&pPhrase->poslist.p, &pPhrase->poslist.n, &pNode->iRowid
|
||||
);
|
||||
pNode->bNomatch = (pPhrase->poslist.n==0);
|
||||
return rc;
|
||||
}
|
||||
@@ -999,9 +907,10 @@ static int fts5ExprNearInitAll(
|
||||
p->pIter = 0;
|
||||
}
|
||||
rc = sqlite3Fts5IndexQuery(
|
||||
pExpr->pIndex, p->zTerm, strlen(p->zTerm),
|
||||
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
|
||||
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
|
||||
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
|
||||
pNear->pColset,
|
||||
&p->pIter
|
||||
);
|
||||
assert( rc==SQLITE_OK || p->pIter==0 );
|
||||
@@ -1609,7 +1518,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
|
||||
int n;
|
||||
sqlite3Fts5Dequote(z);
|
||||
n = strlen(z);
|
||||
n = (int)strlen(z);
|
||||
rc = sqlite3Fts5Tokenize(pConfig, flags, z, n, &sCtx, fts5ParseTokenize);
|
||||
}
|
||||
sqlite3_free(z);
|
||||
@@ -1682,7 +1591,8 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
const char *zTerm = p->zTerm;
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, strlen(zTerm), 0, 0);
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
|
||||
0, 0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -1754,25 +1664,25 @@ void sqlite3Fts5ParseSetDistance(
|
||||
|
||||
/*
|
||||
** The second argument passed to this function may be NULL, or it may be
|
||||
** an existing Fts5ExprColset object. This function returns a pointer to
|
||||
** an existing Fts5Colset object. This function returns a pointer to
|
||||
** a new colset object containing the contents of (p) with new value column
|
||||
** number iCol appended.
|
||||
**
|
||||
** If an OOM error occurs, store an error code in pParse and return NULL.
|
||||
** The old colset object (if any) is not freed in this case.
|
||||
*/
|
||||
static Fts5ExprColset *fts5ParseColset(
|
||||
static Fts5Colset *fts5ParseColset(
|
||||
Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
|
||||
Fts5ExprColset *p, /* Existing colset object */
|
||||
Fts5Colset *p, /* Existing colset object */
|
||||
int iCol /* New column to add to colset object */
|
||||
){
|
||||
int nCol = p ? p->nCol : 0; /* Num. columns already in colset object */
|
||||
Fts5ExprColset *pNew; /* New colset object to return */
|
||||
Fts5Colset *pNew; /* New colset object to return */
|
||||
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
|
||||
|
||||
pNew = sqlite3_realloc(p, sizeof(Fts5ExprColset) + sizeof(int)*nCol);
|
||||
pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
|
||||
if( pNew==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -1797,12 +1707,12 @@ static Fts5ExprColset *fts5ParseColset(
|
||||
return pNew;
|
||||
}
|
||||
|
||||
Fts5ExprColset *sqlite3Fts5ParseColset(
|
||||
Fts5Colset *sqlite3Fts5ParseColset(
|
||||
Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
|
||||
Fts5ExprColset *pColset, /* Existing colset object */
|
||||
Fts5Colset *pColset, /* Existing colset object */
|
||||
Fts5Token *p
|
||||
){
|
||||
Fts5ExprColset *pRet = 0;
|
||||
Fts5Colset *pRet = 0;
|
||||
int iCol;
|
||||
char *z; /* Dequoted copy of token p */
|
||||
|
||||
@@ -1832,7 +1742,7 @@ Fts5ExprColset *sqlite3Fts5ParseColset(
|
||||
void sqlite3Fts5ParseSetColset(
|
||||
Fts5Parse *pParse,
|
||||
Fts5ExprNearset *pNear,
|
||||
Fts5ExprColset *pColset
|
||||
Fts5Colset *pColset
|
||||
){
|
||||
if( pNear ){
|
||||
pNear->pColset = pColset;
|
||||
@@ -1924,7 +1834,7 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
|
||||
|
||||
/* Determine the maximum amount of space required. */
|
||||
for(p=pTerm; p; p=p->pSynonym){
|
||||
nByte += strlen(pTerm->zTerm) * 2 + 3 + 2;
|
||||
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
|
||||
}
|
||||
zQuoted = sqlite3_malloc(nByte);
|
||||
|
||||
@@ -2285,6 +2195,11 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
|
||||
}
|
||||
|
||||
/* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
|
||||
#ifndef NDEBUG
|
||||
(void)sqlite3Fts5ParserTrace;
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2320,4 +2235,3 @@ int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
int iHash;
|
||||
Fts5HashEntry *p = apOld[i];
|
||||
apOld[i] = p->pHashNext;
|
||||
iHash = fts5HashKey(nNew, (u8*)p->zKey, strlen(p->zKey));
|
||||
iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey));
|
||||
p->pHashNext = apNew[iHash];
|
||||
apNew[iHash] = p;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ void sqlite3Fts5HashScanEntry(
|
||||
){
|
||||
Fts5HashEntry *p;
|
||||
if( (p = pHash->pScan) ){
|
||||
int nTerm = strlen(p->zKey);
|
||||
int nTerm = (int)strlen(p->zKey);
|
||||
fts5HashAddPoslistSize(p);
|
||||
*pzTerm = p->zKey;
|
||||
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
|
||||
|
||||
+467
-156
File diff suppressed because it is too large
Load Diff
+181
-69
@@ -440,6 +440,22 @@ static int fts5CreateMethod(
|
||||
#define FTS5_PLAN_SCAN 5 /* No usable constraint */
|
||||
#define FTS5_PLAN_ROWID 6 /* (rowid = ?) */
|
||||
|
||||
/*
|
||||
** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
|
||||
** extension is currently being used by a version of SQLite too old to
|
||||
** support index-info flags. In that case this function is a no-op.
|
||||
*/
|
||||
static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
||||
#if SQLITE_VERSION_NUMBER>=3008012
|
||||
#ifndef SQLITE_CORE
|
||||
if( sqlite3_libversion_number()>=3008012 )
|
||||
#endif
|
||||
{
|
||||
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the xBestIndex method for FTS5 tables. Within the
|
||||
** WHERE constraint, it searches for the following:
|
||||
@@ -492,8 +508,10 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
int omit; /* True to omit this if found */
|
||||
int iConsIndex; /* Index in pInfo->aConstraint[] */
|
||||
} aConstraint[] = {
|
||||
{SQLITE_INDEX_CONSTRAINT_MATCH, FTS5_BI_MATCH, 1, 1, -1},
|
||||
{SQLITE_INDEX_CONSTRAINT_MATCH, FTS5_BI_RANK, 2, 1, -1},
|
||||
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
||||
FTS5_BI_MATCH, 1, 1, -1},
|
||||
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
||||
FTS5_BI_RANK, 2, 1, -1},
|
||||
{SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1},
|
||||
{SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE,
|
||||
FTS5_BI_ROWID_LE, 0, 0, -1},
|
||||
@@ -546,6 +564,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
|
||||
if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
|
||||
pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
|
||||
if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
}else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
||||
pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
|
||||
}else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
||||
@@ -1284,15 +1303,14 @@ static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
|
||||
*/
|
||||
static int fts5SpecialInsert(
|
||||
Fts5Table *pTab, /* Fts5 table object */
|
||||
sqlite3_value *pCmd, /* Value inserted into special column */
|
||||
const char *zCmd, /* Text inserted into table-name column */
|
||||
sqlite3_value *pVal /* Value inserted into rank column */
|
||||
){
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
const char *z = (const char*)sqlite3_value_text(pCmd);
|
||||
int rc = SQLITE_OK;
|
||||
int bError = 0;
|
||||
|
||||
if( 0==sqlite3_stricmp("delete-all", z) ){
|
||||
if( 0==sqlite3_stricmp("delete-all", zCmd) ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
fts5SetVtabError(pTab,
|
||||
"'delete-all' may only be used with a "
|
||||
@@ -1302,7 +1320,7 @@ static int fts5SpecialInsert(
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
|
||||
}
|
||||
}else if( 0==sqlite3_stricmp("rebuild", z) ){
|
||||
}else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NONE ){
|
||||
fts5SetVtabError(pTab,
|
||||
"'rebuild' may not be used with a contentless fts5 table"
|
||||
@@ -1311,27 +1329,27 @@ static int fts5SpecialInsert(
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
|
||||
}
|
||||
}else if( 0==sqlite3_stricmp("optimize", z) ){
|
||||
}else if( 0==sqlite3_stricmp("optimize", zCmd) ){
|
||||
rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
|
||||
}else if( 0==sqlite3_stricmp("merge", z) ){
|
||||
}else if( 0==sqlite3_stricmp("merge", zCmd) ){
|
||||
int nMerge = sqlite3_value_int(pVal);
|
||||
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
|
||||
}else if( 0==sqlite3_stricmp("integrity-check", z) ){
|
||||
}else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
|
||||
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
|
||||
#ifdef SQLITE_DEBUG
|
||||
}else if( 0==sqlite3_stricmp("prefix-index", z) ){
|
||||
}else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
|
||||
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
|
||||
#endif
|
||||
}else{
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, z, pVal, &bError);
|
||||
rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bError ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, z, pVal, 0);
|
||||
rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1352,10 +1370,35 @@ static int fts5SpecialDelete(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void fts5StorageInsert(
|
||||
int *pRc,
|
||||
Fts5Table *pTab,
|
||||
sqlite3_value **apVal,
|
||||
i64 *piRowid
|
||||
){
|
||||
int rc = *pRc;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
|
||||
}
|
||||
*pRc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is the implementation of the xUpdate callback used by
|
||||
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
|
||||
** inserted, updated or deleted.
|
||||
**
|
||||
** A delete specifies a single argument - the rowid of the row to remove.
|
||||
**
|
||||
** Update and insert operations pass:
|
||||
**
|
||||
** 1. The "old" rowid, or NULL.
|
||||
** 2. The "new" rowid.
|
||||
** 3. Values for each of the nCol matchable columns.
|
||||
** 4. Values for the two hidden columns (<tablename> and "rank").
|
||||
*/
|
||||
static int fts5UpdateMethod(
|
||||
sqlite3_vtab *pVtab, /* Virtual table handle */
|
||||
@@ -1366,65 +1409,111 @@ static int fts5UpdateMethod(
|
||||
Fts5Table *pTab = (Fts5Table*)pVtab;
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
int eType0; /* value_type() of apVal[0] */
|
||||
int eConflict; /* ON CONFLICT for this DML */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
/* A transaction must be open when this is called. */
|
||||
assert( pTab->ts.eState==1 );
|
||||
|
||||
assert( pVtab->zErrMsg==0 );
|
||||
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
|
||||
assert( nArg==1
|
||||
|| sqlite3_value_type(apVal[1])==SQLITE_INTEGER
|
||||
|| sqlite3_value_type(apVal[1])==SQLITE_NULL
|
||||
);
|
||||
assert( pTab->pConfig->pzErrmsg==0 );
|
||||
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
||||
|
||||
/* A delete specifies a single argument - the rowid of the row to remove.
|
||||
** Update and insert operations pass:
|
||||
**
|
||||
** 1. The "old" rowid, or NULL.
|
||||
** 2. The "new" rowid.
|
||||
** 3. Values for each of the nCol matchable columns.
|
||||
** 4. Values for the two hidden columns (<tablename> and "rank").
|
||||
*/
|
||||
/* Put any active cursors into REQUIRE_SEEK state. */
|
||||
fts5TripCursors(pTab);
|
||||
|
||||
eType0 = sqlite3_value_type(apVal[0]);
|
||||
eConflict = sqlite3_vtab_on_conflict(pConfig->db);
|
||||
if( eType0==SQLITE_NULL
|
||||
&& sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL
|
||||
){
|
||||
/* A "special" INSERT op. These are handled separately. */
|
||||
const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL
|
||||
&& 0==sqlite3_stricmp("delete", z)
|
||||
){
|
||||
rc = fts5SpecialDelete(pTab, apVal, pRowid);
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
}
|
||||
}else{
|
||||
/* A regular INSERT, UPDATE or DELETE statement. The trick here is that
|
||||
** any conflict on the rowid value must be detected before any
|
||||
** modifications are made to the database file. There are 4 cases:
|
||||
**
|
||||
** 1) DELETE
|
||||
** 2) UPDATE (rowid not modified)
|
||||
** 3) UPDATE (rowid modified)
|
||||
** 4) INSERT
|
||||
**
|
||||
** Cases 3 and 4 may violate the rowid constraint.
|
||||
*/
|
||||
int eConflict = SQLITE_ABORT;
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
eConflict = sqlite3_vtab_on_conflict(pConfig->db);
|
||||
}
|
||||
|
||||
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
|
||||
assert( pVtab->zErrMsg==0 );
|
||||
assert( (nArg==1 && eType0==SQLITE_INTEGER) || nArg==(2+pConfig->nCol+2) );
|
||||
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
|
||||
assert( nArg!=1 || eType0==SQLITE_INTEGER );
|
||||
|
||||
fts5TripCursors(pTab);
|
||||
if( eType0==SQLITE_INTEGER ){
|
||||
if( fts5IsContentless(pTab) ){
|
||||
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
|
||||
** This is not suported. */
|
||||
if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
|
||||
pTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"cannot %s contentless fts5 table: %s",
|
||||
(nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
}
|
||||
|
||||
/* Case 1: DELETE */
|
||||
else if( nArg==1 ){
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel);
|
||||
}
|
||||
}else{
|
||||
sqlite3_value *pCmd = apVal[2 + pConfig->nCol];
|
||||
assert( nArg>1 );
|
||||
if( SQLITE_NULL!=sqlite3_value_type(pCmd) ){
|
||||
const char *z = (const char*)sqlite3_value_text(pCmd);
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL
|
||||
&& 0==sqlite3_stricmp("delete", z)
|
||||
|
||||
/* Case 2: INSERT */
|
||||
else if( eType0!=SQLITE_INTEGER ){
|
||||
/* If this is a REPLACE, first remove the current entry (if any) */
|
||||
if( eConflict==SQLITE_REPLACE
|
||||
&& sqlite3_value_type(apVal[1])==SQLITE_INTEGER
|
||||
){
|
||||
rc = fts5SpecialDelete(pTab, apVal, pRowid);
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, pCmd, apVal[2 + pConfig->nCol + 1]);
|
||||
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew);
|
||||
}
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
|
||||
/* Case 2: UPDATE */
|
||||
else{
|
||||
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
|
||||
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
|
||||
if( iOld!=iNew ){
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew);
|
||||
}
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
goto update_method_out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( rc==SQLITE_OK && nArg>1 ){
|
||||
rc = sqlite3Fts5StorageInsert(pTab->pStorage, apVal, eConflict, pRowid);
|
||||
}
|
||||
|
||||
update_method_out:
|
||||
pTab->pConfig->pzErrmsg = 0;
|
||||
return rc;
|
||||
}
|
||||
@@ -1560,7 +1649,7 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
|
||||
for(i=0; i<nIter; i++){
|
||||
const u8 *a;
|
||||
int n = fts5CsrPoslist(pCsr, i, &a);
|
||||
sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[i]);
|
||||
sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
|
||||
}
|
||||
|
||||
while( 1 ){
|
||||
@@ -1935,20 +2024,20 @@ static void fts5ApiCallback(
|
||||
** Given cursor id iId, return a pointer to the corresponding Fts5Index
|
||||
** object. Or NULL If the cursor id does not exist.
|
||||
**
|
||||
** If successful, set *pnCol to the number of indexed columns in the
|
||||
** table before returning.
|
||||
** If successful, set *ppConfig to point to the associated config object
|
||||
** before returning.
|
||||
*/
|
||||
Fts5Index *sqlite3Fts5IndexFromCsrid(
|
||||
Fts5Global *pGlobal,
|
||||
i64 iCsrId,
|
||||
int *pnCol
|
||||
Fts5Global *pGlobal, /* FTS5 global context for db handle */
|
||||
i64 iCsrId, /* Id of cursor to find */
|
||||
Fts5Config **ppConfig /* OUT: Configuration object */
|
||||
){
|
||||
Fts5Cursor *pCsr;
|
||||
Fts5Table *pTab;
|
||||
|
||||
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
|
||||
pTab = (Fts5Table*)pCsr->base.pVtab;
|
||||
*pnCol = pTab->pConfig->nCol;
|
||||
*ppConfig = pTab->pConfig;
|
||||
|
||||
return pTab->pIndex;
|
||||
}
|
||||
@@ -2132,14 +2221,16 @@ static int fts5CreateAux(
|
||||
int rc = sqlite3_overload_function(pGlobal->db, zName, -1);
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5Auxiliary *pAux;
|
||||
int nName; /* Size of zName in bytes, including \0 */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
|
||||
nByte = sizeof(Fts5Auxiliary) + strlen(zName) + 1;
|
||||
nName = (int)strlen(zName) + 1;
|
||||
nByte = sizeof(Fts5Auxiliary) + nName;
|
||||
pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte);
|
||||
if( pAux ){
|
||||
memset(pAux, 0, nByte);
|
||||
pAux->zFunc = (char*)&pAux[1];
|
||||
strcpy(pAux->zFunc, zName);
|
||||
memcpy(pAux->zFunc, zName, nName);
|
||||
pAux->pGlobal = pGlobal;
|
||||
pAux->pUserData = pUserData;
|
||||
pAux->xFunc = xFunc;
|
||||
@@ -2167,15 +2258,17 @@ static int fts5CreateTokenizer(
|
||||
){
|
||||
Fts5Global *pGlobal = (Fts5Global*)pApi;
|
||||
Fts5TokenizerModule *pNew;
|
||||
int nName; /* Size of zName and its \0 terminator */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
nByte = sizeof(Fts5TokenizerModule) + strlen(zName) + 1;
|
||||
nName = (int)strlen(zName) + 1;
|
||||
nByte = sizeof(Fts5TokenizerModule) + nName;
|
||||
pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte);
|
||||
if( pNew ){
|
||||
memset(pNew, 0, nByte);
|
||||
pNew->zName = (char*)&pNew[1];
|
||||
strcpy(pNew->zName, zName);
|
||||
memcpy(pNew->zName, zName, nName);
|
||||
pNew->pUserData = pUserData;
|
||||
pNew->x = *pTokenizer;
|
||||
pNew->xDestroy = xDestroy;
|
||||
@@ -2310,14 +2403,7 @@ static void fts5SourceIdFunc(
|
||||
sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_fts5_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
static int fts5Init(sqlite3 *db){
|
||||
static const sqlite3_module fts5Mod = {
|
||||
/* iVersion */ 2,
|
||||
/* xCreate */ fts5CreateMethod,
|
||||
@@ -2347,8 +2433,6 @@ int sqlite3_fts5_init(
|
||||
int rc;
|
||||
Fts5Global *pGlobal = 0;
|
||||
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
|
||||
pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
|
||||
if( pGlobal==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -2380,6 +2464,16 @@ int sqlite3_fts5_init(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following functions are used to register the module with SQLite. If
|
||||
** this module is being built as part of the SQLite core (SQLITE_CORE is
|
||||
** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
|
||||
**
|
||||
** Or, if this module is being built as a loadable extension,
|
||||
** sqlite3Fts5Init() is omitted and the two standard entry points
|
||||
** sqlite3_fts_init() and sqlite3_fts5_init() defined instead.
|
||||
*/
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
@@ -2388,7 +2482,25 @@ int sqlite3_fts_init(
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
return sqlite3_fts5_init(db, pzErrMsg, pApi);
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return fts5Init(db);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_fts5_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return fts5Init(db);
|
||||
}
|
||||
#else
|
||||
int sqlite3Fts5Init(sqlite3 *db){
|
||||
return fts5Init(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
+59
-56
@@ -297,10 +297,10 @@ int sqlite3Fts5StorageOpen(
|
||||
int i;
|
||||
int iOff;
|
||||
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
|
||||
iOff = strlen(zDefn);
|
||||
iOff = (int)strlen(zDefn);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
|
||||
iOff += strlen(&zDefn[iOff]);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
}
|
||||
@@ -392,7 +392,7 @@ static int fts5StorageDeleteFromIndex(Fts5Storage *p, i64 iDel){
|
||||
Fts5InsertCtx ctx;
|
||||
ctx.pStorage = p;
|
||||
ctx.iCol = -1;
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iDel);
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
|
||||
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
|
||||
if( pConfig->abUnindexed[iCol-1] ) continue;
|
||||
ctx.szCol = 0;
|
||||
@@ -513,13 +513,15 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
||||
}
|
||||
|
||||
/* Delete the %_content record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pDel, 1, iDel);
|
||||
sqlite3_step(pDel);
|
||||
rc = sqlite3_reset(pDel);
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pDel, 1, iDel);
|
||||
sqlite3_step(pDel);
|
||||
rc = sqlite3_reset(pDel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the averages record */
|
||||
@@ -549,7 +551,7 @@ int sqlite3Fts5StorageSpecialDelete(
|
||||
ctx.pStorage = p;
|
||||
ctx.iCol = -1;
|
||||
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iDel);
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
|
||||
for(iCol=0; rc==SQLITE_OK && iCol<pConfig->nCol; iCol++){
|
||||
if( pConfig->abUnindexed[iCol] ) continue;
|
||||
ctx.szCol = 0;
|
||||
@@ -639,7 +641,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
i64 iRowid = sqlite3_column_int64(pScan, 0);
|
||||
|
||||
sqlite3Fts5BufferZero(&buf);
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iRowid);
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
@@ -705,58 +707,59 @@ static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
|
||||
}
|
||||
|
||||
/*
|
||||
** Insert a new row into the FTS table.
|
||||
** Insert a new row into the FTS content table.
|
||||
*/
|
||||
int sqlite3Fts5StorageInsert(
|
||||
Fts5Storage *p, /* Storage module to write to */
|
||||
sqlite3_value **apVal, /* Array of values passed to xUpdate() */
|
||||
int eConflict, /* on conflict clause */
|
||||
i64 *piRowid /* OUT: rowid of new record */
|
||||
int sqlite3Fts5StorageContentInsert(
|
||||
Fts5Storage *p,
|
||||
sqlite3_value **apVal,
|
||||
i64 *piRowid
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* Insert the new row into the %_content table. */
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
|
||||
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
|
||||
*piRowid = sqlite3_value_int64(apVal[1]);
|
||||
}else{
|
||||
rc = fts5StorageNewRowid(p, piRowid);
|
||||
}
|
||||
}else{
|
||||
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
|
||||
int i; /* Counter variable */
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_reset(pInsert);
|
||||
}
|
||||
*piRowid = sqlite3_last_insert_rowid(pConfig->db);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Insert new entries into the FTS index and %_docsize table.
|
||||
*/
|
||||
int sqlite3Fts5StorageIndexInsert(
|
||||
Fts5Storage *p,
|
||||
sqlite3_value **apVal,
|
||||
i64 iRowid
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
sqlite3_stmt *pInsert = 0; /* Statement used to write %_content table */
|
||||
int eStmt = 0; /* Type of statement used on %_content */
|
||||
int i; /* Counter variable */
|
||||
Fts5InsertCtx ctx; /* Tokenization callback context object */
|
||||
Fts5Buffer buf; /* Buffer used to build up %_docsize blob */
|
||||
|
||||
memset(&buf, 0, sizeof(Fts5Buffer));
|
||||
ctx.pStorage = p;
|
||||
rc = fts5StorageLoadTotals(p, 1);
|
||||
|
||||
/* Insert the new row into the %_content table. */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
|
||||
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
|
||||
*piRowid = sqlite3_value_int64(apVal[1]);
|
||||
}else{
|
||||
rc = fts5StorageNewRowid(p, piRowid);
|
||||
}
|
||||
}else{
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
eStmt = FTS5_STMT_REPLACE_CONTENT;
|
||||
rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
|
||||
}else{
|
||||
eStmt = FTS5_STMT_INSERT_CONTENT;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, eStmt, &pInsert, 0);
|
||||
}
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_reset(pInsert);
|
||||
}
|
||||
*piRowid = sqlite3_last_insert_rowid(pConfig->db);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add new entries to the FTS index */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, *piRowid);
|
||||
ctx.pStorage = p;
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
|
||||
}
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
@@ -776,7 +779,7 @@ int sqlite3Fts5StorageInsert(
|
||||
|
||||
/* Write the %_docsize record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageInsertDocsize(p, *piRowid, &buf);
|
||||
rc = fts5StorageInsertDocsize(p, iRowid, &buf);
|
||||
}
|
||||
sqlite3_free(buf.p);
|
||||
|
||||
@@ -913,12 +916,12 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
|
||||
/* Check that the %_docsize and %_content tables contain the expected
|
||||
** number of rows. */
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
i64 nRow;
|
||||
i64 nRow = 0;
|
||||
rc = fts5StorageCount(p, "content", &nRow);
|
||||
if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
|
||||
}
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
i64 nRow;
|
||||
i64 nRow = 0;
|
||||
rc = fts5StorageCount(p, "docsize", &nRow);
|
||||
if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
|
||||
}
|
||||
|
||||
@@ -976,7 +976,6 @@ static int f5tTokenHash(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int bOld = sqlite3_fts5_may_be_corrupt;
|
||||
char *z;
|
||||
int n;
|
||||
unsigned int iVal;
|
||||
|
||||
@@ -242,7 +242,7 @@ static int fts5UnicodeAddExceptions(
|
||||
int bTokenChars /* 1 for 'tokenchars', 0 for 'separators' */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int n = strlen(z);
|
||||
int n = (int)strlen(z);
|
||||
int *aNew;
|
||||
|
||||
if( n>0 ){
|
||||
|
||||
+150
-38
@@ -55,16 +55,18 @@ struct Fts5VocabCursor {
|
||||
int bEof; /* True if this cursor is at EOF */
|
||||
Fts5IndexIter *pIter; /* Term/rowid iterator object */
|
||||
|
||||
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
|
||||
/* These are used by 'col' tables only */
|
||||
int nCol;
|
||||
Fts5Config *pConfig; /* Fts5 table configuration */
|
||||
int iCol;
|
||||
i64 *aCnt;
|
||||
i64 *aDoc;
|
||||
|
||||
/* Output values */
|
||||
/* Output values used by 'row' and 'col' tables */
|
||||
i64 rowid; /* This table's current rowid value */
|
||||
Fts5Buffer term; /* Current value of 'term' column */
|
||||
i64 aVal[3]; /* Up to three columns left of 'term' */
|
||||
};
|
||||
|
||||
#define FTS5_VOCAB_COL 0
|
||||
@@ -73,6 +75,14 @@ struct Fts5VocabCursor {
|
||||
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
|
||||
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
|
||||
|
||||
/*
|
||||
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||
*/
|
||||
#define FTS5_VOCAB_TERM_EQ 0x01
|
||||
#define FTS5_VOCAB_TERM_GE 0x02
|
||||
#define FTS5_VOCAB_TERM_LE 0x04
|
||||
|
||||
|
||||
/*
|
||||
** Translate a string containing an fts5vocab table type to an
|
||||
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
|
||||
@@ -168,9 +178,9 @@ static int fts5VocabInitVtab(
|
||||
const char *zDb = bDb ? argv[3] : argv[1];
|
||||
const char *zTab = bDb ? argv[4] : argv[3];
|
||||
const char *zType = bDb ? argv[5] : argv[4];
|
||||
int nDb = strlen(zDb)+1;
|
||||
int nTab = strlen(zTab)+1;
|
||||
int eType;
|
||||
int nDb = (int)strlen(zDb)+1;
|
||||
int nTab = (int)strlen(zTab)+1;
|
||||
int eType = 0;
|
||||
|
||||
rc = fts5VocabTableType(zType, pzErr, &eType);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -230,6 +240,45 @@ static int fts5VocabBestIndexMethod(
|
||||
sqlite3_vtab *pVTab,
|
||||
sqlite3_index_info *pInfo
|
||||
){
|
||||
int i;
|
||||
int iTermEq = -1;
|
||||
int iTermGe = -1;
|
||||
int iTermLe = -1;
|
||||
int idxNum = 0;
|
||||
int nArg = 0;
|
||||
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
if( p->usable==0 ) continue;
|
||||
if( p->iColumn==0 ){ /* term column */
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
|
||||
}
|
||||
}
|
||||
|
||||
if( iTermEq>=0 ){
|
||||
idxNum |= FTS5_VOCAB_TERM_EQ;
|
||||
pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
|
||||
pInfo->estimatedCost = 100;
|
||||
}else{
|
||||
pInfo->estimatedCost = 1000000;
|
||||
if( iTermGe>=0 ){
|
||||
idxNum |= FTS5_VOCAB_TERM_GE;
|
||||
pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
|
||||
pInfo->estimatedCost = pInfo->estimatedCost / 2;
|
||||
}
|
||||
if( iTermLe>=0 ){
|
||||
idxNum |= FTS5_VOCAB_TERM_LE;
|
||||
pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
|
||||
pInfo->estimatedCost = pInfo->estimatedCost / 2;
|
||||
}
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxNum;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -242,12 +291,11 @@ static int fts5VocabOpenMethod(
|
||||
){
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
|
||||
Fts5Index *pIndex = 0;
|
||||
int nCol = 0;
|
||||
Fts5Config *pConfig = 0;
|
||||
Fts5VocabCursor *pCsr = 0;
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *zSql = 0;
|
||||
int nByte;
|
||||
|
||||
zSql = sqlite3Fts5Mprintf(&rc,
|
||||
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
||||
@@ -262,7 +310,7 @@ static int fts5VocabOpenMethod(
|
||||
|
||||
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
i64 iId = sqlite3_column_int64(pStmt, 0);
|
||||
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &nCol);
|
||||
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pIndex==0 ){
|
||||
@@ -276,14 +324,17 @@ static int fts5VocabOpenMethod(
|
||||
}
|
||||
}
|
||||
|
||||
nByte = nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
|
||||
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
if( rc==SQLITE_OK ){
|
||||
int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
|
||||
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
}
|
||||
|
||||
if( pCsr ){
|
||||
pCsr->pIndex = pIndex;
|
||||
pCsr->pStmt = pStmt;
|
||||
pCsr->nCol = nCol;
|
||||
pCsr->pConfig = pConfig;
|
||||
pCsr->aCnt = (i64*)&pCsr[1];
|
||||
pCsr->aDoc = &pCsr->aCnt[nCol];
|
||||
pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
|
||||
}else{
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
@@ -296,6 +347,9 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
||||
pCsr->rowid = 0;
|
||||
sqlite3Fts5IterClose(pCsr->pIter);
|
||||
pCsr->pIter = 0;
|
||||
sqlite3_free(pCsr->zLeTerm);
|
||||
pCsr->nLeTerm = -1;
|
||||
pCsr->zLeTerm = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -319,16 +373,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
int nCol = pCsr->pConfig->nCol;
|
||||
|
||||
pCsr->rowid++;
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_COL ){
|
||||
for(pCsr->iCol++; pCsr->iCol<pCsr->nCol; pCsr->iCol++){
|
||||
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
|
||||
if( pCsr->aCnt[pCsr->iCol] ) break;
|
||||
}
|
||||
}
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=pCsr->nCol ){
|
||||
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
||||
pCsr->bEof = 1;
|
||||
}else{
|
||||
@@ -336,10 +391,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int nTerm;
|
||||
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
if( pCsr->nLeTerm>=0 ){
|
||||
int nCmp = MIN(nTerm, pCsr->nLeTerm);
|
||||
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
|
||||
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
|
||||
pCsr->bEof = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
|
||||
memset(pCsr->aVal, 0, sizeof(pCsr->aVal));
|
||||
memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64));
|
||||
memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64));
|
||||
memset(pCsr->aCnt, 0, nCol * sizeof(i64));
|
||||
memset(pCsr->aDoc, 0, nCol * sizeof(i64));
|
||||
pCsr->iCol = 0;
|
||||
|
||||
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
|
||||
@@ -349,13 +412,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
i64 iPos = 0; /* 64-bit position read from poslist */
|
||||
int iOff = 0; /* Current offset within position list */
|
||||
|
||||
rc = sqlite3Fts5IterPoslist(pCsr->pIter, &pPos, &nPos, &dummy);
|
||||
rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aVal[1]++;
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
pCsr->aVal[0]++;
|
||||
pCsr->aDoc[0]++;
|
||||
}else{
|
||||
int iCol = -1;
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
@@ -369,9 +432,12 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ) break;
|
||||
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
|
||||
break;
|
||||
}
|
||||
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
|
||||
}
|
||||
}
|
||||
@@ -380,9 +446,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
|
||||
while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
|
||||
pCsr->aVal[0] = pCsr->iCol;
|
||||
pCsr->aVal[1] = pCsr->aDoc[pCsr->iCol];
|
||||
pCsr->aVal[2] = pCsr->aCnt[pCsr->iCol];
|
||||
assert( pCsr->iCol<pCsr->pConfig->nCol );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -398,11 +462,47 @@ static int fts5VocabFilterMethod(
|
||||
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
||||
){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
int rc;
|
||||
const int flags = FTS5INDEX_QUERY_SCAN;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
int iVal = 0;
|
||||
int f = FTS5INDEX_QUERY_SCAN;
|
||||
const char *zTerm = 0;
|
||||
int nTerm = 0;
|
||||
|
||||
sqlite3_value *pEq = 0;
|
||||
sqlite3_value *pGe = 0;
|
||||
sqlite3_value *pLe = 0;
|
||||
|
||||
fts5VocabResetCursor(pCsr);
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, &pCsr->pIter);
|
||||
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
|
||||
|
||||
if( pEq ){
|
||||
zTerm = (const char *)sqlite3_value_text(pEq);
|
||||
nTerm = sqlite3_value_bytes(pEq);
|
||||
f = 0;
|
||||
}else{
|
||||
if( pGe ){
|
||||
zTerm = (const char *)sqlite3_value_text(pGe);
|
||||
nTerm = sqlite3_value_bytes(pGe);
|
||||
}
|
||||
if( pLe ){
|
||||
const char *zCopy = (const char *)sqlite3_value_text(pLe);
|
||||
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
|
||||
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
|
||||
if( pCsr->zLeTerm==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5VocabNextMethod(pCursor);
|
||||
}
|
||||
@@ -425,17 +525,29 @@ static int fts5VocabColumnMethod(
|
||||
int iCol /* Index of column to read value from */
|
||||
){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
switch( iCol ){
|
||||
case 0: /* term */
|
||||
sqlite3_result_text(
|
||||
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( iCol<4 && iCol>0 );
|
||||
sqlite3_result_int64(pCtx, pCsr->aVal[iCol-1]);
|
||||
break;
|
||||
if( iCol==0 ){
|
||||
sqlite3_result_text(
|
||||
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
|
||||
);
|
||||
}
|
||||
else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){
|
||||
assert( iCol==1 || iCol==2 || iCol==3 );
|
||||
if( iCol==1 ){
|
||||
const char *z = pCsr->pConfig->azCol[pCsr->iCol];
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
|
||||
}else if( iCol==2 ){
|
||||
sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
|
||||
}else{
|
||||
sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
|
||||
}
|
||||
}else{
|
||||
assert( iCol==1 || iCol==2 );
|
||||
if( iCol==1 ){
|
||||
sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
|
||||
}else{
|
||||
sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
%left COLON.
|
||||
|
||||
input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
|
||||
%destructor input { (void)pParse; }
|
||||
|
||||
%type cnearset {Fts5ExprNode*}
|
||||
%type expr {Fts5ExprNode*}
|
||||
@@ -101,9 +102,9 @@ cnearset(A) ::= colset(X) COLON nearset(Y). {
|
||||
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
|
||||
}
|
||||
|
||||
%type colset {Fts5ExprColset*}
|
||||
%type colset {Fts5Colset*}
|
||||
%destructor colset { sqlite3_free($$); }
|
||||
%type colsetlist {Fts5ExprColset*}
|
||||
%type colsetlist {Fts5Colset*}
|
||||
%destructor colsetlist { sqlite3_free($$); }
|
||||
|
||||
colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
|
||||
|
||||
@@ -17,7 +17,6 @@ source $testdir/tester.tcl
|
||||
|
||||
catch {
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
append G(perm:dbconfig) "; load_static_extension \$::dbhandle fts5"
|
||||
reset_db
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aa
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -159,9 +159,20 @@ do_execsql_test 6.3 {
|
||||
}
|
||||
|
||||
do_execsql_test 6.4 {
|
||||
REPLACE INTO t1(x, y) VALUES('x y z', 'x y z');
|
||||
}
|
||||
|
||||
do_execsql_test 6.5 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check')
|
||||
}
|
||||
|
||||
do_execsql_test 6.6 {
|
||||
SELECT rowid, * FROM t1;
|
||||
} {
|
||||
22 {l l l} {l l l}
|
||||
23 {x y z} {x y z}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
@@ -251,7 +251,6 @@ do_execsql_test 4.3.1 {
|
||||
INSERT INTO t3 VALUES('a five');
|
||||
INSERT INTO t3(t3, rank) VALUES('rank', 'bm25()');
|
||||
}
|
||||
breakpoint
|
||||
|
||||
do_execsql_test 4.3.2 {
|
||||
SELECT * FROM t3
|
||||
@@ -260,6 +259,7 @@ do_execsql_test 4.3.2 {
|
||||
} {
|
||||
{a four} {a one} {a five} {a two} {a three}
|
||||
}
|
||||
|
||||
do_execsql_test 4.3.3 {
|
||||
SELECT *, rank FROM t3
|
||||
WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(3)'
|
||||
@@ -268,6 +268,18 @@ do_execsql_test 4.3.3 {
|
||||
{a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2
|
||||
}
|
||||
|
||||
do_execsql_test 4.3.4 {
|
||||
SELECT * FROM t3('a', 'rowidmod(4)') ORDER BY rank ASC;
|
||||
} {
|
||||
{a four} {a one} {a five} {a two} {a three}
|
||||
}
|
||||
|
||||
do_execsql_test 4.3.5 {
|
||||
SELECT *, rank FROM t3('a', 'rowidmod(3)') ORDER BY rank ASC
|
||||
} {
|
||||
{a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2
|
||||
}
|
||||
|
||||
do_catchsql_test 4.4.3 {
|
||||
SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH 'xyz(3)'
|
||||
} {1 {no such function: xyz}}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# 2015 October 27
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# 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 fts5conflict
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, a, b);
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, content=t1, content_rowid=x);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
REPLACE INTO ft(rowid, a, b) VALUES(1, 'a b c', 'a b c');
|
||||
REPLACE INTO t1 VALUES(1, 'a b c', 'a b c');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content=tbl, content_rowid=a);
|
||||
CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN
|
||||
INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
|
||||
END;
|
||||
CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN
|
||||
INSERT INTO fts_idx(fts_idx, rowid, b, c)
|
||||
VALUES('delete', old.a, old.b, old.c);
|
||||
END;
|
||||
CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
|
||||
INSERT INTO fts_idx(fts_idx, rowid, b, c)
|
||||
VALUES('delete', old.a, old.b, old.c);
|
||||
INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA recursive_triggers = 1;
|
||||
INSERT INTO tbl VALUES(1, 'x y z', '1 2 3');
|
||||
INSERT INTO tbl VALUES(10, 'x y z', '1 2 3');
|
||||
INSERT INTO tbl VALUES(100, 'x 1 z', '1 y 3');
|
||||
|
||||
UPDATE tbl SET b = '1 2 x' WHERE rowid=10;
|
||||
REPLACE INTO tbl VALUES(1, '4 5 6', '3 2 1');
|
||||
DELETE FROM tbl WHERE a=100;
|
||||
|
||||
INSERT INTO fts_idx(fts_idx) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -250,8 +250,6 @@ foreach rowid [db eval {SELECT rowid FROM x1_data WHERE rowid>100}] {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
@@ -335,6 +333,44 @@ do_catchsql_test 6.3.5 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
reset_db
|
||||
proc rnddoc {n} {
|
||||
set map [list a b c d]
|
||||
set doc [list]
|
||||
for {set i 0} {$i < $n} {incr i} {
|
||||
lappend doc "x[lindex $map [expr int(rand()*4)]]"
|
||||
}
|
||||
set doc
|
||||
}
|
||||
|
||||
db func rnddoc rnddoc
|
||||
do_test 7.0 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t5 USING fts5(x);
|
||||
INSERT INTO t5 VALUES( rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( rnddoc(10000) );
|
||||
INSERT INTO t5(t5) VALUES('optimize');
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 7.1 {
|
||||
foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] {
|
||||
db eval BEGIN
|
||||
db eval {DELETE FROM t5_data WHERE rowid = $i}
|
||||
set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ]
|
||||
if {$r != "1 {database disk image is malformed}"} { error $r }
|
||||
db eval ROLLBACK
|
||||
}
|
||||
} {}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -90,6 +90,14 @@ do_faultsim_test 3.1 -faults oom-t* -body {
|
||||
faultsim_test_result {0 {0 1 10 11 12 13 14 15 16 17 18 19 2 3 4 5 6 7 8 9}}
|
||||
}
|
||||
|
||||
do_faultsim_test 3.2 -faults oom-t* -body {
|
||||
db eval {
|
||||
SELECT term FROM tv WHERE term BETWEEN '1' AND '2';
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -284,8 +284,6 @@ breakpoint
|
||||
do_faultsim_test 6 -faults oom* -prep {
|
||||
sqlite_orig db test.db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
} -body {
|
||||
load_static_extension db fts5
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {initialization of fts5 failed: }}
|
||||
if {$testrc==0} {
|
||||
|
||||
@@ -87,5 +87,26 @@ do_faultsim_test 1 -faults oom-t* -prep {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test fault-injection when a segment is promoted.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE xy USING fts5(x);
|
||||
INSERT INTO xy(rowid, x) VALUES(1, '1 2 3');
|
||||
INSERT INTO xy(rowid, x) VALUES(2, '2 3 4');
|
||||
INSERT INTO xy(rowid, x) VALUES(3, '3 4 5');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 2 -faults oom-* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
db eval { UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2 }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -84,11 +84,13 @@ lappend vocab xyz
|
||||
do_execsql_test 1.1 {
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(eee, 'row');
|
||||
BEGIN;
|
||||
WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
|
||||
INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii;
|
||||
INSERT INTO eee(eee) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
for {set i 1} {$i <= 100} {incr i} {
|
||||
execsql { INSERT INTO eee VALUES( r($vocab, 5), r($vocab, 7) ) }
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
db eval { SELECT term, doc FROM vocab } {
|
||||
set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file containst tests focused on the integrity-check procedure.
|
||||
# This file contains tests focused on the integrity-check procedure.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
@@ -102,6 +102,53 @@ do_catchsql_test 4.5 {
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r}
|
||||
#exit
|
||||
|
||||
execsql { ROLLBACK }
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that integrity-check works on a reasonably large db with many
|
||||
# different terms.
|
||||
|
||||
# Document generator command.
|
||||
proc rnddoc {n} {
|
||||
set doc [list]
|
||||
for {set i 0} {$i<$n} {incr i} {
|
||||
lappend doc [format %.5d [expr int(rand()*10000)]]
|
||||
}
|
||||
return $doc
|
||||
}
|
||||
db func rnddoc rnddoc
|
||||
|
||||
expr srand(0)
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE gg USING fts5(a, prefix="1,2,3");
|
||||
INSERT INTO gg(gg, rank) VALUES('pgsz', 256);
|
||||
INSERT INTO gg VALUES(rnddoc(20));
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
INSERT INTO gg SELECT rnddoc(20) FROM gg;
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
INSERT INTO gg(gg) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
INSERT INTO gg(gg) VALUES('optimize');
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 5.3 {
|
||||
INSERT INTO gg(gg) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# 2015 Sep 27
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5onepass
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(content);
|
||||
INSERT INTO ft(rowid, content) VALUES(1, '1 2 3');
|
||||
INSERT INTO ft(rowid, content) VALUES(2, '4 5 6');
|
||||
INSERT INTO ft(rowid, content) VALUES(3, '7 8 9');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that UPDATE and DELETE statements that feature "WHERE rowid=?" or
|
||||
# or "WHERE rowid=?" clauses do not use statement journals. But that other
|
||||
# DELETE and UPDATE statements do.
|
||||
#
|
||||
# Note: "MATCH ? AND rowid=?" does use a statement journal.
|
||||
#
|
||||
foreach {tn sql uses} {
|
||||
1.1 { DELETE FROM ft } 1
|
||||
1.2 { DELETE FROM ft WHERE rowid=? } 0
|
||||
1.3 { DELETE FROM ft WHERE rowid=? } 0
|
||||
1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1
|
||||
1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
|
||||
1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
|
||||
|
||||
2.1 { UPDATE ft SET content='a b c' } 1
|
||||
2.2 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
|
||||
2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
|
||||
2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1
|
||||
2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
|
||||
2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
|
||||
} {
|
||||
do_test 1.$tn { sql_uses_stmt db $sql } $uses
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that putting a "DELETE/UPDATE ... WHERE rowid=?" statement in a
|
||||
# trigger program does not prevent the VM from using a statement
|
||||
# transaction. Even if the calling statement cannot hit a constraint.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(x);
|
||||
|
||||
CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN
|
||||
DELETE FROM ft WHERE rowid=new.x;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN
|
||||
UPDATE ft SET content = 'a b c' WHERE rowid=old.x;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN
|
||||
DELETE FROM ft WHERE rowid=old.x;
|
||||
END;
|
||||
}
|
||||
|
||||
foreach {tn sql uses} {
|
||||
1 { INSERT INTO t1 VALUES(1) } 1
|
||||
2 { DELETE FROM t1 WHERE x=4 } 1
|
||||
3 { UPDATE t1 SET x=10 WHERE x=11 } 1
|
||||
} {
|
||||
do_test 2.$tn { sql_uses_stmt db $sql } $uses
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that an "UPDATE ... WHERE rowid=?" works and does not corrupt the
|
||||
# index when it strikes a constraint. Both inside and outside a
|
||||
# transaction.
|
||||
#
|
||||
foreach {tn tcl1 tcl2} {
|
||||
1 {} {}
|
||||
|
||||
2 {
|
||||
execsql BEGIN
|
||||
} {
|
||||
if {[sqlite3_get_autocommit db]==1} { error "transaction rolled back!" }
|
||||
execsql COMMIT
|
||||
}
|
||||
} {
|
||||
|
||||
do_execsql_test 3.$tn.0 {
|
||||
DROP TABLE IF EXISTS ft2;
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(content);
|
||||
INSERT INTO ft2(rowid, content) VALUES(1, 'a b c');
|
||||
INSERT INTO ft2(rowid, content) VALUES(2, 'a b d');
|
||||
INSERT INTO ft2(rowid, content) VALUES(3, 'a b e');
|
||||
}
|
||||
|
||||
eval $tcl1
|
||||
foreach {tn2 sql content} {
|
||||
1 { UPDATE ft2 SET rowid=2 WHERE rowid=1 }
|
||||
{ 1 {a b c} 2 {a b d} 3 {a b e} }
|
||||
|
||||
2 {
|
||||
INSERT INTO ft2(rowid, content) VALUES(4, 'a b f');
|
||||
UPDATE ft2 SET rowid=5 WHERE rowid=4;
|
||||
UPDATE ft2 SET rowid=3 WHERE rowid=5;
|
||||
} { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
|
||||
|
||||
3 {
|
||||
UPDATE ft2 SET rowid=3 WHERE rowid=4; -- matches 0 rows
|
||||
UPDATE ft2 SET rowid=2 WHERE rowid=3;
|
||||
} { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
|
||||
|
||||
4 {
|
||||
INSERT INTO ft2(rowid, content) VALUES(4, 'a b g');
|
||||
UPDATE ft2 SET rowid=-1 WHERE rowid=4;
|
||||
UPDATE ft2 SET rowid=3 WHERE rowid=-1;
|
||||
} {-1 {a b g} 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
|
||||
|
||||
5 {
|
||||
DELETE FROM ft2 WHERE rowid=451;
|
||||
DELETE FROM ft2 WHERE rowid=-1;
|
||||
UPDATE ft2 SET rowid = 2 WHERE rowid = 1;
|
||||
} {1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
|
||||
} {
|
||||
do_catchsql_test 3.$tn.$tn2.a $sql {1 {constraint failed}}
|
||||
do_execsql_test 3.$tn.$tn2.b { SELECT rowid, content FROM ft2 } $content
|
||||
|
||||
do_execsql_test 3.$tn.$tn2.c {
|
||||
INSERT INTO ft2(ft2) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
eval $tcl2
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that DELETE and UPDATE operations can be done without flushing
|
||||
# the in-memory hash table to disk.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.1 {
|
||||
CREATE VIRTUAL TABLE ttt USING fts5(x);
|
||||
BEGIN;
|
||||
INSERT INTO ttt(rowid, x) VALUES(1, 'a b c');
|
||||
INSERT INTO ttt(rowid, x) VALUES(2, 'a b c');
|
||||
INSERT INTO ttt(rowid, x) VALUES(3, 'a b c');
|
||||
COMMIT
|
||||
}
|
||||
do_test 4.1.2 { fts5_level_segs ttt } {1}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
BEGIN;
|
||||
DELETE FROM ttt WHERE rowid=1;
|
||||
DELETE FROM ttt WHERE rowid=3;
|
||||
INSERT INTO ttt(rowid, x) VALUES(4, 'd e f');
|
||||
INSERT INTO ttt(rowid, x) VALUES(5, 'd e f');
|
||||
COMMIT;
|
||||
} {}
|
||||
do_test 4.2.2 { fts5_level_segs ttt } {2}
|
||||
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
BEGIN;
|
||||
UPDATE ttt SET x = 'd e f' WHERE rowid = 2;
|
||||
UPDATE ttt SET x = 'A B C' WHERE rowid = 4;
|
||||
INSERT INTO ttt(rowid, x) VALUES(6, 'd e f');
|
||||
COMMIT;
|
||||
} {}
|
||||
do_test 4.2.2 { fts5_level_segs ttt } {3}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# 2014 Jan 08
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focused on phrase queries.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5phrase
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
|
||||
INSERT INTO t3 VALUES('d e a', 'd i j j f', 'i j i e b f h'); -- 1
|
||||
INSERT INTO t3 VALUES('g a e', 'f g i g a', 'h d g i g h c'); -- 2
|
||||
INSERT INTO t3 VALUES('e a d', 'e i h a f', 'c e h i f b i'); -- 3
|
||||
INSERT INTO t3 VALUES('a g c', 'd j d j c', 'c d f j i g j'); -- 4
|
||||
INSERT INTO t3 VALUES('b c b', 'j g c d f', 'j c j d g f b'); -- 5
|
||||
INSERT INTO t3 VALUES('j a d', 'e b i h h', 'c c f g d i d'); -- 6
|
||||
INSERT INTO t3 VALUES('a d f', 'h g i i i', 'e a g c i f b'); -- 7
|
||||
INSERT INTO t3 VALUES('g f d', 'f c g b j', 'b b h h h j j'); -- 8
|
||||
INSERT INTO t3 VALUES('f h g', 'c j f g j', 'd h d f e b h'); -- 9
|
||||
INSERT INTO t3 VALUES('f h d', 'c i a d b', 'g b j b a d e'); -- 10
|
||||
INSERT INTO t3 VALUES('j h h', 'j i h a g', 'd e i e a g j'); -- 11
|
||||
INSERT INTO t3 VALUES('a b e', 'h g a g c', 'h c a a d e g'); -- 12
|
||||
INSERT INTO t3 VALUES('a j g', 'i h i f i', 'a g h j g i b'); -- 13
|
||||
INSERT INTO t3 VALUES('j h e', 'f e d i e', 'i d c f e d c'); -- 14
|
||||
INSERT INTO t3 VALUES('d j d', 'd b i a c', 'g d h i d b e'); -- 15
|
||||
INSERT INTO t3 VALUES('h j e', 'e b b c f', 'j a f g h d j'); -- 16
|
||||
INSERT INTO t3 VALUES('c b j', 'c a b a i', 'h f i d a d c'); -- 17
|
||||
INSERT INTO t3 VALUES('e e d', 'i d f c c', 'g i d a f e a'); -- 18
|
||||
INSERT INTO t3 VALUES('e i g', 'e a b i h', 'i f d d a d f'); -- 19
|
||||
INSERT INTO t3 VALUES('h g f', 'b h h j d', 'i f d e g j a'); -- 20
|
||||
INSERT INTO t3 VALUES('e h f', 'j c b c f', 'j a j g h a c'); -- 21
|
||||
INSERT INTO t3 VALUES('d c h', 'b g i c e', 'i i c d e h i'); -- 22
|
||||
INSERT INTO t3 VALUES('a h i', 'a g d f f', 'e f i i b b h'); -- 23
|
||||
INSERT INTO t3 VALUES('d d g', 'c c b c g', 'g c h e b c e'); -- 24
|
||||
INSERT INTO t3 VALUES('a b b', 'b f a d i', 'd a h a b c i'); -- 25
|
||||
INSERT INTO t3 VALUES('a f d', 'a j e a h', 'j i h j a i f'); -- 26
|
||||
INSERT INTO t3 VALUES('d j d', 'h a d i a', 'h h f j h g a'); -- 27
|
||||
INSERT INTO t3 VALUES('g a e', 'd g f a g', 'i d b c g g j'); -- 28
|
||||
INSERT INTO t3 VALUES('j e h', 'g h j h g', 'd a e j a a h'); -- 29
|
||||
INSERT INTO t3 VALUES('e j e', 'g e j g c', 'f c e b e e a'); -- 30
|
||||
INSERT INTO t3 VALUES('h f f', 'i j g e c', 'j j f c a i j'); -- 31
|
||||
INSERT INTO t3 VALUES('a g c', 'c g d b i', 'g h c b a a f'); -- 32
|
||||
INSERT INTO t3 VALUES('c h i', 'j d h e e', 'a h i d c c j'); -- 33
|
||||
INSERT INTO t3 VALUES('d a c', 'e d d b j', 'c e b b h i h'); -- 34
|
||||
INSERT INTO t3 VALUES('d f h', 'c a f c c', 'j b b c c j f'); -- 35
|
||||
INSERT INTO t3 VALUES('b g h', 'g c c c f', 'c g c f h e e'); -- 36
|
||||
INSERT INTO t3 VALUES('f e a', 'b h f j h', 'j g h f d g f'); -- 37
|
||||
INSERT INTO t3 VALUES('h f a', 'a e i j g', 'f d a f d f c'); -- 38
|
||||
INSERT INTO t3 VALUES('f i c', 'f i i i i', 'e c f d h j f'); -- 39
|
||||
INSERT INTO t3 VALUES('h h d', 'd i e d i', 'd f e i a h a'); -- 40
|
||||
INSERT INTO t3 VALUES('f g c', 'd a f c h', 'b b g j c e g'); -- 41
|
||||
INSERT INTO t3 VALUES('h i h', 'h d j d e', 'e d b b i e g'); -- 42
|
||||
INSERT INTO t3 VALUES('b h i', 'j e i d a', 'j j h e e c a'); -- 43
|
||||
INSERT INTO t3 VALUES('g i g', 'f c c f d', 'a c i c a d a'); -- 44
|
||||
INSERT INTO t3 VALUES('c c f', 'a b j d b', 'c a e g f e c'); -- 45
|
||||
INSERT INTO t3 VALUES('d h j', 'g c b j d', 'e a h f h j g'); -- 46
|
||||
INSERT INTO t3 VALUES('a a d', 'j e j a i', 'i d c f f f b'); -- 47
|
||||
INSERT INTO t3 VALUES('b g j', 'e c i h f', 'd d h b g a d'); -- 48
|
||||
INSERT INTO t3 VALUES('c i a', 'a c c c c', 'e h i e h i e'); -- 49
|
||||
INSERT INTO t3 VALUES('f f c', 'f f b i i', 'f f a j e c i'); -- 50
|
||||
}
|
||||
|
||||
proc pmatch {col expr} {
|
||||
return [expr {[string first $expr $col]>=0}]
|
||||
}
|
||||
db func pmatch pmatch
|
||||
|
||||
foreach {tn cols tokens} {
|
||||
1 a "c c"
|
||||
2 b "c c"
|
||||
3 c "c c"
|
||||
4 {a b c} "c c"
|
||||
5 {a b c} "b h"
|
||||
6 {a b} "b h"
|
||||
7 {a c} "b h"
|
||||
8 {c a} "b h"
|
||||
9 {c} "i e"
|
||||
10 {b} "i e"
|
||||
11 {a} "i e"
|
||||
} {
|
||||
set fts "{$cols}:[join $tokens +]"
|
||||
set where [list]
|
||||
foreach c $cols { lappend where "pmatch($c, '$tokens')" }
|
||||
set where [join $where " OR "]
|
||||
|
||||
set res [db eval "SELECT rowid FROM t3 WHERE $where"]
|
||||
do_execsql_test "1.$tn.$fts->([llength $res] rows)" {
|
||||
SELECT rowid FROM t3($fts)
|
||||
} $res
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
SELECT rowid,
|
||||
highlight(t3, 0, '*', '*'),
|
||||
highlight(t3, 1, '*', '*'),
|
||||
highlight(t3, 2, '*', '*')
|
||||
FROM t3('a:f+f')
|
||||
} {
|
||||
31 {h *f f*} {i j g e c} {j j f c a i j}
|
||||
50 {*f f* c} {f f b i i} {f f a j e c i}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -62,6 +62,242 @@ foreach {tn q res} {
|
||||
do_execsql_test 2.3.$tn $q $res
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that prefix queries with:
|
||||
#
|
||||
# * a column filter, and
|
||||
# * no prefix index.
|
||||
#
|
||||
# work Ok.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
|
||||
INSERT INTO t3(t3, rank) VALUES('pgsz', 32);
|
||||
BEGIN;
|
||||
INSERT INTO t3 VALUES('acb ccc bba', 'cca bba bca', 'bbc ccc bca'); -- 1
|
||||
INSERT INTO t3 VALUES('cbb cac cab', 'abb aac bba', 'aab ccc cac'); -- 2
|
||||
INSERT INTO t3 VALUES('aac bcb aac', 'acb bcb caa', 'aca bab bca'); -- 3
|
||||
INSERT INTO t3 VALUES('aab ccb ccc', 'aca cba cca', 'aca aac cbb'); -- 4
|
||||
INSERT INTO t3 VALUES('bac aab bab', 'ccb bac cba', 'acb aba abb'); -- 5
|
||||
INSERT INTO t3 VALUES('bab abc ccb', 'acb cba abb', 'cbb aaa cab'); -- 6
|
||||
INSERT INTO t3 VALUES('cbb bbc baa', 'aab aca baa', 'bcc cca aca'); -- 7
|
||||
INSERT INTO t3 VALUES('abc bba abb', 'cac abc cba', 'acc aac cac'); -- 8
|
||||
INSERT INTO t3 VALUES('bbc bbc cab', 'bcb ccb cba', 'bcc cac acb'); -- 9
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
foreach {tn match res} {
|
||||
1 "a : c*" {1 2 4 6 7 9}
|
||||
2 "b : c*" {1 3 4 5 6 8 9}
|
||||
3 "c : c*" {1 2 4 6 7 8 9}
|
||||
4 "a : b*" {1 3 5 6 7 8 9}
|
||||
5 "b : b*" {1 2 3 5 7 9}
|
||||
6 "c : b*" {1 3 7 9}
|
||||
7 "a : a*" {1 3 4 5 6 8}
|
||||
8 "b : a*" {2 3 4 6 7 8}
|
||||
9 "c : a*" {2 3 4 5 6 7 8 9}
|
||||
} {
|
||||
do_execsql_test 3.1.$tn {
|
||||
SELECT rowid FROM t3($match)
|
||||
} $res
|
||||
}
|
||||
|
||||
do_test 3.2 {
|
||||
expr srand(0)
|
||||
execsql { DELETE FROM t3 }
|
||||
for {set i 0} {$i < 1000} {incr i} {
|
||||
set a [fts5_rnddoc 3]
|
||||
set b [fts5_rnddoc 8]
|
||||
set c [fts5_rnddoc 20]
|
||||
execsql { INSERT INTO t3 VALUES($a, $b, $c) }
|
||||
}
|
||||
execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
|
||||
} {}
|
||||
|
||||
proc gmatch {col pattern} {
|
||||
expr {[lsearch -glob $col $pattern]>=0}
|
||||
}
|
||||
db func gmatch gmatch
|
||||
|
||||
proc ghl {col pattern} {
|
||||
foreach t $col {
|
||||
if {[string match $pattern $t]} {
|
||||
lappend res "*$t*"
|
||||
} else {
|
||||
lappend res $t
|
||||
}
|
||||
}
|
||||
set res
|
||||
}
|
||||
db func ghl ghl
|
||||
|
||||
set COLS(a) 0
|
||||
set COLS(b) 1
|
||||
set COLS(c) 2
|
||||
|
||||
for {set x 0} {$x<2} {incr x} {
|
||||
foreach {tn pattern} {
|
||||
1 {xa*}
|
||||
2 {xb*}
|
||||
3 {xc*}
|
||||
4 {xd*}
|
||||
5 {xe*}
|
||||
6 {xf*}
|
||||
7 {xg*}
|
||||
8 {xh*}
|
||||
9 {xi*}
|
||||
10 {xj*}
|
||||
} {
|
||||
foreach col {a b c} {
|
||||
|
||||
# Check that the list of returned rowids is correct.
|
||||
#
|
||||
set res [db eval "SELECT rowid FROM t3 WHERE gmatch($col, '$pattern')"]
|
||||
set query "$col : $pattern"
|
||||
do_execsql_test 3.3.$x.$tn.$col.rowid {
|
||||
SELECT rowid FROM t3($query);
|
||||
} $res
|
||||
|
||||
# Check that the highlight() function works.
|
||||
#
|
||||
set res [db eval \
|
||||
"SELECT ghl($col, '$pattern') FROM t3 WHERE gmatch($col, '$pattern')"
|
||||
]
|
||||
set idx $COLS($col)
|
||||
do_execsql_test 3.3.$x.$tn.$col.highlight {
|
||||
SELECT highlight(t3, $idx, '*', '*') FROM t3($query);
|
||||
} $res
|
||||
}
|
||||
|
||||
foreach colset {{a b} {b c} {c a} {a c} {b a}} {
|
||||
# Check that the list of returned rowids is correct.
|
||||
#
|
||||
foreach {col1 col2} $colset {}
|
||||
set expr "gmatch($col1, '$pattern') OR gmatch($col2, '$pattern')"
|
||||
set res [db eval "SELECT rowid FROM t3 WHERE $expr"]
|
||||
set query "{$colset} : $pattern"
|
||||
do_execsql_test 3.3.$x.$tn.{$colset}.rowid {
|
||||
SELECT rowid FROM t3($query);
|
||||
} $res
|
||||
|
||||
set resq "SELECT ghl($col1, '$pattern'), ghl($col2, '$pattern')"
|
||||
append resq " FROM t3 WHERE $expr"
|
||||
set res [db eval $resq]
|
||||
set idx1 $COLS($col1)
|
||||
set idx2 $COLS($col2)
|
||||
do_execsql_test 3.3.$x.$tn.{$colset}.highlight {
|
||||
SELECT highlight(t3, $idx1, '*', '*'), highlight(t3, $idx2, '*', '*')
|
||||
FROM t3($query)
|
||||
} $res
|
||||
}
|
||||
}
|
||||
execsql { INSERT INTO t3(t3) VALUES('optimize') }
|
||||
execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(c1, c2);
|
||||
INSERT INTO t2 VALUES('xa xb', 'xb xa');
|
||||
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 8
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 16
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 32
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 64
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 128
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 256
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 512
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 1024
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2048
|
||||
INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4096
|
||||
|
||||
SELECT count(*) FROM t2('x*');
|
||||
} {4096}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
UPDATE t2 SET c2 = 'ya yb';
|
||||
SELECT count(*) FROM t2('c1:x*');
|
||||
SELECT count(*) FROM t2('c2:x*');
|
||||
} {4096 0}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
UPDATE t2 SET c2 = 'xa';
|
||||
SELECT count(*) FROM t2('c1:x*');
|
||||
SELECT count(*) FROM t2('c2:x*');
|
||||
} {4096 4096}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
proc rnddoc {n} {
|
||||
set map [list a b c d]
|
||||
set doc [list]
|
||||
for {set i 0} {$i < $n} {incr i} {
|
||||
lappend doc "x[lindex $map [expr int(rand()*4)]]"
|
||||
}
|
||||
set doc
|
||||
}
|
||||
set cols [list]
|
||||
for {set i 1} {$i<250} {incr i} {
|
||||
lappend cols "c$i"
|
||||
lappend vals "'[rnddoc 10]'"
|
||||
}
|
||||
|
||||
do_test 5.0 {
|
||||
execsql "CREATE VIRTUAL TABLE t4 USING fts5([join $cols ,])"
|
||||
execsql {INSERT INTO t4(t4, rank) VALUES('pgsz', 32)}
|
||||
execsql "INSERT INTO t4 VALUES([join $vals ,])"
|
||||
execsql "INSERT INTO t4 VALUES([join $vals ,])"
|
||||
execsql "INSERT INTO t4 VALUES([join $vals ,])"
|
||||
execsql "INSERT INTO t4 VALUES([join $vals ,])"
|
||||
} {}
|
||||
|
||||
proc gmatch {col pattern} {
|
||||
expr {[lsearch -glob $col $pattern]>=0}
|
||||
}
|
||||
db func gmatch gmatch
|
||||
foreach {tn col pattern} {
|
||||
1 c100 {xa*}
|
||||
2 c200 {xb*}
|
||||
} {
|
||||
set res [db eval "SELECT rowid FROM t4 WHERE gmatch($col, \$pattern)"]
|
||||
set query "$col : $pattern"
|
||||
do_execsql_test 5.$tn { SELECT rowid FROM t4($query) } $res
|
||||
}
|
||||
|
||||
reset_db
|
||||
db func fts5_rnddoc fts5_rnddoc
|
||||
do_test 6.0 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t5 USING fts5(x, y);
|
||||
INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
|
||||
INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
|
||||
}
|
||||
} {}
|
||||
|
||||
proc gmatch {col pattern} {
|
||||
expr {[lsearch -glob $col $pattern]>=0}
|
||||
}
|
||||
db func gmatch gmatch
|
||||
foreach {tn col pattern} {
|
||||
1 y {xa*}
|
||||
2 y {xb*}
|
||||
3 y {xc*}
|
||||
4 x {xa*}
|
||||
5 x {xb*}
|
||||
6 x {xc*}
|
||||
} {
|
||||
set res [db eval "SELECT rowid FROM t5 WHERE gmatch($col, \$pattern)"]
|
||||
set query "$col : $pattern"
|
||||
do_execsql_test 6.$tn { SELECT rowid FROM t5($query) } $res
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# 2015 October 27
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# 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 fts5query
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
|
||||
reset_db
|
||||
do_test 1.$tn.1 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz);
|
||||
BEGIN;
|
||||
}
|
||||
foreach x [list aaa bbb ccc ddd eee fff ggg hhh iii jjj] {
|
||||
set doc [string repeat "$x " 30]
|
||||
execsql { INSERT INTO t1 VALUES($doc) }
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
set ret 1
|
||||
foreach x [list a b c d e f g h i j] {
|
||||
do_execsql_test 1.$tn.3.$ret {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH $x || '*';
|
||||
} $ret
|
||||
incr ret
|
||||
}
|
||||
}
|
||||
|
||||
for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
|
||||
reset_db
|
||||
do_test 2.$tn.1 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz);
|
||||
BEGIN;
|
||||
}
|
||||
foreach x [list bbb ddd fff hhh jjj lll nnn ppp rrr ttt] {
|
||||
set doc [string repeat "$x " 30]
|
||||
execsql { INSERT INTO t1 VALUES($doc) }
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
set ret 1
|
||||
foreach x [list a c e g i k m o q s u] {
|
||||
do_execsql_test 2.$tn.3.$ret {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH $x || '*';
|
||||
} {}
|
||||
incr ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ ifcapable !fts5 {
|
||||
return
|
||||
}
|
||||
|
||||
if 1 {
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
set doc "x x [string repeat {y } 50]z z"
|
||||
@@ -137,8 +136,6 @@ do_execsql_test 5.4 {
|
||||
SELECT rowid FROM tt WHERE tt MATCH 'a*';
|
||||
} {1 2}
|
||||
|
||||
}
|
||||
|
||||
do_execsql_test 5.5 {
|
||||
DELETE FROM tt;
|
||||
BEGIN;
|
||||
@@ -184,6 +181,146 @@ do_catchsql_test 6.3 {
|
||||
SELECT * FROM xyz WHERE xyz MATCH NULL
|
||||
} {1 {fts5: syntax error near ""}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(content);
|
||||
INSERT INTO ft2(rowid, content) VALUES(1, 'a b c');
|
||||
INSERT INTO ft2(rowid, content) VALUES(2, 'a b d');
|
||||
}
|
||||
|
||||
do_catchsql_test 7.2 {
|
||||
BEGIN;
|
||||
UPDATE ft2 SET rowid=2 WHERE rowid=1;
|
||||
} {1 {constraint failed}}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
COMMIT;
|
||||
INSERT INTO ft2(ft2) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
do_execsql_test 7.4 {
|
||||
SELECT * FROM ft2;
|
||||
} {{a b c} {a b d}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.1 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(content);
|
||||
INSERT INTO ft2(rowid, content) VALUES(1, 'a b');
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
BEGIN;
|
||||
INSERT INTO ft2(rowid, content) VALUES(4, 'a x');
|
||||
}
|
||||
|
||||
do_execsql_test 8.3 {
|
||||
INSERT INTO ft2(ft2) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the "table function" syntax works.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 9.1 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(content);
|
||||
INSERT INTO ft2(rowid, content) VALUES(1, 'a b');
|
||||
INSERT INTO ft2(rowid, content) VALUES(2, 'a b c d');
|
||||
INSERT INTO ft2(rowid, content) VALUES(3, 'c d e f');
|
||||
}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
SELECT rowid FROM ft2('a');
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 9.3 {
|
||||
SELECT rowid FROM ft2('b AND c');
|
||||
} {2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 10.0 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
|
||||
INSERT INTO t3 VALUES('bac aab bab', 'c bac c', 'acb aba abb'); -- 1
|
||||
INSERT INTO t3 VALUES('bab abc c', 'acb c abb', 'c aaa c'); -- 2
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT rowid FROM t3('c: c*');
|
||||
} {2}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT rowid FROM t3('b: acb');
|
||||
} {2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that character 0x1A is allowed in fts5 barewords.
|
||||
#
|
||||
do_test 11.0 {
|
||||
execsql "CREATE VIRTUAL TABLE t4 USING fts5(x, tokenize=\"ascii tokenchars '\x1A'\")"
|
||||
execsql "
|
||||
INSERT INTO t4 VALUES('a b c \x1A');
|
||||
INSERT INTO t4 VALUES('a b c d\x1A');
|
||||
INSERT INTO t4 VALUES('a b c \x1Ad');
|
||||
INSERT INTO t4 VALUES('a b c d');
|
||||
"
|
||||
} {}
|
||||
|
||||
do_test 11.1 {
|
||||
execsql "SELECT rowid FROM t4('\x1A')"
|
||||
} {1}
|
||||
do_test 11.2 {
|
||||
execsql "SELECT rowid FROM t4('\x1A*')"
|
||||
} {1 3}
|
||||
do_test 11.3 {
|
||||
execsql "SELECT rowid FROM t4('d\x1A')"
|
||||
} {2}
|
||||
|
||||
do_test 11.4 {
|
||||
catchsql "SELECT rowid FROM t4('d\x1B')"
|
||||
} {/fts5: syntax error/}
|
||||
do_test 11.5 {
|
||||
catchsql "SELECT rowid FROM t4('d\x19')"
|
||||
} {/fts5: syntax error/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_test 12.1 {
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE xx USING fts5(x,y);
|
||||
BEGIN;
|
||||
INSERT INTO xx VALUES('1 2 3', 'a b c');
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT rowid FROM xx('x:a');
|
||||
COMMIT;
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try an UPDATE OR REPLACE query.
|
||||
#
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE xy USING fts5(x);
|
||||
INSERT INTO xy(rowid, x) VALUES(1, '1 2 3');
|
||||
INSERT INTO xy(rowid, x) VALUES(2, '2 3 4');
|
||||
INSERT INTO xy(rowid, x) VALUES(3, '3 4 5');
|
||||
}
|
||||
|
||||
do_execsql_test 13.2 {
|
||||
UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2;
|
||||
SELECT rowid, x FROM xy;
|
||||
} {
|
||||
1 {1 2 3}
|
||||
3 {2 3 4}
|
||||
}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
INSERT INTO xy(xy) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+142
-10
@@ -56,7 +56,7 @@ do_execsql_test 1.4.1 {
|
||||
|
||||
do_execsql_test 1.4.2 {
|
||||
SELECT * FROM v2;
|
||||
} {x 0 2 4 y 0 1 1 z 0 1 1}
|
||||
} {x one 2 4 y one 1 1 z one 1 1}
|
||||
|
||||
do_execsql_test 1.5.1 {
|
||||
BEGIN;
|
||||
@@ -67,7 +67,7 @@ do_execsql_test 1.5.1 {
|
||||
do_execsql_test 1.5.2 {
|
||||
SELECT * FROM v2 WHERE term<'d';
|
||||
COMMIT;
|
||||
} {a 0 1 1 b 0 1 1 c 0 1 1}
|
||||
} {a one 1 1 b one 1 1 c one 1 1}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
DELETE FROM t1 WHERE one = 'a b c';
|
||||
@@ -91,14 +91,14 @@ do_execsql_test 2.0 {
|
||||
}
|
||||
|
||||
set res_col {
|
||||
a 0 6 11 a 1 7 9
|
||||
b 0 6 7 b 1 7 7
|
||||
c 0 6 12 c 1 5 8
|
||||
d 0 4 6 d 1 9 13
|
||||
e 0 6 7 e 1 6 6
|
||||
f 0 9 10 f 1 7 10
|
||||
g 0 5 7 g 1 5 7
|
||||
x 0 1 1 y 1 1 1
|
||||
a a 6 11 a b 7 9
|
||||
b a 6 7 b b 7 7
|
||||
c a 6 12 c b 5 8
|
||||
d a 4 6 d b 9 13
|
||||
e a 6 7 e b 6 6
|
||||
f a 9 10 f b 7 10
|
||||
g a 5 7 g b 5 7
|
||||
x a 1 1 y b 1 1
|
||||
}
|
||||
set res_row {
|
||||
a 10 20 b 9 14 c 9 20 d 9 19
|
||||
@@ -213,5 +213,137 @@ do_catchsql_test 6.2 {
|
||||
SELECT * FROM vocab3;
|
||||
} {1 {no such fts5 table: main.lll}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test single term queries on fts5vocab tables (i.e. those with term=?
|
||||
# constraints in the WHERE clause).
|
||||
#
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE tx USING fts5(one, two);
|
||||
INSERT INTO tx VALUES('g a ggg g a b eee', 'cc d aa ff g ee');
|
||||
INSERT INTO tx VALUES('dd fff i a i jjj', 'f fff hh jj e f');
|
||||
INSERT INTO tx VALUES('ggg a f f fff dd aa', 'd ggg f f j gg ddd');
|
||||
INSERT INTO tx VALUES('e bb h jjj ii gg', 'e aa e f c fff');
|
||||
INSERT INTO tx VALUES('j ff aa a h', 'h a j bbb bb');
|
||||
INSERT INTO tx VALUES('cc i ff c d f', 'dd ii fff f c cc d');
|
||||
INSERT INTO tx VALUES('jjj g i bb cc eee', 'hhh iii aaa b bbb aaa');
|
||||
INSERT INTO tx VALUES('hhh hhh hhh bb fff f', 'fff gg aa ii h a');
|
||||
INSERT INTO tx VALUES('b c cc aaa iii ggg f', 'iii ff ee a ff c cc');
|
||||
INSERT INTO tx VALUES('hhh b hhh aaa j i i', 'dd ee ee aa bbb iii');
|
||||
INSERT INTO tx VALUES('hh dd h b g ff i', 'ccc bb cc ccc f a d');
|
||||
INSERT INTO tx VALUES('g d b ggg jj', 'fff jj ff jj g gg ee');
|
||||
INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff');
|
||||
INSERT INTO tx VALUES('c jjj hh ddd dd h', 'e aaa h jjj gg');
|
||||
|
||||
CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row);
|
||||
CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col);
|
||||
}
|
||||
|
||||
proc cont {L elem} {
|
||||
set n 0
|
||||
foreach e $L { if {$elem==$e} {incr n} }
|
||||
set n
|
||||
}
|
||||
db func cont cont
|
||||
|
||||
foreach {term} {
|
||||
a aa aaa
|
||||
b bb bbb
|
||||
c cc ccc
|
||||
d dd ddd
|
||||
e ee eee
|
||||
f ff fff
|
||||
g gg ggg
|
||||
h hh hhh
|
||||
i ii iii
|
||||
j jj jjj
|
||||
} {
|
||||
set resr [db eval {
|
||||
SELECT $term,
|
||||
sum(cont(one || ' ' || two, $term) > 0),
|
||||
sum(cont(one || ' ' || two, $term))
|
||||
FROM tx
|
||||
}]
|
||||
if {[lindex $resr 1]==0} {set resr [list]}
|
||||
|
||||
set r1 [db eval {
|
||||
SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx
|
||||
}]
|
||||
if {[lindex $r1 2]==0} {set r1 [list]}
|
||||
|
||||
set r2 [db eval {
|
||||
SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx
|
||||
}]
|
||||
if {[lindex $r2 2]==0} {set r2 [list]}
|
||||
|
||||
set resc [concat $r1 $r2]
|
||||
do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc
|
||||
do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE txr_c AS SELECT * FROM txr;
|
||||
CREATE TABLE txc_c AS SELECT * FROM txc;
|
||||
}
|
||||
|
||||
# Test range queries on the fts5vocab tables created above.
|
||||
#
|
||||
foreach {tn a b} {
|
||||
1 a jjj
|
||||
2 bb j
|
||||
3 ccc ddd
|
||||
4 dd xyz
|
||||
5 xzy dd
|
||||
6 h hh
|
||||
} {
|
||||
do_execsql_test 7.2.$tn.1 {
|
||||
SELECT * FROM txr WHERE term>=$a
|
||||
} [db eval {SELECT * FROM txr_c WHERE term>=$a}]
|
||||
do_execsql_test 7.2.$tn.2 {
|
||||
SELECT * FROM txr WHERE term<=$b
|
||||
} [db eval {SELECT * FROM txr_c WHERE term <=$b}]
|
||||
do_execsql_test 7.2.$tn.3 {
|
||||
SELECT * FROM txr WHERE term>=$a AND term<=$b
|
||||
} [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}]
|
||||
|
||||
do_execsql_test 7.2.$tn.4 {
|
||||
SELECT * FROM txc WHERE term>=$a
|
||||
} [db eval {SELECT * FROM txc_c WHERE term>=$a}]
|
||||
do_execsql_test 7.2.$tn.5 {
|
||||
SELECT * FROM txc WHERE term<=$b
|
||||
} [db eval {SELECT * FROM txc_c WHERE term <=$b}]
|
||||
do_execsql_test 7.2.$tn.6 {
|
||||
SELECT * FROM txc WHERE term>=$a AND term<=$b
|
||||
} [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}]
|
||||
|
||||
do_execsql_test 7.2.$tn.7 {
|
||||
SELECT * FROM txr WHERE term>$a
|
||||
} [db eval {SELECT * FROM txr_c WHERE term>$a}]
|
||||
do_execsql_test 7.2.$tn.8 {
|
||||
SELECT * FROM txr WHERE term<$b
|
||||
} [db eval {SELECT * FROM txr_c WHERE term<$b}]
|
||||
do_execsql_test 7.2.$tn.9 {
|
||||
SELECT * FROM txr WHERE term>$a AND term<$b
|
||||
} [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}]
|
||||
|
||||
do_execsql_test 7.2.$tn.10 {
|
||||
SELECT * FROM txc WHERE term>$a
|
||||
} [db eval {SELECT * FROM txc_c WHERE term>$a}]
|
||||
do_execsql_test 7.2.$tn.11 {
|
||||
SELECT * FROM txc WHERE term<$b
|
||||
} [db eval {SELECT * FROM txc_c WHERE term<$b}]
|
||||
do_execsql_test 7.2.$tn.12 {
|
||||
SELECT * FROM txc WHERE term>$a AND term<$b
|
||||
} [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}]
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.1 {
|
||||
SELECT count(*) FROM txr, txr_c WHERE txr.term = txr_c.term;
|
||||
} {30}
|
||||
|
||||
do_execsql_test 7.3.2 {
|
||||
SELECT count(*) FROM txc, txc_c
|
||||
WHERE txc.term = txc_c.term AND txc.col=txc_c.col;
|
||||
} {57}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
|
||||
|
||||
proc usage {} {
|
||||
puts stderr "$::argv0 ?OPTIONS? DATABASE FILE1..."
|
||||
puts stderr ""
|
||||
puts stderr "Options are"
|
||||
puts stderr " -fts5"
|
||||
puts stderr " -fts4"
|
||||
puts stderr " -colsize <list of column sizes>"
|
||||
puts stderr {
|
||||
This script is designed to create fts4/5 tables with more than one column.
|
||||
The -colsize option should be set to a Tcl list of integer values, one for
|
||||
each column in the table. Each value is the number of tokens that will be
|
||||
inserted into the column value for each row. For example, setting the -colsize
|
||||
option to "5 10" creates an FTS table with 2 columns, with roughly 5 and 10
|
||||
tokens per row in each, respectively.
|
||||
|
||||
Each "FILE" argument should be a text file. The contents of these text files is
|
||||
split on whitespace characters to form a list of tokens. The first N1 tokens
|
||||
are used for the first column of the first row, where N1 is the first element
|
||||
of the -colsize list. The next N2 are used for the second column of the first
|
||||
row, and so on. Rows are added to the table until the entire list of tokens
|
||||
is exhausted.
|
||||
}
|
||||
exit -1
|
||||
}
|
||||
|
||||
set O(aColSize) [list 10 10 10]
|
||||
set O(tblname) t1
|
||||
set O(fts) fts5
|
||||
|
||||
|
||||
set options_with_values {-colsize}
|
||||
|
||||
for {set i 0} {$i < [llength $argv]} {incr i} {
|
||||
set opt [lindex $argv $i]
|
||||
if {[string range $opt 0 0]!="-"} break
|
||||
|
||||
if {[lsearch $options_with_values $opt]>=0} {
|
||||
incr i
|
||||
if {$i==[llength $argv]} usage
|
||||
set val [lindex $argv $i]
|
||||
}
|
||||
|
||||
switch -- $opt {
|
||||
-colsize {
|
||||
set O(aColSize) $val
|
||||
}
|
||||
|
||||
-fts4 {
|
||||
set O(fts) fts4
|
||||
}
|
||||
|
||||
-fts5 {
|
||||
set O(fts) fts5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$i > [llength $argv]-2} usage
|
||||
set O(db) [lindex $argv $i]
|
||||
set O(files) [lrange $argv [expr $i+1] end]
|
||||
|
||||
sqlite3 db $O(db)
|
||||
|
||||
# Create the FTS table in the db. Return a list of the table columns.
|
||||
#
|
||||
proc create_table {} {
|
||||
global O
|
||||
set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
|
||||
|
||||
set nCol [llength $O(aColSize)]
|
||||
set cols [lrange $cols 0 [expr $nCol-1]]
|
||||
|
||||
set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $O(tblname) USING $O(fts) ("
|
||||
append sql [join $cols ,]
|
||||
append sql ");"
|
||||
|
||||
db eval $sql
|
||||
return $cols
|
||||
}
|
||||
|
||||
# Return a list of tokens from the named file.
|
||||
#
|
||||
proc readfile {file} {
|
||||
set fd [open $file]
|
||||
set data [read $fd]
|
||||
close $fd
|
||||
split $data
|
||||
}
|
||||
|
||||
|
||||
# Load all the data into a big list of tokens.
|
||||
#
|
||||
set tokens [list]
|
||||
foreach f $O(files) {
|
||||
set tokens [concat $tokens [readfile $f]]
|
||||
}
|
||||
|
||||
set N [llength $tokens]
|
||||
set i 0
|
||||
set cols [create_table]
|
||||
set sql "INSERT INTO $O(tblname) VALUES(\$[lindex $cols 0]"
|
||||
foreach c [lrange $cols 1 end] {
|
||||
append sql ", \$A($c)"
|
||||
}
|
||||
append sql ")"
|
||||
|
||||
db eval BEGIN
|
||||
while {$i < $N} {
|
||||
foreach c $cols s $O(aColSize) {
|
||||
set A($c) [lrange $tokens $i [expr $i+$s-1]]
|
||||
incr i $s
|
||||
}
|
||||
db eval $sql
|
||||
}
|
||||
db eval COMMIT
|
||||
|
||||
|
||||
|
||||
+10
-10
@@ -7,6 +7,7 @@ set G(src) [string map [list %dir% $srcdir] {
|
||||
%dir%/fts5.h
|
||||
%dir%/fts5Int.h
|
||||
fts5parse.h
|
||||
fts5parse.c
|
||||
%dir%/fts5_aux.c
|
||||
%dir%/fts5_buffer.c
|
||||
%dir%/fts5_config.c
|
||||
@@ -19,12 +20,11 @@ set G(src) [string map [list %dir% $srcdir] {
|
||||
%dir%/fts5_unicode2.c
|
||||
%dir%/fts5_varint.c
|
||||
%dir%/fts5_vocab.c
|
||||
fts5parse.c
|
||||
}]
|
||||
|
||||
set G(hdr) {
|
||||
|
||||
#if !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_FTS5)
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
@@ -37,7 +37,7 @@ set G(hdr) {
|
||||
|
||||
set G(footer) {
|
||||
|
||||
#endif /* !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_FTS5) */
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -78,7 +78,7 @@ proc fts5c_printfile {zIn} {
|
||||
global G
|
||||
set data [readfile $zIn]
|
||||
set zTail [file tail $zIn]
|
||||
puts $G(fd) "#line 2 \"$zTail\""
|
||||
puts $G(fd) "#line 1 \"$zTail\""
|
||||
|
||||
set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
|
||||
if {$zTail=="fts5parse.c"} {
|
||||
@@ -86,8 +86,12 @@ proc fts5c_printfile {zIn} {
|
||||
}
|
||||
|
||||
foreach line [split $data "\n"] {
|
||||
if {[regexp {^#include.*fts5} $line]} continue
|
||||
if {[regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]} {
|
||||
if {[regexp {^#include.*fts5} $line]} {
|
||||
set line "/* $line */"
|
||||
} elseif {
|
||||
![regexp { sqlite3Fts5Init\(} $line]
|
||||
&& [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]
|
||||
} {
|
||||
set line "static $line"
|
||||
}
|
||||
set line [string map $sub_map $line]
|
||||
@@ -107,7 +111,3 @@ proc fts5c_close {} {
|
||||
fts5c_init fts5.c
|
||||
foreach f $G(src) { fts5c_printfile $f }
|
||||
fts5c_close
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ proc usage {} {
|
||||
puts stderr "usage: $::argv0 ?OPTIONS? database table"
|
||||
puts stderr ""
|
||||
puts stderr " -nterm (count number of terms in each segment)"
|
||||
puts stderr " -segments (output segment contents)"
|
||||
puts stderr ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
set O(nterm) 0
|
||||
set O(segments) 0
|
||||
|
||||
if {[llength $argv]<2} usage
|
||||
foreach a [lrange $argv 0 end-2] {
|
||||
@@ -21,6 +23,10 @@ foreach a [lrange $argv 0 end-2] {
|
||||
set O(nterm) 1
|
||||
}
|
||||
|
||||
-segments {
|
||||
set O(segments) 1
|
||||
}
|
||||
|
||||
default {
|
||||
usage
|
||||
}
|
||||
@@ -78,6 +84,13 @@ db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" {
|
||||
}
|
||||
}
|
||||
|
||||
if {$O(segments)} {
|
||||
puts ""
|
||||
db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id>10" {
|
||||
puts $d
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+76
-27
@@ -21,24 +21,38 @@
|
||||
** This implementation parses JSON text at 250 MB/s, so it is hard to see
|
||||
** how JSONB might improve on that.)
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
|
||||
#if !defined(_SQLITEINT_H_)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define UNUSED_PARAM(X) (void)(X)
|
||||
|
||||
#ifndef LARGEST_INT64
|
||||
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Versions of isspace(), isalnum() and isdigit() to which it is safe
|
||||
** to pass signed char values.
|
||||
*/
|
||||
#define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
#define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
#ifdef sqlite3Isdigit
|
||||
/* Use the SQLite core versions if this routine is part of the
|
||||
** SQLite amalgamation */
|
||||
# define safe_isdigit(x) sqlite3Isdigit(x)
|
||||
# define safe_isalnum(x) sqlite3Isalnum(x)
|
||||
#else
|
||||
/* Use the standard library for separate compilation */
|
||||
#include <ctype.h> /* amalgamator: keep */
|
||||
# define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
# define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
@@ -46,7 +60,7 @@ SQLITE_EXTENSION_INIT1
|
||||
** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
|
||||
*/
|
||||
static const char jsonIsSpace[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -65,10 +79,13 @@ static const char jsonIsSpace[] = {
|
||||
};
|
||||
#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
|
||||
|
||||
/* Unsigned integer types */
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/* Unsigned integer types. These are already defined in the sqliteInt.h,
|
||||
** but the definitions need to be repeated for separate compilation. */
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
#endif
|
||||
|
||||
/* Objects */
|
||||
typedef struct JsonString JsonString;
|
||||
@@ -477,18 +494,42 @@ static void jsonReturn(
|
||||
sqlite3_result_int(pCtx, 0);
|
||||
break;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
double r = strtod(pNode->u.zJContent, 0);
|
||||
sqlite3_result_double(pCtx, r);
|
||||
break;
|
||||
}
|
||||
case JSON_INT: {
|
||||
sqlite3_int64 i = 0;
|
||||
const char *z = pNode->u.zJContent;
|
||||
if( z[0]=='-' ){ z++; }
|
||||
while( z[0]>='0' && z[0]<='9' ){ i = i*10 + *(z++) - '0'; }
|
||||
while( z[0]>='0' && z[0]<='9' ){
|
||||
unsigned v = *(z++) - '0';
|
||||
if( i>=LARGEST_INT64/10 ){
|
||||
if( i>LARGEST_INT64/10 ) goto int_as_real;
|
||||
if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
|
||||
if( v==9 ) goto int_as_real;
|
||||
if( v==8 ){
|
||||
if( pNode->u.zJContent[0]=='-' ){
|
||||
sqlite3_result_int64(pCtx, SMALLEST_INT64);
|
||||
goto int_done;
|
||||
}else{
|
||||
goto int_as_real;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = i*10 + v;
|
||||
}
|
||||
if( pNode->u.zJContent[0]=='-' ){ i = -i; }
|
||||
sqlite3_result_int64(pCtx, i);
|
||||
int_done:
|
||||
break;
|
||||
int_as_real: /* fall through to real */;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
double r;
|
||||
#ifdef SQLITE_AMALGAMATION
|
||||
const char *z = pNode->u.zJContent;
|
||||
sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
#else
|
||||
r = strtod(pNode->u.zJContent, 0);
|
||||
#endif
|
||||
sqlite3_result_double(pCtx, r);
|
||||
break;
|
||||
}
|
||||
case JSON_STRING: {
|
||||
@@ -858,7 +899,7 @@ static int jsonParseFindParents(JsonParse *pParse){
|
||||
** Compare the OBJECT label at pNode against zKey,nKey. Return true on
|
||||
** a match.
|
||||
*/
|
||||
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, int nKey){
|
||||
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
|
||||
if( pNode->jnFlags & JNODE_RAW ){
|
||||
if( pNode->n!=nKey ) return 0;
|
||||
return strncmp(pNode->u.zJContent, zKey, nKey)==0;
|
||||
@@ -1937,19 +1978,12 @@ static sqlite3_module jsonTreeModule = {
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/****************************************************************************
|
||||
** The following routine is the only publically visible identifier in this
|
||||
** file. Call the following routine in order to register the various SQL
|
||||
** The following routines are the only publically visible identifiers in this
|
||||
** file. Call the following routines in order to register the various SQL
|
||||
** functions and the virtual table implemented by this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_json_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int sqlite3Json1Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
static const struct {
|
||||
@@ -1987,8 +2021,6 @@ int sqlite3_json_init(
|
||||
{ "json_tree", &jsonTreeModule },
|
||||
};
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
|
||||
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
|
||||
@@ -2002,3 +2034,20 @@ int sqlite3_json_init(
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_json_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return sqlite3Json1Init(db);
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
|
||||
|
||||
+57
-2
@@ -89,6 +89,10 @@
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
|
||||
#include "sqlite3rbu.h"
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
/* Maximum number of prepared UPDATE statements held by this module */
|
||||
#define SQLITE_RBU_UPDATE_CACHESIZE 16
|
||||
|
||||
@@ -2382,6 +2386,30 @@ static void rbuLockDatabase(sqlite3rbu *p){
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
|
||||
int nChar;
|
||||
LPWSTR zWideFilename;
|
||||
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
|
||||
if( nChar==0 ){
|
||||
return 0;
|
||||
}
|
||||
zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
|
||||
if( zWideFilename==0 ){
|
||||
return 0;
|
||||
}
|
||||
memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
|
||||
nChar);
|
||||
if( nChar==0 ){
|
||||
sqlite3_free(zWideFilename);
|
||||
zWideFilename = 0;
|
||||
}
|
||||
return zWideFilename;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock
|
||||
** on the database file. This proc moves the *-oal file to the *-wal path,
|
||||
@@ -2416,10 +2444,37 @@ static void rbuMoveOalFile(sqlite3rbu *p){
|
||||
rbuObjIterFinalize(&p->objiter);
|
||||
sqlite3_close(p->dbMain);
|
||||
sqlite3_close(p->dbRbu);
|
||||
p->dbMain = 0;
|
||||
p->dbRbu = 0;
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
{
|
||||
LPWSTR zWideOal;
|
||||
LPWSTR zWideWal;
|
||||
|
||||
zWideOal = rbuWinUtf8ToUnicode(zOal);
|
||||
if( zWideOal ){
|
||||
zWideWal = rbuWinUtf8ToUnicode(zWal);
|
||||
if( zWideWal ){
|
||||
if( MoveFileW(zWideOal, zWideWal) ){
|
||||
p->rc = SQLITE_OK;
|
||||
}else{
|
||||
p->rc = SQLITE_IOERR;
|
||||
}
|
||||
sqlite3_free(zWideWal);
|
||||
}else{
|
||||
p->rc = SQLITE_IOERR_NOMEM;
|
||||
}
|
||||
sqlite3_free(zWideOal);
|
||||
}else{
|
||||
p->rc = SQLITE_IOERR_NOMEM;
|
||||
}
|
||||
}
|
||||
#else
|
||||
p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
|
||||
#endif
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
p->dbMain = 0;
|
||||
p->dbRbu = 0;
|
||||
rbuOpenDatabase(p);
|
||||
rbuSetupCheckpoint(p, 0);
|
||||
}
|
||||
|
||||
@@ -269,6 +269,10 @@
|
||||
|
||||
#include "sqlite3.h" /* Required for error code definitions */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct sqlite3rbu sqlite3rbu;
|
||||
|
||||
/*
|
||||
@@ -337,6 +341,9 @@ sqlite3rbu *sqlite3rbu_open(
|
||||
** If an error has occurred, either while opening or stepping the RBU object,
|
||||
** this function may return NULL. The error code and message may be collected
|
||||
** when sqlite3rbu_close() is called.
|
||||
**
|
||||
** Database handles returned by this function remain valid until the next
|
||||
** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db().
|
||||
*/
|
||||
sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
|
||||
|
||||
@@ -447,4 +454,8 @@ int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
|
||||
*/
|
||||
void sqlite3rbu_destroy_vfs(const char *zName);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITE3RBU_H */
|
||||
|
||||
+30
-6
@@ -56,20 +56,34 @@ static int test_sqlite3rbu_cmd(
|
||||
){
|
||||
int ret = TCL_OK;
|
||||
sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
|
||||
const char *azMethod[] = {
|
||||
"step", "close", "create_rbu_delta", "savestate", 0
|
||||
struct RbuCmd {
|
||||
const char *zName;
|
||||
int nArg;
|
||||
const char *zUsage;
|
||||
} aCmd[] = {
|
||||
{"step", 2, ""}, /* 0 */
|
||||
{"close", 2, ""}, /* 1 */
|
||||
{"create_rbu_delta", 2, ""}, /* 2 */
|
||||
{"savestate", 2, ""}, /* 3 */
|
||||
{"dbMain_eval", 3, "SQL"}, /* 4 */
|
||||
{0,0,0}
|
||||
};
|
||||
int iMethod;
|
||||
int iCmd;
|
||||
|
||||
if( objc!=2 ){
|
||||
if( objc<2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){
|
||||
ret = Tcl_GetIndexFromObjStruct(
|
||||
interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd
|
||||
);
|
||||
if( ret ) return TCL_ERROR;
|
||||
if( objc!=aCmd[iCmd].nArg ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
switch( iMethod ){
|
||||
switch( iCmd ){
|
||||
case 0: /* step */ {
|
||||
int rc = sqlite3rbu_step(pRbu);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
@@ -112,6 +126,16 @@ static int test_sqlite3rbu_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: /* dbMain_eval */ {
|
||||
sqlite3 *db = sqlite3rbu_db(pRbu, 0);
|
||||
int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
|
||||
ret = TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: /* seems unlikely */
|
||||
assert( !"cannot happen" );
|
||||
break;
|
||||
|
||||
@@ -34,6 +34,11 @@ set testprefix rtree1
|
||||
#
|
||||
# rtree-12.*: Test that on-conflict clauses are supported.
|
||||
# rtree-13.*: Test that bug [d2889096e7bdeac6d] has been fixed.
|
||||
# rtree-14.*: Test if a non-integer is inserted into the PK column of an
|
||||
# r-tree table, it is converted to an integer before being
|
||||
# inserted. Also that if a non-numeric is inserted into one
|
||||
# of the min/max dimension columns, it is converted to the
|
||||
# required type before being inserted.
|
||||
#
|
||||
|
||||
ifcapable !rtree {
|
||||
@@ -535,4 +540,54 @@ do_execsql_test 13.2 {
|
||||
SELECT * FROM r CROSS JOIN t9 WHERE id=x;
|
||||
} {1 1 0.0 0.0 2 2 0.0 0.0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test if a non-integer is inserted into the PK column of an r-tree
|
||||
# table, it is converted to an integer before being inserted. Also
|
||||
# that if a non-numeric is inserted into one of the min/max dimension
|
||||
# columns, it is converted to the required type before being inserted.
|
||||
#
|
||||
do_execsql_test 14.1 {
|
||||
CREATE VIRTUAL TABLE t10 USING rtree(ii, x1, x2);
|
||||
}
|
||||
|
||||
do_execsql_test 14.2 {
|
||||
INSERT INTO t10 VALUES(NULL, 1, 2);
|
||||
INSERT INTO t10 VALUES(NULL, 2, 3);
|
||||
INSERT INTO t10 VALUES('4xxx', 3, 4);
|
||||
INSERT INTO t10 VALUES(5.0, 4, 5);
|
||||
INSERT INTO t10 VALUES(6.4, 5, 6);
|
||||
}
|
||||
do_execsql_test 14.3 {
|
||||
SELECT * FROM t10;
|
||||
} {
|
||||
1 1.0 2.0 2 2.0 3.0 4 3.0 4.0 5 4.0 5.0 6 5.0 6.0
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
DELETE FROM t10;
|
||||
INSERT INTO t10 VALUES(1, 'one', 'two');
|
||||
INSERT INTO t10 VALUES(2, '52xyz', '81...');
|
||||
}
|
||||
do_execsql_test 14.5 {
|
||||
SELECT * FROM t10;
|
||||
} {
|
||||
1 0.0 0.0
|
||||
2 52.0 81.0
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
DROP TABLE t10;
|
||||
CREATE VIRTUAL TABLE t10 USING rtree_i32(ii, x1, x2);
|
||||
INSERT INTO t10 VALUES(1, 'one', 'two');
|
||||
INSERT INTO t10 VALUES(2, '52xyz', '81...');
|
||||
INSERT INTO t10 VALUES(3, 42.3, 49.9);
|
||||
}
|
||||
do_execsql_test 14.5 {
|
||||
SELECT * FROM t10;
|
||||
} {
|
||||
1 0 0
|
||||
2 52 81
|
||||
3 42 49
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
# THREADLIB Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
# LIBS Extra libraries options
|
||||
#
|
||||
# OPTS Extra compiler command-line options.
|
||||
#
|
||||
# EXE The suffix to add to executable files. ".exe" for windows
|
||||
@@ -35,9 +37,6 @@
|
||||
# LIBREADLINE Linker options needed by programs using readline() must
|
||||
# link against.
|
||||
#
|
||||
# NAWK Nawk compatible awk program. Older (obsolete?) solaris
|
||||
# systems need this to avoid using the original AT&T AWK.
|
||||
#
|
||||
# Once the macros above are defined, the rest of this make script will
|
||||
# build the SQLite library and testing tools.
|
||||
################################################################################
|
||||
@@ -48,19 +47,21 @@ TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
|
||||
TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
|
||||
TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
|
||||
TCCX += -I$(TOP)/ext/fts5
|
||||
THREADLIB += $(LIBS)
|
||||
|
||||
# Object files for the SQLite library.
|
||||
#
|
||||
LIBOBJ+= vdbe.o parse.o \
|
||||
alter.o analyze.o attach.o auth.o \
|
||||
backup.o bitvec.o btmutex.o btree.o build.o \
|
||||
callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o fault.o fkey.o \
|
||||
callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o \
|
||||
fault.o fkey.o \
|
||||
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
|
||||
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
|
||||
fts3_tokenize_vtab.o \
|
||||
fts3_unicode.o fts3_unicode2.o \
|
||||
fts3_write.o func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
fts3_write.o fts5.o func.o global.o hash.o \
|
||||
icu.o insert.o journal.o json1.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
@@ -225,10 +226,11 @@ SRC += \
|
||||
SRC += \
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
|
||||
SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c
|
||||
|
||||
|
||||
# FTS5 things
|
||||
@@ -321,7 +323,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/nextchar.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
@@ -331,8 +332,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
$(TOP)/ext/misc/vfslog.c \
|
||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||
$(TOP)/ext/fts5/fts5_test_mi.c \
|
||||
fts5.c
|
||||
$(TOP)/ext/fts5/fts5_test_mi.c
|
||||
|
||||
|
||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||
@@ -379,7 +379,7 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c
|
||||
$(TOP)/ext/async/sqlite3async.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -451,16 +451,16 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db
|
||||
|
||||
# Extra arguments for including json1 in the build of tools
|
||||
#
|
||||
JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
|
||||
JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
|
||||
JSON1_SRC = $(TOP)/ext/misc/json1.c
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
TESTOPTS = --verbose=file --output=test-out.txt
|
||||
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
#
|
||||
@@ -470,24 +470,23 @@ libsqlite3.a: $(LIBOBJ)
|
||||
$(AR) libsqlite3.a $(LIBOBJ)
|
||||
$(RANLIB) libsqlite3.a
|
||||
|
||||
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(JSON1_DEP)
|
||||
$(TCCX) $(READLINE_FLAGS) $(JSON1_OPT) -o sqlite3$(EXE) \
|
||||
$(TOP)/src/shell.c $(JSON1_SRC) \
|
||||
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
|
||||
sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
|
||||
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
|
||||
$(TOP)/src/shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(JSON1_OPT) $(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c \
|
||||
$(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
||||
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
|
||||
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_MEMSYS5 $(JSON1_OPT) \
|
||||
$(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
|
||||
$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
@@ -515,13 +514,14 @@ sqlite3.o: sqlite3.c
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl
|
||||
target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
|
||||
rm -rf tsrc
|
||||
mkdir tsrc
|
||||
cp -f $(SRC) tsrc
|
||||
rm tsrc/sqlite.h.in tsrc/parse.y
|
||||
tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
|
||||
mv vdbe.new tsrc/vdbe.c
|
||||
cp fts5.c fts5.h tsrc
|
||||
touch target_source
|
||||
|
||||
sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
@@ -532,6 +532,9 @@ sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
|
||||
cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
|
||||
|
||||
sqlite3ext.h: target_source
|
||||
cp tsrc/sqlite3ext.h .
|
||||
|
||||
sqlite3.c-debug: target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
|
||||
echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
|
||||
@@ -576,23 +579,23 @@ tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
|
||||
$(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c
|
||||
opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl
|
||||
tclsh $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
|
||||
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl
|
||||
cat parse.h $(TOP)/src/vdbe.c | \
|
||||
$(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
|
||||
tclsh $(TOP)/tool/mkopcodeh.tcl >opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
parse.h: parse.c
|
||||
|
||||
parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
|
||||
parse.c: $(TOP)/src/parse.y lemon $(TOP)/tool/addopcodes.tcl
|
||||
cp $(TOP)/src/parse.y .
|
||||
rm -f parse.h
|
||||
./lemon -s $(OPTS) parse.y
|
||||
mv parse.h parse.h.temp
|
||||
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
|
||||
tclsh $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
|
||||
|
||||
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
|
||||
tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
|
||||
@@ -665,9 +668,17 @@ fts3_unicode2.o: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
|
||||
|
||||
fts5.o: fts5.c
|
||||
$(TCCX) -DSQLITE_CORE -c fts5.c
|
||||
|
||||
json1.o: $(TOP)/ext/misc/json1.c
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
|
||||
|
||||
fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
|
||||
cp $(TOP)/ext/fts5/fts5parse.y .
|
||||
rm -f fts5parse.h
|
||||
@@ -698,7 +709,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
|
||||
echo "static const char *tclsh_main_loop(void){" >> $@
|
||||
echo "static const char *zMainloop = " >> $@
|
||||
$(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
|
||||
tclsh $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
|
||||
echo "; return zMainloop; }" >> $@
|
||||
|
||||
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
|
||||
@@ -714,9 +725,9 @@ testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB)
|
||||
|
||||
amalgamation-testfixture$(EXE): sqlite3.c fts5.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts5.c \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||
|
||||
fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
C Fix\sa\sfaulty\sassert()\son\sthe\sbenign-malloc\scontroller\scallback\sin\ntest_malloc.c.
|
||||
D 2015-09-25T20:18:52.262
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc f090cdf036f3c07fb13aa2f4494e388c0b1ed1e4
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
C Return\simmediately\sif\ssqlite3PagerWrite()\sis\scalled\swhen\sthe\spager\sis\sin\sPAGER_ERROR\sstate.
|
||||
D 2015-10-30T14:28:16.049
|
||||
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975
|
||||
F VERSION a47917b59f38b632b3a8662d14fd20f94956bdd0
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 27de1af382c82e81f1fe36a7f38528fba004eb1a
|
||||
F autoconf/Makefile.am bd4a90972aa87f079af6624ddea3df3d58f26d2f
|
||||
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
|
||||
F autoconf/config.sub 1efb390a8fb4bfafd74783a15a8fb5311c84300e x
|
||||
F autoconf/configure.ac ba3e99ba1a8171d0682b68443517088fc5d6f13a
|
||||
F autoconf/configure.ac a1fe4eee429fd9d3170be41941514a2b7120ba4e
|
||||
F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
|
||||
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
|
||||
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
|
||||
@@ -38,8 +35,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 2f61915a1bdfbc589244334401cf97d3401e6a39 x
|
||||
F configure.ac 713de38000413e469188db2cb85bed759b56f322
|
||||
F configure 762a66c6eb9331f8af21f5d00b610bd61eaf8e14 x
|
||||
F configure.ac f36bd4fb8c53eed8374c5a5ef319807c08c23fa9
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -78,11 +75,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c b04b0c57761fdba2ae562d9d9ba50c7c4a95d9ea
|
||||
F ext/fts3/fts3.c e028eb13432f108d2e22cded019fc980700e4e00
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 601743955ac43a0e82e6828a931c07bb3b0c95ff
|
||||
F ext/fts3/fts3Int.h c84125c666ee54cef6efce6ff64abb0d0e2f4535
|
||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
|
||||
F ext/fts3/fts3_expr.c dfd571a24412779ac01f25c01d888c6ef7b2d0ef
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
|
||||
@@ -96,7 +93,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c 4f005f78592a1447ca96c8475ef5342ab7dbe02a
|
||||
F ext/fts3/fts3_write.c f442223e4a1914dc1fc12b65af7e4f2c255fa47c
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
|
||||
@@ -105,26 +102,26 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
|
||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 98f802fe41481f9d797fce496f0fefcad72c7782
|
||||
F ext/fts5/fts5Int.h 666aba8432940a8449a3bd4636e898fe906ed95d
|
||||
F ext/fts5/fts5_aux.c 7a307760a9c57c750d043188ec0bad59f5b5ec7e
|
||||
F ext/fts5/fts5_buffer.c 64dcaf36a3ebda9e84b7c3b8788887ec325e12a4
|
||||
F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695
|
||||
F ext/fts5/fts5_expr.c 667faaf14a69a5683ac383acdc8d942cf32c3f93
|
||||
F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246
|
||||
F ext/fts5/fts5_index.c 4fdbc0a321e3a1d73741a623d7aea4db78d6a86d
|
||||
F ext/fts5/fts5_main.c 53116cffeb26898832ff7700cc5ebac5fe085d32
|
||||
F ext/fts5/fts5_storage.c 120f7b143688b5b7710dacbd48cff211609b8059
|
||||
F ext/fts5/fts5_tcl.c 6da58d6e8f42a93c4486b5ba9b187a7f995dee37
|
||||
F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
|
||||
F ext/fts5/fts5Int.h 06594fd3e5a3c74da6df9141e165975dc0ea6ef4
|
||||
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
|
||||
F ext/fts5/fts5_buffer.c 1e49512a535045e621246dc7f4f65f3593fa0fc2
|
||||
F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685
|
||||
F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
|
||||
F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
|
||||
F ext/fts5/fts5_index.c 356481ce027cc2ede8e462c316b578260cda29d2
|
||||
F ext/fts5/fts5_main.c 39358d3d8f0d6ea3757c40e0ddcbb6bc435604c3
|
||||
F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b
|
||||
F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
|
||||
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
||||
F ext/fts5/fts5_tokenize.c f380f46f341af9c9a9908e1aade685ba1eaa157a
|
||||
F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
|
||||
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
||||
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
||||
F ext/fts5/fts5_vocab.c 4622e0b7d84a488a1585aaa56eb214ee67a988bc
|
||||
F ext/fts5/fts5parse.y 833db1101b78c0c47686ab1b84918e38c36e9452
|
||||
F ext/fts5/fts5_vocab.c 3742d0abfe8aa8c3cb4a7df56aa38f2e3c3fb1c2
|
||||
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b6e6a40ef5d069c8e86ca4fbad491e1195485dbc
|
||||
F ext/fts5/test/fts5aa.test 4804f237005bb4ba8ea4a76120d8011ebcb5d611
|
||||
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
|
||||
F ext/fts5/test/fts5aa.test 2c553eea4dab4bc5a75928f56729277c7bc1d206
|
||||
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
|
||||
F ext/fts5/test/fts5ac.test 9737992d08c56bfd4803e933744d2d764e23795c
|
||||
F ext/fts5/test/fts5ad.test e3dfb150fce971b4fd832498c29f56924d451b63
|
||||
@@ -135,7 +132,7 @@ F ext/fts5/test/fts5ah.test e592c4978622dbc4de552cd0f9395df60ac5d54c
|
||||
F ext/fts5/test/fts5ai.test f20e53bbf0c55bc596f1fd47f2740dae028b8f37
|
||||
F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8
|
||||
F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592
|
||||
F ext/fts5/test/fts5al.test 5c79525671862861906fa0a848da462a8473eafb
|
||||
F ext/fts5/test/fts5al.test a1b7b6393376bc2adc216527a28f5ae5594069df
|
||||
F ext/fts5/test/fts5alter.test 6022c61467a82aa11c70822ccad22b328dcf0d04
|
||||
F ext/fts5/test/fts5auto.test caa5bcf917db11944655a2a9bd38c67c520376ca
|
||||
F ext/fts5/test/fts5aux.test 8c687c948cc98e9a94be014df7d518acc1b3b74f
|
||||
@@ -143,10 +140,11 @@ F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
|
||||
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
|
||||
F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
|
||||
F ext/fts5/test/fts5config.test ad2ff42ddc856aed2d05bf89dc1c578c8a39ea3b
|
||||
F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
|
||||
F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1
|
||||
F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62
|
||||
F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c
|
||||
F ext/fts5/test/fts5corrupt3.test a1429635c30f922079189e35b2b631eb7463a2fb
|
||||
F ext/fts5/test/fts5corrupt3.test a2b537c120bdd43c79c42fe2438d7b8c81fe5599
|
||||
F ext/fts5/test/fts5dlidx.test ecba5e62ea8b26c33829961602069c546228046d
|
||||
F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b
|
||||
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
|
||||
@@ -155,25 +153,28 @@ F ext/fts5/test/fts5fault1.test 7a562367cb4a735b57b410dbdb62dcc8d971faec
|
||||
F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341
|
||||
F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
|
||||
F ext/fts5/test/fts5fault4.test 762991d526ee67c2b374351a17248097ea38bee7
|
||||
F ext/fts5/test/fts5fault5.test 54da9fd4c3434a1d4f6abdcb6469299d91cf5875
|
||||
F ext/fts5/test/fts5fault6.test 97bce1a36b7a64e3203fea504ae8e5cfd5ada423
|
||||
F ext/fts5/test/fts5fault7.test f62ed4d98f137eb03f1db94d1fa41b17a771d971
|
||||
F ext/fts5/test/fts5fault5.test f2b8645053d48982e8979749e93994c43011c118
|
||||
F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda
|
||||
F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b
|
||||
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
|
||||
F ext/fts5/test/fts5hash.test 42eb066f667e9a389a63437cb7038c51974d4fc6
|
||||
F ext/fts5/test/fts5integrity.test 29f41d2c7126c6122fbb5d54e556506456876145
|
||||
F ext/fts5/test/fts5hash.test 7cf4607b8657c383f0b520668a99971e95d8b139
|
||||
F ext/fts5/test/fts5integrity.test 87db5d4e7da0ce04a1dcba5ba91658673c997a65
|
||||
F ext/fts5/test/fts5matchinfo.test 2163b0013e824bba65499da9e34ea4da41349cc2
|
||||
F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367
|
||||
F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc
|
||||
F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c
|
||||
F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5
|
||||
F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f
|
||||
F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
|
||||
F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
|
||||
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
|
||||
F ext/fts5/test/fts5prefix.test 552a462f0e8595676611f41643de217fb4ac2808
|
||||
F ext/fts5/test/fts5prefix.test 7ccbdf180ed561a912acef520519e85af8642239
|
||||
F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40
|
||||
F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1
|
||||
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
|
||||
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
|
||||
F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821
|
||||
F ext/fts5/test/fts5simple.test 967b7144644ad4b40b2526160a5adfa896864c55
|
||||
F ext/fts5/test/fts5simple.test 41333e267c6145efc3620342af53dfe65d5676b7
|
||||
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
|
||||
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
|
||||
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
|
||||
@@ -181,10 +182,11 @@ F ext/fts5/test/fts5unicode2.test c1dd890ba32b7609adba78e420faa847abe43b59
|
||||
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
|
||||
F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
|
||||
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
|
||||
F ext/fts5/test/fts5vocab.test cdf97b9678484e9bad5062edf9c9106e5c3b0c5c
|
||||
F ext/fts5/test/fts5vocab.test c88a5554d0409494da95ba647bbdb4879b2624b0
|
||||
F ext/fts5/tool/fts5txt2db.tcl c374c4c4797e8cdfadabdfaeeb5412dcd6686e84
|
||||
F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
|
||||
F ext/fts5/tool/mkfts5c.tcl 5745072c7de346e18c7f491e4c3281fe8a1cfe51
|
||||
F ext/fts5/tool/showfts5.tcl 9eaf6c3df352f98a2ab5ce1921dd94128ab1381d
|
||||
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
@@ -195,7 +197,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
F ext/misc/json1.c 557d6b2d0c3d26625e686a4b4ef8d4a50b8cec94
|
||||
F ext/misc/json1.c 4f45afd9dbcd6feca8c528251efbb7fc09299a09
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
@@ -229,13 +231,13 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
|
||||
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
|
||||
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
F ext/rbu/sqlite3rbu.c 4ba82bd850aa012f73c31dd242d570f18c9cc35a
|
||||
F ext/rbu/sqlite3rbu.h 5357f070cd8c0bcad459b620651ec1656859e4d0
|
||||
F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03
|
||||
F ext/rbu/sqlite3rbu.c ea47de615e911b3a69a8e7fb3be3866298403a25
|
||||
F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde
|
||||
F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9
|
||||
F ext/rtree/rtree1.test 96a80c08440c932cd72aac50660e7af2612d2cda
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
|
||||
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
||||
@@ -261,9 +263,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk d12601118f1d1dadebe1329a53a6d5c512b36d44
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
|
||||
F main.mk 47b879ad92fe896895dcfc1bbec5c119ee2aa690
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -275,50 +275,50 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 4911e1f18fc11b60edbc6410643e938762969a6a
|
||||
F src/alter.c 9d649e46c780166e416fb11dbd23f8d49aab8267
|
||||
F src/analyze.c 4c308880cf53c558070cb8513bdff4ffb1a38a77
|
||||
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c
|
||||
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b
|
||||
F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
|
||||
F src/btree.c 77343aac89c50bb5e06cbca3ace8c057c14de57c
|
||||
F src/btree.h b512723e4f27d7ba16b4b985cdecdb82c0f6d0c0
|
||||
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
|
||||
F src/build.c 8a86f4203ac8a9ac0734f242a96f043edffb6018
|
||||
F src/build.c d6162335d690396dfc5c4bd59e8b2b0c14ba6285
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
||||
F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
|
||||
F src/delete.c 371df4fc86e96efeaed3d37565aef77f956be109
|
||||
F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
|
||||
F src/fault.c a64e879e4713671b3b2bf1db70efa351d6ac9591
|
||||
F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
|
||||
F src/delete.c c4c6fb9da78b946fcba2a6aac5b24bc5c15e752a
|
||||
F src/expr.c ea3e0c2981ffc7bd358714fa6d5132cb2cd5fc3a
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f
|
||||
F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 5b5ce67bc4fe533f49de10b3671fcb92d4d5c4e9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 9748a37e058256eb2ead69f028ab85ebf203ad15
|
||||
F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
|
||||
F src/loadext.c f0b66d28e377fd6c6d36cc9d92df1ff251ebee44
|
||||
F src/main.c 710b2e0433a340a10c40f4dbf29838e359a44427
|
||||
F src/malloc.c 76c62c8ee6b346aa10a373229a372ef2f2344fe9
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c f393acc6e5d604cbe0054376d62f668a5560b3f1
|
||||
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c c1ab1153bd6443bdf6f71e4213c6fb31221b9eb7
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 8cfa6e83c618d2fcae0fe63f4d2b5bb16b11a97a
|
||||
F src/mutex_w32.c 2e025e6642eaf27597403690980f560d1a91f62c
|
||||
F src/mutex_unix.c a94b46f3f7beba307dde1b298b0f99f9c3677a93
|
||||
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
@@ -327,32 +327,32 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c fc93d55f96bb978f0b0168c6ea7d6fc60b0e172c
|
||||
F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 2fbeeba28f4e6d08a15bc106f36c43346a81f09e
|
||||
F src/pager.h ac213f8143ebfee6a8bfb91cf4ca02c9a83343c5
|
||||
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
|
||||
F src/pager.c 9c1eec0d88133484b165fa0b5284a411c24b964c
|
||||
F src/pager.h 1c4fa826c330040c5659a384446c7cc6e8e4200c
|
||||
F src/parse.y 11078cd8e3af00f030505b6a86a06a4536cfdeaa
|
||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
F src/pcache1.c 7f8630a2074997195b86f478840a603818b08d84
|
||||
F src/pragma.c d71b813e67bf03f3116b9dd5164fbfd81ec673a2
|
||||
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
|
||||
F src/pragma.c 8fd4c8a12e25f0d916426f160255ebe25415eba7
|
||||
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a
|
||||
F src/shell.c 15186317f2fcb670400f8d16d298ed18731375a0
|
||||
F src/sqlite.h.in a6f2cb7741fae0133b007843b65c96f7fcd4d7fd
|
||||
F src/select.c 167b4e9058bc8e997d18d6b6b20ecbb0c9c457af
|
||||
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in 3cfc86c55e57c63d86b9e1e92869e2bfb162ca8e
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
|
||||
F src/sqliteInt.h ca695ea39aa6d459a1b1d36391c5121c432f350f
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h b1e72ffe282c91ae30a2bf403319126dbaebd556
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
|
||||
F src/test1.c c96508c835979bf15dc0e3146e2c7a51a2333d3c
|
||||
F src/test1.c 9ac5cbfe3c859ab7518edc5109a2959d6bf7b059
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
F src/test3.c f7ae1d6a4aa07aac257de18a43800c1199b513fc
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
@@ -364,7 +364,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
|
||||
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c fb2e5d354d9a077f5fbb261652eff4787deb104f
|
||||
F src/test_config.c 426527fbb12fc23669a1e973ecdc8c5e92c2e2cf
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -375,7 +375,7 @@ F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 70ce9d5f727174a9bda41bee3252184e7c07ecb9
|
||||
F src/test_malloc.c 27d9e11b6e9d30267465d41ad81edbe24256408b
|
||||
F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c
|
||||
@@ -395,32 +395,32 @@ F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6
|
||||
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22
|
||||
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c eb7ab3ff2928628692a4f14be397c95f4a681d97
|
||||
F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 5048103aa6bc9c01bf1a4620729256d1e873bb6c
|
||||
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
||||
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
||||
F src/vdbe.c dfbaae2570172c523bce14299021d352b8508f7f
|
||||
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
|
||||
F src/vdbeInt.h 33403622c6a8feaaac5f0f3f17f5d1bf6df42286
|
||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||
F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
|
||||
F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a
|
||||
F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
|
||||
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
||||
F src/vdbeaux.c 717bc2ae9cc0b58ef398fff44bd9164bfd96772a
|
||||
F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6
|
||||
F src/vdbemem.c fdd1578e47bea61390d472de53c565781d81e045
|
||||
F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
F src/vtab.c 2ecfe020c10e0a0c7b078203fdba2fae844744bc
|
||||
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
|
||||
F src/where.c a7582b752d436d335bfb62f445e1c2771e7daa95
|
||||
F src/where.c 6aceb72cc58dc06922a9e1604d559c8ca4c3e728
|
||||
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
|
||||
F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f
|
||||
F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
|
||||
F src/wherecode.c 9aa2043685ec3eb73e87fa6f50aa4ec092f197dd
|
||||
F src/whereexpr.c e63244ca06c503e5f3c5b7f3c9aea0db826089ed
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -467,7 +467,7 @@ F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
|
||||
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex5.test 6f487290ce2a667c24517191651bfb8c7d86b6dc
|
||||
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
|
||||
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
@@ -503,6 +503,7 @@ F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
|
||||
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test a755c93482ce2e20c04825304bef27e7b7ea0111
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
@@ -510,6 +511,7 @@ F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cffault.test 1647eef45512817265c360ed4539538eed26ac69
|
||||
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
@@ -565,6 +567,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/cursorhint.test 432811b62bd5ffb812729f49bba3b9ad687550bb
|
||||
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
|
||||
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
@@ -572,7 +575,7 @@ F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
F test/delete4.test d9e7d553a939597b27d205b022d769469f361c1f
|
||||
F test/delete4.test 3ac0b8d23689ba764c2e8b78c1b56b8f1b942fa2
|
||||
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
@@ -621,7 +624,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
||||
F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c
|
||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
@@ -630,6 +633,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
|
||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/fordelete.test ba12ec1d27cc34a4c23db4446029126d773f3849
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
|
||||
@@ -690,7 +694,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
||||
F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
|
||||
F test/fts3conf.test ff90127b2462c788348c0dd7f6f8c573ef9cb5d9
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
@@ -702,7 +706,7 @@ F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
|
||||
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
|
||||
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
||||
F test/fts3fault.test da49627b280b210ebc6657f76344c7851f10ce66
|
||||
@@ -736,6 +740,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
|
||||
F test/fts4onepass.test bfca61f69c6ca74cd71e6dca12a0cdd47192fc24
|
||||
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
@@ -749,10 +754,10 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c b8eb7ee40f6d28548a0b028e0676293522f3427f
|
||||
F test/fuzzcheck.c c84086021a514360268190a1bc6ae8ed78d7c94f
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21
|
||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
@@ -785,7 +790,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
|
||||
F test/indexexpr1.test 4bce4e4b6b1a2d0c34e17d4e04f3957a3bcdc500
|
||||
F test/indexexpr1.test bbb52b5d5717d9f23853826963b0af5110009366
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -816,8 +821,8 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
|
||||
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
|
||||
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test e8b50fbcdbf283cfafbc42632bf2c7dfa4541c46
|
||||
F test/json102.test 796b1c59894c6e0f38fc1a3acb0e690573b952a3
|
||||
F test/json101.test f0178422b3a2418f423fd0d3caf3571c8d1b9863
|
||||
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
@@ -897,6 +902,7 @@ F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
@@ -942,7 +948,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl afdac5c3429dceb034295617c0a51df9954d467a
|
||||
F test/releasetest.tcl 67a82199e6ddee609211488bc04ed3f9ea3aa28a
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
@@ -1028,7 +1034,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 857439869d1cb4db35e1c720ee9c2756eb9ea2a0
|
||||
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/spellfix2.test 1ff48bb65b6198d21674ae24d19bb136e547585a
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test 89b3d5aad05b99f707ee3786bdd4416dccf83304
|
||||
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
||||
@@ -1043,7 +1049,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/tabfunc01.test 83e63be7b6e3f67b6a03519c9c61bc68efb25f31
|
||||
F test/tabfunc01.test 03c4ad422c6ab596cff6dcaf86dd061a9f039525
|
||||
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1239,7 +1245,7 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
|
||||
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
|
||||
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
|
||||
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
|
||||
F test/uri.test 6630ecbdea2aac10df3c89dbae2243f4c2c353e4
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
@@ -1248,7 +1254,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test bfdec45ad4b2ed5dd5fddbc3dcafcfca2ab23574
|
||||
F test/view.test f6c3a39e0c819891265e1d0754e99960d81ef6c9
|
||||
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
|
||||
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
@@ -1332,14 +1338,16 @@ F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/build-all-msvc.bat 761d8c82a1a529261291812732a853a1b4256d85 x
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3
|
||||
F tool/addopcodes.tcl 7cc82ecca456a6b3148abf492b0419b83140881a
|
||||
F tool/build-all-msvc.bat 2b1703b322da121e56b955cb58de091107f777c3 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
|
||||
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
|
||||
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/fuzzershell.c 87cc3d6f00239d786d231954289f106131989cc7
|
||||
F tool/fuzzershell.c b36096cdbcb4af985a2d6c20093d61e55b49bfe1
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
@@ -1349,27 +1357,28 @@ F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
|
||||
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
|
||||
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
|
||||
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 84af2b180484323a2ea22a2279e8bd9e3e1e492e
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
|
||||
F tool/mksqlite3c.tcl 421ecbd437d8cd7123e67430ee8146218396680d
|
||||
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
|
||||
F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84
|
||||
F tool/mksqlite3h.tcl 1d41ab59bffb025121f75b76e183125ce41b3ec8
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl bbe57cd9ae11c6cc70319241101ef8d2b8c3765b
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c b1e16174385d5bd0815823a7fda1ecc82ed6088b
|
||||
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
|
||||
F tool/spaceanal.tcl 93c1fdc9733c525b17a2024c7df193daa002e037
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
@@ -1381,14 +1390,14 @@ F tool/sqldiff.c b318efc2eaf7a7fac4d281a0ce736193cb2506df
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
|
||||
F tool/tostr.tcl 96022f35ada2194f6f8ccf6fd95809e90ed277c4
|
||||
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 2c57b2f38691356405b95245fc22fd5e6bfcb2f1
|
||||
R a6b0049bf1276cc2999d34791c56ef1b
|
||||
U drh
|
||||
Z 175f9b81eac8fdc51f6d8759cf3e7814
|
||||
P 0e09e4a26938cfe0f573449526a8f0f527cef921
|
||||
R f396f7a1d6ed17b52257ec59a2b63902
|
||||
U dan
|
||||
Z 76885908163af131d9fcc88a11feb178
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
64f2cb8dd2a688db7beb6379d90026b230563ab2
|
||||
a6695b008487aeb7badf572fa32bfcba3c9fab03
|
||||
@@ -1,50 +0,0 @@
|
||||
#!/usr/bin/awk -f
|
||||
#
|
||||
# This AWK script scans the opcodes.h file (which is itself generated by
|
||||
# another awk script) and uses the information gleaned to create the
|
||||
# opcodes.c source file.
|
||||
#
|
||||
# Opcodes.c contains strings which are the symbolic names for the various
|
||||
# opcodes used by the VDBE. These strings are used when disassembling a
|
||||
# VDBE program during tracing or as a result of the EXPLAIN keyword.
|
||||
#
|
||||
BEGIN {
|
||||
print "/* Automatically generated. Do not edit */"
|
||||
print "/* See the mkopcodec.awk script for details. */"
|
||||
printf "#if !defined(SQLITE_OMIT_EXPLAIN)"
|
||||
printf " || defined(VDBE_PROFILE)"
|
||||
print " || defined(SQLITE_DEBUG)"
|
||||
print "#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)"
|
||||
print "# define OpHelp(X) \"\\0\" X"
|
||||
print "#else"
|
||||
print "# define OpHelp(X)"
|
||||
print "#endif"
|
||||
print "const char *sqlite3OpcodeName(int i){"
|
||||
print " static const char *const azName[] = { \"?\","
|
||||
mx = 0
|
||||
}
|
||||
/^.define OP_/ {
|
||||
sub("OP_","",$2)
|
||||
i = $3+0
|
||||
label[i] = $2
|
||||
if( mx<i ) mx = i
|
||||
for(j=5; j<NF; j++) if( $j=="synopsis:" ) break
|
||||
if( j<NF ){
|
||||
j++
|
||||
x = $j
|
||||
for(j=j+1; j<NF; j++) x = x " " $j
|
||||
synopsis[i] = x
|
||||
}else{
|
||||
synopsis[i] = ""
|
||||
}
|
||||
}
|
||||
END {
|
||||
for(i=1; i<=mx; i++){
|
||||
printf " /* %3d */ %-18s OpHelp(\"%s\"),\n", i, \
|
||||
"\"" label[i] "\"", synopsis[i]
|
||||
}
|
||||
print " };"
|
||||
print " return azName[i];"
|
||||
print "}"
|
||||
print "#endif"
|
||||
}
|
||||
-228
@@ -1,228 +0,0 @@
|
||||
#!/usr/bin/awk -f
|
||||
#
|
||||
# Generate the file opcodes.h.
|
||||
#
|
||||
# This AWK script scans a concatenation of the parse.h output file from the
|
||||
# parser and the vdbe.c source file in order to generate the opcodes numbers
|
||||
# for all opcodes.
|
||||
#
|
||||
# The lines of the vdbe.c that we are interested in are of the form:
|
||||
#
|
||||
# case OP_aaaa: /* same as TK_bbbbb */
|
||||
#
|
||||
# The TK_ comment is optional. If it is present, then the value assigned to
|
||||
# the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned
|
||||
# a small integer that is different from every other OP_ value.
|
||||
#
|
||||
# We go to the trouble of making some OP_ values the same as TK_ values
|
||||
# as an optimization. During parsing, things like expression operators
|
||||
# are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth. Later
|
||||
# during code generation, we need to generate corresponding opcodes like
|
||||
# OP_Add and OP_Divide. By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide,
|
||||
# code to translate from one to the other is avoided. This makes the
|
||||
# code generator run (infinitesimally) faster and more importantly it makes
|
||||
# the library footprint smaller.
|
||||
#
|
||||
# This script also scans for lines of the form:
|
||||
#
|
||||
# case OP_aaaa: /* jump, in1, in2, in3, out2-prerelease, out3 */
|
||||
#
|
||||
# When such comments are found on an opcode, it means that certain
|
||||
# properties apply to that opcode. Set corresponding flags using the
|
||||
# OPFLG_INITIALIZER macro.
|
||||
#
|
||||
|
||||
|
||||
# Remember the TK_ values from the parse.h file
|
||||
/^#define TK_/ {
|
||||
tk[$2] = 0+$3 # tk[x] holds the numeric value for TK symbol X
|
||||
}
|
||||
|
||||
# Find "/* Opcode: " lines in the vdbe.c file. Each one introduces
|
||||
# a new opcode. Remember which parameters are used.
|
||||
/^.. Opcode: / {
|
||||
currentOp = "OP_" $3
|
||||
m = 0
|
||||
for(i=4; i<=NF; i++){
|
||||
x = $i
|
||||
if( x=="P1" ) m += 1
|
||||
if( x=="P2" ) m += 2
|
||||
if( x=="P3" ) m += 4
|
||||
if( x=="P4" ) m += 8
|
||||
if( x=="P5" ) m += 16
|
||||
}
|
||||
paramused[currentOp] = m
|
||||
}
|
||||
|
||||
# Find "** Synopsis: " lines that follow Opcode:
|
||||
/^.. Synopsis: / {
|
||||
if( currentOp ){
|
||||
x = $3
|
||||
for(i=4; i<=NF; i++){
|
||||
x = x " " $i
|
||||
}
|
||||
synopsis[currentOp] = x
|
||||
}
|
||||
}
|
||||
|
||||
# Scan for "case OP_aaaa:" lines in the vdbe.c file
|
||||
/^case OP_/ {
|
||||
name = $2
|
||||
sub(/:/,"",name)
|
||||
sub("\r","",name)
|
||||
op[name] = -1 # op[x] holds the numeric value for OP symbol x
|
||||
jump[name] = 0
|
||||
in1[name] = 0
|
||||
in2[name] = 0
|
||||
in3[name] = 0
|
||||
out2[name] = 0
|
||||
out3[name] = 0
|
||||
for(i=3; i<NF; i++){
|
||||
if($i=="same" && $(i+1)=="as"){
|
||||
sym = $(i+2)
|
||||
sub(/,/,"",sym)
|
||||
val = tk[sym]
|
||||
op[name] = val
|
||||
used[val] = 1
|
||||
sameas[val] = sym
|
||||
def[val] = name
|
||||
}
|
||||
x = $i
|
||||
sub(",","",x)
|
||||
if(x=="jump"){
|
||||
jump[name] = 1
|
||||
}else if(x=="in1"){
|
||||
in1[name] = 1
|
||||
}else if(x=="in2"){
|
||||
in2[name] = 1
|
||||
}else if(x=="in3"){
|
||||
in3[name] = 1
|
||||
}else if(x=="out2"){
|
||||
out2[name] = 1
|
||||
}else if(x=="out3"){
|
||||
out3[name] = 1
|
||||
}
|
||||
}
|
||||
order[n_op++] = name;
|
||||
}
|
||||
|
||||
# Assign numbers to all opcodes and output the result.
|
||||
END {
|
||||
cnt = 0
|
||||
max = 0
|
||||
print "/* Automatically generated. Do not edit */"
|
||||
print "/* See the mkopcodeh.awk script for details */"
|
||||
op["OP_Noop"] = -1;
|
||||
order[n_op++] = "OP_Noop";
|
||||
op["OP_Explain"] = -1;
|
||||
order[n_op++] = "OP_Explain";
|
||||
|
||||
# Assign small values to opcodes that are processed by resolveP2Values()
|
||||
# to make code generation for the switch() statement smaller and faster.
|
||||
for(i=0; i<n_op; i++){
|
||||
name = order[i];
|
||||
if( op[name]>=0 ) continue;
|
||||
if( name=="OP_Transaction" \
|
||||
|| name=="OP_AutoCommit" \
|
||||
|| name=="OP_Savepoint" \
|
||||
|| name=="OP_Checkpoint" \
|
||||
|| name=="OP_Vacuum" \
|
||||
|| name=="OP_JournalMode" \
|
||||
|| name=="OP_VUpdate" \
|
||||
|| name=="OP_VFilter" \
|
||||
|| name=="OP_Next" \
|
||||
|| name=="OP_NextIfOpen" \
|
||||
|| name=="OP_SorterNext" \
|
||||
|| name=="OP_Prev" \
|
||||
|| name=="OP_PrevIfOpen" \
|
||||
){
|
||||
cnt++
|
||||
while( used[cnt] ) cnt++
|
||||
op[name] = cnt
|
||||
used[cnt] = 1
|
||||
def[cnt] = name
|
||||
}
|
||||
}
|
||||
|
||||
# Generate the numeric values for opcodes
|
||||
for(i=0; i<n_op; i++){
|
||||
name = order[i];
|
||||
if( op[name]<0 ){
|
||||
cnt++
|
||||
while( used[cnt] ) cnt++
|
||||
op[name] = cnt
|
||||
used[cnt] = 1
|
||||
def[cnt] = name
|
||||
}
|
||||
}
|
||||
max = cnt
|
||||
for(i=1; i<=max; i++){
|
||||
if( !used[i] ){
|
||||
def[i] = "OP_NotUsed_" i
|
||||
}
|
||||
printf "#define %-16s %3d", def[i], i
|
||||
com = ""
|
||||
if( sameas[i] ){
|
||||
com = "same as " sameas[i]
|
||||
}
|
||||
x = synopsis[def[i]]
|
||||
if( x ){
|
||||
if( com=="" ){
|
||||
com = "synopsis: " x
|
||||
} else {
|
||||
com = com ", synopsis: " x
|
||||
}
|
||||
}
|
||||
if( com!="" ){
|
||||
printf " /* %-42s */", com
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
# Generate the bitvectors:
|
||||
#
|
||||
# bit 0: jump
|
||||
# bit 1: pushes a result onto stack
|
||||
# bit 2: output to p1. release p1 before opcode runs
|
||||
#
|
||||
for(i=0; i<=max; i++){
|
||||
name = def[i]
|
||||
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
|
||||
if( jump[name] ) a0 = 1;
|
||||
if( in1[name] ) a2 = 2;
|
||||
if( in2[name] ) a3 = 4;
|
||||
if( in3[name] ) a4 = 8;
|
||||
if( out2[name] ) a5 = 16;
|
||||
if( out3[name] ) a6 = 32;
|
||||
bv[i] = a0+a1+a2+a3+a4+a5+a6;
|
||||
}
|
||||
print "\n"
|
||||
print "/* Properties such as \"out2\" or \"jump\" that are specified in"
|
||||
print "** comments following the \"case\" for each opcode in the vdbe.c"
|
||||
print "** are encoded into bitvectors as follows:"
|
||||
print "*/"
|
||||
print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */"
|
||||
print "#define OPFLG_IN1 0x0002 /* in1: P1 is an input */"
|
||||
print "#define OPFLG_IN2 0x0004 /* in2: P2 is an input */"
|
||||
print "#define OPFLG_IN3 0x0008 /* in3: P3 is an input */"
|
||||
print "#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */"
|
||||
print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_INITIALIZER {\\"
|
||||
for(i=0; i<=max; i++){
|
||||
if( i%8==0 ) printf("/* %3d */",i)
|
||||
printf " 0x%02x,", bv[i]
|
||||
if( i%8==7 ) printf("\\\n");
|
||||
}
|
||||
print "}"
|
||||
if( 0 ){
|
||||
print "\n/* Bitmask to indicate which fields (P1..P5) of each opcode are"
|
||||
print "** actually used.\n*/"
|
||||
print "#define OP_PARAM_USED_INITIALIZER {\\"
|
||||
for(i=0; i<=max; i++){
|
||||
if( i%8==0 ) printf("/* %3d */",i)
|
||||
printf " 0x%02x,", paramused[def[i]]
|
||||
if( i%8==7 ) printf("\\\n");
|
||||
}
|
||||
print "}"
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -602,14 +602,14 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
|
||||
if( ALWAYS(v) ){
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
int r2 = sqlite3GetTempReg(pParse);
|
||||
int j1;
|
||||
int addr1;
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
|
||||
addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r2);
|
||||
}
|
||||
|
||||
+38
-16
@@ -661,7 +661,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
||||
pCur->eState = CURSOR_REQUIRESEEK;
|
||||
}
|
||||
|
||||
invalidateOverflowCache(pCur);
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -858,6 +858,26 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
/*
|
||||
** Provide hints to the cursor. The particular hint given (and the type
|
||||
** and number of the varargs parameters) is determined by the eHintType
|
||||
** parameter. See the definitions of the BTREE_HINT_* macros for details.
|
||||
*/
|
||||
void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
|
||||
/* Used only by system that substitute their own storage engine */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Provide flag hints to the cursor.
|
||||
*/
|
||||
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
|
||||
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
|
||||
pCur->hints = x;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
/*
|
||||
** Given a page number of a regular database page, return the page
|
||||
@@ -4055,13 +4075,16 @@ static int btreeCursor(
|
||||
BtCursor *pX; /* Looping over other all cursors */
|
||||
|
||||
assert( sqlite3BtreeHoldsMutex(p) );
|
||||
assert( wrFlag==0 || wrFlag==1 );
|
||||
assert( wrFlag==0
|
||||
|| wrFlag==BTREE_WRCSR
|
||||
|| wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
|
||||
);
|
||||
|
||||
/* The following assert statements verify that if this is a sharable
|
||||
** b-tree database, the connection is holding the required table locks,
|
||||
** and that no other connection has any open cursor that conflicts with
|
||||
** this lock. */
|
||||
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
|
||||
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
|
||||
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
|
||||
|
||||
/* Assert that the caller has opened the required transaction. */
|
||||
@@ -4086,8 +4109,7 @@ static int btreeCursor(
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
pCur->pBtree = p;
|
||||
pCur->pBt = pBt;
|
||||
assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
|
||||
pCur->curFlags = wrFlag;
|
||||
pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
|
||||
pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
|
||||
/* If there are two or more cursors on the same btree, then all such
|
||||
** cursors *must* have the BTCF_Multiple flag set. */
|
||||
@@ -4499,7 +4521,9 @@ static int accessPayload(
|
||||
|
||||
/* If required, populate the overflow page-list cache. */
|
||||
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
|
||||
assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
|
||||
assert( pCur->aOverflow[iIdx]==0
|
||||
|| pCur->aOverflow[iIdx]==nextPage
|
||||
|| CORRUPT_DB );
|
||||
pCur->aOverflow[iIdx] = nextPage;
|
||||
}
|
||||
|
||||
@@ -6499,7 +6523,13 @@ static int pageInsertArray(
|
||||
if( pData<pBegin ) return 1;
|
||||
pSlot = pData;
|
||||
}
|
||||
memcpy(pSlot, pCArray->apCell[i], sz);
|
||||
/* pSlot and pCArray->apCell[i] will never overlap on a well-formed
|
||||
** database. But they might for a corrupt database. Hence use memmove()
|
||||
** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */
|
||||
assert( (pSlot+sz)<=pCArray->apCell[i]
|
||||
|| pSlot>=(pCArray->apCell[i]+sz)
|
||||
|| CORRUPT_DB );
|
||||
memmove(pSlot, pCArray->apCell[i], sz);
|
||||
put2byte(pCellptr, (pSlot - aData));
|
||||
pCellptr += 2;
|
||||
}
|
||||
@@ -7624,7 +7654,7 @@ static int balance_nonroot(
|
||||
** by smaller than the child due to the database header, and so all the
|
||||
** free space needs to be up front.
|
||||
*/
|
||||
assert( nNew==1 );
|
||||
assert( nNew==1 || CORRUPT_DB );
|
||||
rc = defragmentPage(apNew[0]);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
assert( apNew[0]->nFree ==
|
||||
@@ -9616,14 +9646,6 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** set the mask of hint flags for cursor pCsr.
|
||||
*/
|
||||
void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
|
||||
assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 );
|
||||
pCsr->hints = mask;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return true if the cursor has a hint specified. This routine is
|
||||
|
||||
+51
-3
@@ -150,8 +150,37 @@ int sqlite3BtreeNewDb(Btree *p);
|
||||
#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
|
||||
|
||||
/*
|
||||
** Values that may be OR'd together to form the second argument of an
|
||||
** sqlite3BtreeCursorHints() call.
|
||||
** Kinds of hints that can be passed into the sqlite3BtreeCursorHint()
|
||||
** interface.
|
||||
**
|
||||
** BTREE_HINT_RANGE (arguments: Expr*, Mem*)
|
||||
**
|
||||
** The first argument is an Expr* (which is guaranteed to be constant for
|
||||
** the lifetime of the cursor) that defines constraints on which rows
|
||||
** might be fetched with this cursor. The Expr* tree may contain
|
||||
** TK_REGISTER nodes that refer to values stored in the array of registers
|
||||
** passed as the second parameter. In other words, if Expr.op==TK_REGISTER
|
||||
** then the value of the node is the value in Mem[pExpr.iTable]. Any
|
||||
** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th
|
||||
** column of the b-tree of the cursor. The Expr tree will not contain
|
||||
** any function calls nor subqueries nor references to b-trees other than
|
||||
** the cursor being hinted.
|
||||
**
|
||||
** The design of the _RANGE hint is aid b-tree implementations that try
|
||||
** to prefetch content from remote machines - to provide those
|
||||
** implementations with limits on what needs to be prefetched and thereby
|
||||
** reduce network bandwidth.
|
||||
**
|
||||
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
|
||||
** standard SQLite. The other hints are provided for extentions that use
|
||||
** the SQLite parser and code generator but substitute their own storage
|
||||
** engine.
|
||||
*/
|
||||
#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
|
||||
|
||||
/*
|
||||
** Values that may be OR'd together to form the argument to the
|
||||
** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint():
|
||||
**
|
||||
** The BTREE_BULKLOAD flag is set on index cursors when the index is going
|
||||
** to be filled with content that is already in sorted order.
|
||||
@@ -165,6 +194,22 @@ int sqlite3BtreeNewDb(Btree *p);
|
||||
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
|
||||
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
|
||||
|
||||
/*
|
||||
** Flags passed as the third argument to sqlite3BtreeCursor().
|
||||
**
|
||||
** For read-only cursors the wrFlag argument is always zero. For read-write
|
||||
** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or
|
||||
** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will
|
||||
** only be used by SQLite for the following:
|
||||
**
|
||||
** * to seek to and delete specific entries, and/or
|
||||
**
|
||||
** * to read values that will be used to create keys that other
|
||||
** BTREE_FORDELETE cursors will seek to and delete.
|
||||
*/
|
||||
#define BTREE_WRCSR 0x00000004 /* read-write cursor */
|
||||
#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
|
||||
|
||||
int sqlite3BtreeCursor(
|
||||
Btree*, /* BTree containing table to open */
|
||||
int iTable, /* Index of root page */
|
||||
@@ -174,6 +219,10 @@ int sqlite3BtreeCursor(
|
||||
);
|
||||
int sqlite3BtreeCursorSize(void);
|
||||
void sqlite3BtreeCursorZero(BtCursor*);
|
||||
void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
void sqlite3BtreeCursorHint(BtCursor*, int, ...);
|
||||
#endif
|
||||
|
||||
int sqlite3BtreeCloseCursor(BtCursor*);
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
@@ -208,7 +257,6 @@ int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
void sqlite3BtreeIncrblobCursor(BtCursor *);
|
||||
void sqlite3BtreeClearCursor(BtCursor *);
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
|
||||
#endif
|
||||
|
||||
+10
-9
@@ -192,6 +192,8 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
db->aDb[iDb].pSchema->iGeneration /* P4 */
|
||||
);
|
||||
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
|
||||
VdbeComment((v,
|
||||
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
for(i=0; i<pParse->nVtabLock; i++){
|
||||
@@ -983,7 +985,7 @@ void sqlite3StartTable(
|
||||
** now.
|
||||
*/
|
||||
if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
int j1;
|
||||
int addr1;
|
||||
int fileFormat;
|
||||
int reg1, reg2, reg3;
|
||||
/* nullRow[] is an OP_Record encoding of a row containing 5 NULLs */
|
||||
@@ -1004,14 +1006,14 @@ void sqlite3StartTable(
|
||||
reg3 = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
|
||||
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
|
||||
1 : SQLITE_MAX_FILE_FORMAT;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
|
||||
/* This just creates a place-holder record in the sqlite_master table.
|
||||
** The record created does not contain anything yet. It will be replaced
|
||||
@@ -2082,8 +2084,7 @@ void sqlite3CreateView(
|
||||
|
||||
if( pParse->nVar>0 ){
|
||||
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
|
||||
sqlite3SelectDelete(db, pSelect);
|
||||
return;
|
||||
goto create_view_fail;
|
||||
}
|
||||
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
|
||||
p = pParse->pNewTable;
|
||||
@@ -3135,7 +3136,7 @@ Index *sqlite3CreateIndex(
|
||||
/* Analyze the list of expressions that form the terms of the index and
|
||||
** report any errors. In the common case where the expression is exactly
|
||||
** a table column, store that column in aiColumn[]. For general expressions,
|
||||
** populate pIndex->aColExpr and store -2 in aiColumn[].
|
||||
** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[].
|
||||
**
|
||||
** TODO: Issue a warning if two or more columns of the index are identical.
|
||||
** TODO: Issue a warning if the table primary key is used as part of the
|
||||
@@ -3164,8 +3165,8 @@ Index *sqlite3CreateIndex(
|
||||
pListItem = &pCopy->a[i];
|
||||
}
|
||||
}
|
||||
j = -2;
|
||||
pIndex->aiColumn[i] = -2;
|
||||
j = XN_EXPR;
|
||||
pIndex->aiColumn[i] = XN_EXPR;
|
||||
pIndex->uniqNotNull = 0;
|
||||
}else{
|
||||
j = pCExpr->iColumn;
|
||||
@@ -3218,7 +3219,7 @@ Index *sqlite3CreateIndex(
|
||||
}
|
||||
assert( i==pIndex->nColumn );
|
||||
}else{
|
||||
pIndex->aiColumn[i] = -1;
|
||||
pIndex->aiColumn[i] = XN_ROWID;
|
||||
pIndex->azColl[i] = "BINARY";
|
||||
}
|
||||
sqlite3DefaultRowEst(pIndex);
|
||||
|
||||
@@ -96,12 +96,18 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_FTS4
|
||||
"ENABLE_FTS4",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS5
|
||||
"ENABLE_FTS5",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ICU
|
||||
"ENABLE_ICU",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_IOTRACE
|
||||
"ENABLE_IOTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_JSON1
|
||||
"ENABLE_JSON1",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
|
||||
+11
-6
@@ -411,7 +411,7 @@ void sqlite3DeleteFrom(
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF );
|
||||
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
|
||||
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
|
||||
|
||||
/* Keep track of the number of rows to be deleted */
|
||||
@@ -422,7 +422,7 @@ void sqlite3DeleteFrom(
|
||||
/* Extract the rowid or primary key for the current row */
|
||||
if( pPk ){
|
||||
for(i=0; i<nPk; i++){
|
||||
assert( pPk->aiColumn[i]>=(-1) );
|
||||
assert( pPk->aiColumn[i]>=0 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
||||
pPk->aiColumn[i], iPk+i);
|
||||
}
|
||||
@@ -478,12 +478,13 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
if( !isView ){
|
||||
int iAddrOnce = 0;
|
||||
u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||
&iDataCur, &iIdxCur);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur,
|
||||
aToOpen, &iDataCur, &iIdxCur);
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
||||
@@ -494,7 +495,7 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
if( eOnePass!=ONEPASS_OFF ){
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
if( aToOpen[iDataCur-iTabCur] ){
|
||||
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
|
||||
assert( pPk!=0 || pTab->pSelect!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
@@ -516,7 +517,11 @@ void sqlite3DeleteFrom(
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
sqlite3MayAbort(pParse);
|
||||
if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
@@ -854,7 +859,7 @@ int sqlite3GenerateIndexKey(
|
||||
for(j=0; j<nCol; j++){
|
||||
if( pPrior
|
||||
&& pPrior->aiColumn[j]==pIdx->aiColumn[j]
|
||||
&& pPrior->aiColumn[j]>=(-1)
|
||||
&& pPrior->aiColumn[j]!=XN_EXPR
|
||||
){
|
||||
/* This column was already computed by the previous index */
|
||||
continue;
|
||||
|
||||
+50
-16
@@ -1415,6 +1415,22 @@ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
return exprIsConst(p, 4+isInit, 0);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
/*
|
||||
** Walk an expression tree. Return 1 if the expression contains a
|
||||
** subquery of some kind. Return 0 if there are no subqueries.
|
||||
*/
|
||||
int sqlite3ExprContainsSubquery(Expr *p){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = 1;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode==0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If the expression p codes a constant integer that is small enough
|
||||
** to fit in a 32-bit integer, return 1 and put the value of the integer
|
||||
@@ -1595,13 +1611,13 @@ int sqlite3CodeOnce(Parse *pParse){
|
||||
** to be set to NULL if iCur contains one or more NULL values.
|
||||
*/
|
||||
static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
|
||||
int j1;
|
||||
int addr1;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
VdbeComment((v, "first_entry_in(%d)", iCur));
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2201,7 +2217,7 @@ static void sqlite3ExprCodeIN(
|
||||
** the presence of a NULL on the RHS makes a difference in the
|
||||
** outcome.
|
||||
*/
|
||||
int j1;
|
||||
int addr1;
|
||||
|
||||
/* First check to see if the LHS is contained in the RHS. If so,
|
||||
** then the answer is TRUE the presence of NULLs in the RHS does
|
||||
@@ -2209,12 +2225,12 @@ static void sqlite3ExprCodeIN(
|
||||
** answer is NULL if the RHS contains NULLs and the answer is
|
||||
** FALSE if the RHS is NULL-free.
|
||||
*/
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
|
||||
addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, destIfFalse);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2443,15 +2459,15 @@ void sqlite3ExprCodeLoadIndexColumn(
|
||||
int regOut /* Store the index column value in this register */
|
||||
){
|
||||
i16 iTabCol = pIdx->aiColumn[iIdxCol];
|
||||
if( iTabCol>=(-1) ){
|
||||
if( iTabCol==XN_EXPR ){
|
||||
assert( pIdx->aColExpr );
|
||||
assert( pIdx->aColExpr->nExpr>iIdxCol );
|
||||
pParse->iSelfTab = iTabCur;
|
||||
sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
|
||||
}else{
|
||||
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
|
||||
iTabCol, regOut);
|
||||
return;
|
||||
}
|
||||
assert( pIdx->aColExpr );
|
||||
assert( pIdx->aColExpr->nExpr>iIdxCol );
|
||||
pParse->iSelfTab = iTabCur;
|
||||
sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2481,9 +2497,12 @@ void sqlite3ExprCodeGetColumnOfTable(
|
||||
|
||||
/*
|
||||
** Generate code that will extract the iColumn-th column from
|
||||
** table pTab and store the column value in a register. An effort
|
||||
** is made to store the column value in register iReg, but this is
|
||||
** not guaranteed. The location of the column value is returned.
|
||||
** table pTab and store the column value in a register.
|
||||
**
|
||||
** An effort is made to store the column value in register iReg. This
|
||||
** is not garanteeed for GetColumn() - the result can be stored in
|
||||
** any register. But the result is guaranteed to land in register iReg
|
||||
** for GetColumnToReg().
|
||||
**
|
||||
** There must be an open cursor to pTab in iTable when this routine
|
||||
** is called. If iColumn<0 then code is generated that extracts the rowid.
|
||||
@@ -2494,7 +2513,7 @@ int sqlite3ExprCodeGetColumn(
|
||||
int iColumn, /* Index of the table column */
|
||||
int iTable, /* The cursor pointing to the table */
|
||||
int iReg, /* Store results here */
|
||||
u8 p5 /* P5 value for OP_Column */
|
||||
u8 p5 /* P5 value for OP_Column + FLAGS */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
@@ -2516,6 +2535,17 @@ int sqlite3ExprCodeGetColumn(
|
||||
}
|
||||
return iReg;
|
||||
}
|
||||
void sqlite3ExprCodeGetColumnToReg(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
Table *pTab, /* Description of the table we are reading from */
|
||||
int iColumn, /* Index of the table column */
|
||||
int iTable, /* The cursor pointing to the table */
|
||||
int iReg /* Store results here */
|
||||
){
|
||||
int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
|
||||
if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Clear all column cache entries.
|
||||
@@ -3342,6 +3372,10 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
||||
**
|
||||
** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
|
||||
** factored out into initialization code.
|
||||
**
|
||||
** The SQLITE_ECEL_REF flag means that expressions in the list with
|
||||
** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
|
||||
** in registers at srcReg, and so the value can be copied from there.
|
||||
*/
|
||||
int sqlite3ExprCodeExprList(
|
||||
Parse *pParse, /* Parsing context */
|
||||
|
||||
+45
-28
@@ -29,42 +29,59 @@
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
|
||||
/*
|
||||
** The default xBenignCtrl function is a no-op
|
||||
** Global variables.
|
||||
*/
|
||||
static void sqlite3BenignCtrlNoop(int eOp){
|
||||
(void)eOp;
|
||||
typedef struct BenignMallocHooks BenignMallocHooks;
|
||||
static SQLITE_WSD struct BenignMallocHooks {
|
||||
void (*xBenignBegin)(void);
|
||||
void (*xBenignEnd)(void);
|
||||
} sqlite3Hooks = { 0, 0 };
|
||||
|
||||
/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
|
||||
** structure. If writable static data is unsupported on the target,
|
||||
** we have to locate the state vector at run-time. In the more common
|
||||
** case where writable static data is supported, wsdHooks can refer directly
|
||||
** to the "sqlite3Hooks" state vector declared above.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_WSD
|
||||
# define wsdHooksInit \
|
||||
BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
|
||||
# define wsdHooks x[0]
|
||||
#else
|
||||
# define wsdHooksInit
|
||||
# define wsdHooks sqlite3Hooks
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Register hooks to call when sqlite3BeginBenignMalloc() and
|
||||
** sqlite3EndBenignMalloc() are called, respectively.
|
||||
*/
|
||||
void sqlite3BenignMallocHooks(
|
||||
void (*xBenignBegin)(void),
|
||||
void (*xBenignEnd)(void)
|
||||
){
|
||||
wsdHooksInit;
|
||||
wsdHooks.xBenignBegin = xBenignBegin;
|
||||
wsdHooks.xBenignEnd = xBenignEnd;
|
||||
}
|
||||
|
||||
/*
|
||||
** Global variable: Pointer to the benign malloc control interface.
|
||||
*/
|
||||
static void (*sqlite3xBenignCtrl)(int) = sqlite3BenignCtrlNoop;
|
||||
|
||||
/*
|
||||
** Register a pointer to the benign-malloc control interface function.
|
||||
** If the argument is a NULL pointer, register the default no-op controller.
|
||||
*/
|
||||
void sqlite3BenignMallocHooks(void (*xBenignCtrl)(int)){
|
||||
sqlite3xBenignCtrl = xBenignCtrl ? xBenignCtrl : sqlite3BenignCtrlNoop;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3BeginBenignMalloc() and sqlite3EndBenignMalloc() calls bracket
|
||||
** sections of code for which malloc failures are non-fatal.
|
||||
** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
|
||||
** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
|
||||
** indicates that subsequent malloc failures are non-benign.
|
||||
*/
|
||||
void sqlite3BeginBenignMalloc(void){
|
||||
sqlite3xBenignCtrl(1);
|
||||
wsdHooksInit;
|
||||
if( wsdHooks.xBenignBegin ){
|
||||
wsdHooks.xBenignBegin();
|
||||
}
|
||||
}
|
||||
void sqlite3EndBenignMalloc(void){
|
||||
sqlite3xBenignCtrl(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3PreviousBenignMalloc() call indicates that the previous
|
||||
** malloc call (which must have failed) was a benign failure.
|
||||
*/
|
||||
void sqlite3PreviousBenignMalloc(void){
|
||||
sqlite3xBenignCtrl(2);
|
||||
wsdHooksInit;
|
||||
if( wsdHooks.xBenignEnd ){
|
||||
wsdHooks.xBenignEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
|
||||
|
||||
+10
-1
@@ -252,6 +252,8 @@ int sqlite3FkLocateIndex(
|
||||
char *zDfltColl; /* Def. collation for column */
|
||||
char *zIdxCol; /* Name of indexed column */
|
||||
|
||||
if( iCol<0 ) break; /* No foreign keys against expression indexes */
|
||||
|
||||
/* If the index uses a collation sequence that is different from
|
||||
** the default collation sequence for the column, this index is
|
||||
** unusable. Bail out early in this case. */
|
||||
@@ -404,6 +406,7 @@ static void fkLookupParent(
|
||||
for(i=0; i<nCol; i++){
|
||||
int iChild = aiCol[i]+1+regData;
|
||||
int iParent = pIdx->aiColumn[i]+1+regData;
|
||||
assert( pIdx->aiColumn[i]>=0 );
|
||||
assert( aiCol[i]!=pTab->iPKey );
|
||||
if( pIdx->aiColumn[i]==pTab->iPKey ){
|
||||
/* The parent key is a composite key that includes the IPK column */
|
||||
@@ -612,6 +615,7 @@ static void fkScanChildren(
|
||||
assert( pIdx!=0 );
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
i16 iCol = pIdx->aiColumn[i];
|
||||
assert( iCol>=0 );
|
||||
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
|
||||
pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
|
||||
@@ -931,6 +935,7 @@ void sqlite3FkCheck(
|
||||
if( aiCol[i]==pTab->iPKey ){
|
||||
aiCol[i] = -1;
|
||||
}
|
||||
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
/* Request permission to read the parent key columns. If the
|
||||
** authorization callback returns SQLITE_IGNORE, behave as if any
|
||||
@@ -1062,7 +1067,10 @@ u32 sqlite3FkOldmask(
|
||||
Index *pIdx = 0;
|
||||
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
|
||||
if( pIdx ){
|
||||
for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
|
||||
for(i=0; i<pIdx->nKeyCol; i++){
|
||||
assert( pIdx->aiColumn[i]>=0 );
|
||||
mask |= COLUMN_MASK(pIdx->aiColumn[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1185,6 +1193,7 @@ static Trigger *fkActionTrigger(
|
||||
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
|
||||
assert( iFromCol>=0 );
|
||||
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
|
||||
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
|
||||
tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName;
|
||||
tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
|
||||
|
||||
|
||||
+4
-4
@@ -118,11 +118,11 @@ static int rehash(Hash *pH, unsigned int new_size){
|
||||
** use the actual amount of space allocated for the hash table (which
|
||||
** may be larger than the requested amount).
|
||||
*/
|
||||
sqlite3BeginBenignMalloc();
|
||||
new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
|
||||
if( new_ht==0 ){
|
||||
sqlite3PreviousBenignMalloc();
|
||||
return 0;
|
||||
}
|
||||
sqlite3EndBenignMalloc();
|
||||
|
||||
if( new_ht==0 ) return 0;
|
||||
sqlite3_free(pH->ht);
|
||||
pH->ht = new_ht;
|
||||
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
|
||||
|
||||
+28
-22
@@ -90,11 +90,11 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
|
||||
i16 x = pIdx->aiColumn[n];
|
||||
if( x>=0 ){
|
||||
pIdx->zColAff[n] = pTab->aCol[x].affinity;
|
||||
}else if( x==(-1) ){
|
||||
}else if( x==XN_ROWID ){
|
||||
pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
|
||||
}else{
|
||||
char aff;
|
||||
assert( x==(-2) );
|
||||
assert( x==XN_EXPR );
|
||||
assert( pIdx->aColExpr!=0 );
|
||||
aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
|
||||
if( aff==0 ) aff = SQLITE_AFF_BLOB;
|
||||
@@ -260,7 +260,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
|
||||
/* This routine is never called during trigger-generation. It is
|
||||
** only called from the top-level */
|
||||
assert( pParse->pTriggerTab==0 );
|
||||
assert( pParse==sqlite3ParseToplevel(pParse) );
|
||||
assert( sqlite3IsToplevel(pParse) );
|
||||
|
||||
assert( v ); /* We failed long ago if this is not so */
|
||||
for(p = pParse->pAinc; p; p = p->pNext){
|
||||
@@ -313,16 +313,16 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
assert( v );
|
||||
for(p = pParse->pAinc; p; p = p->pNext){
|
||||
Db *pDb = &db->aDb[p->iDb];
|
||||
int j1;
|
||||
int addr1;
|
||||
int iRec;
|
||||
int memId = p->regCtr;
|
||||
|
||||
iRec = sqlite3GetTempReg(pParse);
|
||||
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
|
||||
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
@@ -762,7 +762,7 @@ void sqlite3Insert(
|
||||
/* If this is not a view, open the table and and all indices */
|
||||
if( !isView ){
|
||||
int nIdx;
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
|
||||
&iDataCur, &iIdxCur);
|
||||
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
|
||||
if( aRegIdx==0 ){
|
||||
@@ -814,7 +814,7 @@ void sqlite3Insert(
|
||||
if( ipkColumn<0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
|
||||
}else{
|
||||
int j1;
|
||||
int addr1;
|
||||
assert( !withoutRowid );
|
||||
if( useTempTable ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols);
|
||||
@@ -822,9 +822,9 @@ void sqlite3Insert(
|
||||
assert( pSelect==0 ); /* Otherwise useTempTable is true */
|
||||
sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols);
|
||||
}
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
@@ -898,14 +898,14 @@ void sqlite3Insert(
|
||||
** to generate a unique primary key value.
|
||||
*/
|
||||
if( !appendFlag ){
|
||||
int j1;
|
||||
int addr1;
|
||||
if( !IsVirtual(pTab) ){
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}else{
|
||||
j1 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
|
||||
}
|
||||
@@ -1159,7 +1159,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
int ix; /* Index loop counter */
|
||||
int nCol; /* Number of columns */
|
||||
int onError; /* Conflict resolution strategy */
|
||||
int j1; /* Address of jump instruction */
|
||||
int addr1; /* Address of jump instruction */
|
||||
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
||||
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
|
||||
int ipkTop = 0; /* Top of the rowid change constraint check */
|
||||
@@ -1230,9 +1230,10 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
default: {
|
||||
assert( onError==OE_Replace );
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
|
||||
VdbeCoverage(v);
|
||||
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1408,20 +1409,20 @@ void sqlite3GenerateConstraintChecks(
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
int iField = pIdx->aiColumn[i];
|
||||
int x;
|
||||
if( iField==(-2) ){
|
||||
if( iField==XN_EXPR ){
|
||||
pParse->ckBase = regNewData+1;
|
||||
sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
|
||||
pParse->ckBase = 0;
|
||||
VdbeComment((v, "%s column %d", pIdx->zName, i));
|
||||
}else{
|
||||
if( iField==(-1) || iField==pTab->iPKey ){
|
||||
if( iField==XN_ROWID || iField==pTab->iPKey ){
|
||||
if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
|
||||
x = regNewData;
|
||||
regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i;
|
||||
}else{
|
||||
x = iField + regNewData + 1;
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
|
||||
sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
|
||||
VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
|
||||
}
|
||||
}
|
||||
@@ -1473,6 +1474,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** store it in registers regR..regR+nPk-1 */
|
||||
if( pIdx!=pPk ){
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
assert( pPk->aiColumn[i]>=0 );
|
||||
x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
|
||||
VdbeComment((v, "%s.%s", pTab->zName,
|
||||
@@ -1494,6 +1496,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
|
||||
x = pPk->aiColumn[i];
|
||||
assert( x>=0 );
|
||||
if( i==(pPk->nKeyCol-1) ){
|
||||
addrJump = addrUniqueOk;
|
||||
op = OP_Eq;
|
||||
@@ -1647,6 +1650,7 @@ int sqlite3OpenTableAndIndices(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Table *pTab, /* Table to be opened */
|
||||
int op, /* OP_OpenRead or OP_OpenWrite */
|
||||
u8 p5, /* P5 value for OP_Open* instructions */
|
||||
int iBase, /* Use this for the table cursor, if there is one */
|
||||
u8 *aToOpen, /* If not NULL: boolean for each table and index */
|
||||
int *piDataCur, /* Write the database source cursor number here */
|
||||
@@ -1659,6 +1663,7 @@ int sqlite3OpenTableAndIndices(
|
||||
Vdbe *v;
|
||||
|
||||
assert( op==OP_OpenRead || op==OP_OpenWrite );
|
||||
assert( op==OP_OpenWrite || p5==0 );
|
||||
if( IsVirtual(pTab) ){
|
||||
/* This routine is a no-op for virtual tables. Leave the output
|
||||
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
|
||||
@@ -1686,6 +1691,7 @@ int sqlite3OpenTableAndIndices(
|
||||
if( aToOpen==0 || aToOpen[i+1] ){
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
}
|
||||
}
|
||||
@@ -1745,7 +1751,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
|
||||
if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
|
||||
return 0; /* Different columns indexed */
|
||||
}
|
||||
if( pSrc->aiColumn[i]==(-2) ){
|
||||
if( pSrc->aiColumn[i]==XN_EXPR ){
|
||||
assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 );
|
||||
if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr,
|
||||
pDest->aColExpr->a[i].pExpr, -1)!=0 ){
|
||||
|
||||
+1
-1
@@ -408,7 +408,7 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_value_free,
|
||||
sqlite3_result_zeroblob64,
|
||||
sqlite3_bind_zeroblob64,
|
||||
/* Version 3.8.12 and later */
|
||||
/* Version 3.9.0 and later */
|
||||
sqlite3_value_subtype,
|
||||
sqlite3_result_subtype
|
||||
};
|
||||
|
||||
+77
-16
@@ -25,6 +25,12 @@
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
# include "sqliteicu.h"
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
int sqlite3Json1Init(sqlite3*);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
int sqlite3Fts5Init(sqlite3*);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
|
||||
@@ -664,12 +670,10 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
sz = 0;
|
||||
pStart = 0;
|
||||
}else if( pBuf==0 ){
|
||||
sqlite3BeginBenignMalloc();
|
||||
pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */
|
||||
if( pStart==0 ){
|
||||
sqlite3PreviousBenignMalloc();
|
||||
}else{
|
||||
cnt = sqlite3MallocSize(pStart)/sz;
|
||||
}
|
||||
sqlite3EndBenignMalloc();
|
||||
if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
|
||||
}else{
|
||||
pStart = pBuf;
|
||||
}
|
||||
@@ -736,6 +740,36 @@ int sqlite3_db_release_memory(sqlite3 *db){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush any dirty pages in the pager-cache for any attached database
|
||||
** to disk.
|
||||
*/
|
||||
int sqlite3_db_cacheflush(sqlite3 *db){
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
int bSeenBusy = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
rc = sqlite3PagerFlush(pPager);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
bSeenBusy = 1;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Configuration settings for an individual database connection
|
||||
*/
|
||||
@@ -2874,12 +2908,18 @@ static int openDatabase(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS3
|
||||
#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
|
||||
if( !db->mallocFailed && rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3Init(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
if( !db->mallocFailed && rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5Init(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
if( !db->mallocFailed && rc==SQLITE_OK ){
|
||||
rc = sqlite3IcuInit(db);
|
||||
@@ -2898,6 +2938,12 @@ static int openDatabase(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
if( !db->mallocFailed && rc==SQLITE_OK){
|
||||
rc = sqlite3Json1Init(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
|
||||
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
|
||||
** mode. Doing nothing at all also makes NORMAL the default.
|
||||
@@ -2938,6 +2984,21 @@ opendb_out:
|
||||
void *pArg = sqlite3GlobalConfig.pSqllogArg;
|
||||
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zHexKey = sqlite3_uri_parameter(zOpen, "hexkey");
|
||||
if( zHexKey && zHexKey[0] ){
|
||||
u8 iByte;
|
||||
int i;
|
||||
char zKey[40];
|
||||
for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zHexKey[i]); i++){
|
||||
iByte = (iByte<<4) + sqlite3HexToInt(zHexKey[i]);
|
||||
if( (i&1)!=0 ) zKey[i/2] = iByte;
|
||||
}
|
||||
sqlite3_key_v2(db, 0, zKey, i/2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc & 0xff;
|
||||
}
|
||||
@@ -3442,18 +3503,18 @@ int sqlite3_test_control(int op, ...){
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_test_control(BENIGN_MALLOC_CTRL, xCtrl)
|
||||
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
|
||||
**
|
||||
** Register a callback function that will handle calls to
|
||||
** sqlite3BeginBenignMalloc(), sqlite3EndBenignMalloc(), and
|
||||
** sqlite3PreviousBenignMalloc(). If the callback function pointer
|
||||
** is NULL, then a built-in default (no-op) handler is used.
|
||||
** Register hooks to call to indicate which malloc() failures
|
||||
** are benign.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL: {
|
||||
typedef void (*void_function)(int);
|
||||
void_function xBenignCtrl;
|
||||
xBenignCtrl = va_arg(ap, void_function);
|
||||
sqlite3BenignMallocHooks(xBenignCtrl);
|
||||
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
|
||||
typedef void (*void_function)(void);
|
||||
void_function xBenignBegin;
|
||||
void_function xBenignEnd;
|
||||
xBenignBegin = va_arg(ap, void_function);
|
||||
xBenignEnd = va_arg(ap, void_function);
|
||||
sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+6
-8
@@ -131,9 +131,7 @@ int sqlite3MallocInit(void){
|
||||
sqlite3MemSetDefault();
|
||||
}
|
||||
memset(&mem0, 0, sizeof(mem0));
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
||||
}
|
||||
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
||||
if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
|
||||
&& sqlite3GlobalConfig.nScratch>0 ){
|
||||
int i, n, sz;
|
||||
@@ -224,7 +222,7 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
void *p;
|
||||
assert( sqlite3_mutex_held(mem0.mutex) );
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
if( mem0.alarmThreshold>0 ){
|
||||
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
@@ -316,7 +314,7 @@ void *sqlite3ScratchMalloc(int n){
|
||||
assert( n>0 );
|
||||
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
|
||||
if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
@@ -411,6 +409,7 @@ int sqlite3MallocSize(void *p){
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
assert( p!=0 );
|
||||
if( db==0 || !isLookaside(db,p) ){
|
||||
#if SQLITE_DEBUG
|
||||
if( db==0 ){
|
||||
@@ -430,7 +429,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
sqlite3_uint64 sqlite3_msize(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
||||
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
|
||||
return p ? sqlite3GlobalConfig.m.xSize(p) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,7 +517,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
pNew = pOld;
|
||||
}else if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
|
||||
nDiff = nNew - nOld;
|
||||
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
|
||||
mem0.alarmThreshold-nDiff ){
|
||||
@@ -526,7 +525,6 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
}
|
||||
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
||||
if( pNew==0 && mem0.alarmThreshold>0 ){
|
||||
sqlite3PreviousBenignMalloc();
|
||||
sqlite3MallocAlarm((int)nBytes);
|
||||
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
||||
}
|
||||
|
||||
+3
-2
@@ -172,10 +172,11 @@ static void sqlite3MemFree(void *pPrior){
|
||||
*/
|
||||
static int sqlite3MemSize(void *pPrior){
|
||||
#ifdef SQLITE_MALLOCSIZE
|
||||
return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
|
||||
assert( pPrior!=0 );
|
||||
return (int)SQLITE_MALLOCSIZE(pPrior);
|
||||
#else
|
||||
sqlite3_int64 *p;
|
||||
if( pPrior==0 ) return 0;
|
||||
assert( pPrior!=0 );
|
||||
p = (sqlite3_int64*)pPrior;
|
||||
p--;
|
||||
return (int)p[0];
|
||||
|
||||
+1
-1
@@ -476,7 +476,7 @@ static void memsys3FreeUnsafe(void *pOld){
|
||||
*/
|
||||
static int memsys3Size(void *p){
|
||||
Mem3Block *pBlock;
|
||||
if( p==0 ) return 0;
|
||||
assert( p!=0 );
|
||||
pBlock = (Mem3Block*)p;
|
||||
assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
|
||||
return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
|
||||
|
||||
+5
-6
@@ -200,12 +200,11 @@ static void memsys5Leave(void){
|
||||
** works for chunks that are currently checked out.
|
||||
*/
|
||||
static int memsys5Size(void *p){
|
||||
int iSize = 0;
|
||||
if( p ){
|
||||
int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
|
||||
assert( i>=0 && i<mem5.nBlock );
|
||||
iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
|
||||
}
|
||||
int iSize, i;
|
||||
assert( p!=0 );
|
||||
i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
|
||||
assert( i>=0 && i<mem5.nBlock );
|
||||
iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
|
||||
return iSize;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -81,7 +81,9 @@ static int pthreadMutexNotheld(sqlite3_mutex *p){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Try to provide a memory barrier operation, needed for initialization only.
|
||||
** Try to provide a memory barrier operation, needed for initialization
|
||||
** and also for the implementation of xShmBarrier in the VFS in cases
|
||||
** where SQLite is compiled without mutexes.
|
||||
*/
|
||||
void sqlite3MemoryBarrier(void){
|
||||
#if defined(SQLITE_MEMORY_BARRIER)
|
||||
|
||||
+7
-2
@@ -78,14 +78,19 @@ static int winMutexNotheld(sqlite3_mutex *p){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Try to provide a memory barrier operation, needed for initialization only.
|
||||
** Try to provide a memory barrier operation, needed for initialization
|
||||
** and also for the xShmBarrier method of the VFS in cases when SQLite is
|
||||
** compiled without mutexes (SQLITE_THREADSAFE=0).
|
||||
*/
|
||||
void sqlite3MemoryBarrier(void){
|
||||
#if defined(SQLITE_MEMORY_BARRIER)
|
||||
SQLITE_MEMORY_BARRIER;
|
||||
#elif defined(__GNUC__)
|
||||
__sync_synchronize();
|
||||
#else
|
||||
#elif !defined(SQLITE_DISABLE_INTRINSIC) && \
|
||||
defined(_MSC_VER) && _MSC_VER>=1300
|
||||
_ReadWriteBarrier();
|
||||
#elif defined(MemoryBarrier)
|
||||
MemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
+32
-9
@@ -4473,6 +4473,25 @@ static int pagerStress(void *p, PgHdr *pPg){
|
||||
return pager_error(pPager, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush all unreferenced dirty pages to disk.
|
||||
*/
|
||||
int sqlite3PagerFlush(Pager *pPager){
|
||||
int rc = pPager->errCode;
|
||||
if( !MEMDB ){
|
||||
PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
|
||||
assert( assert_pager_state(pPager) );
|
||||
while( rc==SQLITE_OK && pList ){
|
||||
PgHdr *pNext = pList->pDirty;
|
||||
if( pList->nRef==0 ){
|
||||
rc = pagerStress((void*)pPager, pList);
|
||||
}
|
||||
pList = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and initialize a new Pager object and put a pointer to it
|
||||
@@ -5896,9 +5915,10 @@ int sqlite3PagerWrite(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
||||
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPager) );
|
||||
if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
|
||||
if( pPager->errCode ){
|
||||
return pPager->errCode;
|
||||
}else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
|
||||
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
|
||||
return SQLITE_OK;
|
||||
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
@@ -6076,14 +6096,17 @@ int sqlite3PagerSync(Pager *pPager, const char *zMaster){
|
||||
** returned.
|
||||
*/
|
||||
int sqlite3PagerExclusiveLock(Pager *pPager){
|
||||
int rc = SQLITE_OK;
|
||||
assert( pPager->eState==PAGER_WRITER_CACHEMOD
|
||||
|| pPager->eState==PAGER_WRITER_DBMOD
|
||||
|| pPager->eState==PAGER_WRITER_LOCKED
|
||||
);
|
||||
int rc = pPager->errCode;
|
||||
assert( assert_pager_state(pPager) );
|
||||
if( 0==pagerUseWal(pPager) ){
|
||||
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pPager->eState==PAGER_WRITER_CACHEMOD
|
||||
|| pPager->eState==PAGER_WRITER_DBMOD
|
||||
|| pPager->eState==PAGER_WRITER_LOCKED
|
||||
);
|
||||
assert( assert_pager_state(pPager) );
|
||||
if( 0==pagerUseWal(pPager) ){
|
||||
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ int sqlite3PagerGetJournalMode(Pager*);
|
||||
int sqlite3PagerOkToChangeJournalMode(Pager*);
|
||||
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
|
||||
sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
|
||||
int sqlite3PagerFlush(Pager*);
|
||||
|
||||
/* Functions used to obtain and release page references. */
|
||||
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
|
||||
|
||||
+13
-6
@@ -929,6 +929,13 @@ term(A) ::= CTIME_KW(OP). {
|
||||
pOut->zStart = pLeft->zStart;
|
||||
pOut->zEnd = pRight->zEnd;
|
||||
}
|
||||
|
||||
/* If doNot is true, then add a TK_NOT Expr-node wrapper around the
|
||||
** outside of *ppExpr.
|
||||
*/
|
||||
static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){
|
||||
if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||
@@ -951,7 +958,7 @@ expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] {
|
||||
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
||||
if( OP.bNot ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, OP.bNot, &A.pExpr);
|
||||
A.zStart = X.zStart;
|
||||
A.zEnd = Y.zEnd;
|
||||
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
|
||||
@@ -962,7 +969,7 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
|
||||
pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
||||
if( OP.bNot ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, OP.bNot, &A.pExpr);
|
||||
A.zStart = X.zStart;
|
||||
A.zEnd = E.zEnd;
|
||||
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
|
||||
@@ -1052,7 +1059,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, N, &A.pExpr);
|
||||
A.zStart = W.zStart;
|
||||
A.zEnd = Y.zEnd;
|
||||
}
|
||||
@@ -1107,7 +1114,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
}
|
||||
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, N, &A.pExpr);
|
||||
}
|
||||
A.zStart = X.zStart;
|
||||
A.zEnd = &E.z[E.n];
|
||||
@@ -1133,7 +1140,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
}else{
|
||||
sqlite3SelectDelete(pParse->db, Y);
|
||||
}
|
||||
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, N, &A.pExpr);
|
||||
A.zStart = X.zStart;
|
||||
A.zEnd = &E.z[E.n];
|
||||
}
|
||||
@@ -1147,7 +1154,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
}else{
|
||||
sqlite3SrcListDelete(pParse->db, pSrc);
|
||||
}
|
||||
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
|
||||
exprNot(pParse, N, &A.pExpr);
|
||||
A.zStart = X.zStart;
|
||||
A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
|
||||
}
|
||||
|
||||
+5
-5
@@ -272,6 +272,7 @@ static int pcache1InitBulk(PCache1 *pCache){
|
||||
if( pcache1.nInitPage==0 ) return 0;
|
||||
/* Do not bother with a bulk allocation if the cache size very small */
|
||||
if( pCache->nMax<3 ) return 0;
|
||||
sqlite3BeginBenignMalloc();
|
||||
if( pcache1.nInitPage>0 ){
|
||||
szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
|
||||
}else{
|
||||
@@ -281,9 +282,8 @@ static int pcache1InitBulk(PCache1 *pCache){
|
||||
szBulk = pCache->szAlloc*pCache->nMax;
|
||||
}
|
||||
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
||||
if( zBulk==0 ){
|
||||
sqlite3PreviousBenignMalloc();
|
||||
}else{
|
||||
sqlite3EndBenignMalloc();
|
||||
if( zBulk ){
|
||||
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
|
||||
int i;
|
||||
for(i=0; i<nBulk; i++){
|
||||
@@ -320,7 +320,7 @@ static void *pcache1Alloc(int nByte){
|
||||
pcache1.nFreeSlot--;
|
||||
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
||||
assert( pcache1.nFreeSlot>=0 );
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
}
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
@@ -334,7 +334,7 @@ static void *pcache1Alloc(int nByte){
|
||||
if( p ){
|
||||
int sz = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
|
||||
+9
-8
@@ -1361,8 +1361,9 @@ void sqlite3Pragma(
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList endCode[] = {
|
||||
{ OP_IfNeg, 1, 0, 0}, /* 0 */
|
||||
{ OP_String8, 0, 3, 0}, /* 1 */
|
||||
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||
{ OP_If, 1, 0, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0},
|
||||
};
|
||||
|
||||
@@ -1464,7 +1465,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
@@ -1524,8 +1525,8 @@ void sqlite3Pragma(
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol>=0 && iCol<pTab->nCol );
|
||||
if( pTab->aCol[iCol].notNull ) continue;
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
@@ -1563,9 +1564,9 @@ void sqlite3Pragma(
|
||||
}
|
||||
}
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
|
||||
sqlite3VdbeChangeP3(v, addr, -mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
|
||||
sqlite3VdbeChangeP2(v, addr, -mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr+1);
|
||||
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
|
||||
}
|
||||
break;
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
+72
-92
@@ -579,7 +579,7 @@ static void pushOntoSorter(
|
||||
}else{
|
||||
iLimit = pSelect->iLimit;
|
||||
}
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
|
||||
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
@@ -595,11 +595,8 @@ static void codeOffset(
|
||||
int iContinue /* Jump here to skip the current record */
|
||||
){
|
||||
if( iOffset>0 ){
|
||||
int addr;
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, iContinue);
|
||||
VdbeComment((v, "skip OFFSET records"));
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
|
||||
VdbeComment((v, "OFFSET"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1815,7 +1812,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
Vdbe *v = 0;
|
||||
int iLimit = 0;
|
||||
int iOffset;
|
||||
int addr1, n;
|
||||
int n;
|
||||
if( p->iLimit ) return;
|
||||
|
||||
/*
|
||||
@@ -1850,14 +1847,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
sqlite3ExprCode(pParse, p->pOffset, iOffset);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
|
||||
VdbeComment((v, "OFFSET counter"));
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
|
||||
VdbeComment((v, "LIMIT+OFFSET"));
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2273,6 +2266,11 @@ static int multiSelect(
|
||||
if( p->iLimit ){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
|
||||
VdbeComment((v, "Jump ahead if LIMIT reached"));
|
||||
if( p->iOffset ){
|
||||
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
|
||||
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
|
||||
}
|
||||
}
|
||||
explainSetInteger(iSub2, pParse->iNextSelectId);
|
||||
rc = sqlite3Select(pParse, p, &dest);
|
||||
@@ -2580,12 +2578,12 @@ static int generateOutputSubroutine(
|
||||
/* Suppress duplicates for UNION, EXCEPT, and INTERSECT
|
||||
*/
|
||||
if( regPrev ){
|
||||
int j1, j2;
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
|
||||
j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
|
||||
int addr1, addr2;
|
||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
|
||||
addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
|
||||
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
|
||||
}
|
||||
@@ -2802,7 +2800,7 @@ static int multiSelectOrderBy(
|
||||
int savedOffset; /* Saved value of p->iOffset */
|
||||
int labelCmpr; /* Label for the start of the merge algorithm */
|
||||
int labelEnd; /* Label for the end of the overall SELECT stmt */
|
||||
int j1; /* Jump instructions that get retargetted */
|
||||
int addr1; /* Jump instructions that get retargetted */
|
||||
int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
|
||||
KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
|
||||
KeyInfo *pKeyMerge; /* Comparison information for merging rows */
|
||||
@@ -2938,19 +2936,19 @@ static int multiSelectOrderBy(
|
||||
** left of the compound operator - the "A" select.
|
||||
*/
|
||||
addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
|
||||
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
|
||||
VdbeComment((v, "left SELECT"));
|
||||
pPrior->iLimit = regLimitA;
|
||||
explainSetInteger(iSub1, pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pPrior, &destA);
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
|
||||
/* Generate a coroutine to evaluate the SELECT statement on
|
||||
** the right - the "B" select
|
||||
*/
|
||||
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
|
||||
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
|
||||
VdbeComment((v, "right SELECT"));
|
||||
savedLimit = p->iLimit;
|
||||
savedOffset = p->iOffset;
|
||||
@@ -3041,7 +3039,7 @@ static int multiSelectOrderBy(
|
||||
|
||||
/* This code runs once to initialize everything.
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
|
||||
|
||||
@@ -3084,7 +3082,7 @@ static int multiSelectOrderBy(
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
/* Forward Declarations */
|
||||
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
|
||||
static void substSelect(sqlite3*, Select *, int, ExprList *);
|
||||
static void substSelect(sqlite3*, Select *, int, ExprList*, int);
|
||||
|
||||
/*
|
||||
** Scan through the expression pExpr. Replace every reference to
|
||||
@@ -3121,7 +3119,7 @@ static Expr *substExpr(
|
||||
pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
|
||||
pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
substSelect(db, pExpr->x.pSelect, iTable, pEList);
|
||||
substSelect(db, pExpr->x.pSelect, iTable, pEList, 1);
|
||||
}else{
|
||||
substExprList(db, pExpr->x.pList, iTable, pEList);
|
||||
}
|
||||
@@ -3144,25 +3142,28 @@ static void substSelect(
|
||||
sqlite3 *db, /* Report malloc errors here */
|
||||
Select *p, /* SELECT statement in which to make substitutions */
|
||||
int iTable, /* Table to be replaced */
|
||||
ExprList *pEList /* Substitute values */
|
||||
ExprList *pEList, /* Substitute values */
|
||||
int doPrior /* Do substitutes on p->pPrior too */
|
||||
){
|
||||
SrcList *pSrc;
|
||||
struct SrcList_item *pItem;
|
||||
int i;
|
||||
if( !p ) return;
|
||||
substExprList(db, p->pEList, iTable, pEList);
|
||||
substExprList(db, p->pGroupBy, iTable, pEList);
|
||||
substExprList(db, p->pOrderBy, iTable, pEList);
|
||||
p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
|
||||
p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
|
||||
substSelect(db, p->pPrior, iTable, pEList);
|
||||
pSrc = p->pSrc;
|
||||
assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
|
||||
if( ALWAYS(pSrc) ){
|
||||
do{
|
||||
substExprList(db, p->pEList, iTable, pEList);
|
||||
substExprList(db, p->pGroupBy, iTable, pEList);
|
||||
substExprList(db, p->pOrderBy, iTable, pEList);
|
||||
p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
|
||||
p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
|
||||
pSrc = p->pSrc;
|
||||
assert( pSrc!=0 );
|
||||
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
||||
substSelect(db, pItem->pSelect, iTable, pEList);
|
||||
substSelect(db, pItem->pSelect, iTable, pEList, 1);
|
||||
if( pItem->fg.isTabFunc ){
|
||||
substExprList(db, pItem->u1.pFuncArg, iTable, pEList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}while( doPrior && (p = p->pPrior)!=0 );
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
@@ -3314,7 +3315,7 @@ static int flattenSubquery(
|
||||
int subqueryIsAgg /* True if the subquery uses aggregate functions */
|
||||
){
|
||||
const char *zSavedAuthContext = pParse->zAuthContext;
|
||||
Select *pParent;
|
||||
Select *pParent; /* Current UNION ALL term of the other query */
|
||||
Select *pSub; /* The inner query or "subquery" */
|
||||
Select *pSub1; /* Pointer to the rightmost select in sub-query */
|
||||
SrcList *pSrc; /* The FROM clause of the outer query */
|
||||
@@ -3609,9 +3610,9 @@ static int flattenSubquery(
|
||||
**
|
||||
** The outer query has 3 slots in its FROM clause. One slot of the
|
||||
** outer query (the middle slot) is used by the subquery. The next
|
||||
** block of code will expand the out query to 4 slots. The middle
|
||||
** slot is expanded to two slots in order to make space for the
|
||||
** two elements in the FROM clause of the subquery.
|
||||
** block of code will expand the outer query FROM clause to 4 slots.
|
||||
** The middle slot is expanded to two slots in order to make space
|
||||
** for the two elements in the FROM clause of the subquery.
|
||||
*/
|
||||
if( nSubSrc>1 ){
|
||||
pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
|
||||
@@ -3650,11 +3651,6 @@ static int flattenSubquery(
|
||||
pList->a[i].zName = zName;
|
||||
}
|
||||
}
|
||||
substExprList(db, pParent->pEList, iParent, pSub->pEList);
|
||||
if( isAgg ){
|
||||
substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
|
||||
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
||||
}
|
||||
if( pSub->pOrderBy ){
|
||||
/* At this point, any non-zero iOrderByCol values indicate that the
|
||||
** ORDER BY column expression is identical to the iOrderByCol'th
|
||||
@@ -3674,27 +3670,20 @@ static int flattenSubquery(
|
||||
assert( pSub->pPrior==0 );
|
||||
pParent->pOrderBy = pOrderBy;
|
||||
pSub->pOrderBy = 0;
|
||||
}else if( pParent->pOrderBy ){
|
||||
substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
|
||||
}
|
||||
if( pSub->pWhere ){
|
||||
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
|
||||
}else{
|
||||
pWhere = 0;
|
||||
}
|
||||
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
|
||||
if( subqueryIsAgg ){
|
||||
assert( pParent->pHaving==0 );
|
||||
pParent->pHaving = pParent->pWhere;
|
||||
pParent->pWhere = pWhere;
|
||||
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
|
||||
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
|
||||
sqlite3ExprDup(db, pSub->pHaving, 0));
|
||||
assert( pParent->pGroupBy==0 );
|
||||
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
|
||||
}else{
|
||||
pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
|
||||
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
|
||||
}
|
||||
substSelect(db, pParent, iParent, pSub->pEList, 0);
|
||||
|
||||
/* The flattened query is distinct if either the inner or the
|
||||
** outer query is distinct.
|
||||
@@ -4221,17 +4210,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
*/
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab;
|
||||
assert( pFrom->fg.isRecursive==0 || pFrom->pTab );
|
||||
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
|
||||
if( pFrom->fg.isRecursive ) continue;
|
||||
if( pFrom->pTab!=0 ){
|
||||
/* This statement has already been prepared. There is no need
|
||||
** to go further. */
|
||||
assert( i==0 );
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
selectPopWith(pWalker, p);
|
||||
#endif
|
||||
return WRC_Prune;
|
||||
}
|
||||
assert( pFrom->pTab==0 );
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
if( withExpand(pWalker, pFrom) ) return WRC_Abort;
|
||||
if( pFrom->pTab ) {} else
|
||||
@@ -4267,6 +4248,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pTab->nRef++;
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
|
||||
if( pTab->pSelect || IsVirtual(pTab) ){
|
||||
i16 nCol;
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
|
||||
assert( pFrom->pSelect==0 );
|
||||
if( pFrom->fg.isTabFunc && !IsVirtual(pTab) ){
|
||||
@@ -4275,7 +4257,10 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
|
||||
sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
|
||||
nCol = pTab->nCol;
|
||||
pTab->nCol = -1;
|
||||
sqlite3WalkSelect(pWalker, pFrom->pSelect);
|
||||
pTab->nCol = nCol;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -4467,7 +4452,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
** Walker.xSelectCallback is set to do something useful for every
|
||||
** subquery in the parser tree.
|
||||
*/
|
||||
static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
||||
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
return WRC_Continue;
|
||||
}
|
||||
@@ -4488,7 +4473,7 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
||||
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = exprWalkNoop;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.pParse = pParse;
|
||||
if( pParse->hasCompound ){
|
||||
w.xSelectCallback = convertCompoundSelectToSubquery;
|
||||
@@ -4523,19 +4508,19 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
struct SrcList_item *pFrom;
|
||||
|
||||
assert( p->selFlags & SF_Resolved );
|
||||
if( (p->selFlags & SF_HasTypeInfo)==0 ){
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
|
||||
/* A sub-query in the FROM clause of a SELECT */
|
||||
Select *pSel = pFrom->pSelect;
|
||||
if( pSel ){
|
||||
while( pSel->pPrior ) pSel = pSel->pPrior;
|
||||
selectAddColumnTypeAndCollation(pParse, pTab, pSel);
|
||||
}
|
||||
assert( (p->selFlags & SF_HasTypeInfo)==0 );
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
assert( pTab!=0 );
|
||||
if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
|
||||
/* A sub-query in the FROM clause of a SELECT */
|
||||
Select *pSel = pFrom->pSelect;
|
||||
if( pSel ){
|
||||
while( pSel->pPrior ) pSel = pSel->pPrior;
|
||||
selectAddColumnTypeAndCollation(pParse, pTab, pSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4555,7 +4540,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xSelectCallback2 = selectAddSubqueryTypeInfo;
|
||||
w.xExprCallback = exprWalkNoop;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.pParse = pParse;
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
#endif
|
||||
@@ -5223,7 +5208,7 @@ int sqlite3Select(
|
||||
*/
|
||||
if( pGroupBy ){
|
||||
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
|
||||
int j1; /* A-vs-B comparision jump */
|
||||
int addr1; /* A-vs-B comparision jump */
|
||||
int addrOutputRow; /* Start of subroutine that outputs a result row */
|
||||
int regOutputRow; /* Return address register for output subroutine */
|
||||
int addrSetAbort; /* Set the abort flag and return */
|
||||
@@ -5310,13 +5295,8 @@ int sqlite3Select(
|
||||
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
|
||||
if( pCol->iSorterColumn>=j ){
|
||||
int r1 = j + regBase;
|
||||
int r2;
|
||||
|
||||
r2 = sqlite3ExprCodeGetColumn(pParse,
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
|
||||
if( r1!=r2 ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
|
||||
}
|
||||
sqlite3ExprCodeGetColumnToReg(pParse,
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@@ -5371,8 +5351,8 @@ int sqlite3Select(
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
|
||||
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
|
||||
j1 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v);
|
||||
addr1 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v);
|
||||
|
||||
/* Generate code that runs whenever the GROUP BY changes.
|
||||
** Changes in the GROUP BY are detected by the previous code
|
||||
@@ -5394,7 +5374,7 @@ int sqlite3Select(
|
||||
/* Update the aggregate accumulators based on the content of
|
||||
** the current row
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
updateAccumulator(pParse, &sAggInfo);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
|
||||
VdbeComment((v, "indicate data in accumulator"));
|
||||
|
||||
+50
-17
@@ -2612,6 +2612,22 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Print the current sqlite3_errmsg() value to stderr and return 1.
|
||||
*/
|
||||
static int shellDatabaseError(sqlite3 *db){
|
||||
const char *zErr = sqlite3_errmsg(db);
|
||||
fprintf(stderr, "Error: %s\n", zErr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Print an out-of-memory message to stderr and return 1.
|
||||
*/
|
||||
static int shellNomemError(void){
|
||||
fprintf(stderr, "Error: out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** If an input line begins with "." then invoke this routine to
|
||||
@@ -3713,13 +3729,17 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int ii;
|
||||
open_db(p, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
if( rc ) return rc;
|
||||
if( rc ) return shellDatabaseError(p->db);
|
||||
|
||||
/* Create an SQL statement to query for the list of tables in the
|
||||
** main and all attached databases where the table name matches the
|
||||
** LIKE pattern bound to variable "?1". */
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT name FROM sqlite_master"
|
||||
" WHERE type IN ('table','view')"
|
||||
" AND name NOT LIKE 'sqlite_%%'"
|
||||
" AND name LIKE ?1");
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
|
||||
if( strcmp(zDbName,"temp")==0 ){
|
||||
@@ -3738,11 +3758,17 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
" AND name LIKE ?1", zSql, zDbName, zDbName);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( zSql && rc==SQLITE_OK ){
|
||||
zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
|
||||
if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) return rc;
|
||||
if( !zSql ) return shellNomemError();
|
||||
if( rc ) return shellDatabaseError(p->db);
|
||||
|
||||
/* Run the SQL statement prepared by the above block. Store the results
|
||||
** as an array of nul-terminated strings in azResult[]. */
|
||||
nRow = nAlloc = 0;
|
||||
azResult = 0;
|
||||
if( nArg>1 ){
|
||||
@@ -3756,17 +3782,25 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int n2 = nAlloc*2 + 10;
|
||||
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
|
||||
if( azNew==0 ){
|
||||
fprintf(stderr, "Error: out of memory\n");
|
||||
rc = shellNomemError();
|
||||
break;
|
||||
}
|
||||
nAlloc = n2;
|
||||
azResult = azNew;
|
||||
}
|
||||
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
|
||||
if( azResult[nRow] ) nRow++;
|
||||
if( 0==azResult[nRow] ){
|
||||
rc = shellNomemError();
|
||||
break;
|
||||
}
|
||||
nRow++;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
if( nRow>0 ){
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
rc = shellDatabaseError(p->db);
|
||||
}
|
||||
|
||||
/* Pretty-print the contents of array azResult[] to the output */
|
||||
if( rc==0 && nRow>0 ){
|
||||
int len, maxlen = 0;
|
||||
int i, j;
|
||||
int nPrintCol, nPrintRow;
|
||||
@@ -3785,6 +3819,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
fprintf(p->out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
|
||||
sqlite3_free(azResult);
|
||||
}else
|
||||
@@ -3799,6 +3834,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "prng_reset", SQLITE_TESTCTRL_PRNG_RESET },
|
||||
{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST },
|
||||
{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL },
|
||||
{ "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS },
|
||||
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE },
|
||||
{ "assert", SQLITE_TESTCTRL_ASSERT },
|
||||
{ "always", SQLITE_TESTCTRL_ALWAYS },
|
||||
@@ -3913,6 +3949,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
break;
|
||||
|
||||
case SQLITE_TESTCTRL_BITVEC_TEST:
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL:
|
||||
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
|
||||
case SQLITE_TESTCTRL_SCRATCHMALLOC:
|
||||
default:
|
||||
fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
|
||||
azArg[1]);
|
||||
@@ -4614,13 +4654,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
}
|
||||
data.out = stdout;
|
||||
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
{
|
||||
extern int sqlite3_json_init(sqlite3*);
|
||||
sqlite3_auto_extension((void(*)(void))sqlite3_json_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Go ahead and open the database file if it already exists. If the
|
||||
** file does not exist, delay opening it. This prevents empty database
|
||||
** files from being created if a user mistypes the database name argument
|
||||
|
||||
+61
-6
@@ -478,6 +478,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
|
||||
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
|
||||
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
|
||||
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
||||
@@ -4360,7 +4361,7 @@ int sqlite3_value_type(sqlite3_value*);
|
||||
int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtaining SQL Values
|
||||
** CAPI3REF: Finding The Subtype Of SQL Values
|
||||
** METHOD: sqlite3_value
|
||||
**
|
||||
** The sqlite3_value_subtype(V) function returns the subtype for
|
||||
@@ -5634,13 +5635,31 @@ struct sqlite3_module {
|
||||
** ^The estimatedRows value is an estimate of the number of rows that
|
||||
** will be returned by the strategy.
|
||||
**
|
||||
** The xBestIndex method may optionally populate the idxFlags field with a
|
||||
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
|
||||
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
|
||||
** assumes that the strategy may visit at most one row.
|
||||
**
|
||||
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
|
||||
** SQLite also assumes that if a call to the xUpdate() method is made as
|
||||
** part of the same statement to delete or update a virtual table row and the
|
||||
** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
|
||||
** any database changes. In other words, if the xUpdate() returns
|
||||
** SQLITE_CONSTRAINT, the database contents must be exactly as they were
|
||||
** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
|
||||
** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
|
||||
** the xUpdate method are automatically rolled back by SQLite.
|
||||
**
|
||||
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
|
||||
** structure for SQLite version 3.8.2. If a virtual table extension is
|
||||
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
||||
** to read or write the estimatedRows field are undefined (but are likely
|
||||
** to included crashing the application). The estimatedRows field should
|
||||
** therefore only be used if [sqlite3_libversion_number()] returns a
|
||||
** value greater than or equal to 3008002.
|
||||
** value greater than or equal to 3008002. Similarly, the idxFlags field
|
||||
** was added for version 3.9.0. It may therefore only be used if
|
||||
** sqlite3_libversion_number() returns a value greater than or equal to
|
||||
** 3009000.
|
||||
*/
|
||||
struct sqlite3_index_info {
|
||||
/* Inputs */
|
||||
@@ -5668,8 +5687,15 @@ struct sqlite3_index_info {
|
||||
double estimatedCost; /* Estimated cost of using this index */
|
||||
/* Fields below are only available in SQLite 3.8.2 and later */
|
||||
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
|
||||
/* Fields below are only available in SQLite 3.9.0 and later */
|
||||
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
||||
};
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Scan Flags
|
||||
*/
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Constraint Operator Codes
|
||||
**
|
||||
@@ -6418,7 +6444,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PRNG_RESET 7
|
||||
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
||||
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
||||
#define SQLITE_TESTCTRL_PENDING_BYTE 11
|
||||
#define SQLITE_TESTCTRL_ASSERT 12
|
||||
#define SQLITE_TESTCTRL_ALWAYS 13
|
||||
@@ -6434,8 +6460,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ISINIT 23
|
||||
#define SQLITE_TESTCTRL_SORTER_MMAP 24
|
||||
#define SQLITE_TESTCTRL_IMPOSTER 25
|
||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL 26
|
||||
#define SQLITE_TESTCTRL_LAST 26
|
||||
#define SQLITE_TESTCTRL_LAST 25
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
@@ -6548,7 +6573,8 @@ int sqlite3_status64(
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
||||
** <dd>This parameter records the deepest parser stack. It is only
|
||||
** <dd>The *pHighwater parameter records the deepest parser stack.
|
||||
** The *pCurrent value is undefined. The *pHighwater value is only
|
||||
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
|
||||
** </dl>
|
||||
**
|
||||
@@ -7766,6 +7792,35 @@ int sqlite3_stmt_scanstatus(
|
||||
*/
|
||||
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flush caches to disk mid-transaction
|
||||
**
|
||||
** If a write-transaction is open when this function is called, any dirty
|
||||
** pages in the pager-cache that are not currently in use are written out
|
||||
** to disk. A dirty page may be in use if a database cursor created by an
|
||||
** active SQL statement is reading from it, or if it is page 1 of a database
|
||||
** file (page 1 is always "in use"). Dirty pages are flushed for all
|
||||
** databases - "main", "temp" and any attached databases.
|
||||
**
|
||||
** If this function needs to obtain extra database locks before dirty pages
|
||||
** can be flushed to disk, it does so. If said locks cannot be obtained
|
||||
** immediately and there is a busy-handler callback configured, it is invoked
|
||||
** in the usual manner. If the required lock still cannot be obtained, then
|
||||
** the database is skipped and an attempt made to flush any dirty pages
|
||||
** belonging to the next (if any) database. If any databases are skipped
|
||||
** because locks cannot be obtained, but no other error occurs, this
|
||||
** function returns SQLITE_BUSY.
|
||||
**
|
||||
** If any other error occurs while flushing dirty pages to disk (for
|
||||
** example an IO error or out-of-memory condition), then processing is
|
||||
** abandoned and an SQLite error code returned to the caller immediately.
|
||||
**
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
**
|
||||
** This function does not set the database handle error code or message
|
||||
** returned by the sqlite3_errcode() and sqlite3_errmsg() functions.
|
||||
*/
|
||||
int sqlite3_db_cacheflush(sqlite3*);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
|
||||
+2
-2
@@ -272,7 +272,7 @@ struct sqlite3_api_routines {
|
||||
void (*value_free)(sqlite3_value*);
|
||||
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
||||
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
||||
/* Version 3.8.12 and later */
|
||||
/* Version 3.9.0 and later */
|
||||
unsigned int (*value_subtype)(sqlite3_value*);
|
||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
||||
};
|
||||
@@ -511,7 +511,7 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_value_free sqlite3_api->value_free
|
||||
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
||||
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
||||
/* Version 3.8.12 and later */
|
||||
/* Version 3.9.0 and later */
|
||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
+21
-6
@@ -196,6 +196,7 @@
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_byteswap_ushort)
|
||||
# pragma intrinsic(_byteswap_ulong)
|
||||
# pragma intrinsic(_ReadWriteBarrier)
|
||||
# else
|
||||
# include <cmnintrin.h>
|
||||
# endif
|
||||
@@ -1309,6 +1310,7 @@ struct sqlite3 {
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
||||
#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@@ -1917,6 +1919,12 @@ struct Index {
|
||||
/* Return true if index X is a UNIQUE index */
|
||||
#define IsUniqueIndex(X) ((X)->onError!=OE_None)
|
||||
|
||||
/* The Index.aiColumn[] values are normally positive integer. But
|
||||
** there are some negative values that have special meaning:
|
||||
*/
|
||||
#define XN_ROWID (-1) /* Indexed column is the rowid */
|
||||
#define XN_EXPR (-2) /* Indexed column is an expression */
|
||||
|
||||
/*
|
||||
** Each sample stored in the sqlite_stat3 table is represented in memory
|
||||
** using a structure of this type. See documentation at the top of the
|
||||
@@ -2787,7 +2795,8 @@ struct AuthContext {
|
||||
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
||||
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
|
||||
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
|
||||
#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
|
||||
#define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */
|
||||
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
|
||||
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
|
||||
|
||||
/*
|
||||
@@ -3016,6 +3025,7 @@ struct Walker {
|
||||
int iCur; /* A cursor number */
|
||||
SrcList *pSrcList; /* FROM clause */
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -3025,6 +3035,7 @@ int sqlite3WalkExprList(Walker*, ExprList*);
|
||||
int sqlite3WalkSelect(Walker*, Select*);
|
||||
int sqlite3WalkSelectExpr(Walker*, Select*);
|
||||
int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
int sqlite3ExprWalkNoop(Walker*, Expr*);
|
||||
|
||||
/*
|
||||
** Return code from the parse-tree walking primitives and their
|
||||
@@ -3156,7 +3167,7 @@ void *sqlite3PageMalloc(int);
|
||||
void sqlite3PageFree(void*);
|
||||
void sqlite3MemSetDefault(void);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
void sqlite3BenignMallocHooks(void (*)(int));
|
||||
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
|
||||
#endif
|
||||
int sqlite3HeapNearlyFull(void);
|
||||
|
||||
@@ -3202,7 +3213,7 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
||||
sqlite3_int64 sqlite3StatusValue(int);
|
||||
void sqlite3StatusUp(int, int);
|
||||
void sqlite3StatusDown(int, int);
|
||||
void sqlite3StatusSet(int, int);
|
||||
void sqlite3StatusHighwater(int, int);
|
||||
|
||||
/* Access to mutexes used by sqlite3_status() */
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
@@ -3386,6 +3397,7 @@ int sqlite3WhereOkOnePass(WhereInfo*, int*);
|
||||
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
|
||||
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
||||
void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
void sqlite3ExprCacheStore(Parse*, int, int, int);
|
||||
@@ -3440,6 +3452,9 @@ int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
int sqlite3ExprIsInteger(Expr*, int*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
@@ -3452,7 +3467,7 @@ void sqlite3ResolvePartIdxLabel(Parse*,int);
|
||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||
u8,u8,int,int*);
|
||||
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
|
||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
|
||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||
void sqlite3MultiWrite(Parse*);
|
||||
void sqlite3MayAbort(Parse*);
|
||||
@@ -3504,6 +3519,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
|
||||
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
|
||||
u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
|
||||
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
|
||||
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
|
||||
#else
|
||||
# define sqlite3TriggersExist(B,C,D,E,F) 0
|
||||
# define sqlite3DeleteTrigger(A,B)
|
||||
@@ -3513,6 +3529,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
|
||||
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
|
||||
# define sqlite3TriggerList(X, Y) 0
|
||||
# define sqlite3ParseToplevel(p) p
|
||||
# define sqlite3IsToplevel(p) 1
|
||||
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
|
||||
#endif
|
||||
|
||||
@@ -3836,11 +3853,9 @@ const char *sqlite3JournalModename(int);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
void sqlite3BeginBenignMalloc(void);
|
||||
void sqlite3EndBenignMalloc(void);
|
||||
void sqlite3PreviousBenignMalloc(void);
|
||||
#else
|
||||
#define sqlite3BeginBenignMalloc()
|
||||
#define sqlite3EndBenignMalloc()
|
||||
#define sqlite3PreviousBenignMalloc()
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
+23
-17
@@ -19,15 +19,15 @@
|
||||
/*
|
||||
** Variables in which to record status information.
|
||||
*/
|
||||
#if SQLITE_PTRSIZE>4
|
||||
typedef sqlite3_int64 sqlite3StatValueType;
|
||||
#else
|
||||
typedef u32 sqlite3StatValueType;
|
||||
#endif
|
||||
typedef struct sqlite3StatType sqlite3StatType;
|
||||
static SQLITE_WSD struct sqlite3StatType {
|
||||
#if SQLITE_PTRSIZE>4
|
||||
sqlite3_int64 nowValue[10]; /* Current value */
|
||||
sqlite3_int64 mxValue[10]; /* Maximum value */
|
||||
#else
|
||||
u32 nowValue[10]; /* Current value */
|
||||
u32 mxValue[10]; /* Maximum value */
|
||||
#endif
|
||||
sqlite3StatValueType nowValue[10]; /* Current value */
|
||||
sqlite3StatValueType mxValue[10]; /* Maximum value */
|
||||
} sqlite3Stat = { {0,}, {0,} };
|
||||
|
||||
/*
|
||||
@@ -108,18 +108,24 @@ void sqlite3StatusDown(int op, int N){
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the value of a status to X. The highwater mark is adjusted if
|
||||
** necessary. The caller must hold the appropriate mutex.
|
||||
** Adjust the highwater mark if necessary.
|
||||
** The caller must hold the appropriate mutex.
|
||||
*/
|
||||
void sqlite3StatusSet(int op, int X){
|
||||
void sqlite3StatusHighwater(int op, int X){
|
||||
sqlite3StatValueType newValue;
|
||||
wsdStatInit;
|
||||
assert( X>=0 );
|
||||
newValue = (sqlite3StatValueType)X;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] = X;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
assert( op==SQLITE_STATUS_MALLOC_SIZE
|
||||
|| op==SQLITE_STATUS_PAGECACHE_SIZE
|
||||
|| op==SQLITE_STATUS_SCRATCH_SIZE
|
||||
|| op==SQLITE_STATUS_PARSER_STACK );
|
||||
if( newValue>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,10 +258,10 @@ int sqlite3_db_status(
|
||||
+ pSchema->idxHash.count
|
||||
+ pSchema->fkeyHash.count
|
||||
);
|
||||
nByte += sqlite3MallocSize(pSchema->tblHash.ht);
|
||||
nByte += sqlite3MallocSize(pSchema->trigHash.ht);
|
||||
nByte += sqlite3MallocSize(pSchema->idxHash.ht);
|
||||
nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
|
||||
nByte += sqlite3_msize(pSchema->tblHash.ht);
|
||||
nByte += sqlite3_msize(pSchema->trigHash.ht);
|
||||
nByte += sqlite3_msize(pSchema->idxHash.ht);
|
||||
nByte += sqlite3_msize(pSchema->fkeyHash.ht);
|
||||
|
||||
for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
|
||||
sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
|
||||
|
||||
+34
-7
@@ -4688,6 +4688,34 @@ static int test_db_release_memory(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_db_cacheflush DB
|
||||
**
|
||||
** Attempt to flush any dirty pages to disk.
|
||||
*/
|
||||
static int test_db_cacheflush(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
rc = sqlite3_db_cacheflush(db);
|
||||
if( rc ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_db_filename DB DBNAME
|
||||
**
|
||||
@@ -6377,7 +6405,6 @@ static int tclLoadStaticExtensionCmd(
|
||||
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_json_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -6385,7 +6412,6 @@ static int tclLoadStaticExtensionCmd(
|
||||
extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fts5_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
static const struct {
|
||||
const char *zExtName;
|
||||
int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -6393,13 +6419,9 @@ static int tclLoadStaticExtensionCmd(
|
||||
{ "amatch", sqlite3_amatch_init },
|
||||
{ "closure", sqlite3_closure_init },
|
||||
{ "eval", sqlite3_eval_init },
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
{ "fts5", sqlite3_fts5_init },
|
||||
#endif
|
||||
{ "fileio", sqlite3_fileio_init },
|
||||
{ "fuzzer", sqlite3_fuzzer_init },
|
||||
{ "ieee754", sqlite3_ieee_init },
|
||||
{ "json", sqlite3_json_init },
|
||||
{ "nextchar", sqlite3_nextchar_init },
|
||||
{ "percentile", sqlite3_percentile_init },
|
||||
{ "regexp", sqlite3_regexp_init },
|
||||
@@ -6426,7 +6448,11 @@ static int tclLoadStaticExtensionCmd(
|
||||
Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = aExtension[i].pInit(db, &zErrMsg, 0);
|
||||
if( aExtension[i].pInit ){
|
||||
rc = aExtension[i].pInit(db, &zErrMsg, 0);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( rc!=SQLITE_OK || zErrMsg ){
|
||||
Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
|
||||
(char*)0);
|
||||
@@ -6878,6 +6904,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
|
||||
{ "sqlite3_release_memory", test_release_memory, 0},
|
||||
{ "sqlite3_db_release_memory", test_db_release_memory, 0},
|
||||
{ "sqlite3_db_cacheflush", test_db_cacheflush, 0},
|
||||
{ "sqlite3_db_filename", test_db_filename, 0},
|
||||
{ "sqlite3_db_readonly", test_db_readonly, 0},
|
||||
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
||||
|
||||
+46
-1
@@ -214,11 +214,12 @@ static int btree_cursor(
|
||||
pBt = sqlite3TestTextToPtr(argv[1]);
|
||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
|
||||
if( wrFlag ) wrFlag = BTREE_WRCSR;
|
||||
pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
|
||||
memset(pCur, 0, sqlite3BtreeCursorSize());
|
||||
sqlite3BtreeEnter(pBt);
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
|
||||
rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
|
||||
@@ -598,6 +599,48 @@ static int btree_set_cache_size(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** usage: btree_insert CSR ?KEY? VALUE
|
||||
**
|
||||
** Set the size of the cache used by btree $ID.
|
||||
*/
|
||||
static int btree_insert(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[]
|
||||
){
|
||||
BtCursor *pCur;
|
||||
int rc;
|
||||
void *pKey = 0;
|
||||
int nKey = 0;
|
||||
void *pData = 0;
|
||||
int nData = 0;
|
||||
|
||||
if( objc!=4 && objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( objc==4 ){
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &nKey) ) return TCL_ERROR;
|
||||
pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &nData);
|
||||
}else{
|
||||
pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
||||
}
|
||||
pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
|
||||
sqlite3BtreeEnter(pCur->pBtree);
|
||||
rc = sqlite3BtreeInsert(pCur, pKey, nKey, pData, nData, 0, 0, 0);
|
||||
sqlite3BtreeLeave(pCur->pBtree);
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -629,5 +672,7 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
|
||||
}
|
||||
|
||||
Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -119,6 +119,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -167,6 +173,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_ATTACH
|
||||
Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
+10
-24
@@ -169,27 +169,12 @@ static int faultsimPending(void){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL callback. The eOp argument means:
|
||||
**
|
||||
** 0: Leave benign malloc mode
|
||||
** 1: Enter benign malloc mode (may be nested)
|
||||
** 2: Make the previous malloc failure benign if it was not already so
|
||||
*/
|
||||
static void faultsimBenignCtrl(int eOp){
|
||||
switch( eOp ){
|
||||
case 0: /* Leave benign malloc mode */
|
||||
assert( memfault.isBenignMode>0 );
|
||||
memfault.isBenignMode--;
|
||||
break;
|
||||
case 1: /* Enter benign malloc mode */
|
||||
memfault.isBenignMode++;
|
||||
break;
|
||||
case 2: /* Previous failure is benign */
|
||||
assert( memfault.nFail>0 || memfault.enable==0 );
|
||||
if( memfault.isBenignMode==0 ) memfault.nBenign++;
|
||||
break;
|
||||
}
|
||||
|
||||
static void faultsimBeginBenign(void){
|
||||
memfault.isBenignMode++;
|
||||
}
|
||||
static void faultsimEndBenign(void){
|
||||
memfault.isBenignMode--;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -222,8 +207,9 @@ static int faultsimInstall(int install){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
|
||||
}
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL,
|
||||
faultsimBenignCtrl);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
|
||||
faultsimBeginBenign, faultsimEndBenign
|
||||
);
|
||||
}else{
|
||||
sqlite3_mem_methods m2;
|
||||
assert(memfault.m.xMalloc);
|
||||
@@ -236,7 +222,7 @@ static int faultsimInstall(int install){
|
||||
assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, 0);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+11
-2
@@ -67,6 +67,10 @@ int sqlite3ThreadCreate(
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->xTask = xTask;
|
||||
p->pIn = pIn;
|
||||
/* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
|
||||
** function that returns SQLITE_ERROR when passed the argument 200, that
|
||||
** forces worker threads to run sequentially and deterministically
|
||||
** for testing purposes. */
|
||||
if( sqlite3FaultSim(200) ){
|
||||
rc = 1;
|
||||
}else{
|
||||
@@ -151,7 +155,12 @@ int sqlite3ThreadCreate(
|
||||
*ppThread = 0;
|
||||
p = sqlite3Malloc(sizeof(*p));
|
||||
if( p==0 ) return SQLITE_NOMEM;
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0 ){
|
||||
/* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
|
||||
** function that returns SQLITE_ERROR when passed the argument 200, that
|
||||
** forces worker threads to run sequentially and deterministically
|
||||
** (via the sqlite3FaultSim() term of the conditional) for testing
|
||||
** purposes. */
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
|
||||
memset(p, 0, sizeof(*p));
|
||||
}else{
|
||||
p->xTask = xTask;
|
||||
@@ -179,7 +188,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
assert( ppOut!=0 );
|
||||
if( NEVER(p==0) ) return SQLITE_NOMEM;
|
||||
if( p->xTask==0 ){
|
||||
assert( p->id==GetCurrentThreadId() );
|
||||
/* assert( p->id==GetCurrentThreadId() ); */
|
||||
rc = WAIT_OBJECT_0;
|
||||
assert( p->tid==0 );
|
||||
}else{
|
||||
|
||||
+1
-1
@@ -467,7 +467,7 @@ abort_parse:
|
||||
}
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
sqlite3_mutex_enter(sqlite3MallocMutex());
|
||||
sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
|
||||
sqlite3ParserStackPeak(pEngine)
|
||||
);
|
||||
sqlite3_mutex_leave(sqlite3MallocMutex());
|
||||
|
||||
+116
-85
@@ -134,9 +134,9 @@ void sqlite3Update(
|
||||
|
||||
/* Register Allocations */
|
||||
int regRowCount = 0; /* A count of rows changed */
|
||||
int regOldRowid; /* The old rowid */
|
||||
int regNewRowid; /* The new rowid */
|
||||
int regNew; /* Content of the NEW.* table in triggers */
|
||||
int regOldRowid = 0; /* The old rowid */
|
||||
int regNewRowid = 0; /* The new rowid */
|
||||
int regNew = 0; /* Content of the NEW.* table in triggers */
|
||||
int regOld = 0; /* Content of OLD.* table in triggers */
|
||||
int regRowSet = 0; /* Rowset of rows to be updated */
|
||||
int regKey = 0; /* composite PRIMARY KEY value */
|
||||
@@ -300,29 +300,20 @@ void sqlite3Update(
|
||||
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Virtual tables must be handled separately */
|
||||
if( IsVirtual(pTab) ){
|
||||
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
|
||||
pWhere, onError);
|
||||
pWhere = 0;
|
||||
pTabList = 0;
|
||||
goto update_cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate required registers. */
|
||||
regRowSet = ++pParse->nMem;
|
||||
regOldRowid = regNewRowid = ++pParse->nMem;
|
||||
if( chngPk || pTrigger || hasFK ){
|
||||
regOld = pParse->nMem + 1;
|
||||
if( !IsVirtual(pTab) ){
|
||||
regRowSet = ++pParse->nMem;
|
||||
regOldRowid = regNewRowid = ++pParse->nMem;
|
||||
if( chngPk || pTrigger || hasFK ){
|
||||
regOld = pParse->nMem + 1;
|
||||
pParse->nMem += pTab->nCol;
|
||||
}
|
||||
if( chngKey || pTrigger || hasFK ){
|
||||
regNewRowid = ++pParse->nMem;
|
||||
}
|
||||
regNew = pParse->nMem + 1;
|
||||
pParse->nMem += pTab->nCol;
|
||||
}
|
||||
if( chngKey || pTrigger || hasFK ){
|
||||
regNewRowid = ++pParse->nMem;
|
||||
}
|
||||
regNew = pParse->nMem + 1;
|
||||
pParse->nMem += pTab->nCol;
|
||||
|
||||
/* Start the view context. */
|
||||
if( isView ){
|
||||
@@ -345,6 +336,15 @@ void sqlite3Update(
|
||||
goto update_cleanup;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Virtual tables must be handled separately */
|
||||
if( IsVirtual(pTab) ){
|
||||
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
|
||||
pWhere, onError);
|
||||
goto update_cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Begin the database scan
|
||||
*/
|
||||
if( HasRowid(pTab) ){
|
||||
@@ -384,7 +384,7 @@ void sqlite3Update(
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
for(i=0; i<nPk; i++){
|
||||
assert( pPk->aiColumn[i]>=(-1) );
|
||||
assert( pPk->aiColumn[i]>=0 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
|
||||
iPk+i);
|
||||
}
|
||||
@@ -429,7 +429,7 @@ void sqlite3Update(
|
||||
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
|
||||
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
@@ -507,7 +507,6 @@ void sqlite3Update(
|
||||
newmask = sqlite3TriggerColmask(
|
||||
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
||||
);
|
||||
/*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
@@ -523,7 +522,7 @@ void sqlite3Update(
|
||||
*/
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
||||
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
@@ -565,7 +564,7 @@ void sqlite3Update(
|
||||
}
|
||||
|
||||
if( !isView ){
|
||||
int j1 = 0; /* Address of jump instruction */
|
||||
int addr1 = 0; /* Address of jump instruction */
|
||||
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
|
||||
|
||||
/* Do constraint checks. */
|
||||
@@ -581,9 +580,9 @@ void sqlite3Update(
|
||||
/* Delete the index entries associated with the current record. */
|
||||
if( bReplace || chngKey ){
|
||||
if( pPk ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
||||
addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
||||
}else{
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
||||
addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
||||
}
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
@@ -594,7 +593,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
|
||||
}
|
||||
if( bReplace || chngKey ){
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}
|
||||
|
||||
if( hasFK ){
|
||||
@@ -685,21 +684,23 @@ update_cleanup:
|
||||
/*
|
||||
** Generate code for an UPDATE of a virtual table.
|
||||
**
|
||||
** The strategy is that we create an ephemeral table that contains
|
||||
** There are two possible strategies - the default and the special
|
||||
** "onepass" strategy. Onepass is only used if the virtual table
|
||||
** implementation indicates that pWhere may match at most one row.
|
||||
**
|
||||
** The default strategy is to create an ephemeral table that contains
|
||||
** for each row to be changed:
|
||||
**
|
||||
** (A) The original rowid of that row.
|
||||
** (B) The revised rowid for the row. (note1)
|
||||
** (B) The revised rowid for the row.
|
||||
** (C) The content of every column in the row.
|
||||
**
|
||||
** Then we loop over this ephemeral table and for each row in
|
||||
** the ephemeral table call VUpdate.
|
||||
** Then loop through the contents of this ephemeral table executing a
|
||||
** VUpdate for each row. When finished, drop the ephemeral table.
|
||||
**
|
||||
** When finished, drop the ephemeral table.
|
||||
**
|
||||
** (note1) Actually, if we know in advance that (A) is always the same
|
||||
** as (B) we only store (A), then duplicate (A) when pulling
|
||||
** it out of the ephemeral table before calling VUpdate.
|
||||
** The "onepass" strategy does not use an ephemeral table. Instead, it
|
||||
** stores the same values (A, B and C above) in a register array and
|
||||
** makes a single invocation of VUpdate.
|
||||
*/
|
||||
static void updateVirtualTable(
|
||||
Parse *pParse, /* The parsing context */
|
||||
@@ -712,65 +713,95 @@ static void updateVirtualTable(
|
||||
int onError /* ON CONFLICT strategy */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
|
||||
ExprList *pEList = 0; /* The result set of the SELECT statement */
|
||||
Select *pSelect = 0; /* The SELECT statement */
|
||||
Expr *pExpr; /* Temporary expression */
|
||||
int ephemTab; /* Table holding the result of the SELECT */
|
||||
int i; /* Loop counter */
|
||||
int addr; /* Address of top of loop */
|
||||
int iReg; /* First register in set passed to OP_VUpdate */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
|
||||
SelectDest dest;
|
||||
WhereInfo *pWInfo;
|
||||
int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */
|
||||
int regArg; /* First register in VUpdate arg array */
|
||||
int regRec; /* Register in which to assemble record */
|
||||
int regRowid; /* Register for ephem table rowid */
|
||||
int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */
|
||||
int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */
|
||||
int bOnePass; /* True to use onepass strategy */
|
||||
int addr; /* Address of OP_OpenEphemeral */
|
||||
|
||||
/* Construct the SELECT statement that will find the new values for
|
||||
** all updated rows.
|
||||
*/
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_"));
|
||||
if( pRowid ){
|
||||
pEList = sqlite3ExprListAppend(pParse, pEList,
|
||||
sqlite3ExprDup(db, pRowid, 0));
|
||||
}
|
||||
assert( pTab->iPKey<0 );
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( aXRef[i]>=0 ){
|
||||
pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0);
|
||||
}else{
|
||||
pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName);
|
||||
}
|
||||
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
|
||||
}
|
||||
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
/* Create the ephemeral table into which the update results will
|
||||
** be stored.
|
||||
*/
|
||||
/* Allocate nArg registers to martial the arguments to VUpdate. Then
|
||||
** create and open the ephemeral table in which the records created from
|
||||
** these arguments will be temporarily stored. */
|
||||
assert( v );
|
||||
ephemTab = pParse->nTab++;
|
||||
addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
|
||||
regArg = pParse->nMem + 1;
|
||||
pParse->nMem += nArg;
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
|
||||
/* fill the ephemeral table
|
||||
*/
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab);
|
||||
sqlite3Select(pParse, pSelect, &dest);
|
||||
/* Start scanning the virtual table */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
|
||||
if( pWInfo==0 ) return;
|
||||
|
||||
/* Generate code to scan the ephemeral table and call VUpdate. */
|
||||
iReg = ++pParse->nMem;
|
||||
pParse->nMem += pTab->nCol+1;
|
||||
addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
|
||||
/* Populate the argument registers. */
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
|
||||
if( pRowid ){
|
||||
sqlite3ExprCode(pParse, pRowid, regArg+1);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
|
||||
}
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
|
||||
if( aXRef[i]>=0 ){
|
||||
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
|
||||
}
|
||||
}
|
||||
|
||||
bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
|
||||
|
||||
if( bOnePass ){
|
||||
/* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
|
||||
** above. Also, if this is a top-level parse (not a trigger), clear the
|
||||
** multi-write flag so that the VM does not open a statement journal */
|
||||
sqlite3VdbeChangeToNoop(v, addr);
|
||||
if( sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
}
|
||||
}else{
|
||||
/* Create a record from the argument register contents and insert it into
|
||||
** the ephemeral table. */
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
|
||||
}
|
||||
|
||||
|
||||
if( bOnePass==0 ){
|
||||
/* End the virtual table scan */
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
/* Begin scannning through the ephemeral table. */
|
||||
addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v);
|
||||
|
||||
/* Extract arguments from the current row of the ephemeral table and
|
||||
** invoke the VUpdate method. */
|
||||
for(i=0; i<nArg; i++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i);
|
||||
}
|
||||
}
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
|
||||
sqlite3MayAbort(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
|
||||
|
||||
/* Cleanup */
|
||||
sqlite3SelectDelete(db, pSelect);
|
||||
/* End of the ephemeral table scan. Or, if using the onepass strategy,
|
||||
** jump to here if the scan visited zero rows. */
|
||||
if( bOnePass==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
|
||||
}else{
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
+112
-71
@@ -518,16 +518,24 @@ static int checkSavepointCount(sqlite3 *db){
|
||||
/*
|
||||
** Return the register of pOp->p2 after first preparing it to be
|
||||
** overwritten with an integer value.
|
||||
*/
|
||||
*/
|
||||
static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
pOut->flags = MEM_Int;
|
||||
return pOut;
|
||||
}
|
||||
static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
|
||||
Mem *pOut;
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=(p->nMem-p->nCursor) );
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
memAboutToChange(p, pOut);
|
||||
if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
|
||||
pOut->flags = MEM_Int;
|
||||
return pOut;
|
||||
if( VdbeMemDynamic(pOut) ){
|
||||
return out2PrereleaseWithClear(pOut);
|
||||
}else{
|
||||
pOut->flags = MEM_Int;
|
||||
return pOut;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1265,6 +1273,22 @@ case OP_SCopy: { /* out2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IntCopy P1 P2 * * *
|
||||
** Synopsis: r[P2]=r[P1]
|
||||
**
|
||||
** Transfer the integer value held in register P1 into register P2.
|
||||
**
|
||||
** This is an optimized version of SCopy that works only for integer
|
||||
** values.
|
||||
*/
|
||||
case OP_IntCopy: { /* out2 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Int)!=0 );
|
||||
pOut = &aMem[pOp->p2];
|
||||
sqlite3VdbeMemSetInt64(pOut, pIn1->u.i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ResultRow P1 P2 * * *
|
||||
** Synopsis: output=r[P1@P2]
|
||||
**
|
||||
@@ -2344,7 +2368,7 @@ case OP_Column: {
|
||||
const u8 *zHdr; /* Next unparsed byte of the header */
|
||||
const u8 *zEndHdr; /* Pointer to first byte after the header */
|
||||
u32 offset; /* Offset into the data */
|
||||
u32 szField; /* Number of bytes in the content of a field */
|
||||
u64 offset64; /* 64-bit offset */
|
||||
u32 avail; /* Number of bytes of available data */
|
||||
u32 t; /* A type code from the record header */
|
||||
u16 fx; /* pDest->flags value */
|
||||
@@ -2415,19 +2439,6 @@ case OP_Column: {
|
||||
pC->nHdrParsed = 0;
|
||||
aOffset[0] = offset;
|
||||
|
||||
/* Make sure a corrupt database has not given us an oversize header.
|
||||
** Do this now to avoid an oversize memory allocation.
|
||||
**
|
||||
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
|
||||
** types use so much data space that there can only be 4096 and 32 of
|
||||
** them, respectively. So the maximum header length results from a
|
||||
** 3-byte type for each of the maximum of 32768 columns plus three
|
||||
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
|
||||
*/
|
||||
if( offset > 98307 || offset > pC->payloadSize ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto op_column_error;
|
||||
}
|
||||
|
||||
if( avail<offset ){
|
||||
/* pC->aRow does not have to hold the entire row, but it does at least
|
||||
@@ -2436,6 +2447,20 @@ case OP_Column: {
|
||||
** dynamically allocated. */
|
||||
pC->aRow = 0;
|
||||
pC->szRow = 0;
|
||||
|
||||
/* Make sure a corrupt database has not given us an oversize header.
|
||||
** Do this now to avoid an oversize memory allocation.
|
||||
**
|
||||
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
|
||||
** types use so much data space that there can only be 4096 and 32 of
|
||||
** them, respectively. So the maximum header length results from a
|
||||
** 3-byte type for each of the maximum of 32768 columns plus three
|
||||
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
|
||||
*/
|
||||
if( offset > 98307 || offset > pC->payloadSize ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto op_column_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* The following goto is an optimization. It can be omitted and
|
||||
@@ -2458,11 +2483,8 @@ case OP_Column: {
|
||||
/* Make sure zData points to enough of the record to cover the header. */
|
||||
if( pC->aRow==0 ){
|
||||
memset(&sMem, 0, sizeof(sMem));
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0],
|
||||
!pC->isTable, &sMem);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto op_column_error;
|
||||
}
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem);
|
||||
if( rc!=SQLITE_OK ) goto op_column_error;
|
||||
zData = (u8*)sMem.z;
|
||||
}else{
|
||||
zData = pC->aRow;
|
||||
@@ -2470,44 +2492,32 @@ case OP_Column: {
|
||||
|
||||
/* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
|
||||
i = pC->nHdrParsed;
|
||||
offset = aOffset[i];
|
||||
offset64 = aOffset[i];
|
||||
zHdr = zData + pC->iHdrOffset;
|
||||
zEndHdr = zData + aOffset[0];
|
||||
assert( i<=p2 && zHdr<zEndHdr );
|
||||
do{
|
||||
if( zHdr[0]<0x80 ){
|
||||
t = zHdr[0];
|
||||
if( (t = zHdr[0])<0x80 ){
|
||||
zHdr++;
|
||||
offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
|
||||
}else{
|
||||
zHdr += sqlite3GetVarint32(zHdr, &t);
|
||||
offset64 += sqlite3VdbeSerialTypeLen(t);
|
||||
}
|
||||
pC->aType[i] = t;
|
||||
szField = sqlite3VdbeSerialTypeLen(t);
|
||||
offset += szField;
|
||||
if( offset<szField ){ /* True if offset overflows */
|
||||
zHdr = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
aOffset[i] = offset;
|
||||
pC->aType[i++] = t;
|
||||
aOffset[i] = (u32)(offset64 & 0xffffffff);
|
||||
}while( i<=p2 && zHdr<zEndHdr );
|
||||
pC->nHdrParsed = i;
|
||||
pC->iHdrOffset = (u32)(zHdr - zData);
|
||||
if( pC->aRow==0 ){
|
||||
sqlite3VdbeMemRelease(&sMem);
|
||||
sMem.flags = MEM_Null;
|
||||
}
|
||||
if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
|
||||
|
||||
/* The record is corrupt if any of the following are true:
|
||||
** (1) the bytes of the header extend past the declared header size
|
||||
** (zHdr>zEndHdr)
|
||||
** (2) the entire header was used but not all data was used
|
||||
** (zHdr==zEndHdr && offset!=pC->payloadSize)
|
||||
** (3) the end of the data extends beyond the end of the record.
|
||||
** (offset > pC->payloadSize)
|
||||
*/
|
||||
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset!=pC->payloadSize))
|
||||
|| (offset > pC->payloadSize)
|
||||
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
|
||||
|| (offset64 > pC->payloadSize)
|
||||
){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto op_column_error;
|
||||
@@ -2526,6 +2536,8 @@ case OP_Column: {
|
||||
}
|
||||
goto op_column_out;
|
||||
}
|
||||
}else{
|
||||
t = pC->aType[p2];
|
||||
}
|
||||
|
||||
/* Extract the content for the p2+1-th column. Control can only
|
||||
@@ -2536,7 +2548,7 @@ case OP_Column: {
|
||||
assert( rc==SQLITE_OK );
|
||||
assert( sqlite3VdbeCheckMemInvariants(pDest) );
|
||||
if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
|
||||
t = pC->aType[p2];
|
||||
assert( t==pC->aType[p2] );
|
||||
if( pC->szRow>=aOffset[p2+1] ){
|
||||
/* This is the common case where the desired content fits on the original
|
||||
** page - where the content is not on an overflow page */
|
||||
@@ -2648,7 +2660,7 @@ case OP_MakeRecord: {
|
||||
int file_format; /* File format to use for encoding */
|
||||
int i; /* Space used in zNewRecord[] header */
|
||||
int j; /* Space used in zNewRecord[] content */
|
||||
int len; /* Length of a field */
|
||||
u32 len; /* Length of a field */
|
||||
|
||||
/* Assuming the record contains N fields, the record format looks
|
||||
** like this:
|
||||
@@ -2698,8 +2710,7 @@ case OP_MakeRecord: {
|
||||
pRec = pLast;
|
||||
do{
|
||||
assert( memIsValid(pRec) );
|
||||
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format);
|
||||
len = sqlite3VdbeSerialTypeLen(serial_type);
|
||||
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
||||
if( pRec->flags & MEM_Zero ){
|
||||
if( nData ){
|
||||
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
|
||||
@@ -3313,7 +3324,6 @@ case OP_ReopenIdx: {
|
||||
case OP_OpenRead:
|
||||
case OP_OpenWrite:
|
||||
|
||||
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
|
||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
|
||||
assert( p->bIsReader );
|
||||
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|
||||
@@ -3334,7 +3344,8 @@ case OP_OpenWrite:
|
||||
pX = pDb->pBt;
|
||||
assert( pX!=0 );
|
||||
if( pOp->opcode==OP_OpenWrite ){
|
||||
wrFlag = 1;
|
||||
assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
|
||||
wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
||||
p->minWriteFileFormat = pDb->pSchema->file_format;
|
||||
@@ -3386,8 +3397,12 @@ case OP_OpenWrite:
|
||||
open_cursor_set_hints:
|
||||
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
||||
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
|
||||
sqlite3BtreeCursorHints(pCur->pCursor,
|
||||
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
|
||||
testcase( pOp->p5 & OPFLAG_BULKCSR );
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINT
|
||||
testcase( pOp->p2 & OPFLAG_SEEKEQ );
|
||||
#endif
|
||||
sqlite3BtreeCursorHintFlags(pCur->pCursor,
|
||||
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3454,11 +3469,11 @@ case OP_OpenEphemeral: {
|
||||
assert( pKeyInfo->db==db );
|
||||
assert( pKeyInfo->enc==ENC(db) );
|
||||
pCx->pKeyInfo = pKeyInfo;
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, pKeyInfo, pCx->pCursor);
|
||||
}
|
||||
pCx->isTable = 0;
|
||||
}else{
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, 0, pCx->pCursor);
|
||||
pCx->isTable = 1;
|
||||
}
|
||||
}
|
||||
@@ -5671,12 +5686,12 @@ case OP_MemMax: { /* in2 */
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||
|
||||
/* Opcode: IfPos P1 P2 * * *
|
||||
** Synopsis: if r[P1]>0 goto P2
|
||||
/* Opcode: IfPos P1 P2 P3 * *
|
||||
** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
|
||||
**
|
||||
** Register P1 must contain an integer.
|
||||
** If the value of register P1 is 1 or greater, jump to P2 and
|
||||
** add the literal value P3 to register P1.
|
||||
** If the value of register P1 is 1 or greater, subtract P3 from the
|
||||
** value in P1 and jump to P2.
|
||||
**
|
||||
** If the initial value of register P1 is less than 1, then the
|
||||
** value is unchanged and control passes through to the next instruction.
|
||||
@@ -5685,38 +5700,44 @@ case OP_IfPos: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
VdbeBranchTaken( pIn1->u.i>0, 2);
|
||||
if( pIn1->u.i>0 ) goto jump_to_p2;
|
||||
if( pIn1->u.i>0 ){
|
||||
pIn1->u.i -= pOp->p3;
|
||||
goto jump_to_p2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfNeg P1 P2 P3 * *
|
||||
** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
|
||||
/* Opcode: SetIfNotPos P1 P2 P3 * *
|
||||
** Synopsis: if r[P1]<=0 then r[P2]=P3
|
||||
**
|
||||
** Register P1 must contain an integer. Add literal P3 to the value in
|
||||
** register P1 then if the value of register P1 is less than zero, jump to P2.
|
||||
** Register P1 must contain an integer.
|
||||
** If the value of register P1 is not positive (if it is less than 1) then
|
||||
** set the value of register P2 to be the integer P3.
|
||||
*/
|
||||
case OP_IfNeg: { /* jump, in1 */
|
||||
case OP_SetIfNotPos: { /* in1, in2 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
pIn1->u.i += pOp->p3;
|
||||
VdbeBranchTaken(pIn1->u.i<0, 2);
|
||||
if( pIn1->u.i<0 ) goto jump_to_p2;
|
||||
if( pIn1->u.i<=0 ){
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
pOut->u.i = pOp->p3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfNotZero P1 P2 P3 * *
|
||||
** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
|
||||
** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
|
||||
**
|
||||
** Register P1 must contain an integer. If the content of register P1 is
|
||||
** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
|
||||
** initially zero, leave it unchanged and fall through.
|
||||
** initially nonzero, then subtract P3 from the value in register P1 and
|
||||
** jump to P2. If register P1 is initially zero, leave it unchanged
|
||||
** and fall through.
|
||||
*/
|
||||
case OP_IfNotZero: { /* jump, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags&MEM_Int );
|
||||
VdbeBranchTaken(pIn1->u.i<0, 2);
|
||||
if( pIn1->u.i ){
|
||||
pIn1->u.i += pOp->p3;
|
||||
pIn1->u.i -= pOp->p3;
|
||||
goto jump_to_p2;
|
||||
}
|
||||
break;
|
||||
@@ -6570,6 +6591,26 @@ case OP_Init: { /* jump */
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
/* Opcode: CursorHint P1 * * P4 *
|
||||
**
|
||||
** Provide a hint to cursor P1 that it only needs to return rows that
|
||||
** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
|
||||
** to values currently held in registers. TK_COLUMN terms in the P4
|
||||
** expression refer to columns in the b-tree to which cursor P1 is pointing.
|
||||
*/
|
||||
case OP_CursorHint: {
|
||||
VdbeCursor *pC;
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p4type==P4_EXPR );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
if( pC ){
|
||||
sqlite3BtreeCursorHint(pC->pCursor, BTREE_HINT_RANGE, pOp->p4.pExpr, aMem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||
|
||||
/* Opcode: Noop * * * * *
|
||||
**
|
||||
|
||||
@@ -60,6 +60,9 @@ struct VdbeOp {
|
||||
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
|
||||
int *ai; /* Used when p4type is P4_INTARRAY */
|
||||
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
Expr *pExpr; /* Used when p4type is P4_EXPR */
|
||||
#endif
|
||||
int (*xAdvance)(BtCursor *, int *);
|
||||
} p4;
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
@@ -110,6 +113,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
|
||||
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
|
||||
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
|
||||
#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */
|
||||
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
|
||||
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
||||
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
||||
|
||||
+13
-1
@@ -26,6 +26,17 @@
|
||||
# define SQLITE_MAX_SCHEMA_RETRY 50
|
||||
#endif
|
||||
|
||||
/*
|
||||
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
|
||||
** "explain" P4 display logic is enabled.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|
||||
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
||||
# define VDBE_DISPLAY_P4 1
|
||||
#else
|
||||
# define VDBE_DISPLAY_P4 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** SQL is translated into a sequence of instructions to be
|
||||
** executed by a virtual machine. Each instruction is an instance
|
||||
@@ -412,7 +423,8 @@ int sqlite3VdbeCursorRestore(VdbeCursor*);
|
||||
void sqlite3VdbePrintOp(FILE*, int, Op*);
|
||||
#endif
|
||||
u32 sqlite3VdbeSerialTypeLen(u32);
|
||||
u32 sqlite3VdbeSerialType(Mem*, int);
|
||||
u8 sqlite3VdbeOneByteSerialTypeLen(u8);
|
||||
u32 sqlite3VdbeSerialType(Mem*, int, u32*);
|
||||
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
|
||||
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
|
||||
|
||||
+140
-14
@@ -763,6 +763,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
|
||||
break;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
case P4_EXPR: {
|
||||
sqlite3ExprDelete(db, (Expr*)p4);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case P4_MPRINTF: {
|
||||
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
||||
break;
|
||||
@@ -895,6 +901,15 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
|
||||
}else if( n==P4_KEYINFO ){
|
||||
pOp->p4.p = (void*)zP4;
|
||||
pOp->p4type = P4_KEYINFO;
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
}else if( n==P4_EXPR ){
|
||||
/* Responsibility for deleting the Expr tree is handed over to the
|
||||
** VDBE by this operation. The caller should have already invoked
|
||||
** sqlite3ExprDup() or whatever other routine is needed to make a
|
||||
** private copy of the tree. */
|
||||
pOp->p4.pExpr = (Expr*)zP4;
|
||||
pOp->p4type = P4_EXPR;
|
||||
#endif
|
||||
}else if( n==P4_VTAB ){
|
||||
pOp->p4.p = (void*)zP4;
|
||||
pOp->p4type = P4_VTAB;
|
||||
@@ -1085,9 +1100,84 @@ static int displayComment(
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
|
||||
/*
|
||||
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
|
||||
** that can be displayed in the P4 column of EXPLAIN output.
|
||||
*/
|
||||
static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){
|
||||
const char *zOp = 0;
|
||||
int n;
|
||||
switch( pExpr->op ){
|
||||
case TK_STRING:
|
||||
sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken);
|
||||
break;
|
||||
case TK_INTEGER:
|
||||
sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue);
|
||||
break;
|
||||
case TK_NULL:
|
||||
sqlite3_snprintf(nTemp, zTemp, "NULL");
|
||||
break;
|
||||
case TK_REGISTER: {
|
||||
sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable);
|
||||
break;
|
||||
}
|
||||
case TK_COLUMN: {
|
||||
if( pExpr->iColumn<0 ){
|
||||
sqlite3_snprintf(nTemp, zTemp, "rowid");
|
||||
}else{
|
||||
sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_LT: zOp = "LT"; break;
|
||||
case TK_LE: zOp = "LE"; break;
|
||||
case TK_GT: zOp = "GT"; break;
|
||||
case TK_GE: zOp = "GE"; break;
|
||||
case TK_NE: zOp = "NE"; break;
|
||||
case TK_EQ: zOp = "EQ"; break;
|
||||
case TK_IS: zOp = "IS"; break;
|
||||
case TK_ISNOT: zOp = "ISNOT"; break;
|
||||
case TK_AND: zOp = "AND"; break;
|
||||
case TK_OR: zOp = "OR"; break;
|
||||
case TK_PLUS: zOp = "ADD"; break;
|
||||
case TK_STAR: zOp = "MUL"; break;
|
||||
case TK_MINUS: zOp = "SUB"; break;
|
||||
case TK_REM: zOp = "REM"; break;
|
||||
case TK_BITAND: zOp = "BITAND"; break;
|
||||
case TK_BITOR: zOp = "BITOR"; break;
|
||||
case TK_SLASH: zOp = "DIV"; break;
|
||||
case TK_LSHIFT: zOp = "LSHIFT"; break;
|
||||
case TK_RSHIFT: zOp = "RSHIFT"; break;
|
||||
case TK_CONCAT: zOp = "CONCAT"; break;
|
||||
case TK_UMINUS: zOp = "MINUS"; break;
|
||||
case TK_UPLUS: zOp = "PLUS"; break;
|
||||
case TK_BITNOT: zOp = "BITNOT"; break;
|
||||
case TK_NOT: zOp = "NOT"; break;
|
||||
case TK_ISNULL: zOp = "ISNULL"; break;
|
||||
case TK_NOTNULL: zOp = "NOTNULL"; break;
|
||||
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|
||||
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
||||
default:
|
||||
sqlite3_snprintf(nTemp, zTemp, "%s", "expr");
|
||||
break;
|
||||
}
|
||||
|
||||
if( zOp ){
|
||||
sqlite3_snprintf(nTemp, zTemp, "%s(", zOp);
|
||||
n = sqlite3Strlen30(zTemp);
|
||||
n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft);
|
||||
if( n<nTemp-1 && pExpr->pRight ){
|
||||
zTemp[n++] = ',';
|
||||
n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight);
|
||||
}
|
||||
sqlite3_snprintf(nTemp-n, zTemp+n, ")");
|
||||
}
|
||||
return sqlite3Strlen30(zTemp);
|
||||
}
|
||||
#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */
|
||||
|
||||
|
||||
#if VDBE_DISPLAY_P4
|
||||
/*
|
||||
** Compute a string that describes the P4 parameter for an opcode.
|
||||
** Use zTemp for any required temporary buffer space.
|
||||
@@ -1127,6 +1217,12 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
assert( i<nTemp );
|
||||
break;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
case P4_EXPR: {
|
||||
displayP4Expr(nTemp, zTemp, pOp->p4.pExpr);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case P4_COLLSEQ: {
|
||||
CollSeq *pColl = pOp->p4.pColl;
|
||||
sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
|
||||
@@ -1202,7 +1298,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
assert( zP4!=0 );
|
||||
return zP4;
|
||||
}
|
||||
#endif
|
||||
#endif /* VDBE_DISPLAY_P4 */
|
||||
|
||||
/*
|
||||
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
|
||||
@@ -1516,12 +1612,12 @@ int sqlite3VdbeList(
|
||||
pMem->u.i = pOp->p3; /* P3 */
|
||||
pMem++;
|
||||
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, 32) ){ /* P4 */
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
zP4 = displayP4(pOp, pMem->z, 32);
|
||||
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
|
||||
if( zP4!=pMem->z ){
|
||||
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
||||
}else{
|
||||
@@ -2940,11 +3036,13 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
|
||||
/*
|
||||
** Return the serial-type for the value stored in pMem.
|
||||
*/
|
||||
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
|
||||
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
|
||||
int flags = pMem->flags;
|
||||
u32 n;
|
||||
|
||||
assert( pLen!=0 );
|
||||
if( flags&MEM_Null ){
|
||||
*pLen = 0;
|
||||
return 0;
|
||||
}
|
||||
if( flags&MEM_Int ){
|
||||
@@ -2958,15 +3056,23 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
|
||||
u = i;
|
||||
}
|
||||
if( u<=127 ){
|
||||
return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
|
||||
if( (i&1)==i && file_format>=4 ){
|
||||
*pLen = 0;
|
||||
return 8+(u32)u;
|
||||
}else{
|
||||
*pLen = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( u<=32767 ) return 2;
|
||||
if( u<=8388607 ) return 3;
|
||||
if( u<=2147483647 ) return 4;
|
||||
if( u<=MAX_6BYTE ) return 5;
|
||||
if( u<=32767 ){ *pLen = 2; return 2; }
|
||||
if( u<=8388607 ){ *pLen = 3; return 3; }
|
||||
if( u<=2147483647 ){ *pLen = 4; return 4; }
|
||||
if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
|
||||
*pLen = 8;
|
||||
return 6;
|
||||
}
|
||||
if( flags&MEM_Real ){
|
||||
*pLen = 8;
|
||||
return 7;
|
||||
}
|
||||
assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
|
||||
@@ -2975,26 +3081,46 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
|
||||
if( flags & MEM_Zero ){
|
||||
n += pMem->u.nZero;
|
||||
}
|
||||
*pLen = n;
|
||||
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
|
||||
}
|
||||
|
||||
/*
|
||||
** The sizes for serial types less than 12
|
||||
** The sizes for serial types less than 128
|
||||
*/
|
||||
static const u8 sqlite3SmallTypeSizes[] = {
|
||||
0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0
|
||||
/* 0 1 2 3 4 5 6 7 8 9 */
|
||||
/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
|
||||
/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
|
||||
/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
|
||||
/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
|
||||
/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
|
||||
/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
|
||||
/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
|
||||
/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33,
|
||||
/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
|
||||
/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43,
|
||||
/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48,
|
||||
/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53,
|
||||
/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57
|
||||
};
|
||||
|
||||
/*
|
||||
** Return the length of the data corresponding to the supplied serial-type.
|
||||
*/
|
||||
u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
|
||||
if( serial_type>=12 ){
|
||||
if( serial_type>=128 ){
|
||||
return (serial_type-12)/2;
|
||||
}else{
|
||||
assert( serial_type<12
|
||||
|| sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 );
|
||||
return sqlite3SmallTypeSizes[serial_type];
|
||||
}
|
||||
}
|
||||
u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
|
||||
assert( serial_type<128 );
|
||||
return sqlite3SmallTypeSizes[serial_type];
|
||||
}
|
||||
|
||||
/*
|
||||
** If we are on an architecture with mixed-endian floating
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ int sqlite3_blob_open(
|
||||
int j;
|
||||
for(j=0; j<pIdx->nKeyCol; j++){
|
||||
/* FIXME: Be smarter about indexes that use expressions */
|
||||
if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==(-2) ){
|
||||
if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){
|
||||
zFault = "indexed";
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user