Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c62f1026c3 | |||
| 9d46f26ce5 | |||
| 511eb67522 | |||
| 332ed080d7 | |||
| 047800eadd | |||
| a649776664 | |||
| 0b086403b4 | |||
| b43b711587 | |||
| f4f968443b | |||
| cec7dec006 | |||
| f2c26ed17b | |||
| df705d8185 | |||
| 58a8a9236e | |||
| bfad7be78a | |||
| 2906490b71 | |||
| d12b636330 | |||
| 48310f8c51 | |||
| 72724da95a | |||
| c5971cc859 | |||
| 728e0f91bb | |||
| 9a4718ff73 | |||
| a0882fad7c | |||
| 8deb4b8b17 | |||
| 6cac258245 | |||
| 2572751be8 | |||
| 8381be4ace | |||
| c4e6d1775e | |||
| b5c8d27c7d | |||
| 64db184efa | |||
| ce1d9f546b | |||
| 0008ce7cc5 | |||
| 45fac88951 | |||
| c306e08ad5 | |||
| d3b90a2e41 | |||
| 23fda8242c | |||
| 56eac26897 | |||
| 351ccb3825 | |||
| 056d7acf25 | |||
| 50065656f7 | |||
| b2682eb14b | |||
| d7fd6aa4ba | |||
| 98e713bb8d | |||
| 08114efde4 | |||
| 22c7cca21f | |||
| 1dcc97cd3a | |||
| d46cc33131 | |||
| 92099b0753 | |||
| 6418ffab82 | |||
| 6bd7456edd | |||
| ee38148785 | |||
| 91a3ecb0ad | |||
| 8b0cf38a12 | |||
| a2507137f3 | |||
| 9f1ef45f6a | |||
| 8d9837acd5 | |||
| 6f832d3dff | |||
| f24bebe37a | |||
| 2c1023df09 | |||
| a0f197b842 | |||
| 06f8c635ef | |||
| bca189d5d8 | |||
| 5171e911f2 | |||
| 105865acf9 | |||
| 9b5351d439 | |||
| e755e10a78 | |||
| d95bb39c52 | |||
| 4b92f98ccc | |||
| e60856980a | |||
| 65c4f591be | |||
| 4ad0971919 |
+25
-19
@@ -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
|
||||
#
|
||||
@@ -175,7 +175,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 +272,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 +347,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 +420,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 +543,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 +575,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 +614,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
|
||||
@@ -990,6 +993,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 = \
|
||||
|
||||
+16
-13
@@ -1008,7 +1008,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 +1211,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
|
||||
#
|
||||
@@ -1231,19 +1232,19 @@ libsqlite3.lib: $(LIBOBJ)
|
||||
libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib
|
||||
$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(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) \
|
||||
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 $(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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
|
||||
@@ -1269,7 +1270,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 +1278,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
|
||||
|
||||
@@ -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.2.
|
||||
#
|
||||
#
|
||||
# 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.2'
|
||||
PACKAGE_STRING='sqlite 3.9.2'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -902,6 +902,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 +1459,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.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1519,7 +1524,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.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1544,6 +1549,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 +1644,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.2
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2053,7 +2063,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.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3911,13 +3921,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:3924: $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:3927: $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:3930: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5123,7 +5133,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5126 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5136 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6648,11 +6658,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:6661: $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:6665: \$? = $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 +6997,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:7000: $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:7004: \$? = $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 +7102,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:7105: $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:7109: \$? = $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 +7157,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:7160: $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:7164: \$? = $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 +9537,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 9540 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9623,7 +9633,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 9636 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11223,6 +11233,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 +11989,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.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -11874,7 +12055,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.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -560,6 +560,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*);
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+15
-18
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+37
-124
@@ -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;
|
||||
}
|
||||
@@ -1002,6 +910,7 @@ static int fts5ExprNearInitAll(
|
||||
pExpr->pIndex, p->zTerm, 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 );
|
||||
@@ -1754,25 +1663,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 +1706,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 +1741,7 @@ Fts5ExprColset *sqlite3Fts5ParseColset(
|
||||
void sqlite3Fts5ParseSetColset(
|
||||
Fts5Parse *pParse,
|
||||
Fts5ExprNearset *pNear,
|
||||
Fts5ExprColset *pColset
|
||||
Fts5Colset *pColset
|
||||
){
|
||||
if( pNear ){
|
||||
pNear->pColset = pColset;
|
||||
@@ -2285,6 +2194,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 +2234,3 @@ int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
|
||||
+357
-107
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1780,6 +1780,7 @@ static void fts5SegIterNext(
|
||||
pIter->iEndofDoclist = nList+1;
|
||||
sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
|
||||
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
|
||||
if( pbNewTerm ) *pbNewTerm = 1;
|
||||
}
|
||||
}else{
|
||||
iOff = 0;
|
||||
@@ -1940,14 +1941,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 +1987,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 +2023,7 @@ static void fts5LeafSeek(
|
||||
iOff = iTermOff;
|
||||
|
||||
/* Read the nKeep field of the next term. */
|
||||
fts5IndexGetVarint32(a, iOff, nKeep);
|
||||
fts5FastGetVarint32(a, iOff, nKeep);
|
||||
}
|
||||
|
||||
search_failed:
|
||||
@@ -2733,6 +2726,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 +3699,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 ); \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3938,12 +3937,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 +4024,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 = pColset ? fts5IndexColsetTest(pColset, 0) : 1;
|
||||
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 +4183,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 +4234,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 +4308,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 +4348,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 +4383,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 +4392,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 +4499,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 +4559,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 +4586,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 +4630,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 +4710,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 +4740,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 +4748,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 +4778,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 +4956,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)
|
||||
){
|
||||
@@ -5103,7 +5330,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 +5470,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 +5594,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 +5611,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]);
|
||||
|
||||
+169
-63
@@ -440,6 +440,19 @@ 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
|
||||
if( sqlite3_libversion_number()>=3008012 ){
|
||||
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 +505,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 +561,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 +1300,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 +1317,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 +1326,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 +1367,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 +1406,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 +1643,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 +2215,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 +2252,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 +2397,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 +2427,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 +2458,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 +2476,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
|
||||
|
||||
+56
-45
@@ -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,69 @@ 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 */
|
||||
#if 0
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
eStmt = FTS5_STMT_REPLACE_CONTENT;
|
||||
rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
|
||||
}else{
|
||||
eStmt = FTS5_STMT_INSERT_CONTENT;
|
||||
}
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
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 +787,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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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} {
|
||||
|
||||
@@ -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,140 @@ 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') }
|
||||
}
|
||||
|
||||
|
||||
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,124 @@ 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;
|
||||
} {}
|
||||
|
||||
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
|
||||
@@ -48,19 +50,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 +229,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 +326,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 +335,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 +382,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 +454,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 +473,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 +517,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
|
||||
@@ -668,9 +671,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
|
||||
@@ -717,9 +728,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,24 @@
|
||||
C Remove\sdead\scode,\sreplacing\swith\sassert()\sstatements\sthat\smake\ssure\sthe\ncode\sreally\swas\sdead.
|
||||
D 2015-09-29T15:50:04.571
|
||||
C Version\s3.9.2
|
||||
D 2015-11-02T18:31:45.544
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412
|
||||
F Makefile.in f0088ff0d2ac949fce6de7c00f13a99ac5bdb663
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc b9054642ab305be4174d8b0433c9951c2839701d
|
||||
F Makefile.msc 0ed934b4ae6a5ec0b9d7e770104864f8372414ab
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975
|
||||
F VERSION 36a3ce894ac495d8cb9006319eced49e72998587
|
||||
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 +38,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 f0b449016511057506dae6a525433b004df9cc4c x
|
||||
F configure.ac 1e87304e51af110950c48a1eea6ffc7a577f600e
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -82,7 +82,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 +96,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,25 +105,25 @@ 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.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
|
||||
F ext/fts5/fts5Int.h 38667e39859ff3f3bc91f47efe672023a145a118
|
||||
F ext/fts5/fts5_aux.c b09aa27dcdaa3d50a30be433fddaa48a50aa827b
|
||||
F ext/fts5/fts5_buffer.c e99224a316cc5b2c574ccccdc7f2344bca54784d
|
||||
F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695
|
||||
F ext/fts5/fts5_expr.c 667faaf14a69a5683ac383acdc8d942cf32c3f93
|
||||
F ext/fts5/fts5_expr.c bc31478fd04de55150031f6e6a652939d3e335ac
|
||||
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_index.c f73968357818455039ecb79dcd4b082c3baaeaeb
|
||||
F ext/fts5/fts5_main.c bf43550b8e9a68514abd179500f1917a2256cd7a
|
||||
F ext/fts5/fts5_storage.c df061a5caf9e50fbbd43113009b5b248362f4995
|
||||
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_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 a05027ab6abb692ad27654c85137a4f1061a159e
|
||||
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b6e6a40ef5d069c8e86ca4fbad491e1195485dbc
|
||||
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
|
||||
F ext/fts5/test/fts5aa.test 4804f237005bb4ba8ea4a76120d8011ebcb5d611
|
||||
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
|
||||
F ext/fts5/test/fts5ac.test 9737992d08c56bfd4803e933744d2d764e23795c
|
||||
@@ -135,7 +135,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
|
||||
@@ -156,7 +156,7 @@ 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/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda
|
||||
F ext/fts5/test/fts5fault7.test f62ed4d98f137eb03f1db94d1fa41b17a771d971
|
||||
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
|
||||
F ext/fts5/test/fts5hash.test 42eb066f667e9a389a63437cb7038c51974d4fc6
|
||||
@@ -164,16 +164,18 @@ 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 ad3069f099ff593a2196422244fa218f8942dfb9
|
||||
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 f8463172dc2d4bf9f74c78e9df9c83e942c63a94
|
||||
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
|
||||
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
|
||||
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
|
||||
@@ -182,8 +184,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 +198,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 +232,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,7 +264,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 main.mk 645d30a780fb304cf7fa79537b78728e32dd46fc
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@@ -275,37 +278,37 @@ 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 0b74bc28b2dc907cba03b5b4b3b81584273be699
|
||||
F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
|
||||
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
|
||||
F src/build.c 361f58b73aad7804f5706bf62d210bd9cd608041
|
||||
F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19
|
||||
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 b89dfbb8a385a45411c487355597c01f4ea4c882
|
||||
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 3c522beb5bf50a2efee1fca1e80fd40942e5817c
|
||||
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/loadext.c c5916a158f1fb74d955847c84f7ebdb6f5de9d8c
|
||||
F src/main.c fec97668771438033a7559883401067b139729e1
|
||||
F src/malloc.c 3a37ce6979a40f499d8cea9e9ab4e8517854d35d
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
@@ -318,7 +321,7 @@ 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
|
||||
@@ -333,24 +336,24 @@ 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/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 0bc9cd2e1cacfdc9cdc9a83884cc100f166e80a4
|
||||
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in dc35357824c6bb84a04acd4e99dee3e07299a8c6
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308
|
||||
F src/sqliteInt.h b6516bb2727876348b4e05aadd12237797626270
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h e21cc96bc24161df7373f6b24367cf580496889d
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
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 +367,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
|
||||
@@ -399,28 +402,28 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6
|
||||
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c d8f0afe1a1c66b97cbd87e5236f4e71d35ab4840
|
||||
F src/update.c dc37664095ca8604293ff1de2d9a547c6efb5e6e
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 5048103aa6bc9c01bf1a4620729256d1e873bb6c
|
||||
F src/vdbe.c 1e0bf8d6a2308ce916d444ef399921407fd5d972
|
||||
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
||||
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||
F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
|
||||
F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a
|
||||
F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6
|
||||
F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
|
||||
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
||||
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 e3724b7b31d1e13869308ed4125305364f7d823a
|
||||
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
|
||||
F src/wherecode.c a87238178f8c300fd27afec54326ea8d0a18baa2
|
||||
F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
|
||||
F src/wherecode.c cdfff200d065e7fb1af827b3274ed46b10a91d65
|
||||
F src/whereexpr.c e63244ca06c503e5f3c5b7f3c9aea0db826089ed
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -467,7 +470,7 @@ F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
|
||||
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex5.test 6f487290ce2a667c24517191651bfb8c7d86b6dc
|
||||
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
|
||||
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
@@ -621,7 +624,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
||||
F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c
|
||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
@@ -690,7 +693,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 +705,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 +753,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
|
||||
@@ -780,7 +783,7 @@ F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
|
||||
F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
|
||||
F test/index3.test fa3e49bbaa4f38091c9c742e36a1abe67c4ef1fc
|
||||
F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
|
||||
@@ -817,8 +820,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 83e6ebfb3cef6329853ab854403ec82b1787b537
|
||||
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
@@ -898,6 +901,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 +947,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 +1033,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 +1048,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 +1244,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 +1253,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
|
||||
@@ -1336,11 +1340,10 @@ F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/build-all-msvc.bat 761d8c82a1a529261291812732a853a1b4256d85 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
|
||||
@@ -1354,13 +1357,12 @@ 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/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
@@ -1370,7 +1372,6 @@ 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
|
||||
@@ -1389,7 +1390,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 59662cd2b65255a30e1a420331c07c51b644621a
|
||||
R cec1f3888d085a601a5cfb22d1afd716
|
||||
P c0c4b6b39648be9aa9b1e218e6d281ab17812536
|
||||
R 56b278dd241b099a55f2d39b092fbea8
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.9.2 *
|
||||
U drh
|
||||
Z 0ae71f6c4f92a526967039eb67c1881e
|
||||
Z ea2f853532ec0d2d6055c0d00a95dc82
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
0e317dda5dfd35b742afd70dacb5bfb39aa3fc4a
|
||||
bda77dda9697c463c3d0704014d51627fceee328
|
||||
+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);
|
||||
}
|
||||
|
||||
+9
-3
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6499,7 +6499,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 +7630,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 ==
|
||||
|
||||
+32
-31
@@ -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
|
||||
@@ -1271,6 +1271,30 @@ void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
|
||||
sqlite3ExprDelete(db, pSpan->pExpr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Backwards Compatibility Hack:
|
||||
**
|
||||
** Historical versions of SQLite accepted strings as column names in
|
||||
** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
|
||||
**
|
||||
** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
|
||||
** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
|
||||
**
|
||||
** This is goofy. But to preserve backwards compatibility we continue to
|
||||
** accept it. This routine does the necessary conversion. It converts
|
||||
** the expression given in its argument from a TK_STRING into a TK_ID
|
||||
** if the expression is just a TK_STRING with an optional COLLATE clause.
|
||||
** If the epxression is anything other than TK_STRING, the expression is
|
||||
** unchanged.
|
||||
*/
|
||||
static void sqlite3StringToId(Expr *p){
|
||||
if( p->op==TK_STRING ){
|
||||
p->op = TK_ID;
|
||||
}else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
|
||||
p->pLeft->op = TK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Designate the PRIMARY KEY for the table. pList is a list of names
|
||||
** of columns that form the primary key. If pList is NULL, then the
|
||||
@@ -1317,6 +1341,7 @@ void sqlite3AddPrimaryKey(
|
||||
for(i=0; i<nTerm; i++){
|
||||
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
|
||||
assert( pCExpr!=0 );
|
||||
sqlite3StringToId(pCExpr);
|
||||
if( pCExpr->op==TK_ID ){
|
||||
const char *zCName = pCExpr->u.zToken;
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
@@ -2855,30 +2880,6 @@ Index *sqlite3AllocateIndexObject(
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Backwards Compatibility Hack:
|
||||
**
|
||||
** Historical versions of SQLite accepted strings as column names in
|
||||
** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
|
||||
**
|
||||
** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
|
||||
** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
|
||||
**
|
||||
** This is goofy. But to preserve backwards compatibility we continue to
|
||||
** accept it. This routine does the necessary conversion. It converts
|
||||
** the expression given in its argument from a TK_STRING into a TK_ID
|
||||
** if the expression is just a TK_STRING with an optional COLLATE clause.
|
||||
** If the epxression is anything other than TK_STRING, the expression is
|
||||
** unchanged.
|
||||
*/
|
||||
static void sqlite3StringToId(Expr *p){
|
||||
if( p->op==TK_STRING ){
|
||||
p->op = TK_ID;
|
||||
}else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
|
||||
p->pLeft->op = TK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new index for an SQL table. pName1.pName2 is the name of the index
|
||||
** and pTblList is the name of the table that is to be indexed. Both will
|
||||
@@ -3136,7 +3137,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 +3166,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 +3220,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;
|
||||
|
||||
+12
-12
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
+22
-19
@@ -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,13 +1409,13 @@ 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;
|
||||
@@ -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 ){
|
||||
|
||||
+2
-2
@@ -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
|
||||
};
|
||||
@@ -615,7 +615,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
|
||||
** dummy pointer.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
static const sqlite3_api_routines sqlite3Apis = { 0 };
|
||||
static const sqlite3_api_routines sqlite3Apis;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+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
|
||||
|
||||
+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
|
||||
}
|
||||
|
||||
+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 */
|
||||
|
||||
+52
-59
@@ -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 */
|
||||
@@ -5363,8 +5356,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 +5379,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
|
||||
|
||||
+3
-3
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
+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) */
|
||||
|
||||
@@ -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
|
||||
|
||||
+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
|
||||
|
||||
+5
-5
@@ -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);
|
||||
}
|
||||
@@ -564,7 +564,7 @@ void sqlite3Update(
|
||||
}
|
||||
|
||||
if( !isView ){
|
||||
int j1 = 0; /* Address of jump instruction */
|
||||
int addr1 = 0; /* Address of jump instruction */
|
||||
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
|
||||
|
||||
/* Do constraint checks. */
|
||||
@@ -580,9 +580,9 @@ void sqlite3Update(
|
||||
/* Delete the index entries associated with the current record. */
|
||||
if( bReplace || chngKey ){
|
||||
if( pPk ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
||||
addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
||||
}else{
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
||||
addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
||||
}
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
@@ -593,7 +593,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
|
||||
}
|
||||
if( bReplace || chngKey ){
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
}
|
||||
|
||||
if( hasFK ){
|
||||
|
||||
+23
-17
@@ -5671,12 +5671,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 +5685,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;
|
||||
|
||||
+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
-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);
|
||||
|
||||
+40
-17
@@ -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;
|
||||
@@ -485,14 +485,20 @@ static LogEst estLog(LogEst N){
|
||||
** Convert OP_Column opcodes to OP_Copy in previously generated code.
|
||||
**
|
||||
** This routine runs over generated VDBE code and translates OP_Column
|
||||
** opcodes into OP_Copy, and OP_Rowid into OP_Null, when the table is being
|
||||
** accessed via co-routine instead of via table lookup.
|
||||
** opcodes into OP_Copy when the table is being accessed via co-routine
|
||||
** instead of via table lookup.
|
||||
**
|
||||
** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on
|
||||
** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero,
|
||||
** then each OP_Rowid is transformed into an instruction to increment the
|
||||
** value stored in its output register.
|
||||
*/
|
||||
static void translateColumnToCopy(
|
||||
Vdbe *v, /* The VDBE containing code to translate */
|
||||
int iStart, /* Translate from this opcode to the end */
|
||||
int iTabCur, /* OP_Column/OP_Rowid references to this table */
|
||||
int iRegister /* The first column is in this register */
|
||||
int iRegister, /* The first column is in this register */
|
||||
int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */
|
||||
){
|
||||
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
|
||||
int iEnd = sqlite3VdbeCurrentAddr(v);
|
||||
@@ -504,9 +510,16 @@ static void translateColumnToCopy(
|
||||
pOp->p2 = pOp->p3;
|
||||
pOp->p3 = 0;
|
||||
}else if( pOp->opcode==OP_Rowid ){
|
||||
pOp->opcode = OP_Null;
|
||||
pOp->p1 = 0;
|
||||
pOp->p3 = 0;
|
||||
if( bIncrRowid ){
|
||||
/* Increment the value stored in the P2 operand of the OP_Rowid. */
|
||||
pOp->opcode = OP_AddImm;
|
||||
pOp->p1 = pOp->p2;
|
||||
pOp->p2 = 1;
|
||||
}else{
|
||||
pOp->opcode = OP_Null;
|
||||
pOp->p1 = 0;
|
||||
pOp->p3 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -614,6 +627,8 @@ static void constructAutomaticIndex(
|
||||
Expr *pPartial = 0; /* Partial Index Expression */
|
||||
int iContinue = 0; /* Jump here to skip excluded rows */
|
||||
struct SrcList_item *pTabItem; /* FROM clause term being indexed */
|
||||
int addrCounter; /* Address where integer counter is initialized */
|
||||
int regBase; /* Array of registers where record is assembled */
|
||||
|
||||
/* Generate code to skip over the creation and initialization of the
|
||||
** transient index on 2nd and subsequent iterations of the loop. */
|
||||
@@ -727,7 +742,7 @@ static void constructAutomaticIndex(
|
||||
}
|
||||
}
|
||||
assert( n==nKeyCol );
|
||||
pIdx->aiColumn[n] = -1;
|
||||
pIdx->aiColumn[n] = XN_ROWID;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
|
||||
/* Create the automatic index */
|
||||
@@ -742,6 +757,7 @@ static void constructAutomaticIndex(
|
||||
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
int regYield = pTabItem->regReturn;
|
||||
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
|
||||
VdbeCoverage(v);
|
||||
@@ -755,12 +771,15 @@ static void constructAutomaticIndex(
|
||||
pLoop->wsFlags |= WHERE_PARTIALIDX;
|
||||
}
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
|
||||
regBase = sqlite3GenerateIndexKey(
|
||||
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
|
||||
);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult);
|
||||
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
|
||||
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1);
|
||||
sqlite3VdbeGoto(v, addrTop);
|
||||
pTabItem->fg.viaCoroutine = 0;
|
||||
}else{
|
||||
@@ -2242,7 +2261,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 +2463,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 +3251,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 +3284,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
revIdx = pIndex->aSortOrder[j];
|
||||
if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
|
||||
}else{
|
||||
iColumn = -1;
|
||||
iColumn = XN_ROWID;
|
||||
revIdx = 0;
|
||||
}
|
||||
|
||||
@@ -4506,7 +4528,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
*/
|
||||
if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){
|
||||
translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur,
|
||||
pTabItem->regResult);
|
||||
pTabItem->regResult, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4562,6 +4584,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 ){
|
||||
|
||||
+8
-7
@@ -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);
|
||||
@@ -1323,7 +1324,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 +1343,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 );
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix autoindex5
|
||||
|
||||
# Schema is from the Debian security database
|
||||
#
|
||||
@@ -103,6 +104,26 @@ do_execsql_test autoindex5-1.1 {
|
||||
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
|
||||
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
|
||||
} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that ticket [8a2adec1] has been fixed.
|
||||
#
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE one(o);
|
||||
INSERT INTO one DEFAULT VALUES;
|
||||
|
||||
CREATE TABLE t1(x, z);
|
||||
INSERT INTO t1 VALUES('aaa', 4.0);
|
||||
INSERT INTO t1 VALUES('aaa', 4.0);
|
||||
CREATE VIEW vvv AS
|
||||
SELECT * FROM t1
|
||||
UNION ALL
|
||||
SELECT 0, 0 WHERE 0;
|
||||
|
||||
SELECT (
|
||||
SELECT sum(z) FROM vvv WHERE x='aaa'
|
||||
) FROM one;
|
||||
} {8.0}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -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.
@@ -62,6 +62,21 @@ do_execsql_test index3-2.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a FROM t1 WHERE b='ab005xy' COLLATE nocase;
|
||||
} {/USING INDEX/}
|
||||
do_execsql_test index3-2.3 {
|
||||
SELECT name FROM sqlite_master WHERE tbl_name='t1' ORDER BY name
|
||||
} {sqlite_autoindex_t1_1 sqlite_autoindex_t1_2 t1 t1c t1d}
|
||||
do_execsql_test index3-2.4 {
|
||||
CREATE TABLE t2a(a integer, b, PRIMARY KEY(a));
|
||||
CREATE TABLE t2b("a" integer, b, PRIMARY KEY("a"));
|
||||
CREATE TABLE t2c([a] integer, b, PRIMARY KEY([a]));
|
||||
CREATE TABLE t2d('a' integer, b, PRIMARY KEY('a'));
|
||||
}
|
||||
do_execsql_test index3-2.5 {
|
||||
SELECT name FROM sqlite_master WHERE tbl_name LIKE 't2_' ORDER BY name
|
||||
} {t2a t2b t2c t2d}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# This test corrupts the database file so it must be the last test
|
||||
|
||||
+5
-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"]}
|
||||
|
||||
+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
|
||||
#
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
** A utility for printing the differences between two SQLite database files.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define PAGESIZE 1024
|
||||
static int db1 = -1;
|
||||
static int db2 = -1;
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int iPg;
|
||||
unsigned char a1[PAGESIZE], a2[PAGESIZE];
|
||||
if( argc!=3 ){
|
||||
fprintf(stderr,"Usage: %s FILENAME FILENAME\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
db1 = open(argv[1], O_RDONLY);
|
||||
if( db1<0 ){
|
||||
fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
db2 = open(argv[2], O_RDONLY);
|
||||
if( db2<0 ){
|
||||
fprintf(stderr,"%s: can't open %s\n", argv[0], argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
iPg = 1;
|
||||
while( read(db1, a1, PAGESIZE)==PAGESIZE && read(db2,a2,PAGESIZE)==PAGESIZE ){
|
||||
if( memcmp(a1,a2,PAGESIZE) ){
|
||||
printf("Page %d\n", iPg);
|
||||
}
|
||||
iPg++;
|
||||
}
|
||||
printf("%d pages checked\n", iPg-1);
|
||||
close(db1);
|
||||
close(db2);
|
||||
}
|
||||
@@ -726,12 +726,6 @@ int main(int argc, char **argv){
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
{
|
||||
extern int sqlite3_json_init(sqlite3*);
|
||||
sqlite3_json_init(db);
|
||||
}
|
||||
#endif
|
||||
sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
|
||||
sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
|
||||
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
|
||||
|
||||
+4
-1
@@ -211,7 +211,8 @@ proc copy_file {filename} {
|
||||
puts $out "#if 0"
|
||||
} elseif {!$linemacros && [regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
|
||||
} elseif {$addstatic
|
||||
&& ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
|
||||
# Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
|
||||
# functions if this header file does not need it.
|
||||
if {![info exists varonly_hdr($tail)]
|
||||
@@ -378,6 +379,8 @@ foreach file {
|
||||
fts3_icu.c
|
||||
sqlite3rbu.c
|
||||
dbstat.c
|
||||
json1.c
|
||||
fts5.c
|
||||
} {
|
||||
copy_file tsrc/$file
|
||||
}
|
||||
|
||||
+2
-1
@@ -71,6 +71,7 @@ fconfigure stdout -translation lf
|
||||
set filelist [subst {
|
||||
$TOP/src/sqlite.h.in
|
||||
$TOP/ext/rtree/sqlite3rtree.h
|
||||
$TOP/ext/fts5/fts5.h
|
||||
}]
|
||||
|
||||
# These are the functions that accept a variable number of arguments. They
|
||||
@@ -97,7 +98,7 @@ foreach file $filelist {
|
||||
# File sqlite3rtree.h contains a line "#include <sqlite3.h>". Omit this
|
||||
# line when copying sqlite3rtree.h into sqlite3.h.
|
||||
#
|
||||
if {[string match {*#include*<sqlite3.h>*} $line]} continue
|
||||
if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue
|
||||
|
||||
regsub -- --VERS-- $line $zVersion line
|
||||
regsub -- --VERSION-NUMBER-- $line $nVersion line
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#
|
||||
# Extract opcode documentation for sqliteVdbe.c and generate HTML
|
||||
#
|
||||
BEGIN {
|
||||
print "<html><body bgcolor=white>"
|
||||
print "<h1>SQLite Virtual Database Engine Opcodes</h1>"
|
||||
print "<table>"
|
||||
}
|
||||
/ Opcode: /,/\*\// {
|
||||
if( $2=="Opcode:" ){
|
||||
printf "<tr><td>%s %s %s %s</td>\n<td>\n", $3, $4, $5, $6
|
||||
}else if( $1=="*/" ){
|
||||
printf "</td></tr>\n"
|
||||
}else if( NF>1 ){
|
||||
sub(/^ *\*\* /,"")
|
||||
gsub(/</,"<")
|
||||
gsub(/&/,"&")
|
||||
print
|
||||
}
|
||||
}
|
||||
END {
|
||||
print "</table></body></html>"
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
# Run this TCL script using "testfixture" in order get a report that shows
|
||||
# how much disk space is used by a particular data to actually store data
|
||||
# versus how much space is unused.
|
||||
#
|
||||
|
||||
# Get the name of the database to analyze
|
||||
#
|
||||
if {[llength $argv]!=1} {
|
||||
puts stderr "Usage: $argv0 database-name"
|
||||
exit 1
|
||||
}
|
||||
set file_to_analyze [lindex $argv 0]
|
||||
|
||||
# Open the database
|
||||
#
|
||||
sqlite db [lindex $argv 0]
|
||||
set DB [btree_open [lindex $argv 0]]
|
||||
|
||||
# Output the schema for the generated report
|
||||
#
|
||||
puts \
|
||||
{BEGIN;
|
||||
CREATE TABLE space_used(
|
||||
name clob, -- Name of a table or index in the database file
|
||||
is_index boolean, -- TRUE if it is an index, false for a table
|
||||
payload int, -- Total amount of data stored in this table or index
|
||||
pri_pages int, -- Number of primary pages used
|
||||
ovfl_pages int, -- Number of overflow pages used
|
||||
pri_unused int, -- Number of unused bytes on primary pages
|
||||
ovfl_unused int -- Number of unused bytes on overflow pages
|
||||
);}
|
||||
|
||||
# This query will be used to find the root page number for every index and
|
||||
# table in the database.
|
||||
#
|
||||
set sql {
|
||||
SELECT name, type, rootpage FROM sqlite_master
|
||||
UNION ALL
|
||||
SELECT 'sqlite_master', 'table', 2
|
||||
ORDER BY 1
|
||||
}
|
||||
|
||||
# Initialize variables used for summary statistics.
|
||||
#
|
||||
set total_size 0
|
||||
set total_primary 0
|
||||
set total_overflow 0
|
||||
set total_unused_primary 0
|
||||
set total_unused_ovfl 0
|
||||
|
||||
# Analyze every table in the database, one at a time.
|
||||
#
|
||||
foreach {name type rootpage} [db eval $sql] {
|
||||
set cursor [btree_cursor $DB $rootpage 0]
|
||||
set go [btree_first $cursor]
|
||||
set size 0
|
||||
catch {unset pg_used}
|
||||
set unused_ovfl 0
|
||||
set n_overflow 0
|
||||
while {$go==0} {
|
||||
set payload [btree_payload_size $cursor]
|
||||
incr size $payload
|
||||
set stat [btree_cursor_dump $cursor]
|
||||
set pgno [lindex $stat 0]
|
||||
set freebytes [lindex $stat 4]
|
||||
set pg_used($pgno) $freebytes
|
||||
if {$payload>238} {
|
||||
set n [expr {($payload-238+1019)/1020}]
|
||||
incr n_overflow $n
|
||||
incr unused_ovfl [expr {$n*1020+238-$payload}]
|
||||
}
|
||||
set go [btree_next $cursor]
|
||||
}
|
||||
btree_close_cursor $cursor
|
||||
set n_primary [llength [array names pg_used]]
|
||||
set unused_primary 0
|
||||
foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
|
||||
regsub -all ' $name '' name
|
||||
puts -nonewline "INSERT INTO space_used VALUES('$name'"
|
||||
puts -nonewline ",[expr {$type=="index"}]"
|
||||
puts ",$size,$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
|
||||
incr total_size $size
|
||||
incr total_primary $n_primary
|
||||
incr total_overflow $n_overflow
|
||||
incr total_unused_primary $unused_primary
|
||||
incr total_unused_ovfl $unused_ovfl
|
||||
}
|
||||
|
||||
# Output summary statistics:
|
||||
#
|
||||
puts "-- Total payload size: $total_size"
|
||||
puts "-- Total pages used: $total_primary primary and $total_overflow overflow"
|
||||
set file_pgcnt [expr {[file size [lindex $argv 0]]/1024}]
|
||||
puts -nonewline "-- Total unused bytes on primary pages: $total_unused_primary"
|
||||
if {$total_primary>0} {
|
||||
set upp [expr {$total_unused_primary/$total_primary}]
|
||||
puts " (avg $upp bytes/page)"
|
||||
} else {
|
||||
puts ""
|
||||
}
|
||||
puts -nonewline "-- Total unused bytes on overflow pages: $total_unused_ovfl"
|
||||
if {$total_overflow>0} {
|
||||
set upp [expr {$total_unused_ovfl/$total_overflow}]
|
||||
puts " (avg $upp bytes/page)"
|
||||
} else {
|
||||
puts ""
|
||||
}
|
||||
set n_free [expr {$file_pgcnt-$total_primary-$total_overflow}]
|
||||
if {$n_free>0} {incr n_free -1}
|
||||
puts "-- Total pages on freelist: $n_free"
|
||||
puts "COMMIT;"
|
||||
Reference in New Issue
Block a user