Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 311e951d7e | |||
| b0df963465 | |||
| f170ea44d4 | |||
| 04ce31fafe | |||
| a649776664 | |||
| 0b086403b4 | |||
| 1cfc44392c | |||
| 49472655d4 | |||
| b9e8f59b63 | |||
| be37c12423 | |||
| faf3727904 | |||
| 95fa606616 | |||
| 848a3326f7 | |||
| c24658b5d7 | |||
| c6ce388301 | |||
| ce78bc6e7e | |||
| fed7ac6f04 | |||
| 9eef8c6934 | |||
| 59a052359d | |||
| 039ca6ab59 | |||
| b02392e6f0 | |||
| 9676c48199 | |||
| 8873996b7b | |||
| 460cd9ccfd | |||
| 5f93ccd7fc | |||
| cdabd7bd50 | |||
| 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 | |||
| 4ad0971919 |
@@ -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
|
||||
+32
-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_SHELL_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,13 +611,14 @@ 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
|
||||
@@ -899,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
|
||||
@@ -990,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 = \
|
||||
@@ -1096,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
|
||||
|
||||
+67
-52
@@ -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
|
||||
@@ -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
|
||||
@@ -1210,11 +1215,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 +1234,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 +1274,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 +1282,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 +1317,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 +1338,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 +1575,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 +1604,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 +1738,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 +1769,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 +1789,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 +1804,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 +1873,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
|
||||
|
||||
+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;
|
||||
|
||||
+15
-8
@@ -1322,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 );
|
||||
}
|
||||
@@ -1569,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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
+33
-10
@@ -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
|
||||
@@ -240,7 +254,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 +265,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 +317,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 +333,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 +345,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 +383,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 +448,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.
|
||||
**************************************************************************/
|
||||
@@ -526,7 +549,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 +589,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 +656,9 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
Fts5ExprPhrase*
|
||||
);
|
||||
|
||||
Fts5ExprColset *sqlite3Fts5ParseColset(
|
||||
Fts5Colset *sqlite3Fts5ParseColset(
|
||||
Fts5Parse*,
|
||||
Fts5ExprColset*,
|
||||
Fts5Colset*,
|
||||
Fts5Token *
|
||||
);
|
||||
|
||||
@@ -644,7 +667,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;
|
||||
}
|
||||
|
||||
+17
-20
@@ -92,7 +92,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 +185,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 +203,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 +227,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==sqlite3Fts5BufferGrow(&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 +264,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 +286,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];
|
||||
|
||||
+362
-111
@@ -291,7 +291,7 @@ struct Fts5Index {
|
||||
int nMaxPendingData; /* Max pending data before flush to disk */
|
||||
int nPendingData; /* Current bytes of pending data */
|
||||
i64 iWriteRowid; /* Rowid for current doc being written */
|
||||
Fts5Buffer scratch;
|
||||
int bDelete; /* Current write is a delete */
|
||||
|
||||
/* Error state. */
|
||||
int rc; /* Current error code */
|
||||
@@ -307,14 +307,13 @@ struct Fts5Index {
|
||||
};
|
||||
|
||||
struct Fts5DoclistIter {
|
||||
u8 *a;
|
||||
int n;
|
||||
int i;
|
||||
u8 *aEof; /* Pointer to 1 byte past end of doclist */
|
||||
|
||||
/* Output variables. aPoslist==0 at EOF */
|
||||
i64 iRowid;
|
||||
u8 *aPoslist;
|
||||
int nPoslist;
|
||||
int nSize;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -512,8 +511,9 @@ struct Fts5IndexIter {
|
||||
|
||||
int nSeg; /* Size of aSeg[] array */
|
||||
int bRev; /* True to iterate in reverse order */
|
||||
int bSkipEmpty; /* True to skip deleted entries */
|
||||
int bEof; /* True at EOF */
|
||||
u8 bSkipEmpty; /* True to skip deleted entries */
|
||||
u8 bEof; /* True at EOF */
|
||||
u8 bFiltered; /* True if column-filter already applied */
|
||||
|
||||
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
|
||||
Fts5CResult *aFirst; /* Current merge state (see above) */
|
||||
@@ -1458,7 +1458,8 @@ static void fts5SegIterNextPage(
|
||||
*/
|
||||
static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){
|
||||
int nSz;
|
||||
int n = fts5GetVarint32(p, nSz);
|
||||
int n = 0;
|
||||
fts5FastGetVarint32(p, n, nSz);
|
||||
assert_nc( nSz>=0 );
|
||||
*pnSz = nSz/2;
|
||||
*pbDel = nSz & 0x0001;
|
||||
@@ -1479,13 +1480,12 @@ static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){
|
||||
static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
int iOff = pIter->iLeafOffset; /* Offset to read at */
|
||||
int nSz;
|
||||
ASSERT_SZLEAF_OK(pIter->pLeaf);
|
||||
if( iOff>=pIter->pLeaf->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
const u8 *a = &pIter->pLeaf->p[iOff];
|
||||
pIter->iLeafOffset += fts5GetPoslistSize(a, &pIter->nPos, &pIter->bDel);
|
||||
}
|
||||
fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
|
||||
pIter->bDel = (nSz & 0x0001);
|
||||
pIter->nPos = nSz>>1;
|
||||
pIter->iLeafOffset = iOff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1766,6 +1766,7 @@ static void fts5SegIterNext(
|
||||
const u8 *pList = 0;
|
||||
const char *zTerm = 0;
|
||||
int nList = 0;
|
||||
assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
|
||||
if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
|
||||
sqlite3Fts5HashScanNext(p->pHash);
|
||||
sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
|
||||
@@ -1778,8 +1779,10 @@ static void fts5SegIterNext(
|
||||
pIter->pLeaf->nn = nList;
|
||||
pIter->pLeaf->szLeaf = nList;
|
||||
pIter->iEndofDoclist = nList+1;
|
||||
sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
|
||||
sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
|
||||
(u8*)zTerm);
|
||||
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
|
||||
*pbNewTerm = 1;
|
||||
}
|
||||
}else{
|
||||
iOff = 0;
|
||||
@@ -1940,14 +1943,6 @@ static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){
|
||||
pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
|
||||
}
|
||||
|
||||
#define fts5IndexGetVarint32(a, iOff, nVal) { \
|
||||
nVal = (a)[iOff++]; \
|
||||
if( nVal & 0x80 ){ \
|
||||
iOff--; \
|
||||
iOff += fts5GetVarint32(&(a)[iOff], nVal); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define fts5IndexSkipVarint(a, iOff) { \
|
||||
int iEnd = iOff+9; \
|
||||
while( (a[iOff++] & 0x80) && iOff<iEnd ); \
|
||||
@@ -1994,7 +1989,7 @@ static void fts5LeafSeek(
|
||||
while( 1 ){
|
||||
|
||||
/* Figure out how many new bytes are in this term */
|
||||
fts5IndexGetVarint32(a, iOff, nNew);
|
||||
fts5FastGetVarint32(a, iOff, nNew);
|
||||
if( nKeep<nMatch ){
|
||||
goto search_failed;
|
||||
}
|
||||
@@ -2030,7 +2025,7 @@ static void fts5LeafSeek(
|
||||
iOff = iTermOff;
|
||||
|
||||
/* Read the nKeep field of the next term. */
|
||||
fts5IndexGetVarint32(a, iOff, nKeep);
|
||||
fts5FastGetVarint32(a, iOff, nKeep);
|
||||
}
|
||||
|
||||
search_failed:
|
||||
@@ -2192,7 +2187,7 @@ static void fts5SegIterHashInit(
|
||||
if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
|
||||
p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
|
||||
sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList);
|
||||
n = (z ? strlen((const char*)z) : 0);
|
||||
n = (z ? (int)strlen((const char*)z) : 0);
|
||||
}else{
|
||||
pIter->flags |= FTS5_SEGITER_ONETERM;
|
||||
sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList);
|
||||
@@ -2733,6 +2728,7 @@ static void fts5MultiIterNew2(
|
||||
if( pNew ){
|
||||
Fts5SegIter *pIter = &pNew->aSeg[1];
|
||||
|
||||
pNew->bFiltered = 1;
|
||||
pIter->flags = FTS5_SEGITER_ONETERM;
|
||||
if( pData->szLeaf>0 ){
|
||||
pIter->pLeaf = pData;
|
||||
@@ -3705,10 +3701,15 @@ static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
|
||||
assert( pBuf->nSpace>=(pBuf->n+nBlob) ); \
|
||||
memcpy(&pBuf->p[pBuf->n], pBlob, nBlob); \
|
||||
pBuf->n += nBlob; \
|
||||
#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
|
||||
assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \
|
||||
memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \
|
||||
(pBuf)->n += nBlob; \
|
||||
}
|
||||
|
||||
#define fts5BufferSafeAppendVarint(pBuf, iVal) { \
|
||||
(pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \
|
||||
assert( (pBuf)->nSpace>=(pBuf)->n ); \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3759,7 +3760,7 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
|
||||
/* Write the term for this entry to disk. */
|
||||
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
|
||||
fts5WriteAppendTerm(p, &writer, strlen(zTerm), (const u8*)zTerm);
|
||||
fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
|
||||
|
||||
assert( writer.bFirstRowidInPage==0 );
|
||||
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
|
||||
@@ -3938,12 +3939,81 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
|
||||
|
||||
static void fts5PoslistCallback(
|
||||
Fts5Index *p,
|
||||
void *pCtx,
|
||||
void *pContext,
|
||||
const u8 *pChunk, int nChunk
|
||||
){
|
||||
assert_nc( nChunk>=0 );
|
||||
if( nChunk>0 ){
|
||||
fts5BufferAppendBlob(&p->rc, (Fts5Buffer*)pCtx, nChunk, pChunk);
|
||||
fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct PoslistCallbackCtx PoslistCallbackCtx;
|
||||
struct PoslistCallbackCtx {
|
||||
Fts5Buffer *pBuf; /* Append to this buffer */
|
||||
Fts5Colset *pColset; /* Restrict matches to this column */
|
||||
int eState; /* See above */
|
||||
};
|
||||
|
||||
/*
|
||||
** TODO: Make this more efficient!
|
||||
*/
|
||||
static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
|
||||
int i;
|
||||
for(i=0; i<pColset->nCol; i++){
|
||||
if( pColset->aiCol[i]==iCol ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fts5PoslistFilterCallback(
|
||||
Fts5Index *p,
|
||||
void *pContext,
|
||||
const u8 *pChunk, int nChunk
|
||||
){
|
||||
PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
|
||||
assert_nc( nChunk>=0 );
|
||||
if( nChunk>0 ){
|
||||
/* Search through to find the first varint with value 1. This is the
|
||||
** start of the next columns hits. */
|
||||
int i = 0;
|
||||
int iStart = 0;
|
||||
|
||||
if( pCtx->eState==2 ){
|
||||
int iCol;
|
||||
fts5FastGetVarint32(pChunk, i, iCol);
|
||||
if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
|
||||
pCtx->eState = 1;
|
||||
fts5BufferSafeAppendVarint(pCtx->pBuf, 1);
|
||||
}else{
|
||||
pCtx->eState = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
while( i<nChunk && pChunk[i]!=0x01 ){
|
||||
while( pChunk[i] & 0x80 ) i++;
|
||||
i++;
|
||||
}
|
||||
if( pCtx->eState ){
|
||||
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
|
||||
}
|
||||
if( i<nChunk ){
|
||||
int iCol;
|
||||
iStart = i;
|
||||
i++;
|
||||
if( i>=nChunk ){
|
||||
pCtx->eState = 2;
|
||||
}else{
|
||||
fts5FastGetVarint32(pChunk, i, iCol);
|
||||
pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
|
||||
if( pCtx->eState ){
|
||||
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
|
||||
iStart = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}while( i<nChunk );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3956,54 +4026,157 @@ static void fts5PoslistCallback(
|
||||
static void fts5SegiterPoslist(
|
||||
Fts5Index *p,
|
||||
Fts5SegIter *pSeg,
|
||||
Fts5Colset *pColset,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
|
||||
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
|
||||
if( pColset==0 ){
|
||||
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
|
||||
}else{
|
||||
PoslistCallbackCtx sCtx;
|
||||
sCtx.pBuf = pBuf;
|
||||
sCtx.pColset = pColset;
|
||||
sCtx.eState = fts5IndexColsetTest(pColset, 0);
|
||||
assert( sCtx.eState==0 || sCtx.eState==1 );
|
||||
fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterator pMulti currently points to a valid entry (not EOF). This
|
||||
** function appends a copy of the position-list of the entry pMulti
|
||||
** currently points to to buffer pBuf.
|
||||
**
|
||||
** If an error occurs, an error code is left in p->rc. It is assumed
|
||||
** no error has already occurred when this function is called.
|
||||
** 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 void fts5MultiIterPoslist(
|
||||
static int fts5IndexExtractCol(
|
||||
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; /* Anything before the first 0x01 is col 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Iterator pMulti currently points to a valid entry (not EOF). This
|
||||
** function appends the following to buffer pBuf:
|
||||
**
|
||||
** * The varint iDelta, and
|
||||
** * the position list that currently points to, including the size field.
|
||||
**
|
||||
** If argument pColset is NULL, then the position list is filtered according
|
||||
** to pColset before being appended to the buffer. If this means there are
|
||||
** no entries in the position list, nothing is appended to the buffer (not
|
||||
** even iDelta).
|
||||
**
|
||||
** If an error occurs, an error code is left in p->rc.
|
||||
*/
|
||||
static int fts5AppendPoslist(
|
||||
Fts5Index *p,
|
||||
i64 iDelta,
|
||||
Fts5IndexIter *pMulti,
|
||||
int bSz, /* Append a size field before the data */
|
||||
Fts5Colset *pColset,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
|
||||
assert( fts5MultiIterEof(p, pMulti)==0 );
|
||||
assert( pSeg->nPos>0 );
|
||||
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
|
||||
int iSv1;
|
||||
int iSv2;
|
||||
int iData;
|
||||
|
||||
/* Append iDelta */
|
||||
iSv1 = pBuf->n;
|
||||
fts5BufferSafeAppendVarint(pBuf, iDelta);
|
||||
|
||||
if( bSz ){
|
||||
/* WRITEPOSLISTSIZE */
|
||||
fts5BufferAppendVarint(&p->rc, pBuf, pSeg->nPos*2);
|
||||
iSv2 = pBuf->n;
|
||||
fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2);
|
||||
iData = pBuf->n;
|
||||
|
||||
if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
|
||||
&& (pColset==0 || pColset->nCol==1)
|
||||
){
|
||||
const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
|
||||
int nPos;
|
||||
if( pColset ){
|
||||
nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]);
|
||||
}else{
|
||||
nPos = pSeg->nPos;
|
||||
}
|
||||
fts5BufferSafeAppendBlob(pBuf, pPos, nPos);
|
||||
}else{
|
||||
fts5SegiterPoslist(p, pSeg, pColset, pBuf);
|
||||
}
|
||||
|
||||
if( pColset ){
|
||||
int nActual = pBuf->n - iData;
|
||||
if( nActual!=pSeg->nPos ){
|
||||
if( nActual==0 ){
|
||||
pBuf->n = iSv1;
|
||||
return 1;
|
||||
}else{
|
||||
int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2));
|
||||
while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; }
|
||||
sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fts5SegiterPoslist(p, pSeg, pBuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
|
||||
if( pIter->i<pIter->n ){
|
||||
int bDummy;
|
||||
if( pIter->i ){
|
||||
i64 iDelta;
|
||||
pIter->i += fts5GetVarint(&pIter->a[pIter->i], (u64*)&iDelta);
|
||||
pIter->iRowid += iDelta;
|
||||
}else{
|
||||
pIter->i += fts5GetVarint(&pIter->a[pIter->i], (u64*)&pIter->iRowid);
|
||||
}
|
||||
pIter->i += fts5GetPoslistSize(
|
||||
&pIter->a[pIter->i], &pIter->nPoslist, &bDummy
|
||||
);
|
||||
pIter->aPoslist = &pIter->a[pIter->i];
|
||||
pIter->i += pIter->nPoslist;
|
||||
}else{
|
||||
u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
|
||||
|
||||
assert( pIter->aPoslist );
|
||||
if( p>=pIter->aEof ){
|
||||
pIter->aPoslist = 0;
|
||||
}else{
|
||||
i64 iDelta;
|
||||
|
||||
p += fts5GetVarint(p, (u64*)&iDelta);
|
||||
pIter->iRowid += iDelta;
|
||||
|
||||
/* Read position list size */
|
||||
if( p[0] & 0x80 ){
|
||||
int nPos;
|
||||
pIter->nSize = fts5GetVarint32(p, nPos);
|
||||
pIter->nPoslist = (nPos>>1);
|
||||
}else{
|
||||
pIter->nPoslist = ((int)(p[0])) >> 1;
|
||||
pIter->nSize = 1;
|
||||
}
|
||||
|
||||
pIter->aPoslist = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4012,27 +4185,34 @@ static void fts5DoclistIterInit(
|
||||
Fts5DoclistIter *pIter
|
||||
){
|
||||
memset(pIter, 0, sizeof(*pIter));
|
||||
pIter->a = pBuf->p;
|
||||
pIter->n = pBuf->n;
|
||||
pIter->aPoslist = pBuf->p;
|
||||
pIter->aEof = &pBuf->p[pBuf->n];
|
||||
fts5DoclistIterNext(pIter);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** Append a doclist to buffer pBuf.
|
||||
**
|
||||
** This function assumes that space within the buffer has already been
|
||||
** allocated.
|
||||
*/
|
||||
static void fts5MergeAppendDocid(
|
||||
int *pRc, /* IN/OUT: Error code */
|
||||
Fts5Buffer *pBuf, /* Buffer to write to */
|
||||
i64 *piLastRowid, /* IN/OUT: Previous rowid written (if any) */
|
||||
i64 iRowid /* Rowid to append */
|
||||
){
|
||||
if( pBuf->n==0 ){
|
||||
fts5BufferAppendVarint(pRc, pBuf, iRowid);
|
||||
}else{
|
||||
fts5BufferAppendVarint(pRc, pBuf, iRowid - *piLastRowid);
|
||||
}
|
||||
assert( pBuf->n!=0 || (*piLastRowid)==0 );
|
||||
fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid);
|
||||
*piLastRowid = iRowid;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
|
||||
assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
|
||||
fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
|
||||
(iLastRowid) = (iRowid); \
|
||||
}
|
||||
|
||||
/*
|
||||
** Buffers p1 and p2 contain doclists. This function merges the content
|
||||
@@ -4056,53 +4236,58 @@ static void fts5MergePrefixLists(
|
||||
memset(&out, 0, sizeof(out));
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
sqlite3Fts5BufferGrow(&p->rc, &out, p1->n + p2->n);
|
||||
fts5DoclistIterInit(p1, &i1);
|
||||
fts5DoclistIterInit(p2, &i2);
|
||||
while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){
|
||||
if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowid<i2.iRowid) ){
|
||||
/* Copy entry from i1 */
|
||||
fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i1.iRowid);
|
||||
/* WRITEPOSLISTSIZE */
|
||||
fts5BufferAppendVarint(&p->rc, &out, i1.nPoslist * 2);
|
||||
fts5BufferAppendBlob(&p->rc, &out, i1.nPoslist, i1.aPoslist);
|
||||
fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
|
||||
fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
|
||||
fts5DoclistIterNext(&i1);
|
||||
}
|
||||
else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){
|
||||
/* Copy entry from i2 */
|
||||
fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i2.iRowid);
|
||||
/* WRITEPOSLISTSIZE */
|
||||
fts5BufferAppendVarint(&p->rc, &out, i2.nPoslist * 2);
|
||||
fts5BufferAppendBlob(&p->rc, &out, i2.nPoslist, i2.aPoslist);
|
||||
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
|
||||
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
|
||||
fts5DoclistIterNext(&i2);
|
||||
}
|
||||
else{
|
||||
Fts5PoslistReader r1;
|
||||
Fts5PoslistReader r2;
|
||||
Fts5PoslistWriter writer;
|
||||
i64 iPos1 = 0;
|
||||
i64 iPos2 = 0;
|
||||
int iOff1 = 0;
|
||||
int iOff2 = 0;
|
||||
u8 *a1 = &i1.aPoslist[i1.nSize];
|
||||
u8 *a2 = &i2.aPoslist[i2.nSize];
|
||||
|
||||
Fts5PoslistWriter writer;
|
||||
memset(&writer, 0, sizeof(writer));
|
||||
|
||||
/* Merge the two position lists. */
|
||||
fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i2.iRowid);
|
||||
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
|
||||
fts5BufferZero(&tmp);
|
||||
sqlite3Fts5PoslistReaderInit(-1, i1.aPoslist, i1.nPoslist, &r1);
|
||||
sqlite3Fts5PoslistReaderInit(-1, i2.aPoslist, i2.nPoslist, &r2);
|
||||
while( p->rc==SQLITE_OK && (r1.bEof==0 || r2.bEof==0) ){
|
||||
|
||||
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
|
||||
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
|
||||
|
||||
while( p->rc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){
|
||||
i64 iNew;
|
||||
if( r2.bEof || (r1.bEof==0 && r1.iPos<r2.iPos) ){
|
||||
iNew = r1.iPos;
|
||||
sqlite3Fts5PoslistReaderNext(&r1);
|
||||
if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){
|
||||
iNew = iPos1;
|
||||
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
|
||||
}else{
|
||||
iNew = r2.iPos;
|
||||
sqlite3Fts5PoslistReaderNext(&r2);
|
||||
if( r1.iPos==r2.iPos ) sqlite3Fts5PoslistReaderNext(&r1);
|
||||
iNew = iPos2;
|
||||
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
|
||||
if( iPos1==iPos2 ){
|
||||
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
|
||||
}
|
||||
}
|
||||
p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
|
||||
}
|
||||
|
||||
/* WRITEPOSLISTSIZE */
|
||||
fts5BufferAppendVarint(&p->rc, &out, tmp.n * 2);
|
||||
fts5BufferAppendBlob(&p->rc, &out, tmp.n, tmp.p);
|
||||
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
|
||||
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
|
||||
fts5DoclistIterNext(&i1);
|
||||
fts5DoclistIterNext(&i2);
|
||||
}
|
||||
@@ -4125,7 +4310,8 @@ static void fts5SetupPrefixIter(
|
||||
int bDesc, /* True for "ORDER BY rowid DESC" */
|
||||
const u8 *pToken, /* Buffer containing prefix to match */
|
||||
int nToken, /* Size of buffer pToken in bytes */
|
||||
Fts5IndexIter **ppIter /* OUT: New iterator */
|
||||
Fts5Colset *pColset, /* Restrict matches to these columns */
|
||||
Fts5IndexIter **ppIter /* OUT: New iterator */
|
||||
){
|
||||
Fts5Structure *pStruct;
|
||||
Fts5Buffer *aBuf;
|
||||
@@ -4164,14 +4350,18 @@ static void fts5SetupPrefixIter(
|
||||
fts5BufferZero(&aBuf[i]);
|
||||
}
|
||||
}
|
||||
iLastRowid = 0;
|
||||
}
|
||||
|
||||
fts5MergeAppendDocid(&p->rc, &doclist, &iLastRowid, iRowid);
|
||||
fts5MultiIterPoslist(p, p1, 1, &doclist);
|
||||
if( !fts5AppendPoslist(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
|
||||
iLastRowid = iRowid;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<nBuf; i++){
|
||||
fts5MergePrefixLists(p, &doclist, &aBuf[i]);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
fts5MergePrefixLists(p, &doclist, &aBuf[i]);
|
||||
}
|
||||
fts5BufferFree(&aBuf[i]);
|
||||
}
|
||||
fts5MultiIterFree(p, p1);
|
||||
@@ -4195,7 +4385,7 @@ static void fts5SetupPrefixIter(
|
||||
** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
|
||||
** to the document with rowid iRowid.
|
||||
*/
|
||||
int sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
|
||||
int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
|
||||
/* Allocate the hash table if it has not already been allocated */
|
||||
@@ -4204,10 +4394,15 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
|
||||
}
|
||||
|
||||
/* Flush the hash table to disk if required */
|
||||
if( iRowid<=p->iWriteRowid || (p->nPendingData > p->nMaxPendingData) ){
|
||||
if( iRowid<p->iWriteRowid
|
||||
|| (iRowid==p->iWriteRowid && p->bDelete==0)
|
||||
|| (p->nPendingData > p->nMaxPendingData)
|
||||
){
|
||||
fts5IndexFlush(p);
|
||||
}
|
||||
|
||||
p->iWriteRowid = iRowid;
|
||||
p->bDelete = bDelete;
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -4306,7 +4501,6 @@ int sqlite3Fts5IndexClose(Fts5Index *p){
|
||||
sqlite3_finalize(p->pIdxDeleter);
|
||||
sqlite3_finalize(p->pIdxSelect);
|
||||
sqlite3Fts5HashFree(p->pHash);
|
||||
sqlite3Fts5BufferFree(&p->scratch);
|
||||
sqlite3_free(p->zDataTbl);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -4367,6 +4561,7 @@ int sqlite3Fts5IndexWrite(
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
|
||||
assert( p->rc==SQLITE_OK );
|
||||
assert( (iCol<0)==p->bDelete );
|
||||
|
||||
/* Add the entry to the main terms index. */
|
||||
rc = sqlite3Fts5HashWrite(
|
||||
@@ -4393,6 +4588,7 @@ 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 */
|
||||
Fts5Colset *pColset, /* Match these columns only */
|
||||
Fts5IndexIter **ppIter /* OUT: New iterator object */
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
@@ -4436,7 +4632,7 @@ int sqlite3Fts5IndexQuery(
|
||||
}else{
|
||||
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
|
||||
buf.p[0] = FTS5_MAIN_PREFIX;
|
||||
fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, &pRet);
|
||||
fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
|
||||
}
|
||||
|
||||
if( p->rc ){
|
||||
@@ -4516,6 +4712,26 @@ const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){
|
||||
}
|
||||
|
||||
|
||||
static int fts5IndexExtractColset (
|
||||
Fts5Colset *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 = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
|
||||
if( nSub ){
|
||||
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer containing a copy of the position list for
|
||||
** the current entry. Output variable *pn is set to the size of the buffer
|
||||
@@ -4526,6 +4742,7 @@ const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){
|
||||
*/
|
||||
int sqlite3Fts5IterPoslist(
|
||||
Fts5IndexIter *pIter,
|
||||
Fts5Colset *pColset, /* Column filter (or NULL) */
|
||||
const u8 **pp, /* OUT: Pointer to position-list data */
|
||||
int *pn, /* OUT: Size of position-list in bytes */
|
||||
i64 *piRowid /* OUT: Current rowid */
|
||||
@@ -4533,13 +4750,25 @@ int sqlite3Fts5IterPoslist(
|
||||
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
|
||||
assert( pIter->pIndex->rc==SQLITE_OK );
|
||||
*piRowid = pSeg->iRowid;
|
||||
*pn = pSeg->nPos;
|
||||
if( pSeg->iLeafOffset+pSeg->nPos <= pSeg->pLeaf->szLeaf ){
|
||||
*pp = &pSeg->pLeaf->p[pSeg->iLeafOffset];
|
||||
if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
|
||||
u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
|
||||
if( pColset==0 || pIter->bFiltered ){
|
||||
*pn = pSeg->nPos;
|
||||
*pp = pPos;
|
||||
}else if( pColset->nCol==1 ){
|
||||
*pp = pPos;
|
||||
*pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]);
|
||||
}else{
|
||||
fts5BufferZero(&pIter->poslist);
|
||||
fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist);
|
||||
*pp = pIter->poslist.p;
|
||||
*pn = pIter->poslist.n;
|
||||
}
|
||||
}else{
|
||||
fts5BufferZero(&pIter->poslist);
|
||||
fts5SegiterPoslist(pIter->pIndex, pSeg, &pIter->poslist);
|
||||
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
|
||||
*pp = pIter->poslist.p;
|
||||
*pn = pIter->poslist.n;
|
||||
}
|
||||
return fts5IndexReturn(pIter->pIndex);
|
||||
}
|
||||
@@ -4551,10 +4780,10 @@ int sqlite3Fts5IterPoslist(
|
||||
*/
|
||||
int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){
|
||||
Fts5Index *p = pIter->pIndex;
|
||||
|
||||
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
|
||||
assert( p->rc==SQLITE_OK );
|
||||
fts5BufferZero(pBuf);
|
||||
fts5MultiIterPoslist(p, pIter, 0, pBuf);
|
||||
fts5SegiterPoslist(p, pSeg, 0, pBuf);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -4729,17 +4958,17 @@ static int fts5QueryCksum(
|
||||
){
|
||||
u64 cksum = *pCksum;
|
||||
Fts5IndexIter *pIdxIter = 0;
|
||||
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, &pIdxIter);
|
||||
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
|
||||
|
||||
while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){
|
||||
i64 dummy;
|
||||
const u8 *pPos;
|
||||
int nPos;
|
||||
i64 rowid = sqlite3Fts5IterRowid(pIdxIter);
|
||||
rc = sqlite3Fts5IterPoslist(pIdxIter, &pPos, &nPos, &dummy);
|
||||
rc = sqlite3Fts5IterPoslist(pIdxIter, 0, &pPos, &nPos, &dummy);
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5PoslistReader sReader;
|
||||
for(sqlite3Fts5PoslistReaderInit(-1, pPos, nPos, &sReader);
|
||||
for(sqlite3Fts5PoslistReaderInit(pPos, nPos, &sReader);
|
||||
sReader.bEof==0;
|
||||
sqlite3Fts5PoslistReaderNext(&sReader)
|
||||
){
|
||||
@@ -4969,7 +5198,6 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
fts5DataRelease(pLeaf);
|
||||
if( p->rc ) break;
|
||||
|
||||
|
||||
/* Now check that the iter.nEmpty leaves following the current leaf
|
||||
** (a) exist and (b) contain no terms. */
|
||||
fts5IndexIntegrityCheckEmpty(
|
||||
@@ -5103,7 +5331,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
|
||||
fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
|
||||
|
||||
poslist.n = 0;
|
||||
fts5MultiIterPoslist(p, pIter, 0, &poslist);
|
||||
fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst] , 0, &poslist);
|
||||
while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
|
||||
int iCol = FTS5_POS2COLUMN(iPos);
|
||||
int iTokOff = FTS5_POS2OFFSET(iPos);
|
||||
@@ -5243,6 +5471,29 @@ static void fts5DecodeStructure(
|
||||
fts5StructureRelease(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** This is part of the fts5_decode() debugging aid.
|
||||
**
|
||||
** Arguments pBlob/nBlob contain an "averages" record. This function
|
||||
** appends a human-readable representation of record to the buffer passed
|
||||
** as the second argument.
|
||||
*/
|
||||
static void fts5DecodeAverages(
|
||||
int *pRc, /* IN/OUT: error code */
|
||||
Fts5Buffer *pBuf,
|
||||
const u8 *pBlob, int nBlob
|
||||
){
|
||||
int i = 0;
|
||||
const char *zSpace = "";
|
||||
|
||||
while( i<nBlob ){
|
||||
u64 iVal;
|
||||
i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
|
||||
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
|
||||
zSpace = " ";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
|
||||
** each varint and append its string representation to buffer pBuf. Return
|
||||
@@ -5344,7 +5595,7 @@ static void fts5DecodeFunction(
|
||||
}
|
||||
}else if( iSegid==0 ){
|
||||
if( iRowid==FTS5_AVERAGES_ROWID ){
|
||||
/* todo */
|
||||
fts5DecodeAverages(&rc, &s, a, n);
|
||||
}else{
|
||||
fts5DecodeStructure(&rc, &s, a, n);
|
||||
}
|
||||
@@ -5361,7 +5612,7 @@ static void fts5DecodeFunction(
|
||||
memset(&term, 0, sizeof(Fts5Buffer));
|
||||
|
||||
if( n<4 ){
|
||||
sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt");
|
||||
sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt");
|
||||
goto decode_out;
|
||||
}else{
|
||||
iRowidOff = fts5GetU16(&a[0]);
|
||||
|
||||
+172
-63
@@ -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,108 @@ 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 = 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 +1646,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 ){
|
||||
@@ -2132,14 +2218,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 +2255,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 +2400,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 +2430,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 +2461,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 +2479,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
|
||||
|
||||
+48
-47
@@ -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;
|
||||
@@ -549,7 +549,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 +639,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 +705,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 +777,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);
|
||||
|
||||
|
||||
@@ -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 ){
|
||||
|
||||
@@ -168,8 +168,8 @@ 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 nDb = (int)strlen(zDb)+1;
|
||||
int nTab = (int)strlen(zTab)+1;
|
||||
int eType;
|
||||
|
||||
rc = fts5VocabTableType(zType, pzErr, &eType);
|
||||
@@ -349,7 +349,7 @@ 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) ){
|
||||
@@ -402,7 +402,7 @@ static int fts5VocabFilterMethod(
|
||||
const int flags = FTS5INDEX_QUERY_SCAN;
|
||||
|
||||
fts5VocabResetCursor(pCsr);
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, &pCsr->pIter);
|
||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, 0, &pCsr->pIter);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5VocabNextMethod(pCursor);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
|
||||
|
||||
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]
|
||||
|
||||
foreach {k v} [lrange $argv 0 end-2] {
|
||||
switch -- $k {
|
||||
-colsize {
|
||||
set O(aColSize) $v
|
||||
}
|
||||
|
||||
-colsize {
|
||||
set O(aColSize) $v
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sqlite3 db $O(db)
|
||||
load_static_extension db fts5
|
||||
|
||||
|
||||
# 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 ", \$$c"
|
||||
}
|
||||
append sql ")"
|
||||
|
||||
db eval BEGIN
|
||||
while {$i < $N} {
|
||||
foreach c $cols s $O(aColsize) {
|
||||
set $c [lrange $tokens $i [expr $i+$s-1]]
|
||||
incr i $s
|
||||
}
|
||||
db eval $sql
|
||||
}
|
||||
db eval COMMIT
|
||||
|
||||
|
||||
|
||||
@@ -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) */
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -87,7 +87,9 @@ 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 { 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 +109,3 @@ proc fts5c_close {} {
|
||||
fts5c_init fts5.c
|
||||
foreach f $G(src) { fts5c_printfile $f }
|
||||
fts5c_close
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+59
-15
@@ -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;
|
||||
@@ -1995,6 +2036,7 @@ int sqlite3Json1Init(sqlite3 *db){
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
@@ -2007,3 +2049,5 @@ int sqlite3_json_init(
|
||||
(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;
|
||||
|
||||
/*
|
||||
@@ -447,4 +451,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 */
|
||||
|
||||
@@ -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_SHELL_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
|
||||
@@ -579,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
|
||||
@@ -668,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
|
||||
@@ -701,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
|
||||
@@ -717,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 Remove\sdead\scode,\sreplacing\swith\sassert()\sstatements\sthat\smake\ssure\sthe\ncode\sreally\swas\sdead.
|
||||
D 2015-09-29T15:50:04.571
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc b9054642ab305be4174d8b0433c9951c2839701d
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
C Change\sthe\scode\sgenerator\sfor\sUPDATE\sto\sgenerate\scode\sin\san\sorder\sthat\smight\nrun\smore\sefficiently\sin\smany\scases.
|
||||
D 2015-10-17T01:00:03.352
|
||||
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 4eb750e0fdf52050a06d881e1b060f4bb116ed7e
|
||||
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
|
||||
@@ -82,7 +79,7 @@ F ext/fts3/fts3.c e028eb13432f108d2e22cded019fc980700e4e00
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
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 6f7233a06df17084d5cd968899053731bf953f94
|
||||
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 38667e39859ff3f3bc91f47efe672023a145a118
|
||||
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
|
||||
F ext/fts5/fts5_buffer.c 9a3aa73a4e7b26b1c805b9c92c1344ba3d19d2a8
|
||||
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 c76d636d6cd22e3b82b1dbf3a3993447091c3bed
|
||||
F ext/fts5/fts5_main.c d3fde32e1fdd7962dc7062400d1d8c7ec2297acf
|
||||
F ext/fts5/fts5_storage.c 9b30115742b758706de70595a8d1d084e940c978
|
||||
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 85ebf2e93089c9d3d136cc69163370592fc040f3
|
||||
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 34ad813e9e958115d388658b2c4a8dde6b1474a5
|
||||
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
|
||||
@@ -146,7 +143,7 @@ F ext/fts5/test/fts5config.test ad2ff42ddc856aed2d05bf89dc1c578c8a39ea3b
|
||||
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
|
||||
@@ -156,24 +153,26 @@ 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/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/fts5hash.test 7cf4607b8657c383f0b520668a99971e95d8b139
|
||||
F ext/fts5/test/fts5integrity.test 29f41d2c7126c6122fbb5d54e556506456876145
|
||||
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/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
|
||||
@@ -182,8 +181,9 @@ 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/tool/fts5txt2db.tcl 3d19fb8ffb234031d33d7d2151acfbc55e9cfcc4
|
||||
F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
|
||||
F ext/fts5/tool/mkfts5c.tcl 5745072c7de346e18c7f491e4c3281fe8a1cfe51
|
||||
F ext/fts5/tool/mkfts5c.tcl 09ce6a7997440508360f5ba1651ab7e923a8bf31
|
||||
F ext/fts5/tool/showfts5.tcl 9eaf6c3df352f98a2ab5ce1921dd94128ab1381d
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
|
||||
@@ -195,7 +195,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 263cac0292302b7cf7ecb2e8bd698a50d1aedecc
|
||||
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 +229,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/sqlite3rbu.c ea47de615e911b3a69a8e7fb3be3866298403a25
|
||||
F ext/rbu/sqlite3rbu.h 1d568cb33738d7900975cc5c72e6f68049f15914
|
||||
F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03
|
||||
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 +261,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 151fcaba704fdeeb0a1941857ef6e1d6216732d8
|
||||
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 +273,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.c ea8c62f65e57e49bd6b0988cd681aca7246b51af
|
||||
F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
|
||||
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
|
||||
F src/build.c 361f58b73aad7804f5706bf62d210bd9cd608041
|
||||
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 46bb5e217f83af68574ccb613421485578c41ba8
|
||||
F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
|
||||
F src/delete.c 35c939eb8bacc9dd8a6715964e5f69feb8c20e44
|
||||
F src/expr.c d9896fda47a8f67d0ed203e1fa981444424200c6
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f
|
||||
F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 81d6bf397c05b4e8ddc4af2ff6637c113ee7e37a
|
||||
F src/insert.c 6dadbb671c2cc035ddbbf11a0b0209185d5bfe2c
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
|
||||
F src/loadext.c f0b66d28e377fd6c6d36cc9d92df1ff251ebee44
|
||||
F src/main.c c80ea19ec71609ccbec21f334fbcf475bb6af2fc
|
||||
F src/malloc.c 3a37ce6979a40f499d8cea9e9ab4e8517854d35d
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c fec97668771438033a7559883401067b139729e1
|
||||
F src/malloc.c 0a2e42b835c980ba91c17866e9b6a9810ff54d75
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
F src/mem1.c 52485a88f22649c3b3b4f3eb15760505d49ccf71
|
||||
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 a94b46f3f7beba307dde1b298b0f99f9c3677a93
|
||||
F src/mutex_w32.c b483d3e5914b84c82516a6a9919582f12ef3b838
|
||||
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
@@ -332,25 +330,25 @@ F src/pager.h ac213f8143ebfee6a8bfb91cf4ca02c9a83343c5
|
||||
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
|
||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083
|
||||
F src/pragma.c 577f70c3899ee6fc2e5a4c37158c69c1c23f71e7
|
||||
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
|
||||
F src/pragma.c dcfe3a35d2de935feeaba1455528b4a5c4f1208c
|
||||
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 e49f4af9748c9e0cc1bf864b4190aa94841c8409
|
||||
F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0
|
||||
F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc
|
||||
F src/select.c dbf1fb82317043304da334a33206add211487f96
|
||||
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in 839c818e16ea68703d90d17bd2bb3607191debce
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
|
||||
F src/sqliteInt.h b6516bb2727876348b4e05aadd12237797626270
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h 1ad779ee62efee60494af0a75d8d45592f9f53c3
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/status.c 286f6398a4d2cd1e8ff0771e3d30f8dddb4768ea
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
|
||||
F src/test1.c c96508c835979bf15dc0e3146e2c7a51a2333d3c
|
||||
F src/test1.c 8fff9c5aa63d6490f516d018b70c12a9cb9a4d8a
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
@@ -364,7 +362,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 ada6f38b0acb6722fb7f0ed8c54fd66df41085b9
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -396,31 +394,31 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6
|
||||
F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22
|
||||
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c d8f0afe1a1c66b97cbd87e5236f4e71d35ab4840
|
||||
F src/update.c 04ed5f0334d313221cd084d46c5c2e0ad29ecb52
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 5048103aa6bc9c01bf1a4620729256d1e873bb6c
|
||||
F src/vdbe.c e9315575bed64f9aa559151283c873be34143914
|
||||
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
||||
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
||||
F src/vdbeInt.h 777dd76d513347acb1a71d94df2be00516add637
|
||||
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 906bc74ea90707b57a23e4264727fff7b48d0cb5
|
||||
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 b7f928b6b8ce091f385ba5ac2394928608431550
|
||||
F src/where.c 4c4646675e794ac71e701289edefd7cd81bac844
|
||||
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
|
||||
F src/wherecode.c a87238178f8c300fd27afec54326ea8d0a18baa2
|
||||
F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
|
||||
F src/wherecode.c b924b78acd9e623fb69bfa2cb65cd7d542166dd3
|
||||
F src/whereexpr.c e63244ca06c503e5f3c5b7f3c9aea0db826089ed
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -621,7 +619,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
|
||||
@@ -690,7 +688,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 92bc4cc67f948b2f53f73c8ab0ebf4be9eee92aa
|
||||
F test/fts3conf.test ff90127b2462c788348c0dd7f6f8c573ef9cb5d9
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
@@ -702,7 +700,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
|
||||
@@ -750,10 +748,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
|
||||
@@ -817,8 +815,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
|
||||
@@ -898,6 +896,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
|
||||
@@ -943,7 +942,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
|
||||
@@ -1029,7 +1028,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
|
||||
@@ -1044,7 +1043,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
|
||||
@@ -1240,7 +1239,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
|
||||
@@ -1249,7 +1248,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 0d8935e64867ae01492347884f5cbb47f056f4c8
|
||||
F test/view.test f6c3a39e0c819891265e1d0754e99960d81ef6c9
|
||||
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
|
||||
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
@@ -1333,14 +1332,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
|
||||
@@ -1350,27 +1351,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
|
||||
@@ -1382,14 +1384,17 @@ 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 59662cd2b65255a30e1a420331c07c51b644621a
|
||||
R cec1f3888d085a601a5cfb22d1afd716
|
||||
P 0df371d1a51c2028aefa4c704707773750317689
|
||||
R 54a047417394c2361e73646ac2a70fb9
|
||||
T *branch * improved-update
|
||||
T *sym-improved-update *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 0ae71f6c4f92a526967039eb67c1881e
|
||||
Z 6145fe123cad180747a41342b799e5b4
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
0e317dda5dfd35b742afd70dacb5bfb39aa3fc4a
|
||||
c6239bf943fc42b8fc1ece95c9268240b7c53e80
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+12
-4
@@ -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;
|
||||
}
|
||||
|
||||
@@ -4499,7 +4499,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 +6501,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 +7632,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 ==
|
||||
|
||||
+7
-7
@@ -985,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 */
|
||||
@@ -1006,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
|
||||
@@ -3136,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
|
||||
@@ -3165,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;
|
||||
@@ -3219,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
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
@@ -858,7 +858,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;
|
||||
|
||||
+34
-16
@@ -1595,13 +1595,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 +2201,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 +2209,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 +2443,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 +2481,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 +2497,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 +2519,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 +3356,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 */
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
+23
-20
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -1745,7 +1748,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
|
||||
};
|
||||
|
||||
+13
-2
@@ -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
|
||||
@@ -2872,12 +2878,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,7 +2910,6 @@ static int openDatabase(
|
||||
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
if( !db->mallocFailed && rc==SQLITE_OK){
|
||||
extern int sqlite3Json1Init(sqlite3*);
|
||||
rc = sqlite3Json1Init(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
+7
-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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -456,7 +455,7 @@ void sqlite3_free(void *p){
|
||||
** *db->pnBytesFreed.
|
||||
*/
|
||||
static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
|
||||
*db->pnBytesFreed += sqlite3DbMallocSize(db,p);
|
||||
if( p ) *db->pnBytesFreed += sqlite3DbMallocSize(db,p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -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 ){
|
||||
|
||||
+2
-2
@@ -171,11 +171,11 @@ static void sqlite3MemFree(void *pPrior){
|
||||
** or xRealloc().
|
||||
*/
|
||||
static int sqlite3MemSize(void *pPrior){
|
||||
assert( pPrior!=0 );
|
||||
#ifdef SQLITE_MALLOCSIZE
|
||||
return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
|
||||
return (int)SQLITE_MALLOCSIZE(pPrior);
|
||||
#else
|
||||
sqlite3_int64 *p;
|
||||
if( pPrior==0 ) return 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;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -87,7 +87,10 @@ void sqlite3MemoryBarrier(void){
|
||||
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
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
+7
-6
@@ -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},
|
||||
};
|
||||
|
||||
@@ -1524,7 +1525,7 @@ void sqlite3Pragma(
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=(-1) && iCol<pTab->nCol );
|
||||
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 */
|
||||
|
||||
+54
-66
@@ -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.
|
||||
@@ -4259,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) ){
|
||||
@@ -4267,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
|
||||
}
|
||||
@@ -5215,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 */
|
||||
@@ -5302,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++;
|
||||
}
|
||||
}
|
||||
@@ -5363,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
|
||||
@@ -5386,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"));
|
||||
|
||||
+45
-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
|
||||
@@ -4619,13 +4654,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
}
|
||||
data.out = stdout;
|
||||
|
||||
#ifdef SQLITE_SHELL_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
|
||||
|
||||
+5
-4
@@ -5656,9 +5656,9 @@ struct sqlite3_module {
|
||||
** 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. Similarly, the idxFlags field
|
||||
** was added for version 3.8.12. It may therefore only be used if
|
||||
** 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
|
||||
** 3008012.
|
||||
** 3009000.
|
||||
*/
|
||||
struct sqlite3_index_info {
|
||||
/* Inputs */
|
||||
@@ -5686,7 +5686,7 @@ 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.8.12 and later */
|
||||
/* Fields below are only available in SQLite 3.9.0 and later */
|
||||
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
||||
};
|
||||
|
||||
@@ -6572,7 +6572,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>
|
||||
**
|
||||
|
||||
+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) */
|
||||
|
||||
+9
-1
@@ -196,6 +196,7 @@
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_byteswap_ushort)
|
||||
# pragma intrinsic(_byteswap_ulong)
|
||||
# pragma intrinsic(_ReadWriteBarrier)
|
||||
# else
|
||||
# include <cmnintrin.h>
|
||||
# endif
|
||||
@@ -1917,6 +1918,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
|
||||
@@ -3202,7 +3209,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 +3393,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);
|
||||
|
||||
+13
-10
@@ -108,18 +108,21 @@ 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){
|
||||
wsdStatInit;
|
||||
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( X>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = X;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,10 +255,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));
|
||||
|
||||
+5
-7
@@ -6377,7 +6377,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 +6384,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 +6391,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 +6420,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);
|
||||
|
||||
@@ -167,6 +167,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
|
||||
|
||||
+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());
|
||||
|
||||
+26
-23
@@ -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);
|
||||
}
|
||||
@@ -496,6 +496,13 @@ void sqlite3Update(
|
||||
** table and index records, and as the values for any new.* references
|
||||
** made by triggers.
|
||||
**
|
||||
** As an optimization, the array is loaded in two passes. The first pass
|
||||
** loads unchanged values using OP_Column opcodes so that they can be
|
||||
** cached and potentially reused by subsequent expressions. Also, the
|
||||
** OP_Columns are loaded in reverse order so that the row type/offset cache
|
||||
** inside the OP_Column implementation in the VDBE will warm up completely
|
||||
** on the first opcode, rather than incrementally across each opcode.
|
||||
**
|
||||
** If there are one or more BEFORE triggers, then do not populate the
|
||||
** registers associated with columns that are (a) not modified by
|
||||
** this UPDATE statement and (b) not accessed by new.* references. The
|
||||
@@ -507,25 +514,21 @@ void sqlite3Update(
|
||||
newmask = sqlite3TriggerColmask(
|
||||
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
||||
);
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
for(i=pTab->nCol-1; i>=0; i--){
|
||||
if( aXRef[i]>=0 && i!=pTab->iPKey ) continue;
|
||||
if( i!=pTab->iPKey
|
||||
&& (0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i))!=0)
|
||||
){
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
|
||||
}else{
|
||||
j = aXRef[i];
|
||||
if( j>=0 ){
|
||||
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
|
||||
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
|
||||
/* This branch loads the value of a column that will not be changed
|
||||
** into a register. This is done if there are no BEFORE triggers, or
|
||||
** if there are one or more BEFORE triggers that use this value via
|
||||
** a new.* reference in a trigger program.
|
||||
*/
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
}
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( (j = aXRef[i])>=0 && i!=pTab->iPKey ){
|
||||
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,7 +567,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. */
|
||||
@@ -580,9 +583,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);
|
||||
}
|
||||
@@ -593,7 +596,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
|
||||
}
|
||||
if( bReplace || chngKey ){
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}
|
||||
|
||||
if( hasFK ){
|
||||
|
||||
+82
-65
@@ -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;
|
||||
@@ -5671,12 +5682,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 +5696,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;
|
||||
|
||||
+2
-1
@@ -412,7 +412,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);
|
||||
|
||||
+39
-9
@@ -2940,11 +2940,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 +2960,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 +2985,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";
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -1427,17 +1427,16 @@ static void recordFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const int file_format = 1;
|
||||
int iSerial; /* Serial type */
|
||||
u32 iSerial; /* Serial type */
|
||||
int nSerial; /* Bytes of space for iSerial as varint */
|
||||
int nVal; /* Bytes of space required for argv[0] */
|
||||
u32 nVal; /* Bytes of space required for argv[0] */
|
||||
int nRet;
|
||||
sqlite3 *db;
|
||||
u8 *aRet;
|
||||
|
||||
UNUSED_PARAMETER( argc );
|
||||
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
|
||||
iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
|
||||
nSerial = sqlite3VarintLen(iSerial);
|
||||
nVal = sqlite3VdbeSerialTypeLen(iSerial);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
|
||||
nRet = 1 + nSerial + nVal;
|
||||
|
||||
+1
-1
@@ -978,7 +978,7 @@ int sqlite3VdbeSorterInit(
|
||||
}
|
||||
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
||||
pSorter->nTask = nWorker + 1;
|
||||
pSorter->iPrev = nWorker-1;
|
||||
pSorter->iPrev = (u8)(nWorker - 1);
|
||||
pSorter->bUseThreads = (pSorter->nTask>1);
|
||||
pSorter->db = db;
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
|
||||
+3
-1
@@ -937,7 +937,9 @@ int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pModule->xBegin(pVTab->pVtab);
|
||||
if( rc==SQLITE_OK ){
|
||||
int iSvpt = db->nStatement + db->nSavepoint;
|
||||
addToVTrans(db, pVTab);
|
||||
if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1143,7 +1145,7 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
|
||||
*/
|
||||
void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){
|
||||
Table *pTab = pMod->pEpoTab;
|
||||
if( (pTab = pMod->pEpoTab)!=0 ){
|
||||
if( pTab!=0 ){
|
||||
sqlite3DeleteColumnNames(db, pTab);
|
||||
sqlite3VtabClear(db, pTab);
|
||||
sqlite3DbFree(db, pTab);
|
||||
|
||||
+12
-8
@@ -189,12 +189,12 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
while( pScan->iEquiv<=pScan->nEquiv ){
|
||||
iCur = pScan->aiCur[pScan->iEquiv-1];
|
||||
iColumn = pScan->aiColumn[pScan->iEquiv-1];
|
||||
if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0;
|
||||
if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
|
||||
while( (pWC = pScan->pWC)!=0 ){
|
||||
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
|
||||
if( pTerm->leftCursor==iCur
|
||||
&& pTerm->u.leftColumn==iColumn
|
||||
&& (iColumn!=(-2)
|
||||
&& (iColumn!=XN_EXPR
|
||||
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
|
||||
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
|
||||
){
|
||||
@@ -288,7 +288,7 @@ static WhereTerm *whereScanInit(
|
||||
if( pIdx ){
|
||||
j = iColumn;
|
||||
iColumn = pIdx->aiColumn[j];
|
||||
if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
|
||||
if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
|
||||
}
|
||||
if( pIdx && iColumn>=0 ){
|
||||
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
|
||||
@@ -727,7 +727,7 @@ static void constructAutomaticIndex(
|
||||
}
|
||||
}
|
||||
assert( n==nKeyCol );
|
||||
pIdx->aiColumn[n] = -1;
|
||||
pIdx->aiColumn[n] = XN_ROWID;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
|
||||
/* Create the automatic index */
|
||||
@@ -2242,7 +2242,9 @@ static int whereLoopAddBtreeIndex(
|
||||
int iCol = pProbe->aiColumn[saved_nEq];
|
||||
pNew->wsFlags |= WHERE_COLUMN_EQ;
|
||||
assert( saved_nEq==pNew->u.btree.nEq );
|
||||
if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){
|
||||
if( iCol==XN_ROWID
|
||||
|| (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}else{
|
||||
@@ -2442,7 +2444,7 @@ static int indexMightHelpWithOrderBy(
|
||||
}
|
||||
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
|
||||
for(jj=0; jj<pIndex->nKeyCol; jj++){
|
||||
if( pIndex->aiColumn[jj]!=(-2) ) continue;
|
||||
if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
|
||||
if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
|
||||
return 1;
|
||||
}
|
||||
@@ -3230,7 +3232,8 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
nKeyCol = pIndex->nKeyCol;
|
||||
nColumn = pIndex->nColumn;
|
||||
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
|
||||
assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
|
||||
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|
||||
|| !HasRowid(pIndex->pTable));
|
||||
isOrderDistinct = IsUniqueIndex(pIndex);
|
||||
}
|
||||
|
||||
@@ -3262,7 +3265,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
revIdx = pIndex->aSortOrder[j];
|
||||
if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
|
||||
}else{
|
||||
iColumn = -1;
|
||||
iColumn = XN_ROWID;
|
||||
revIdx = 0;
|
||||
}
|
||||
|
||||
@@ -4562,6 +4565,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
if( !HasRowid(pTab) ){
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
x = pPk->aiColumn[x];
|
||||
assert( x>=0 );
|
||||
}
|
||||
x = sqlite3ColumnOfIndex(pIdx, x);
|
||||
if( x>=0 ){
|
||||
|
||||
+9
-12
@@ -46,8 +46,8 @@ static void explainAppendTerm(
|
||||
*/
|
||||
static const char *explainIndexColumnName(Index *pIdx, int i){
|
||||
i = pIdx->aiColumn[i];
|
||||
if( i==(-2) ) return "<expr>";
|
||||
if( i==(-1) ) return "rowid";
|
||||
if( i==XN_EXPR ) return "<expr>";
|
||||
if( i==XN_ROWID ) return "rowid";
|
||||
return pIdx->pTable->aCol[i].zName;
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ static int codeAllEqualityTerms(
|
||||
sqlite3VdbeJumpHere(v, j);
|
||||
for(j=0; j<nSkip; j++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
|
||||
testcase( pIdx->aiColumn[j]==(-2) );
|
||||
testcase( pIdx->aiColumn[j]==XN_EXPR );
|
||||
VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
|
||||
}
|
||||
}
|
||||
@@ -1266,7 +1266,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
|
||||
int j1 = 0; /* Address of jump operation */
|
||||
int jmp1 = 0; /* Address of jump operation */
|
||||
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
|
||||
pAndExpr->pLeft = pOrExpr;
|
||||
pOrExpr = pAndExpr;
|
||||
@@ -1293,7 +1293,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
if( HasRowid(pTab) ){
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet);
|
||||
jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0,
|
||||
r,iSet);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
@@ -1304,11 +1305,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
r = sqlite3GetTempRange(pParse, nPk);
|
||||
for(iPk=0; iPk<nPk; iPk++){
|
||||
int iCol = pPk->aiColumn[iPk];
|
||||
int rx;
|
||||
rx = sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur,r+iPk,0);
|
||||
if( rx!=r+iPk ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, rx, r+iPk);
|
||||
}
|
||||
sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk);
|
||||
}
|
||||
|
||||
/* Check if the temp table already contains this key. If so,
|
||||
@@ -1323,7 +1320,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** need to insert the key into the temp table, as it will never
|
||||
** be tested for. */
|
||||
if( iSet ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
|
||||
jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( iSet>=0 ){
|
||||
@@ -1342,7 +1339,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
|
||||
/* Jump here (skipping the main loop body subroutine) if the
|
||||
** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
|
||||
if( j1 ) sqlite3VdbeJumpHere(v, j1);
|
||||
if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1);
|
||||
|
||||
/* The pSubWInfo->untestedTerms flag means that this OR term
|
||||
** contained one or more AND term from a notReady table. The
|
||||
|
||||
@@ -950,7 +950,6 @@ static void exprAnalyze(
|
||||
pNew = pTerm;
|
||||
}
|
||||
exprCommute(pParse, pDup);
|
||||
pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
|
||||
pNew->leftCursor = iCur;
|
||||
pNew->u.leftColumn = iColumn;
|
||||
testcase( (prereqLeft | extraRight) != prereqLeft );
|
||||
|
||||
@@ -151,4 +151,38 @@ do_execsql_test fkey1-4.2 {
|
||||
PRAGMA table_info="""1";
|
||||
} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test fkey1-5.1 {
|
||||
CREATE TABLE t11(
|
||||
x INTEGER PRIMARY KEY,
|
||||
parent REFERENCES t11 ON DELETE CASCADE
|
||||
);
|
||||
INSERT INTO t11 VALUES (1, NULL), (2, 1), (3, 2);
|
||||
} {}
|
||||
|
||||
# The REPLACE part of this statement deletes the row (2, 1). Then the
|
||||
# DELETE CASCADE caused by deleting that row removes the (3, 2) row. Which
|
||||
# would have been the parent of the new row being inserted. Causing an
|
||||
# FK violation.
|
||||
#
|
||||
do_catchsql_test fkey1-5.2 {
|
||||
INSERT OR REPLACE INTO t11 VALUES (2, 3);
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
# A similar test to the above.
|
||||
do_execsql_test fkey1-5.3 {
|
||||
CREATE TABLE Foo (
|
||||
Id INTEGER PRIMARY KEY,
|
||||
ParentId INTEGER REFERENCES Foo(Id) ON DELETE CASCADE, C1
|
||||
);
|
||||
INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (1, null, 'A');
|
||||
INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 1, 'A-2-1');
|
||||
INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (3, 2, 'A-3-2');
|
||||
INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (4, 3, 'A-4-3');
|
||||
}
|
||||
do_catchsql_test fkey1-5.4 {
|
||||
INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3');
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -178,4 +178,38 @@ do_execsql_test 3.8 {
|
||||
SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
|
||||
} {X'0200000002000000'}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the xSavepoint is invoked correctly if the first write
|
||||
# operation within a transaction is to a virtual table.
|
||||
#
|
||||
do_catchsql_test 4.1.1 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4;
|
||||
BEGIN;
|
||||
INSERT INTO t0(rowid, content) SELECT
|
||||
1, 'abc' UNION ALL SELECT
|
||||
2, 'def' UNION ALL SELECT
|
||||
1, 'ghi';
|
||||
} {1 {constraint failed}}
|
||||
do_execsql_test 4.1.2 {
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 4.1.3 {
|
||||
SELECT * FROM t0 WHERE t0 MATCH 'abc';
|
||||
INSERT INTO t0(t0) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
CREATE VIRTUAL TABLE t01 USING fts4;
|
||||
BEGIN;
|
||||
SAVEPOINT abc;
|
||||
INSERT INTO t01 VALUES('a b c');
|
||||
ROLLBACK TO abc;
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 4.2.2 {
|
||||
SELECT * FROM t01 WHERE t01 MATCH 'b';
|
||||
INSERT INTO t01(t01) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ proc balanced_andor_tree {nEntry} {
|
||||
return $tree
|
||||
}
|
||||
|
||||
if 1 {
|
||||
|
||||
# Test that queries like "1 AND 2 AND 3 AND 4..." are transformed to
|
||||
# balanced trees by FTS.
|
||||
#
|
||||
@@ -202,5 +204,35 @@ do_faultsim_test fts3expr3-fault-1 -faults oom-* -body {
|
||||
faultsim_test_result [list 0 $::result]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
foreach {tn expr res} {
|
||||
1 {1 OR 2 OR 3 OR 4} {OR {OR {P 1} {P 2}} {OR {P 3} {P 4}}}
|
||||
2 {1 OR (2 AND 3 AND 4 AND 5)}
|
||||
{OR {P 1} {AND {AND {P 2} {P 3}} {AND {P 4} {P 5}}}}
|
||||
3 {(2 AND 3 AND 4 AND 5) OR 1}
|
||||
{OR {AND {AND {P 2} {P 3}} {AND {P 4} {P 5}}} {P 1}}
|
||||
|
||||
4 {1 AND (2 OR 3 OR 4 OR 5)}
|
||||
{AND {P 1} {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}}}
|
||||
5 {(2 OR 3 OR 4 OR 5) AND 1}
|
||||
{AND {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}} {P 1}}
|
||||
|
||||
6 {(2 OR 3 OR 4 OR 5) NOT 1}
|
||||
{NOT {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}} {P 1}}
|
||||
|
||||
7 {1 NOT (2 OR 3 OR 4 OR 5)}
|
||||
{NOT {P 1} {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}}}
|
||||
|
||||
8 {(1 OR 2 OR 3 OR 4) NOT (5 AND 6 AND 7 AND 8)}
|
||||
{NOT {OR {OR {P 1} {P 2}} {OR {P 3} {P 4}}} {AND {AND {P 5} {P 6}} {AND {P 7} {P 8}}}}
|
||||
} {
|
||||
do_test 5.1.$tn {
|
||||
test_fts3expr2 $expr
|
||||
} $res
|
||||
}
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
finish_test
|
||||
|
||||
@@ -1051,7 +1051,6 @@ int main(int argc, char **argv){
|
||||
|
||||
/* Print the description, if there is one */
|
||||
if( !quietFlag ){
|
||||
int i;
|
||||
zDbName = azSrcDb[iSrcDb];
|
||||
i = strlen(zDbName) - 1;
|
||||
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
|
||||
@@ -1127,12 +1126,6 @@ int main(int argc, char **argv){
|
||||
}
|
||||
rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
|
||||
if( rc ) fatalError("cannot open inmem database");
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
{
|
||||
extern int sqlite3_json_init(sqlite3*);
|
||||
sqlite3_json_init(db);
|
||||
}
|
||||
#endif
|
||||
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
|
||||
setAlarm(iTimeout);
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
|
||||
Binary file not shown.
+22
-1
@@ -15,7 +15,11 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db json
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json101-1.1.00 {
|
||||
SELECT json_array(1,2.5,null,'hello');
|
||||
} {[1,2.5,null,"hello"]}
|
||||
@@ -320,5 +324,22 @@ do_execsql_test json-6.4 {
|
||||
SELECT json_valid('["a",55,"b",72]');
|
||||
} {1}
|
||||
|
||||
# White-space tests. Note that form-feed is not white-space in JSON.
|
||||
# ticket [57eec374ae1d0a1d4a23077a95f4e173fe269113]
|
||||
#
|
||||
foreach {tn isvalid ws} {
|
||||
7.1 1 char(0x20)
|
||||
7.2 1 char(0x09)
|
||||
7.3 1 char(0x0A)
|
||||
7.4 1 char(0x0D)
|
||||
7.5 0 char(0x0C)
|
||||
7.6 1 char(0x20,0x09,0x0a,0x0d,0x20)
|
||||
7.7 0 char(0x20,0x09,0x0a,0x0c,0x0d,0x20)
|
||||
} {
|
||||
do_execsql_test json-$tn.1 \
|
||||
"SELECT json_valid(printf('%s{%s\"x\"%s:%s9%s}%s',
|
||||
$::ws,$::ws,$::ws,$::ws,$::ws,$::ws));" \
|
||||
$isvalid
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+5
-1
@@ -18,7 +18,11 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db json
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json102-100 {
|
||||
SELECT json_object('ex','[52,3.14159]');
|
||||
} {{{"ex":"[52,3.14159]"}}}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
# 2015-10-06
|
||||
#
|
||||
# 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 test cases for the [b65cb2c8d91f6685841d7d1e13b6]
|
||||
# bug: Correct handling of LIMIT and OFFSET on a UNION ALL query where
|
||||
# the right-hand SELECT contains an ORDER BY in a subquery.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !compound {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test offset1-1.1 {
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e');
|
||||
CREATE TABLE t2(x,y);
|
||||
INSERT INTO t2 VALUES(8,'y'),(9,'z'),(6,'w'),(7,'x');
|
||||
SELECT count(*) FROM t1, t2;
|
||||
} {20}
|
||||
|
||||
do_execsql_test offset1-1.2.0 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 0;
|
||||
} {1 a 2 b 3 c}
|
||||
do_execsql_test offset1-1.2.1 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 1;
|
||||
} {2 b 3 c 4 d}
|
||||
do_execsql_test offset1-1.2.2 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 2;
|
||||
} {3 c 4 d 5 e}
|
||||
do_execsql_test offset1-1.2.3 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 3;
|
||||
} {4 d 5 e 6 w}
|
||||
do_execsql_test offset1-1.2.4 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 4;
|
||||
} {5 e 6 w 7 x}
|
||||
do_execsql_test offset1-1.2.5 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 5;
|
||||
} {6 w 7 x 8 y}
|
||||
do_execsql_test offset1-1.2.6 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 6;
|
||||
} {7 x 8 y 9 z}
|
||||
do_execsql_test offset1-1.2.7 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 7;
|
||||
} {8 y 9 z}
|
||||
do_execsql_test offset1-1.2.8 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 8;
|
||||
} {9 z}
|
||||
do_execsql_test offset1-1.2.9 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 9;
|
||||
} {}
|
||||
|
||||
do_execsql_test offset1-1.3.0 {
|
||||
SELECT * FROM t1 LIMIT 0;
|
||||
} {}
|
||||
|
||||
do_execsql_test offset1-1.4.0 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 0 OFFSET 1;
|
||||
} {}
|
||||
do_execsql_test offset1-1.4.1 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 1 OFFSET 1;
|
||||
} {2 b}
|
||||
do_execsql_test offset1-1.4.2 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 2 OFFSET 1;
|
||||
} {2 b 3 c}
|
||||
do_execsql_test offset1-1.4.3 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 3 OFFSET 1;
|
||||
} {2 b 3 c 4 d}
|
||||
do_execsql_test offset1-1.4.4 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 4 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e}
|
||||
do_execsql_test offset1-1.4.5 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 5 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e 6 w}
|
||||
do_execsql_test offset1-1.4.6 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 6 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e 6 w 7 x}
|
||||
do_execsql_test offset1-1.4.7 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 7 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e 6 w 7 x 8 y}
|
||||
do_execsql_test offset1-1.4.8 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 8 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z}
|
||||
do_execsql_test offset1-1.4.9 {
|
||||
SELECT a, b FROM t1
|
||||
UNION ALL
|
||||
SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
|
||||
LIMIT 9 OFFSET 1;
|
||||
} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -78,6 +78,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_DEFAULT_FILE_FORMAT=4
|
||||
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS
|
||||
--enable-json1
|
||||
}
|
||||
"Check-Symbols" {
|
||||
-DSQLITE_MEMDEBUG=1
|
||||
@@ -95,6 +96,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS
|
||||
--enable-json1 --enable-fts5
|
||||
}
|
||||
"Debug-One" {
|
||||
--disable-shared
|
||||
@@ -135,6 +137,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_OMIT_PROGRESS_CALLBACK=1
|
||||
-DSQLITE_OMIT_VIRTUALTABLE=1
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
--enable-json1
|
||||
}
|
||||
"Device-Two" {
|
||||
-DSQLITE_4_BYTE_ALIGNED_MALLOC=1
|
||||
@@ -152,6 +155,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_OMIT_TRACE=1
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
-DSQLITE_THREADSAFE=2
|
||||
--enable-json1 --enable-fts5
|
||||
}
|
||||
"Locking-Style" {
|
||||
-O2
|
||||
@@ -163,6 +167,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_DEFAULT_MEMSTATUS=0
|
||||
-DSQLITE_THREADSAFE=2
|
||||
-DSQLITE_OS_UNIX=1
|
||||
-DSQLITE_ENABLE_JSON1=1
|
||||
-DSQLITE_ENABLE_LOCKING_STYLE=1
|
||||
-DUSE_PREAD=1
|
||||
-DSQLITE_ENABLE_RTREE=1
|
||||
@@ -174,6 +179,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_DEBUG=1
|
||||
-DSQLITE_PREFER_PROXY_LOCKING=1
|
||||
-DSQLITE_ENABLE_API_ARMOR=1
|
||||
--enable-json1 --enable-fts5
|
||||
}
|
||||
"Extra-Robustness" {
|
||||
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
|
||||
@@ -187,6 +193,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_FTS4_PARENTHESIS
|
||||
-DSQLITE_DISABLE_FTS4_DEFERRED
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
--enable-json1 --enable-fts5
|
||||
}
|
||||
"No-lookaside" {
|
||||
-DSQLITE_TEST_REALLOC_STRESS=1
|
||||
@@ -197,6 +204,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
--enable-json1
|
||||
}
|
||||
|
||||
# The next group of configurations are used only by the
|
||||
|
||||
+30
-28
@@ -76,40 +76,42 @@ do_execsql_test 1.5 {
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT word, distance, matchlen FROM demo
|
||||
WHERE word MATCH 'amstedam*' AND distance <= 100;
|
||||
WHERE word MATCH 'amstedam*' AND distance <= 100
|
||||
ORDER BY distance, word;
|
||||
} {
|
||||
amsterdam 100 9 amsterdamh 100 9
|
||||
amsterdamm 100 9 amsterdamn 100 9
|
||||
amsterdama 100 9 amsterdame 100 9
|
||||
amsterdami 100 9 amsterdamo 100 9
|
||||
amsterdamu 100 9 amsterdamy 100 9
|
||||
amsterdammetje 100 9 amsterdamania 100 9
|
||||
amsterdamb 100 9 amsterdamf 100 9
|
||||
amsterdamp 100 9 amsterdamv 100 9
|
||||
amsterdamw 100 9 amsterdamweg 100 9
|
||||
amsterdamc 100 9 amsterdamg 100 9
|
||||
amsterdamj 100 9 amsterdamk 100 9
|
||||
amsterdamq 100 9 amsterdams 100 9
|
||||
amsterdamx 100 9 amsterdamz 100 9
|
||||
amsterdamsestraat 100 9 amsterdamd 100 9
|
||||
amsterdamt 100 9 amsterdaml 100 9
|
||||
amsterdamlaan 100 9 amsterdamr 100 9
|
||||
amsterdam 100 9 amsterdama 100 9
|
||||
amsterdamania 100 9 amsterdamb 100 9
|
||||
amsterdamc 100 9 amsterdamd 100 9
|
||||
amsterdame 100 9 amsterdamf 100 9
|
||||
amsterdamg 100 9 amsterdamh 100 9
|
||||
amsterdami 100 9 amsterdamj 100 9
|
||||
amsterdamk 100 9 amsterdaml 100 9
|
||||
amsterdamlaan 100 9 amsterdamm 100 9
|
||||
amsterdammetje 100 9 amsterdamn 100 9
|
||||
amsterdamo 100 9 amsterdamp 100 9
|
||||
amsterdamq 100 9 amsterdamr 100 9
|
||||
amsterdams 100 9 amsterdamsestraat 100 9
|
||||
amsterdamt 100 9 amsterdamu 100 9
|
||||
amsterdamv 100 9 amsterdamw 100 9
|
||||
amsterdamweg 100 9 amsterdamx 100 9
|
||||
amsterdamy 100 9 amsterdamz 100 9
|
||||
}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
SELECT word, distance, matchlen FROM demo
|
||||
WHERE word MATCH 'amstedam*' AND distance <= 100 AND top=20;
|
||||
WHERE word MATCH 'amstedam*' AND distance <= 100 AND top=20
|
||||
ORDER BY distance, word;
|
||||
} {
|
||||
amsterdam 100 9 amsterdamh 100 9
|
||||
amsterdamm 100 9 amsterdamn 100 9
|
||||
amsterdama 100 9 amsterdame 100 9
|
||||
amsterdami 100 9 amsterdamo 100 9
|
||||
amsterdamu 100 9 amsterdamy 100 9
|
||||
amsterdammetje 100 9 amsterdamania 100 9
|
||||
amsterdamb 100 9 amsterdamf 100 9
|
||||
amsterdamp 100 9 amsterdamv 100 9
|
||||
amsterdamw 100 9 amsterdamweg 100 9
|
||||
amsterdamc 100 9 amsterdamg 100 9
|
||||
amsterdam 100 9 amsterdama 100 9
|
||||
amsterdamania 100 9 amsterdamb 100 9
|
||||
amsterdamc 100 9 amsterdame 100 9
|
||||
amsterdamf 100 9 amsterdamg 100 9
|
||||
amsterdamh 100 9 amsterdami 100 9
|
||||
amsterdamm 100 9 amsterdammetje 100 9
|
||||
amsterdamn 100 9 amsterdamo 100 9
|
||||
amsterdamp 100 9 amsterdamu 100 9
|
||||
amsterdamv 100 9 amsterdamw 100 9
|
||||
amsterdamweg 100 9 amsterdamy 100 9
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-1
@@ -75,8 +75,12 @@ do_execsql_test tabfunc01-2.1 {
|
||||
INSERT INTO t1(x) VALUES(2),(3);
|
||||
SELECT *, '|' FROM t1, generate_series(1,x) ORDER BY 1, 2
|
||||
} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |}
|
||||
|
||||
do_execsql_test tabfunc01-2.2 {
|
||||
SELECT *, '|' FROM (SELECT x FROM t1) AS y, generate_series(1,y.x)
|
||||
ORDER BY 1, 2;
|
||||
} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |}
|
||||
|
||||
do_execsql_test tabfunc01-2.50 {
|
||||
SELECT * FROM generate_series() LIMIT 5;
|
||||
} {0 1 2 3 4}
|
||||
|
||||
|
||||
@@ -63,6 +63,14 @@ foreach {tn uri file} {
|
||||
#
|
||||
if {$tn>14} break
|
||||
|
||||
#
|
||||
# NOTE: When running on Tcl 8.6 (or higher?) on Windows, a colon within
|
||||
# the file name no longer tries to access an alternate data stream
|
||||
# (ADS) named "test.db" for the "http" file, causing some spurious
|
||||
# failures of this test.
|
||||
#
|
||||
if {$tn==12 && $::tcl_version>=8.6} continue
|
||||
|
||||
#
|
||||
# NOTE: On Windows, we need to account for the fact that the current
|
||||
# directory does not start with a forward slash.
|
||||
|
||||
@@ -499,6 +499,13 @@ do_test view-14.1 {
|
||||
SELECT * FROM temp.t1;
|
||||
}
|
||||
} {1 {view t1 is circularly defined}}
|
||||
do_test view-14.2 {
|
||||
catchsql {
|
||||
DROP VIEW IF EXISTS temp.t1;
|
||||
CREATE TEMP VIEW t1(a,b) AS SELECT a,b FROM t1;
|
||||
SELECT * FROM temp.t1;
|
||||
}
|
||||
} {1 {view t1 is circularly defined}}
|
||||
|
||||
# Tickets #1688, #1709
|
||||
#
|
||||
|
||||
+450
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
** 2015 October 7
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains C# code to download a single file based on a URI.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#region Assembly Metadata
|
||||
[assembly: AssemblyTitle("GetFile Tool")]
|
||||
[assembly: AssemblyDescription("Download a single file based on a URI.")]
|
||||
[assembly: AssemblyCompany("SQLite Development Team")]
|
||||
[assembly: AssemblyProduct("SQLite")]
|
||||
[assembly: AssemblyCopyright("Public Domain")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("5c4b3728-1693-4a33-a218-8e6973ca15a6")]
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
#if DEBUG
|
||||
[assembly: AssemblyConfiguration("Debug")]
|
||||
#else
|
||||
[assembly: AssemblyConfiguration("Release")]
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace GetFile
|
||||
{
|
||||
/// <summary>
|
||||
/// This enumeration is used to represent all the possible exit codes from
|
||||
/// this tool.
|
||||
/// </summary>
|
||||
internal enum ExitCode
|
||||
{
|
||||
/// <summary>
|
||||
/// The file download was a success.
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The command line arguments are missing (i.e. null). Generally,
|
||||
/// this should not happen.
|
||||
/// </summary>
|
||||
MissingArgs = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The wrong number of command line arguments was supplied.
|
||||
/// </summary>
|
||||
WrongNumArgs = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The URI specified on the command line could not be parsed as a
|
||||
/// supported absolute URI.
|
||||
/// </summary>
|
||||
BadUri = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The file name portion of the URI specified on the command line
|
||||
/// could not be extracted from it.
|
||||
/// </summary>
|
||||
BadFileName = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The temporary directory is either invalid (i.e. null) or does not
|
||||
/// represent an available directory.
|
||||
/// </summary>
|
||||
BadTempPath = 5,
|
||||
|
||||
/// <summary>
|
||||
/// An exception was caught in <see cref="Main" />. Generally, this
|
||||
/// should not happen.
|
||||
/// </summary>
|
||||
Exception = 6,
|
||||
|
||||
/// <summary>
|
||||
/// The file download was canceled. This tool does not make use of
|
||||
/// the <see cref="WebClient.CancelAsync" /> method; therefore, this
|
||||
/// should not happen.
|
||||
/// </summary>
|
||||
DownloadCanceled = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The file download encountered an error. Further information about
|
||||
/// this error should be displayed on the console.
|
||||
/// </summary>
|
||||
DownloadError = 8
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
#region Private Data
|
||||
/// <summary>
|
||||
/// This is used to synchronize multithreaded access to the
|
||||
/// <see cref="previousPercent" /> and <see cref="exitCode"/>
|
||||
/// fields.
|
||||
/// </summary>
|
||||
private static readonly object syncRoot = new object();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
/// This event will be signed when the file download has completed,
|
||||
/// even if the file download itself was canceled or unsuccessful.
|
||||
/// </summary>
|
||||
private static EventWaitHandle doneEvent;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
/// The previous file download completion percentage seen by the
|
||||
/// <see cref="DownloadProgressChanged" /> event handler. This value
|
||||
/// is never decreased, nor is it ever reset to zero.
|
||||
/// </summary>
|
||||
private static int previousPercent = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
/// This will be the exit code returned by this tool after the file
|
||||
/// download completes, successfully or otherwise. This value is only
|
||||
/// changed by the <see cref="DownloadFileCompleted" /> event handler.
|
||||
/// </summary>
|
||||
private static ExitCode exitCode = ExitCode.Success;
|
||||
#endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#region Private Support Methods
|
||||
/// <summary>
|
||||
/// This method displays an error message to the console and/or
|
||||
/// displays the command line usage information for this tool.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// The error message to display, if any.
|
||||
/// </param>
|
||||
/// <param name="usage">
|
||||
/// Non-zero to display the command line usage information.
|
||||
/// </param>
|
||||
private static void Error(
|
||||
string message,
|
||||
bool usage
|
||||
)
|
||||
{
|
||||
if (message != null)
|
||||
Console.WriteLine(message);
|
||||
|
||||
string fileName = Path.GetFileName(
|
||||
Process.GetCurrentProcess().MainModule.FileName);
|
||||
|
||||
Console.WriteLine(String.Format("usage: {0} <uri>", fileName));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
/// This method attempts to determine the file name portion of the
|
||||
/// specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">
|
||||
/// The URI to process.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The file name portion of the specified URI -OR- null if it cannot
|
||||
/// be determined.
|
||||
/// </returns>
|
||||
private static string GetFileName(
|
||||
Uri uri
|
||||
)
|
||||
{
|
||||
if (uri == null)
|
||||
return null;
|
||||
|
||||
string pathAndQuery = uri.PathAndQuery;
|
||||
|
||||
if (String.IsNullOrEmpty(pathAndQuery))
|
||||
return null;
|
||||
|
||||
int index = pathAndQuery.LastIndexOf('/');
|
||||
|
||||
if ((index < 0) || (index == pathAndQuery.Length))
|
||||
return null;
|
||||
|
||||
return pathAndQuery.Substring(index + 1);
|
||||
}
|
||||
#endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#region Private Event Handlers
|
||||
/// <summary>
|
||||
/// This method is an event handler that is called when the file
|
||||
/// download completion percentage changes. It will display progress
|
||||
/// on the console. Special care is taken to make sure that progress
|
||||
/// events are not displayed out-of-order, even if duplicate and/or
|
||||
/// out-of-order events are received.
|
||||
/// </summary>
|
||||
/// <param name="sender">
|
||||
/// The source of the event.
|
||||
/// </param>
|
||||
/// <param name="e">
|
||||
/// Information for the event being processed.
|
||||
/// </param>
|
||||
private static void DownloadProgressChanged(
|
||||
object sender,
|
||||
DownloadProgressChangedEventArgs e
|
||||
)
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
int percent = e.ProgressPercentage;
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
if (percent > previousPercent)
|
||||
{
|
||||
Console.Write('.');
|
||||
|
||||
if ((percent % 10) == 0)
|
||||
Console.Write(" {0}% ", percent);
|
||||
|
||||
previousPercent = percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
/// This method is an event handler that is called when the file
|
||||
/// download has completed, successfully or otherwise. It will
|
||||
/// display the overall result of the file download on the console,
|
||||
/// including any <see cref="Exception" /> information, if applicable.
|
||||
/// The <see cref="exitCode" /> field is changed by this method to
|
||||
/// indicate the overall result of the file download and the event
|
||||
/// within the <see cref="doneEvent" /> field will be signaled.
|
||||
/// </summary>
|
||||
/// <param name="sender">
|
||||
/// The source of the event.
|
||||
/// </param>
|
||||
/// <param name="e">
|
||||
/// Information for the event being processed.
|
||||
/// </param>
|
||||
private static void DownloadFileCompleted(
|
||||
object sender,
|
||||
AsyncCompletedEventArgs e
|
||||
)
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
if (previousPercent < 100)
|
||||
Console.Write(' ');
|
||||
}
|
||||
|
||||
if (e.Cancelled)
|
||||
{
|
||||
Console.WriteLine("Canceled");
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
exitCode = ExitCode.DownloadCanceled;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Exception error = e.Error;
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
Console.WriteLine("Error: {0}", error);
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
exitCode = ExitCode.DownloadError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doneEvent != null)
|
||||
doneEvent.Set();
|
||||
}
|
||||
#endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#region Program Entry Point
|
||||
/// <summary>
|
||||
/// This is the entry-point for this tool. It handles processing the
|
||||
/// command line arguments, setting up the web client, downloading the
|
||||
/// file, and saving it to the file system.
|
||||
/// </summary>
|
||||
/// <param name="args">
|
||||
/// The command line arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Zero upon success; non-zero on failure. This will be one of the
|
||||
/// values from the <see cref="ExitCode" /> enumeration.
|
||||
/// </returns>
|
||||
private static int Main(
|
||||
string[] args
|
||||
)
|
||||
{
|
||||
//
|
||||
// NOTE: Sanity check the command line arguments.
|
||||
//
|
||||
if (args == null)
|
||||
{
|
||||
Error(null, true);
|
||||
return (int)ExitCode.MissingArgs;
|
||||
}
|
||||
|
||||
if (args.Length != 1)
|
||||
{
|
||||
Error(null, true);
|
||||
return (int)ExitCode.WrongNumArgs;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: Attempt to convert the first (and only) command line
|
||||
// argument to an absolute URI.
|
||||
//
|
||||
Uri uri;
|
||||
|
||||
if (!Uri.TryCreate(args[0], UriKind.Absolute, out uri))
|
||||
{
|
||||
Error("Could not create absolute URI from argument.", false);
|
||||
return (int)ExitCode.BadUri;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: Attempt to extract the file name portion of the URI we
|
||||
// just created.
|
||||
//
|
||||
string fileName = GetFileName(uri);
|
||||
|
||||
if (fileName == null)
|
||||
{
|
||||
Error("Could not extract the file name from the URI.", false);
|
||||
return (int)ExitCode.BadFileName;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: Grab the temporary path setup for this process. If it is
|
||||
// unavailable, we will not continue.
|
||||
//
|
||||
string directory = Path.GetTempPath();
|
||||
|
||||
if (String.IsNullOrEmpty(directory) ||
|
||||
!Directory.Exists(directory))
|
||||
{
|
||||
Error("Temporary directory is invalid or unavailable.", false);
|
||||
return (int)ExitCode.BadTempPath;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (WebClient webClient = new WebClient())
|
||||
{
|
||||
//
|
||||
// NOTE: Create the event used to signal completion of the
|
||||
// file download.
|
||||
//
|
||||
doneEvent = new ManualResetEvent(false);
|
||||
|
||||
//
|
||||
// NOTE: Hookup the event handlers we care about on the web
|
||||
// client. These are necessary because the file is
|
||||
// downloaded asynchronously.
|
||||
//
|
||||
webClient.DownloadProgressChanged +=
|
||||
new DownloadProgressChangedEventHandler(
|
||||
DownloadProgressChanged);
|
||||
|
||||
webClient.DownloadFileCompleted +=
|
||||
new AsyncCompletedEventHandler(
|
||||
DownloadFileCompleted);
|
||||
|
||||
//
|
||||
// NOTE: Build the fully qualified path and file name,
|
||||
// within the temporary directory, where the file to
|
||||
// be downloaded will be saved.
|
||||
//
|
||||
fileName = Path.Combine(directory, fileName);
|
||||
|
||||
//
|
||||
// NOTE: If the file name already exists (in the temporary)
|
||||
// directory, delete it.
|
||||
//
|
||||
// TODO: Perhaps an error should be raised here instead?
|
||||
//
|
||||
if (File.Exists(fileName))
|
||||
File.Delete(fileName);
|
||||
|
||||
//
|
||||
// NOTE: After kicking off the asynchronous file download
|
||||
// process, wait [forever] until the "done" event is
|
||||
// signaled.
|
||||
//
|
||||
Console.WriteLine(
|
||||
"Downloading \"{0}\" to \"{1}\"...", uri, fileName);
|
||||
|
||||
webClient.DownloadFileAsync(uri, fileName);
|
||||
doneEvent.WaitOne();
|
||||
}
|
||||
|
||||
lock (syncRoot)
|
||||
{
|
||||
return (int)exitCode;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//
|
||||
// NOTE: An exception was caught. Report it via the console
|
||||
// and return failure.
|
||||
//
|
||||
Error(e.ToString(), false);
|
||||
return (int)ExitCode.Exception;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user