Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 952dce9160 |
+19
-28
@@ -165,7 +165,6 @@ LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
|
||||
###############################################################################
|
||||
|
||||
USE_AMALGAMATION = @USE_AMALGAMATION@
|
||||
AMALGAMATION_LINE_MACROS = @AMALGAMATION_LINE_MACROS@
|
||||
|
||||
# Object files for the SQLite library (non-amalgamation).
|
||||
#
|
||||
@@ -180,7 +179,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 json.lo legacy.lo loadext.lo \
|
||||
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
@@ -234,7 +233,6 @@ SRC = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/json.c \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
@@ -367,6 +365,7 @@ SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Generated source code files
|
||||
@@ -433,7 +432,7 @@ TESTSRC = \
|
||||
$(TOP)/ext/fts3/fts3_term.c \
|
||||
$(TOP)/ext/fts3/fts3_test.c \
|
||||
$(TOP)/ext/session/test_session.c \
|
||||
$(TOP)/ext/rbu/test_rbu.c
|
||||
$(TOP)/ext/rbu/test_rbu.c
|
||||
|
||||
# Statically linked extensions
|
||||
#
|
||||
@@ -441,7 +440,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/test_expert.c \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/carray.c \
|
||||
$(TOP)/ext/misc/cksumvfs.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
@@ -460,7 +458,6 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/prefixes.c \
|
||||
$(TOP)/ext/misc/qpvtab.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
@@ -469,8 +466,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/rtree/test_rtreedoc.c
|
||||
$(TOP)/ext/userauth/userauth.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
#
|
||||
@@ -524,8 +520,7 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c \
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/misc/stmt.c \
|
||||
fts5.c
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
#
|
||||
@@ -609,7 +604,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
|
||||
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
SHELL_OPT = -DSQLITE_ENABLE_FTS4
|
||||
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
|
||||
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_RTREE
|
||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
@@ -619,13 +614,15 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUZZERSHELL_OPT =
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
|
||||
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
@@ -696,6 +693,7 @@ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
|
||||
DBFUZZ2_OPTS = \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_DESERIALIZE \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
@@ -759,7 +757,7 @@ mptest: mptester$(TEXE)
|
||||
touch .target_source
|
||||
|
||||
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS)
|
||||
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
|
||||
cp tsrc/sqlite3ext.h .
|
||||
cp $(TOP)/ext/session/sqlite3session.h .
|
||||
|
||||
@@ -874,9 +872,6 @@ hash.lo: $(TOP)/src/hash.c $(HDR)
|
||||
insert.lo: $(TOP)/src/insert.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c
|
||||
|
||||
json.lo: $(TOP)/src/json.c
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c
|
||||
|
||||
legacy.lo: $(TOP)/src/legacy.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c
|
||||
|
||||
@@ -1092,7 +1087,6 @@ SHELL_SRC = \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
@@ -1180,6 +1174,9 @@ userauth.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
stmt.lo: $(TOP)/ext/misc/stmt.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
@@ -1236,6 +1233,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||
@@ -1252,10 +1250,7 @@ coretestprogs: $(TESTPROGS)
|
||||
testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)
|
||||
|
||||
# A very detailed test running most or all test cases
|
||||
fulltest: alltest fuzztest
|
||||
|
||||
# Run most or all tcl test cases
|
||||
alltest: $(TESTPROGS)
|
||||
fulltest: $(TESTPROGS) fuzztest
|
||||
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
|
||||
|
||||
# Really really long testing
|
||||
@@ -1272,7 +1267,7 @@ fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuz
|
||||
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
|
||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
|
||||
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
|
||||
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
@@ -1434,9 +1429,6 @@ threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
|
||||
threadtest: threadtest3$(TEXE)
|
||||
./threadtest3$(TEXE)
|
||||
|
||||
threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
|
||||
$(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS)
|
||||
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
|
||||
|
||||
@@ -1490,7 +1482,6 @@ clean:
|
||||
rm -f sqldiff sqldiff.exe
|
||||
rm -f dbhash dbhash.exe
|
||||
rm -f fts5.* fts5parse.*
|
||||
rm -f threadtest5
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.log config.status libtool Makefile sqlite3.pc
|
||||
|
||||
+32
-50
@@ -235,9 +235,8 @@ DEBUG = 0
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
# By default, use --linemacros=1 argument to the mksqlite3c.tcl tool, which
|
||||
# is used to build the amalgamation. This can be turned off to ease debug
|
||||
# of the amalgamation away from the source tree.
|
||||
# Disable use of the --linemacros argument to the mksqlite3c.tcl tool, which
|
||||
# is used to build the amalgamation.
|
||||
#
|
||||
!IFNDEF NO_LINEMACROS
|
||||
NO_LINEMACROS = 0
|
||||
@@ -363,10 +362,12 @@ SQLITE_TCL_DEP =
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -579,17 +580,17 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
@@ -788,9 +789,9 @@ MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
|
||||
|
||||
!IFNDEF MKSQLITE3C_ARGS
|
||||
!IF $(DEBUG)>1 && $(NO_LINEMACROS)==0
|
||||
MKSQLITE3C_ARGS = --linemacros=1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS = --linemacros=0
|
||||
MKSQLITE3C_ARGS =
|
||||
!ENDIF
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
|
||||
@@ -1247,7 +1248,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
fts5.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo json.lo legacy.lo loadext.lo \
|
||||
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
@@ -1314,7 +1315,6 @@ SRC00 = \
|
||||
$(TOP)\src\global.c \
|
||||
$(TOP)\src\hash.c \
|
||||
$(TOP)\src\insert.c \
|
||||
$(TOP)\src\json.c \
|
||||
$(TOP)\src\legacy.c \
|
||||
$(TOP)\src\loadext.c \
|
||||
$(TOP)\src\main.c \
|
||||
@@ -1445,6 +1445,7 @@ SRC07 = \
|
||||
$(TOP)\ext\rtree\rtree.c \
|
||||
$(TOP)\ext\session\sqlite3session.c \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||
$(TOP)\ext\misc\json1.c \
|
||||
$(TOP)\ext\misc\stmt.c
|
||||
|
||||
# Extension header files, part 1.
|
||||
@@ -1551,7 +1552,7 @@ TESTSRC = \
|
||||
$(TOP)\ext\fts3\fts3_term.c \
|
||||
$(TOP)\ext\fts3\fts3_test.c \
|
||||
$(TOP)\ext\rbu\test_rbu.c \
|
||||
$(TOP)\ext\session\test_session.c
|
||||
$(TOP)\ext\session\test_session.c
|
||||
|
||||
# Statically linked extensions.
|
||||
#
|
||||
@@ -1559,7 +1560,6 @@ TESTEXT = \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\test_expert.c \
|
||||
$(TOP)\ext\misc\amatch.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\carray.c \
|
||||
$(TOP)\ext\misc\cksumvfs.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
@@ -1578,16 +1578,13 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\normalize.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\prefixes.c \
|
||||
$(TOP)\ext\misc\qpvtab.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\spellfix.c \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
$(TOP)\ext\rtree\test_rtreedoc.c \
|
||||
fts5.c
|
||||
$(TOP)\ext\misc\wholenumber.c
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
#
|
||||
@@ -1690,16 +1687,17 @@ FUZZDATA = \
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
# Extra compiler options for various test tools.
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS =
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS5
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
@@ -1990,9 +1988,6 @@ hash.lo: $(TOP)\src\hash.c $(HDR)
|
||||
insert.lo: $(TOP)\src\insert.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c
|
||||
|
||||
json.lo: $(TOP)\src\json.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\json.c
|
||||
|
||||
legacy.lo: $(TOP)\src\legacy.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c
|
||||
|
||||
@@ -2214,11 +2209,10 @@ SHELL_SRC = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
@@ -2301,6 +2295,9 @@ fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
|
||||
|
||||
json1.lo: $(TOP)\ext\misc\json1.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\json1.c
|
||||
|
||||
stmt.lo: $(TOP)\ext\misc\stmt.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\stmt.c
|
||||
|
||||
@@ -2392,6 +2389,8 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
@@ -2437,9 +2436,7 @@ coretestprogs: $(TESTPROGS)
|
||||
|
||||
testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe
|
||||
|
||||
fulltest: alltest fuzztest
|
||||
|
||||
alltest: $(TESTPROGS)
|
||||
fulltest: $(TESTPROGS) fuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
|
||||
|
||||
@@ -2467,11 +2464,7 @@ quicktest: testfixture.exe sourcetest
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
tcltest: testfixture.exe
|
||||
test: $(TESTPROGS) sourcetest fuzztest
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
|
||||
|
||||
@@ -2593,17 +2586,6 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
THREADTEST3_SRC = \
|
||||
$(TOP)\test\threadtest3.c \
|
||||
$(TOP)\test\tt3_checkpoint.c \
|
||||
$(TOP)\test\tt3_index.c \
|
||||
$(TOP)\test\tt3_vacuum.c \
|
||||
$(TOP)\test\tt3_stress.c \
|
||||
$(TOP)\test\tt3_lookaside1.c
|
||||
|
||||
threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
LSMDIR=$(TOP)\ext\lsm1
|
||||
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||
|
||||
@@ -2641,7 +2623,7 @@ clean:
|
||||
del /Q sqlite-*-output.vsix 2>NUL
|
||||
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
|
||||
del /Q sqltclsh.* 2>NUL
|
||||
del /Q dbfuzz.exe sessionfuzz.exe threadtest3.exe 2>NUL
|
||||
del /Q dbfuzz.exe sessionfuzz.exe 2>NUL
|
||||
del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
|
||||
del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1 align="center">SQLite Source Repository</h1>
|
||||
|
||||
This repository contains the complete source code for the
|
||||
[SQLite database engine](https://sqlite.org/). Some test scripts
|
||||
This repository contains the complete source code for the
|
||||
[SQLite database engine](https://sqlite.org/). Some test scripts
|
||||
are also included. However, many other test scripts
|
||||
and most of the documentation are managed separately.
|
||||
|
||||
@@ -15,7 +15,7 @@ The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.
|
||||
If you are reading this on GitHub or some other Git repository or service,
|
||||
then you are looking at a mirror. The names of check-ins and
|
||||
other artifacts in a Git mirror are different from the official
|
||||
names for those objects. The official names for check-ins are
|
||||
names for those objects. The offical names for check-ins are
|
||||
found in a footer on the check-in comment for authorized mirrors.
|
||||
The official check-in name can also be seen in the `manifest.uuid` file
|
||||
in the root of the tree. Always use the official name, not the
|
||||
@@ -30,7 +30,7 @@ verify its integrity, there are hints on how to do that in the
|
||||
If you do not want to use Fossil, you can download tarballs or ZIP
|
||||
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
|
||||
* Latest trunk check-in as
|
||||
* Lastest trunk check-in as
|
||||
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
|
||||
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
|
||||
@@ -47,28 +47,28 @@ archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
then click on the "Tarball" or "ZIP Archive" links on the information
|
||||
page.
|
||||
|
||||
If you do want to use Fossil to check out the source tree,
|
||||
If you do want to use Fossil to check out the source tree,
|
||||
first install Fossil version 2.0 or later.
|
||||
(Source tarballs and precompiled binaries available
|
||||
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
executable file and put that file someplace on your $PATH.)
|
||||
Then run commands like this:
|
||||
|
||||
mkdir -p ~/sqlite ~/Fossils
|
||||
mkdir ~/sqlite
|
||||
cd ~/sqlite
|
||||
fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
|
||||
fossil open ~/Fossils/sqlite.fossil
|
||||
|
||||
fossil clone https://www.sqlite.org/src sqlite.fossil
|
||||
fossil open sqlite.fossil
|
||||
|
||||
After setting up a repository using the steps above, you can always
|
||||
update to the latest version using:
|
||||
update to the lastest version using:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
Or type "fossil ui" to get a web-based user interface.
|
||||
|
||||
## Compiling for Unix-like systems
|
||||
## Compiling
|
||||
|
||||
First create a directory in which to place
|
||||
the build products. It is recommended, but not required, that the
|
||||
@@ -94,22 +94,22 @@ script does not work out for you, there is a generic makefile named
|
||||
can copy and edit to suit your needs. Comments on the generic makefile
|
||||
show what changes are needed.
|
||||
|
||||
## Using MSVC for Windows systems
|
||||
## Using MSVC
|
||||
|
||||
On Windows, all applicable build products can be compiled with MSVC.
|
||||
First open the command prompt window associated with the desired compiler
|
||||
version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE
|
||||
with the provided "Makefile.msc" to build one of the supported targets.
|
||||
|
||||
For example, from the parent directory of the source subtree named "sqlite":
|
||||
For example:
|
||||
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f ..\sqlite\Makefile.msc TOP=..\sqlite
|
||||
nmake /f ..\sqlite\Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f ..\sqlite\Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f ..\sqlite\Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f ..\sqlite\Makefile.msc test TOP=..\sqlite
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
|
||||
There are several build options that can be set via the NMAKE command
|
||||
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
|
||||
@@ -136,7 +136,7 @@ the "tclsqlite.c" file which implements the
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
|
||||
Test scripts and programs are found in the **test/** subdirectory.
|
||||
Additional test code is found in other source repositories.
|
||||
Addtional test code is found in other source repositories.
|
||||
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
|
||||
additional information.
|
||||
|
||||
@@ -170,7 +170,7 @@ at just the right spots. Note that comment text in the sqlite3.h file is
|
||||
used to generate much of the SQLite API documentation. The Tcl scripts
|
||||
used to generate that documentation are in a separate source repository.
|
||||
|
||||
The SQL language parser is **parse.c** which is generated from a grammar in
|
||||
The SQL language parser is **parse.c** which is generate from a grammar in
|
||||
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
|
||||
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
|
||||
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
|
||||
@@ -180,7 +180,7 @@ generates parse.c.
|
||||
|
||||
The **opcodes.h** header file contains macros that define the numbers
|
||||
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
|
||||
file is generated by scanning the src/vdbe.c source file. The
|
||||
file is generated by the scanning the src/vdbe.c source file. The
|
||||
Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
|
||||
A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
|
||||
the **opcodes.c** source file, which contains a reverse mapping from
|
||||
@@ -237,7 +237,7 @@ prepared statements, the description of
|
||||
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
|
||||
|
||||
Years of effort have gone into optimizing SQLite, both
|
||||
Years of effort have gone into optimizating SQLite, both
|
||||
for small size and high performance. And optimizations tend to result in
|
||||
complex code. So there is a lot of complexity in the current SQLite
|
||||
implementation. It will not be the easiest library in the world to hack.
|
||||
@@ -294,11 +294,11 @@ Key files:
|
||||
building the "testfixture.exe" program. The testfixture.exe program is
|
||||
an enhanced Tcl shell. The testfixture.exe program runs scripts in the
|
||||
test/ folder to validate the core SQLite code. The testfixture program
|
||||
(and some other test programs too) is built and run when you type
|
||||
(and some other test programs too) is build and run when you type
|
||||
"make test".
|
||||
|
||||
* **ext/misc/json1.c** - This file implements the various JSON functions
|
||||
that are built into SQLite.
|
||||
that are build into SQLite.
|
||||
|
||||
There are many other source files. Each has a succinct header comment that
|
||||
describes its purpose and role within the larger system.
|
||||
@@ -307,13 +307,11 @@ describes its purpose and role within the larger system.
|
||||
## Verifying Code Authenticity
|
||||
|
||||
The `manifest` file at the root directory of the source tree
|
||||
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
|
||||
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
|
||||
older files) for every source file in the repository.
|
||||
The name of the version of the entire source tree is just the
|
||||
SHA3-256 hash of the `manifest` file itself, possibly with the
|
||||
last line of that file omitted if the last line begins with
|
||||
"`# Remove this line`".
|
||||
The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
The SHA3-256 hash of the `manifest`
|
||||
file itself is the official name of the version of the source tree that you
|
||||
have. The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
`manifest` file. If all of the above hash comparisons are correct, then
|
||||
you can be confident that your source tree is authentic and unadulterated.
|
||||
|
||||
|
||||
@@ -285,10 +285,12 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -301,9 +303,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
!ENDIF
|
||||
|
||||
# Always enable math functions on Windows
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
||||
|
||||
# Should the rbu extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
@@ -501,12 +500,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
@@ -958,6 +957,7 @@ LIBRESOBJS =
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ may be specified in this manner as some require the amalgamation to be built
|
||||
with them enabled (see http://www.sqlite.org/compile.html). For example, the
|
||||
following will work:
|
||||
|
||||
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"
|
||||
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
|
||||
|
||||
However, the following will not compile unless the amalgamation was built
|
||||
with it enabled:
|
||||
|
||||
+11
-40
@@ -111,34 +111,14 @@ AC_MSG_CHECKING([for whether to support dynamic extensions])
|
||||
AC_MSG_RESULT($enable_dynamic_extensions)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-math
|
||||
#
|
||||
AC_ARG_ENABLE(math, [AS_HELP_STRING(
|
||||
[--enable-math], [SQL math functions [default=yes]])],
|
||||
[], [enable_math=yes])
|
||||
AC_MSG_CHECKING([SQL math functions])
|
||||
if test x"$enable_math" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS"
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts4
|
||||
#
|
||||
AC_ARG_ENABLE(fts4, [AS_HELP_STRING(
|
||||
[--enable-fts4], [include fts4 support [default=yes]])],
|
||||
[], [enable_fts4=yes])
|
||||
AC_MSG_CHECKING([FTS4 extension])
|
||||
if test x"$enable_fts4" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -148,12 +128,8 @@ fi
|
||||
AC_ARG_ENABLE(fts3, [AS_HELP_STRING(
|
||||
[--enable-fts3], [include fts3 support [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([FTS3 extension])
|
||||
if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -163,13 +139,20 @@ fi
|
||||
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
|
||||
[--enable-fts5], [include fts5 support [default=yes]])],
|
||||
[], [enable_fts5=yes])
|
||||
AC_MSG_CHECKING([FTS5 extension])
|
||||
if test x"$enable_fts5" = "xyes"; then
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(log, m)
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5"
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-json1
|
||||
#
|
||||
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
|
||||
[--enable-json1], [include json1 support [default=yes]])],
|
||||
[],[enable_json1=yes])
|
||||
if test x"$enable_json1" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -179,12 +162,8 @@ fi
|
||||
AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
|
||||
[--enable-rtree], [include rtree support [default=yes]])],
|
||||
[], [enable_rtree=yes])
|
||||
AC_MSG_CHECKING([RTREE extension])
|
||||
if test x"$enable_rtree" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -194,12 +173,8 @@ fi
|
||||
AC_ARG_ENABLE(session, [AS_HELP_STRING(
|
||||
[--enable-session], [enable the session extension [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Session extension])
|
||||
if test x"$enable_session" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -209,13 +184,9 @@ fi
|
||||
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
|
||||
[--enable-debug], [build with debugging features enabled [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Build type])
|
||||
if test x"$enable_debug" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
|
||||
CFLAGS="-g -O0"
|
||||
AC_MSG_RESULT([debug])
|
||||
else
|
||||
AC_MSG_RESULT([release])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
|
||||
+47
-168
@@ -14,10 +14,13 @@
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#include <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
#define NO_SHLWAPI_GDI
|
||||
#define NO_SHLWAPI_STREAM
|
||||
#define NO_SHLWAPI_REG
|
||||
#include <shlwapi.h>
|
||||
#pragma comment (lib, "user32.lib")
|
||||
#pragma comment (lib, "kernel32.lib")
|
||||
#endif
|
||||
#pragma comment (lib, "shlwapi.lib")
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -36,15 +39,15 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* protos */
|
||||
|
||||
static int CheckForCompilerFeature(const char *option);
|
||||
static int CheckForLinkerFeature(char **options, int count);
|
||||
static int CheckForLinkerFeature(const char *option);
|
||||
static int IsIn(const char *string, const char *substring);
|
||||
static int SubstituteFile(const char *substs, const char *filename);
|
||||
static int QualifyPath(const char *path);
|
||||
static int LocateDependency(const char *keyfile);
|
||||
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
|
||||
static const char *GetVersionFromFile(const char *filename, const char *match);
|
||||
static DWORD WINAPI ReadFromPipe(LPVOID args);
|
||||
|
||||
/* globals */
|
||||
@@ -56,8 +59,8 @@ typedef struct {
|
||||
char buffer[STATICBUFFERSIZE];
|
||||
} pipeinfo;
|
||||
|
||||
pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
|
||||
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};
|
||||
pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
|
||||
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
|
||||
|
||||
/*
|
||||
* exitcodes: 0 == no, 1 == yes, 2 == error
|
||||
@@ -71,7 +74,6 @@ main(
|
||||
char msg[300];
|
||||
DWORD dwWritten;
|
||||
int chars;
|
||||
const char *s;
|
||||
|
||||
/*
|
||||
* Make sure children (cl.exe and link.exe) are kept quiet.
|
||||
@@ -100,16 +102,16 @@ main(
|
||||
}
|
||||
return CheckForCompilerFeature(argv[2]);
|
||||
case 'l':
|
||||
if (argc < 3) {
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -l <linker option> ?<mandatory option> ...?\n"
|
||||
"usage: %s -l <linker option>\n"
|
||||
"Tests for whether link.exe supports an option\n"
|
||||
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return CheckForLinkerFeature(&argv[2], argc-2);
|
||||
return CheckForLinkerFeature(argv[2]);
|
||||
case 'f':
|
||||
if (argc == 2) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
@@ -151,13 +153,8 @@ main(
|
||||
&dwWritten, NULL);
|
||||
return 0;
|
||||
}
|
||||
s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
|
||||
if (s && *s) {
|
||||
printf("%s\n", s);
|
||||
return 0;
|
||||
} else
|
||||
return 1; /* Version not found. Return non-0 exit code */
|
||||
|
||||
printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
|
||||
return 0;
|
||||
case 'Q':
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
@@ -169,18 +166,6 @@ main(
|
||||
return 2;
|
||||
}
|
||||
return QualifyPath(argv[2]);
|
||||
|
||||
case 'L':
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -L keypath\n"
|
||||
"Emit the fully qualified path of directory containing keypath\n"
|
||||
"exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return LocateDependency(argv[2]);
|
||||
}
|
||||
}
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
@@ -275,7 +260,7 @@ CheckForCompilerFeature(
|
||||
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
|
||||
(300-chars), 0);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
|
||||
return 2;
|
||||
@@ -328,8 +313,7 @@ CheckForCompilerFeature(
|
||||
|
||||
static int
|
||||
CheckForLinkerFeature(
|
||||
char **options,
|
||||
int count)
|
||||
const char *option)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
@@ -338,8 +322,7 @@ CheckForLinkerFeature(
|
||||
char msg[300];
|
||||
BOOL ok;
|
||||
HANDLE hProcess, h, pipeThreads[2];
|
||||
int i;
|
||||
char cmdline[255];
|
||||
char cmdline[100];
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
@@ -385,11 +368,7 @@ CheckForLinkerFeature(
|
||||
* Append our option for testing.
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
lstrcat(cmdline, " \"");
|
||||
lstrcat(cmdline, options[i]);
|
||||
lstrcat(cmdline, "\"");
|
||||
}
|
||||
lstrcat(cmdline, option);
|
||||
|
||||
ok = CreateProcess(
|
||||
NULL, /* Module name. */
|
||||
@@ -409,7 +388,7 @@ CheckForLinkerFeature(
|
||||
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
|
||||
(300-chars), 0);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
|
||||
return 2;
|
||||
@@ -454,9 +433,7 @@ CheckForLinkerFeature(
|
||||
return !(strstr(Out.buffer, "LNK1117") != NULL ||
|
||||
strstr(Err.buffer, "LNK1117") != NULL ||
|
||||
strstr(Out.buffer, "LNK4044") != NULL ||
|
||||
strstr(Err.buffer, "LNK4044") != NULL ||
|
||||
strstr(Out.buffer, "LNK4224") != NULL ||
|
||||
strstr(Err.buffer, "LNK4224") != NULL);
|
||||
strstr(Err.buffer, "LNK4044") != NULL);
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
@@ -502,9 +479,9 @@ IsIn(
|
||||
static const char *
|
||||
GetVersionFromFile(
|
||||
const char *filename,
|
||||
const char *match,
|
||||
int numdots)
|
||||
const char *match)
|
||||
{
|
||||
size_t cbBuffer = 100;
|
||||
static char szBuffer[100];
|
||||
char *szResult = NULL;
|
||||
FILE *fp = fopen(filename, "rt");
|
||||
@@ -514,17 +491,16 @@ GetVersionFromFile(
|
||||
* Read data until we see our match string.
|
||||
*/
|
||||
|
||||
while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
|
||||
while (fgets(szBuffer, cbBuffer, fp) != NULL) {
|
||||
LPSTR p, q;
|
||||
|
||||
p = strstr(szBuffer, match);
|
||||
if (p != NULL) {
|
||||
/*
|
||||
* Skip to first digit after the match.
|
||||
* Skip to first digit.
|
||||
*/
|
||||
|
||||
p += strlen(match);
|
||||
while (*p && !isdigit((unsigned char)*p)) {
|
||||
while (*p && !isdigit(*p)) {
|
||||
++p;
|
||||
}
|
||||
|
||||
@@ -533,13 +509,13 @@ GetVersionFromFile(
|
||||
*/
|
||||
|
||||
q = p;
|
||||
while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
|
||||
&& !strchr("ab", q[-1])) || --numdots))) {
|
||||
while (*q && (isalnum(*q) || *q == '.')) {
|
||||
++q;
|
||||
}
|
||||
|
||||
*q = 0;
|
||||
szResult = p;
|
||||
memcpy(szBuffer, p, q - p);
|
||||
szBuffer[q-p] = 0;
|
||||
szResult = szBuffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -562,7 +538,7 @@ typedef struct list_item_t {
|
||||
static list_item_t *
|
||||
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
|
||||
{
|
||||
list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
|
||||
list_item_t *itemPtr = malloc(sizeof(list_item_t));
|
||||
if (itemPtr) {
|
||||
itemPtr->key = strdup(key);
|
||||
itemPtr->value = strdup(value);
|
||||
@@ -611,7 +587,9 @@ SubstituteFile(
|
||||
const char *substitutions,
|
||||
const char *filename)
|
||||
{
|
||||
size_t cbBuffer = 1024;
|
||||
static char szBuffer[1024], szCopy[1024];
|
||||
char *szResult = NULL;
|
||||
list_item_t *substPtr = NULL;
|
||||
FILE *fp, *sp;
|
||||
|
||||
@@ -624,7 +602,7 @@ SubstituteFile(
|
||||
|
||||
sp = fopen(substitutions, "rt");
|
||||
if (sp != NULL) {
|
||||
while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
|
||||
while (fgets(szBuffer, cbBuffer, sp) != NULL) {
|
||||
unsigned char *ks, *ke, *vs, *ve;
|
||||
ks = (unsigned char*)szBuffer;
|
||||
while (ks && *ks && isspace(*ks)) ++ks;
|
||||
@@ -641,7 +619,7 @@ SubstituteFile(
|
||||
}
|
||||
|
||||
/* debug: dump the list */
|
||||
#ifndef NDEBUG
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
int n = 0;
|
||||
list_item_t *p = NULL;
|
||||
@@ -650,12 +628,12 @@ SubstituteFile(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Run the substitutions over each line of the input
|
||||
*/
|
||||
|
||||
while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
|
||||
|
||||
while (fgets(szBuffer, cbBuffer, fp) != NULL) {
|
||||
list_item_t *p = NULL;
|
||||
for (p = substPtr; p != NULL; p = p->nextPtr) {
|
||||
char *m = strstr(szBuffer, p->key);
|
||||
@@ -672,26 +650,15 @@ SubstituteFile(
|
||||
memcpy(szBuffer, szCopy, sizeof(szCopy));
|
||||
}
|
||||
}
|
||||
printf("%s", szBuffer);
|
||||
printf(szBuffer);
|
||||
}
|
||||
|
||||
|
||||
list_free(&substPtr);
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL FileExists(LPCTSTR szPath)
|
||||
{
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
DWORD pathAttr = GetFileAttributes(szPath);
|
||||
return (pathAttr != INVALID_FILE_ATTRIBUTES &&
|
||||
!(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* QualifyPath --
|
||||
*
|
||||
@@ -705,105 +672,17 @@ QualifyPath(
|
||||
const char *szPath)
|
||||
{
|
||||
char szCwd[MAX_PATH + 1];
|
||||
|
||||
GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
|
||||
char szTmp[MAX_PATH + 1];
|
||||
char *p;
|
||||
GetCurrentDirectory(MAX_PATH, szCwd);
|
||||
while ((p = strchr(szPath, '/')) && *p)
|
||||
*p = '\\';
|
||||
PathCombine(szTmp, szCwd, szPath);
|
||||
PathCanonicalize(szCwd, szTmp);
|
||||
printf("%s\n", szCwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements LocateDependency for a single directory. See that command
|
||||
* for an explanation.
|
||||
* Returns 0 if found after printing the directory.
|
||||
* Returns 1 if not found but no errors.
|
||||
* Returns 2 on any kind of error
|
||||
* Basically, these are used as exit codes for the process.
|
||||
*/
|
||||
static int LocateDependencyHelper(const char *dir, const char *keypath)
|
||||
{
|
||||
HANDLE hSearch;
|
||||
char path[MAX_PATH+1];
|
||||
size_t dirlen;
|
||||
int keylen, ret;
|
||||
WIN32_FIND_DATA finfo;
|
||||
|
||||
if (dir == NULL || keypath == NULL)
|
||||
return 2; /* Have no real error reporting mechanism into nmake */
|
||||
dirlen = strlen(dir);
|
||||
if ((dirlen + 3) > sizeof(path))
|
||||
return 2;
|
||||
strncpy(path, dir, dirlen);
|
||||
strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
|
||||
keylen = strlen(keypath);
|
||||
|
||||
#if 0 /* This function is not available in Visual C++ 6 */
|
||||
/*
|
||||
* Use numerics 0 -> FindExInfoStandard,
|
||||
* 1 -> FindExSearchLimitToDirectories,
|
||||
* as these are not defined in Visual C++ 6
|
||||
*/
|
||||
hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
|
||||
#else
|
||||
hSearch = FindFirstFile(path, &finfo);
|
||||
#endif
|
||||
if (hSearch == INVALID_HANDLE_VALUE)
|
||||
return 1; /* Not found */
|
||||
|
||||
/* Loop through all subdirs checking if the keypath is under there */
|
||||
ret = 1; /* Assume not found */
|
||||
do {
|
||||
int sublen;
|
||||
/*
|
||||
* We need to check it is a directory despite the
|
||||
* FindExSearchLimitToDirectories in the above call. See SDK docs
|
||||
*/
|
||||
if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
continue;
|
||||
sublen = strlen(finfo.cFileName);
|
||||
if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
|
||||
continue; /* Path does not fit, assume not matched */
|
||||
strncpy(path+dirlen+1, finfo.cFileName, sublen);
|
||||
path[dirlen+1+sublen] = '\\';
|
||||
strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
|
||||
if (FileExists(path)) {
|
||||
/* Found a match, print to stdout */
|
||||
path[dirlen+1+sublen] = '\0';
|
||||
QualifyPath(path);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} while (FindNextFile(hSearch, &finfo));
|
||||
FindClose(hSearch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* LocateDependency --
|
||||
*
|
||||
* Locates a dependency for a package.
|
||||
* keypath - a relative path within the package directory
|
||||
* that is used to confirm it is the correct directory.
|
||||
* The search path for the package directory is currently only
|
||||
* the parent and grandparent of the current working directory.
|
||||
* If found, the command prints
|
||||
* name_DIRPATH=<full path of located directory>
|
||||
* and returns 0. If not found, does not print anything and returns 1.
|
||||
*/
|
||||
static int LocateDependency(const char *keypath)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
|
||||
|
||||
for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
|
||||
ret = LocateDependencyHelper(paths[i], keypath);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.39.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.35.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.39.0'
|
||||
PACKAGE_STRING='sqlite 3.39.0'
|
||||
PACKAGE_VERSION='3.35.0'
|
||||
PACKAGE_STRING='sqlite 3.35.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -770,7 +770,6 @@ ac_includes_default="\
|
||||
ac_subst_vars='LTLIBOBJS
|
||||
LIBOBJS
|
||||
BUILD_CFLAGS
|
||||
AMALGAMATION_LINE_MACROS
|
||||
USE_GCOV
|
||||
OPT_FEATURE_FLAGS
|
||||
HAVE_ZLIB
|
||||
@@ -905,13 +904,13 @@ enable_debug
|
||||
enable_amalgamation
|
||||
enable_load_extension
|
||||
enable_math
|
||||
enable_json
|
||||
enable_all
|
||||
enable_memsys5
|
||||
enable_memsys3
|
||||
enable_all
|
||||
enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_update_limit
|
||||
enable_geopoly
|
||||
enable_rtree
|
||||
@@ -1468,7 +1467,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.39.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.35.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1533,7 +1532,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.39.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.35.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1560,13 +1559,13 @@ Optional Features:
|
||||
--disable-load-extension
|
||||
Disable loading of external extensions
|
||||
--disable-math Disable math functions
|
||||
--disable-json Disable JSON functions
|
||||
--enable-all Enable FTS4, FTS5, Geopoly, RTree, Sessions
|
||||
--enable-memsys5 Enable MEMSYS5
|
||||
--enable-memsys3 Enable MEMSYS3
|
||||
--enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
|
||||
--enable-fts3 Enable the FTS3 extension
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
|
||||
--enable-geopoly Enable the GEOPOLY extension
|
||||
--enable-rtree Enable the RTREE extension
|
||||
@@ -1661,7 +1660,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.39.0
|
||||
sqlite configure 3.35.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2080,7 +2079,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.39.0, which was
|
||||
It was created by sqlite $as_me 3.35.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3938,13 +3937,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:3941: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3940: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3944: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3943: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3947: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3946: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5150,7 +5149,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5153 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5152 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6675,11 +6674,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:6678: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6677: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6682: \$? = $ac_status" >&5
|
||||
echo "$as_me:6681: \$? = $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.
|
||||
@@ -7014,11 +7013,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:7017: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7016: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7021: \$? = $ac_status" >&5
|
||||
echo "$as_me:7020: \$? = $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.
|
||||
@@ -7119,11 +7118,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:7122: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7121: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7126: \$? = $ac_status" >&5
|
||||
echo "$as_me:7125: \$? = $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
|
||||
@@ -7174,11 +7173,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:7177: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7176: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7181: \$? = $ac_status" >&5
|
||||
echo "$as_me:7180: \$? = $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
|
||||
@@ -9554,7 +9553,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9557 "configure"
|
||||
#line 9556 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9650,7 +9649,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9653 "configure"
|
||||
#line 9652 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11252,16 +11251,10 @@ if test "${enable_debug+set}" = set; then :
|
||||
enableval=$enable_debug;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build type" >&5
|
||||
$as_echo_n "checking build type... " >&6; }
|
||||
if test "${enable_debug}" = "yes" ; then
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
|
||||
$as_echo "debug" >&6; }
|
||||
else
|
||||
TARGET_DEBUG="-DNDEBUG"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5
|
||||
$as_echo "release" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
@@ -11497,34 +11490,6 @@ fi
|
||||
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support JSON functions
|
||||
#
|
||||
# Check whether --enable-json was given.
|
||||
if test "${enable_json+set}" = set; then :
|
||||
enableval=$enable_json;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON functions" >&5
|
||||
$as_echo_n "checking whether to support JSON functions... " >&6; }
|
||||
if test "$enable_json" = "no"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-all argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
# Check whether --enable-all was given.
|
||||
if test "${enable_all+set}" = set; then :
|
||||
enableval=$enable_all;
|
||||
fi
|
||||
|
||||
|
||||
##########
|
||||
# Do we want to support memsys3 and/or memsys5
|
||||
#
|
||||
@@ -11559,6 +11524,15 @@ else
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-extensions argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
# Check whether --enable-all was given.
|
||||
if test "${enable_all+set}" = set; then :
|
||||
enableval=$enable_all;
|
||||
fi
|
||||
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
# Check whether --enable-fts3 was given.
|
||||
@@ -11566,26 +11540,15 @@ if test "${enable_fts3+set}" = set; then :
|
||||
enableval=$enable_fts3;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS3" >&5
|
||||
$as_echo_n "checking whether to support FTS3... " >&6; }
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
# Check whether --enable-fts4 was given.
|
||||
if test "${enable_fts4+set}" = set; then :
|
||||
enableval=$enable_fts4;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS4" >&5
|
||||
$as_echo_n "checking whether to support FTS4... " >&6; }
|
||||
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
@@ -11643,20 +11606,13 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
# Check whether --enable-fts5 was given.
|
||||
if test "${enable_fts5+set}" = set; then :
|
||||
enableval=$enable_fts5;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS5" >&5
|
||||
$as_echo_n "checking whether to support FTS5... " >&6; }
|
||||
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
@@ -11714,9 +11670,17 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
# Check whether --enable-json1 was given.
|
||||
if test "${enable_json1+set}" = set; then :
|
||||
enableval=$enable_json1;
|
||||
fi
|
||||
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11727,15 +11691,8 @@ if test "${enable_update_limit+set}" = set; then :
|
||||
enableval=$enable_update_limit;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support LIMIT on UPDATE and DELETE statements" >&5
|
||||
$as_echo_n "checking whether to support LIMIT on UPDATE and DELETE statements... " >&6; }
|
||||
if test "${enable_update_limit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11747,16 +11704,9 @@ else
|
||||
enable_geopoly=no
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support GEOPOLY" >&5
|
||||
$as_echo_n "checking whether to support GEOPOLY... " >&6; }
|
||||
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
|
||||
enable_rtree=yes
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11766,15 +11716,8 @@ if test "${enable_rtree+set}" = set; then :
|
||||
enableval=$enable_rtree;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support RTREE" >&5
|
||||
$as_echo_n "checking whether to support RTREE... " >&6; }
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11784,16 +11727,9 @@ if test "${enable_session+set}" = set; then :
|
||||
enableval=$enable_session;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support SESSION" >&5
|
||||
$as_echo_n "checking whether to support SESSION... " >&6; }
|
||||
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11861,17 +11797,6 @@ else
|
||||
fi
|
||||
|
||||
|
||||
#########
|
||||
# Enable/disabled amalagamation line macros
|
||||
########
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
if test "${amalgamation_line_macros}" = "yes" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=1
|
||||
fi
|
||||
if test "${amalgamation_line_macros}" = "no" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
fi
|
||||
|
||||
|
||||
#########
|
||||
# Output the config header
|
||||
@@ -12390,7 +12315,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.39.0, which was
|
||||
This file was extended by sqlite $as_me 3.35.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12456,7 +12381,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.39.0
|
||||
sqlite config.status 3.35.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+13
-61
@@ -555,13 +555,10 @@ AC_SEARCH_LIBS(fdatasync, [rt])
|
||||
#########
|
||||
# check for debug enabled
|
||||
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
|
||||
AC_MSG_CHECKING([build type])
|
||||
if test "${enable_debug}" = "yes" ; then
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
|
||||
AC_MSG_RESULT([debug])
|
||||
else
|
||||
TARGET_DEBUG="-DNDEBUG"
|
||||
AC_MSG_RESULT([release])
|
||||
fi
|
||||
AC_SUBST(TARGET_DEBUG)
|
||||
|
||||
@@ -605,25 +602,6 @@ else
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support JSON functions
|
||||
#
|
||||
AC_ARG_ENABLE(json,
|
||||
AC_HELP_STRING([--disable-json],[Disable JSON functions]))
|
||||
AC_MSG_CHECKING([whether to support JSON functions])
|
||||
if test "$enable_json" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-all argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
|
||||
[Enable FTS4, FTS5, Geopoly, RTree, Sessions]))
|
||||
|
||||
##########
|
||||
# Do we want to support memsys3 and/or memsys5
|
||||
#
|
||||
@@ -646,36 +624,37 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-extensions argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
|
||||
[Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
||||
[Enable the FTS3 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS3])
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS4])
|
||||
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS5])
|
||||
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -683,12 +662,8 @@ fi
|
||||
# statements.
|
||||
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
|
||||
[Enable the UPDATE/DELETE LIMIT clause]))
|
||||
AC_MSG_CHECKING([whether to support LIMIT on UPDATE and DELETE statements])
|
||||
if test "${enable_update_limit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -696,38 +671,26 @@ fi
|
||||
AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly],
|
||||
[Enable the GEOPOLY extension]),
|
||||
[enable_geopoly=yes],[enable_geopoly=no])
|
||||
AC_MSG_CHECKING([whether to support GEOPOLY])
|
||||
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
|
||||
enable_rtree=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
[Enable the RTREE extension]))
|
||||
AC_MSG_CHECKING([whether to support RTREE])
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the SESSION extension
|
||||
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]))
|
||||
AC_MSG_CHECKING([whether to support SESSION])
|
||||
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -792,17 +755,6 @@ else
|
||||
fi
|
||||
AC_SUBST(USE_GCOV)
|
||||
|
||||
#########
|
||||
# Enable/disabled amalagamation line macros
|
||||
########
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
if test "${amalgamation_line_macros}" = "yes" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=1
|
||||
fi
|
||||
if test "${amalgamation_line_macros}" = "no" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
fi
|
||||
AC_SUBST(AMALGAMATION_LINE_MACROS)
|
||||
|
||||
#########
|
||||
# Output the config header
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
# JSON Functions Enhancements (2022)
|
||||
|
||||
This document summaries enhancements to the SQLite JSON support added in
|
||||
early 2022.
|
||||
|
||||
## 1.0 Change summary:
|
||||
|
||||
1. New **->** and **->>** operators that work like MySQL and PostgreSQL (PG).
|
||||
2. JSON functions are built-in rather than being an extension. They
|
||||
are included by default, but can be omitted using the
|
||||
-DSQLITE_OMIT_JSON compile-time option.
|
||||
|
||||
|
||||
## 2.0 New operators **->** and **->>**
|
||||
|
||||
The SQLite language adds two new binary operators **->** and **->>**.
|
||||
Both operators are similar to json_extract(). The left operand is
|
||||
JSON and the right operand is a JSON path expression (possibly abbreviated
|
||||
for compatibility with PG - see below). So they are similar to a
|
||||
two-argument call to json_extract().
|
||||
|
||||
The difference between -> and ->> (and json_extract()) is as follows:
|
||||
|
||||
* The -> operator always returns JSON.
|
||||
|
||||
* The ->> operator converts the answer into a primitive SQL datatype
|
||||
such as TEXT, INTEGER, REAL, or NULL. If a JSON object or array
|
||||
is selected, that object or array is rendered as text. If a JSON
|
||||
value is selected, that value is converted into its corresponding
|
||||
SQL type
|
||||
|
||||
* The json_extract() interface returns JSON when a JSON object or
|
||||
array is selected, or a primitive SQL datatype when a JSON value
|
||||
is selected. This is different from MySQL, in which json_extract()
|
||||
always returns JSON, but the difference is retained because it has
|
||||
worked that way for 6 years and changing it now would likely break
|
||||
a lot of legacy code.
|
||||
|
||||
In MySQL and PG, the ->> operator always returns TEXT (or NULL) and never
|
||||
INTEGER or REAL. This is due to limitations in the type handling capabilities
|
||||
of those systems. In MySQL and PG, the result type a function or operator
|
||||
may only depend on the type of its arguments, never the value of its arguments.
|
||||
But the underlying JSON type depends on the value of the JSON path
|
||||
expression, not the type of the JSON path expression (which is always TEXT).
|
||||
Hence, the result type of ->> in MySQL and PG is unable to vary according
|
||||
to the type of the JSON value being extracted.
|
||||
|
||||
The type system in SQLite is more general. Functions in SQLite are able
|
||||
to return different datatypes depending on the value of their arguments.
|
||||
So the ->> operator in SQLite is able to return TEXT, INTEGER, REAL, or NULL
|
||||
depending on the JSON type of the value being extracted. This means that
|
||||
the behavior of the ->> is slightly different in SQLite versus MySQL and PG
|
||||
in that it will sometimes return INTEGER and REAL values, depending on its
|
||||
inputs. It is possible to implement the ->> operator in SQLite so that it
|
||||
always operates exactly like MySQL and PG and always returns TEXT or NULL,
|
||||
but I have been unable to think of any situations where returning the
|
||||
actual JSON value this would cause problems, so I'm including the enhanced
|
||||
functionality in SQLite.
|
||||
|
||||
The table below attempts to summarize the differences between the
|
||||
-> and ->> operators and the json_extract() function, for SQLite, MySQL,
|
||||
and PG. JSON values are shown using their SQL text representation but
|
||||
in a bold font.
|
||||
|
||||
|
||||
<table border=1 cellpadding=5 cellspacing=0>
|
||||
<tr><th>JSON<th>PATH<th>-> operator<br>(all)<th>->> operator<br>(MySQL/PG)
|
||||
<th>->> operator<br>(SQLite)<th>json_extract()<br>(SQLite)
|
||||
<tr><td> **'{"a":123}'** <td>'$.a'<td> **'123'** <td> '123' <td> 123 <td> 123
|
||||
<tr><td> **'{"a":4.5}'** <td>'$.a'<td> **'4.5'** <td> '4.5' <td> 4.5 <td> 4.5
|
||||
<tr><td> **'{"a":"xyz"}'** <td>'$.a'<td> **'"xyz"'** <td> 'xyz' <td> 'xyz' <td> 'xyz'
|
||||
<tr><td> **'{"a":null}'** <td>'$.a'<td> **'null'** <td> NULL <td> NULL <td> NULL
|
||||
<tr><td> **'{"a":[6,7,8]}'** <td>'$.a'<td> **'[6,7,8]'** <td> '[6,7,8]' <td> '[6,7,8]' <td> **'[6,7,8]'**
|
||||
<tr><td> **'{"a":{"x":9}}'** <td>'$.a'<td> **'{"x":9}'** <td> '{"x":9}' <td> '{"x":9}' <td> **'{"x":9}'**
|
||||
<tr><td> **'{"b":999}'** <td>'$.a'<td> NULL <td> NULL <td> NULL <td> NULL
|
||||
</table>
|
||||
|
||||
Important points about the table above:
|
||||
|
||||
* The -> operator always returns either JSON or NULL.
|
||||
|
||||
* The ->> operator never returns JSON. It always returns TEXT or NULL, or in the
|
||||
case of SQLite, INTEGER or REAL.
|
||||
|
||||
* The MySQL json_extract() function works exactly the same
|
||||
as the MySQL -> operator.
|
||||
|
||||
* The SQLite json_extract() operator works like -> for JSON objects and
|
||||
arrays, and like ->> for JSON values.
|
||||
|
||||
* The -> operator works the same for all systems.
|
||||
|
||||
* The only difference in ->> between SQLite and other systems is that
|
||||
when the JSON value is numeric, SQLite returns a numeric SQL value,
|
||||
whereas the other systems return a text representation of the numeric
|
||||
value.
|
||||
|
||||
### 2.1 Abbreviated JSON path expressions for PG compatibility
|
||||
|
||||
The table above always shows the full JSON path expression: '$.a'. But
|
||||
PG does not accept this syntax. PG only allows a single JSON object label
|
||||
name or a single integer array index. In order to provide compatibility
|
||||
with PG, The -> and ->> operators in SQLite are extended to also support
|
||||
a JSON object label or an integer array index for the right-hand side
|
||||
operand, in addition to a full JSON path expression.
|
||||
|
||||
Thus, a -> or ->> operator that works on MySQL will work in
|
||||
SQLite. And a -> or ->> operator that works in PG will work in SQLite.
|
||||
But because SQLite supports the union of the disjoint capabilities of
|
||||
MySQL and PG, there will always be -> and ->> operators that work in
|
||||
SQLite that do not work in one of MySQL and PG. This is an unavoidable
|
||||
consequence of the different syntax for -> and ->> in MySQL and PG.
|
||||
|
||||
In the following table, assume that "value1" is a JSON object and
|
||||
"value2" is a JSON array.
|
||||
|
||||
<table border=1 cellpadding=5 cellspacing=0>
|
||||
<tr><th>SQL expression <th>Works in MySQL?<th>Works in PG?<th>Works in SQLite
|
||||
<tr><td>value1->'$.a' <td> yes <td> no <td> yes
|
||||
<tr><td>value1->'a' <td> no <td> yes <td> yes
|
||||
<tr><td>value2->'$[2]' <td> yes <td> no <td> yes
|
||||
<tr><td>value2->2 <td> no <td> yes <td> yes
|
||||
</table>
|
||||
|
||||
The abbreviated JSON path expressions only work for the -> and ->> operators
|
||||
in SQLite. The json_extract() function, and all other built-in SQLite
|
||||
JSON functions, continue to require complete JSON path expressions for their
|
||||
PATH arguments.
|
||||
|
||||
## 3.0 JSON moved into the core
|
||||
|
||||
The JSON interface is now moved into the SQLite core.
|
||||
|
||||
When originally written in 2015, the JSON functions were an extension
|
||||
that could be optionally included at compile-time, or loaded at run-time.
|
||||
The implementation was in a source file named ext/misc/json1.c in the
|
||||
source tree. JSON functions were only compiled in if the
|
||||
-DSQLITE_ENABLE_JSON1 compile-time option was used.
|
||||
|
||||
After these enhancements, the JSON functions are now built-ins.
|
||||
The source file that implements the JSON functions is moved to src/json.c.
|
||||
No special compile-time options are needed to load JSON into the build.
|
||||
Instead, there is a new -DSQLITE_OMIT_JSON compile-time option to leave
|
||||
them out.
|
||||
+5
-29
@@ -697,7 +697,6 @@ other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
<li><tt><a href='#stack_size'>%stack_size</a></tt>
|
||||
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
|
||||
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
|
||||
<li><tt><a href='#token'>%token</a></tt>
|
||||
<li><tt><a href='#token_class'>%token_class</a></tt>
|
||||
<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
|
||||
<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
|
||||
@@ -1080,37 +1079,14 @@ can choose a different start symbol using the
|
||||
|
||||
<p>See <a href='#errors'>Error Processing</a>.</p>
|
||||
|
||||
<a id='token'></a>
|
||||
<h4>4.4.20 The <tt>%token</tt> directive</h4>
|
||||
|
||||
<p>Tokens are normally created automatically, the first time they are used.
|
||||
Any identifier that begins with an upper-case letter is a token.
|
||||
|
||||
<p>Sometimes it is useful to declare tokens in advance, however. The
|
||||
integer values assigned to each token determined by the order in which
|
||||
the tokens are seen. So by declaring tokens in advance, it is possible to
|
||||
cause some tokens to have low-numbered values, which might be desirable in
|
||||
some grammers, or to have sequential values assigned to a sequence of
|
||||
related tokens. For this reason, the %token directive is provided to
|
||||
declare tokens in advance. The syntax is as follows:
|
||||
|
||||
<blockquote>
|
||||
<tt>%token</tt> <i>TOKEN</i> <i>TOKEN...</i> <b>.</b>
|
||||
</blockquote></p>
|
||||
|
||||
<p>The %token directive is followed by zero or more token symbols and
|
||||
terminated by a single ".". Each token named is created if it does not
|
||||
already exist. Tokens are created in order.
|
||||
|
||||
|
||||
<a id='token_class'></a>
|
||||
<h4>4.4.21 The <tt>%token_class</tt> directive</h4>
|
||||
<h4>4.4.20 The <tt>%token_class</tt> directive</h4>
|
||||
|
||||
<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
|
||||
<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
|
||||
|
||||
<a id='token_destructor'></a>
|
||||
<h4>4.4.22 The <tt>%token_destructor</tt> directive</h4>
|
||||
<h4>4.4.21 The <tt>%token_destructor</tt> directive</h4>
|
||||
|
||||
<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
|
||||
symbol. (See the description of the
|
||||
@@ -1126,7 +1102,7 @@ Other than that, the token destructor works just like the non-terminal
|
||||
destructors.</p>
|
||||
|
||||
<a id='token_prefix'></a>
|
||||
<h4>4.4.23 The <tt>%token_prefix</tt> directive</h4>
|
||||
<h4>4.4.22 The <tt>%token_prefix</tt> directive</h4>
|
||||
|
||||
<p>Lemon generates #defines that assign small integer constants
|
||||
to each terminal symbol in the grammar. If desired, Lemon will
|
||||
@@ -1153,7 +1129,7 @@ to each of the #defines it generates.</p>
|
||||
</pre>
|
||||
|
||||
<a id='token_type'></a><a id='ptype'></a>
|
||||
<h4>4.4.24 The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
|
||||
<h4>4.4.23 The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
|
||||
|
||||
<p>These directives are used to specify the data types for values
|
||||
on the parser's stack associated with terminal and non-terminal
|
||||
@@ -1190,7 +1166,7 @@ entry parser stack will require 100K of heap space. If you are willing
|
||||
and able to pay that price, fine. You just need to know.</p>
|
||||
|
||||
<a id='pwildcard'></a>
|
||||
<h4>4.4.25 The <tt>%wildcard</tt> directive</h4>
|
||||
<h4>4.4.24 The <tt>%wildcard</tt> directive</h4>
|
||||
|
||||
<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
|
||||
period. This directive specifies that the identified token should
|
||||
|
||||
+35
-34
@@ -103,7 +103,7 @@ do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
(no new indexes)
|
||||
SCAN t1
|
||||
SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.2 {
|
||||
@@ -112,7 +112,7 @@ do_setup_rec_test $tn.2 {
|
||||
SELECT * FROM t1 WHERE b>?;
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b);
|
||||
SEARCH t1 USING INDEX t1_idx_00000062 (b>?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.3 {
|
||||
@@ -121,7 +121,7 @@ do_setup_rec_test $tn.3 {
|
||||
SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
|
||||
} {
|
||||
CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
|
||||
SEARCH t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.4 {
|
||||
@@ -130,7 +130,7 @@ do_setup_rec_test $tn.4 {
|
||||
SELECT a FROM t1 ORDER BY b;
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b);
|
||||
SCAN t1 USING INDEX t1_idx_00000062
|
||||
SCAN TABLE t1 USING INDEX t1_idx_00000062
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.5 {
|
||||
@@ -139,7 +139,7 @@ do_setup_rec_test $tn.5 {
|
||||
SELECT a FROM t1 WHERE a=? ORDER BY b;
|
||||
} {
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b);
|
||||
SEARCH t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
|
||||
}
|
||||
|
||||
if 0 {
|
||||
@@ -149,7 +149,7 @@ do_setup_rec_test $tn.6 {
|
||||
SELECT min(a) FROM t1
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a);
|
||||
SEARCH t1 USING COVERING INDEX t1_idx_00000061
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ do_setup_rec_test $tn.7 {
|
||||
SELECT * FROM t1 ORDER BY a, b, c;
|
||||
} {
|
||||
CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
|
||||
SCAN t1 USING COVERING INDEX t1_idx_033e95fe
|
||||
SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
|
||||
}
|
||||
|
||||
#do_setup_rec_test $tn.1.8 {
|
||||
@@ -168,7 +168,7 @@ do_setup_rec_test $tn.7 {
|
||||
# SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
|
||||
#} {
|
||||
# CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
|
||||
# 0|0|0|SCAN t1 USING COVERING INDEX t1_idx_5be6e222
|
||||
# 0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
|
||||
#}
|
||||
|
||||
do_setup_rec_test $tn.8.1 {
|
||||
@@ -177,7 +177,7 @@ do_setup_rec_test $tn.8.1 {
|
||||
SELECT * FROM t1 WHERE a=?
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a);
|
||||
SEARCH t1 USING INDEX t1_idx_00000061 (a=?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
|
||||
}
|
||||
do_setup_rec_test $tn.8.2 {
|
||||
CREATE TABLE t1(a, b COLLATE nocase, c);
|
||||
@@ -185,7 +185,7 @@ do_setup_rec_test $tn.8.2 {
|
||||
SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
|
||||
} {
|
||||
CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
|
||||
SCAN t1 USING COVERING INDEX t1_idx_5cb97285
|
||||
SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
|
||||
}
|
||||
|
||||
|
||||
@@ -196,8 +196,8 @@ do_setup_rec_test $tn.9.1 {
|
||||
} {
|
||||
SELECT * FROM "t t" WHERE a=?
|
||||
} {
|
||||
CREATE INDEX "t t_idx_00000061" ON "t t"(a);
|
||||
SEARCH t t USING INDEX t t_idx_00000061 (a=?)
|
||||
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
|
||||
SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.9.2 {
|
||||
@@ -205,8 +205,8 @@ do_setup_rec_test $tn.9.2 {
|
||||
} {
|
||||
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
|
||||
} {
|
||||
CREATE INDEX "t t_idx_00000062" ON "t t"(b);
|
||||
SEARCH t t USING INDEX t t_idx_00000062 (b>? AND b<?)
|
||||
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
|
||||
SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
|
||||
}
|
||||
|
||||
# Columns with names that require quotes.
|
||||
@@ -217,7 +217,7 @@ do_setup_rec_test $tn.10.1 {
|
||||
SELECT * FROM t3 WHERE "b b" = ?
|
||||
} {
|
||||
CREATE INDEX t3_idx_00050c52 ON t3('b b');
|
||||
SEARCH t3 USING INDEX t3_idx_00050c52 (b b=?)
|
||||
SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.10.2 {
|
||||
@@ -226,7 +226,7 @@ do_setup_rec_test $tn.10.2 {
|
||||
SELECT * FROM t3 ORDER BY "b b"
|
||||
} {
|
||||
CREATE INDEX t3_idx_00050c52 ON t3('b b');
|
||||
SCAN t3 USING INDEX t3_idx_00050c52
|
||||
SCAN TABLE t3 USING INDEX t3_idx_00050c52
|
||||
}
|
||||
|
||||
# Transitive constraints
|
||||
@@ -239,8 +239,8 @@ do_setup_rec_test $tn.11.1 {
|
||||
} {
|
||||
CREATE INDEX t5_idx_000123a7 ON t5(a, b);
|
||||
CREATE INDEX t6_idx_00000063 ON t6(c);
|
||||
SEARCH t6 USING INDEX t6_idx_00000063 (c=?)
|
||||
SEARCH t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
|
||||
SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
|
||||
SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
|
||||
}
|
||||
|
||||
# OR terms.
|
||||
@@ -254,9 +254,9 @@ do_setup_rec_test $tn.12.1 {
|
||||
CREATE INDEX t7_idx_00000061 ON t7(a);
|
||||
MULTI-INDEX OR
|
||||
INDEX 1
|
||||
SEARCH t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
INDEX 2
|
||||
SEARCH t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
# rowid terms.
|
||||
@@ -267,7 +267,7 @@ do_setup_rec_test $tn.13.1 {
|
||||
SELECT * FROM t8 WHERE rowid=?
|
||||
} {
|
||||
(no new indexes)
|
||||
SEARCH t8 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_setup_rec_test $tn.13.2 {
|
||||
CREATE TABLE t8(a, b);
|
||||
@@ -275,7 +275,7 @@ do_setup_rec_test $tn.13.2 {
|
||||
SELECT * FROM t8 ORDER BY rowid
|
||||
} {
|
||||
(no new indexes)
|
||||
SCAN t8
|
||||
SCAN TABLE t8
|
||||
}
|
||||
do_setup_rec_test $tn.13.3 {
|
||||
CREATE TABLE t8(a, b);
|
||||
@@ -283,7 +283,7 @@ do_setup_rec_test $tn.13.3 {
|
||||
SELECT * FROM t8 WHERE a=? ORDER BY rowid
|
||||
} {
|
||||
CREATE INDEX t8_idx_00000061 ON t8(a);
|
||||
SEARCH t8 USING INDEX t8_idx_00000061 (a=?)
|
||||
SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
|
||||
}
|
||||
|
||||
# Triggers
|
||||
@@ -298,7 +298,7 @@ do_setup_rec_test $tn.14 {
|
||||
INSERT INTO t9 VALUES(?, ?, ?);
|
||||
} {
|
||||
CREATE INDEX t10_idx_00000062 ON t10(b);
|
||||
SEARCH t10 USING INDEX t10_idx_00000062 (b=?)
|
||||
SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.15 {
|
||||
@@ -314,8 +314,8 @@ do_setup_rec_test $tn.15 {
|
||||
SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
|
||||
} {
|
||||
CREATE INDEX t2_idx_00000064 ON t2(d);
|
||||
SEARCH t2 USING INDEX t2_idx_00000064 (d=?)
|
||||
SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
|
||||
SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.16 {
|
||||
@@ -324,7 +324,7 @@ do_setup_rec_test $tn.16 {
|
||||
SELECT * FROM t1 WHERE b IS NOT NULL;
|
||||
} {
|
||||
(no new indexes)
|
||||
SCAN t1
|
||||
SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.17.1 {
|
||||
@@ -333,7 +333,7 @@ do_setup_rec_test $tn.17.1 {
|
||||
SELECT * FROM example WHERE a=?
|
||||
} {
|
||||
(no new indexes)
|
||||
SEARCH example USING INDEX sqlite_autoindex_example_1 (A=?)
|
||||
SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=?)
|
||||
}
|
||||
do_setup_rec_test $tn.17.2 {
|
||||
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
|
||||
@@ -341,7 +341,7 @@ do_setup_rec_test $tn.17.2 {
|
||||
SELECT * FROM example WHERE b=?
|
||||
} {
|
||||
CREATE INDEX example_idx_00000042 ON example(B);
|
||||
SEARCH example USING INDEX example_idx_00000042 (B=?)
|
||||
SEARCH TABLE example USING INDEX example_idx_00000042 (B=?)
|
||||
}
|
||||
do_setup_rec_test $tn.17.3 {
|
||||
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
|
||||
@@ -349,7 +349,7 @@ do_setup_rec_test $tn.17.3 {
|
||||
SELECT * FROM example WHERE a=? AND b=?
|
||||
} {
|
||||
(no new indexes)
|
||||
SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
|
||||
SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
|
||||
}
|
||||
do_setup_rec_test $tn.17.4 {
|
||||
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
|
||||
@@ -357,7 +357,7 @@ do_setup_rec_test $tn.17.4 {
|
||||
SELECT * FROM example WHERE a=? AND b>?
|
||||
} {
|
||||
(no new indexes)
|
||||
SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
|
||||
SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
|
||||
}
|
||||
do_setup_rec_test $tn.17.5 {
|
||||
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
|
||||
@@ -365,7 +365,7 @@ do_setup_rec_test $tn.17.5 {
|
||||
SELECT * FROM example WHERE a>? AND b=?
|
||||
} {
|
||||
CREATE INDEX example_idx_0000cb3f ON example(B, A);
|
||||
SEARCH example USING INDEX example_idx_0000cb3f (B=? AND A>?)
|
||||
SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.18.0 {
|
||||
@@ -377,7 +377,7 @@ do_setup_rec_test $tn.18.0 {
|
||||
SELECT x FROM SomeObject;
|
||||
} {
|
||||
(no new indexes)
|
||||
SCAN SomeObject
|
||||
SCAN TABLE SomeObject
|
||||
}
|
||||
do_setup_rec_test $tn.18.1 {
|
||||
CREATE TABLE SomeObject (
|
||||
@@ -388,7 +388,7 @@ do_setup_rec_test $tn.18.1 {
|
||||
SELECT * FROM SomeObject WHERE x=?;
|
||||
} {
|
||||
CREATE INDEX SomeObject_idx_00000078 ON SomeObject(x);
|
||||
SEARCH SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
|
||||
SEARCH TABLE SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -455,3 +455,4 @@ do_execsql_test 5.3 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+26
-108
@@ -15,23 +15,6 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(SQLITE_AMALGAMATION)
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_AMALGAMATION) */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
typedef sqlite3_int64 i64;
|
||||
@@ -697,31 +680,21 @@ static int idxGetTableInfo(
|
||||
){
|
||||
sqlite3_stmt *p1 = 0;
|
||||
int nCol = 0;
|
||||
int nTab;
|
||||
int nByte;
|
||||
int nTab = STRLEN(zTab);
|
||||
int nByte = sizeof(IdxTable) + nTab + 1;
|
||||
IdxTable *pNew = 0;
|
||||
int rc, rc2;
|
||||
char *pCsr = 0;
|
||||
int nPk = 0;
|
||||
|
||||
*ppOut = 0;
|
||||
if( zTab==0 ) return SQLITE_ERROR;
|
||||
nTab = STRLEN(zTab);
|
||||
nByte = sizeof(IdxTable) + nTab + 1;
|
||||
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
||||
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
||||
const char *zColSeq = 0;
|
||||
if( zCol==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
nByte += 1 + STRLEN(zCol);
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
|
||||
db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
|
||||
);
|
||||
if( zColSeq==0 ) zColSeq = "binary";
|
||||
nByte += 1 + STRLEN(zColSeq);
|
||||
nByte += 1 + STRLEN(zCol);
|
||||
nCol++;
|
||||
nPk += (sqlite3_column_int(p1, 5)>0);
|
||||
}
|
||||
@@ -741,23 +714,19 @@ static int idxGetTableInfo(
|
||||
nCol = 0;
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
||||
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
||||
const char *zColSeq = 0;
|
||||
int nCopy;
|
||||
if( zCol==0 ) continue;
|
||||
nCopy = STRLEN(zCol) + 1;
|
||||
int nCopy = STRLEN(zCol) + 1;
|
||||
pNew->aCol[nCol].zName = pCsr;
|
||||
pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
|
||||
memcpy(pCsr, zCol, nCopy);
|
||||
pCsr += nCopy;
|
||||
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
|
||||
db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( zColSeq==0 ) zColSeq = "binary";
|
||||
nCopy = STRLEN(zColSeq) + 1;
|
||||
nCopy = STRLEN(zCol) + 1;
|
||||
pNew->aCol[nCol].zColl = pCsr;
|
||||
memcpy(pCsr, zColSeq, nCopy);
|
||||
memcpy(pCsr, zCol, nCopy);
|
||||
pCsr += nCopy;
|
||||
}
|
||||
|
||||
@@ -768,9 +737,9 @@ static int idxGetTableInfo(
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(pNew);
|
||||
pNew = 0;
|
||||
}else if( ALWAYS(pNew!=0) ){
|
||||
}else{
|
||||
pNew->zName = pCsr;
|
||||
if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
|
||||
memcpy(pNew->zName, zTab, nTab+1);
|
||||
}
|
||||
|
||||
*ppOut = pNew;
|
||||
@@ -896,7 +865,6 @@ static int idxFindCompatible(
|
||||
IdxConstraint *pT = pTail;
|
||||
sqlite3_stmt *pInfo = 0;
|
||||
const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
|
||||
if( zIdx==0 ) continue;
|
||||
|
||||
/* Zero the IdxConstraint.bFlag values in the pEq list */
|
||||
for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
|
||||
@@ -942,19 +910,6 @@ static int idxFindCompatible(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for sqlite3_exec() with query with leading count(*) column.
|
||||
* The first argument is expected to be an int*, referent to be incremented
|
||||
* if that leading column is not exactly '0'.
|
||||
*/
|
||||
static int countNonzeros(void* pCount, int nc,
|
||||
char* azResults[], char* azColumns[]){
|
||||
(void)azColumns; /* Suppress unused parameter warning */
|
||||
if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){
|
||||
*((int *)pCount) += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int idxCreateFromCons(
|
||||
sqlite3expert *p,
|
||||
IdxScan *pScan,
|
||||
@@ -981,40 +936,17 @@ static int idxCreateFromCons(
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Hash the list of columns to come up with a name for the index */
|
||||
const char *zTable = pScan->pTab->zName;
|
||||
int quoteTable = idxIdentifierRequiresQuotes(zTable);
|
||||
char *zName = 0; /* Index name */
|
||||
int collisions = 0;
|
||||
do{
|
||||
int i;
|
||||
char *zFind;
|
||||
for(i=0; zCols[i]; i++){
|
||||
h += ((h<<3) + zCols[i]);
|
||||
}
|
||||
sqlite3_free(zName);
|
||||
zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
|
||||
if( zName==0 ) break;
|
||||
/* Is is unique among table, view and index names? */
|
||||
zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q"
|
||||
" AND type in ('index','table','view')";
|
||||
zFind = sqlite3_mprintf(zFmt, zName);
|
||||
i = 0;
|
||||
rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0);
|
||||
assert(rc==SQLITE_OK);
|
||||
sqlite3_free(zFind);
|
||||
if( i==0 ){
|
||||
collisions = 0;
|
||||
break;
|
||||
}
|
||||
++collisions;
|
||||
}while( collisions<50 && zName!=0 );
|
||||
if( collisions ){
|
||||
/* This return means "Gave up trying to find a unique index name." */
|
||||
rc = SQLITE_BUSY_TIMEOUT;
|
||||
}else if( zName==0 ){
|
||||
char *zName; /* Index name */
|
||||
int i;
|
||||
for(i=0; zCols[i]; i++){
|
||||
h += ((h<<3) + zCols[i]);
|
||||
}
|
||||
zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
|
||||
if( zName==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( quoteTable ){
|
||||
zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)";
|
||||
if( idxIdentifierRequiresQuotes(zTable) ){
|
||||
zFmt = "CREATE INDEX '%q' ON %Q(%s)";
|
||||
}else{
|
||||
zFmt = "CREATE INDEX %s ON %s(%s)";
|
||||
}
|
||||
@@ -1023,11 +955,7 @@ static int idxCreateFromCons(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
rc = SQLITE_BUSY_TIMEOUT;
|
||||
}else{
|
||||
idxHashAdd(&rc, &p->hIdx, zName, zIdx);
|
||||
}
|
||||
idxHashAdd(&rc, &p->hIdx, zName, zIdx);
|
||||
}
|
||||
sqlite3_free(zName);
|
||||
sqlite3_free(zIdx);
|
||||
@@ -1179,7 +1107,7 @@ static void idxWriteFree(IdxWrite *pTab){
|
||||
** runs all the queries to see which indexes they prefer, and populates
|
||||
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
|
||||
*/
|
||||
static int idxFindIndexes(
|
||||
int idxFindIndexes(
|
||||
sqlite3expert *p,
|
||||
char **pzErr /* OUT: Error message (sqlite3_malloc) */
|
||||
){
|
||||
@@ -1308,7 +1236,6 @@ static int idxProcessOneTrigger(
|
||||
rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
|
||||
const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
|
||||
if( zCreate==0 ) continue;
|
||||
rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
|
||||
}
|
||||
idxFinalize(&rc, pSelect);
|
||||
@@ -1411,9 +1338,8 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
|
||||
|
||||
if( zType==0 || zName==0 ) continue;
|
||||
if( zType[0]=='v' || zType[1]=='r' ){
|
||||
if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
|
||||
rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
|
||||
}else{
|
||||
IdxTable *pTab;
|
||||
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
|
||||
@@ -1550,7 +1476,6 @@ static void idxRemFunc(
|
||||
case SQLITE_BLOB:
|
||||
case SQLITE_TEXT: {
|
||||
int nByte = sqlite3_value_bytes(argv[1]);
|
||||
const void *pData = 0;
|
||||
if( nByte>pSlot->nByte ){
|
||||
char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
|
||||
if( zNew==0 ){
|
||||
@@ -1562,11 +1487,9 @@ static void idxRemFunc(
|
||||
}
|
||||
pSlot->n = nByte;
|
||||
if( pSlot->eType==SQLITE_BLOB ){
|
||||
pData = sqlite3_value_blob(argv[1]);
|
||||
if( pData ) memcpy(pSlot->z, pData, nByte);
|
||||
memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
|
||||
}else{
|
||||
pData = sqlite3_value_text(argv[1]);
|
||||
memcpy(pSlot->z, pData, nByte);
|
||||
memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1777,7 +1700,6 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
|
||||
const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
|
||||
const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
|
||||
if( zTab==0 || zIdx==0 ) continue;
|
||||
if( p->iSample<100 && iPrev!=iRowid ){
|
||||
samplectx.target = (double)p->iSample / 100.0;
|
||||
samplectx.iTarget = p->iSample;
|
||||
@@ -1844,14 +1766,14 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
|
||||
/* Copy the entire schema of database [db] into [dbm]. */
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_stmt *pSql = 0;
|
||||
sqlite3_stmt *pSql;
|
||||
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
|
||||
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
|
||||
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
|
||||
);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
|
||||
if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
|
||||
rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
|
||||
}
|
||||
idxFinalize(&rc, pSql);
|
||||
}
|
||||
@@ -1957,10 +1879,6 @@ int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
|
||||
/* Create candidate indexes within the in-memory database file */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = idxCreateCandidates(p);
|
||||
}else if ( rc==SQLITE_BUSY_TIMEOUT ){
|
||||
if( pzErr )
|
||||
*pzErr = sqlite3_mprintf("Cannot find a unique index name to propose.");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Generate the stat1 data */
|
||||
|
||||
+40
-56
@@ -308,26 +308,25 @@
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
|
||||
typedef struct Fts3HashWrapper Fts3HashWrapper;
|
||||
struct Fts3HashWrapper {
|
||||
Fts3Hash hash; /* Hash table */
|
||||
int nRef; /* Number of pointers to this object */
|
||||
};
|
||||
|
||||
static int fts3EvalNext(Fts3Cursor *pCsr);
|
||||
static int fts3EvalStart(Fts3Cursor *pCsr);
|
||||
static int fts3TermSegReaderCursor(
|
||||
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# if defined(SQLITE_DEBUG)
|
||||
int sqlite3Fts3Always(int b) { assert( b ); return b; }
|
||||
int sqlite3Fts3Never(int b) { assert( !b ); return b; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This variable is set to false when running tests for which the on disk
|
||||
** structures should not be corrupt. Otherwise, true. If it is false, extra
|
||||
** assert() conditions in the fts3 code are activated - conditions that are
|
||||
** only true if it is guaranteed that the fts3 database is not corrupt.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3_fts3_may_be_corrupt = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Write a 64-bit variable-length integer to memory starting at p[0].
|
||||
@@ -1178,7 +1177,7 @@ static int fts3InitVtab(
|
||||
sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
|
||||
char **pzErr /* Write any error message here */
|
||||
){
|
||||
Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash;
|
||||
Fts3Hash *pHash = (Fts3Hash *)pAux;
|
||||
Fts3Table *p = 0; /* Pointer to allocated vtab */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* Iterator variable */
|
||||
@@ -1898,7 +1897,7 @@ static int fts3ScanInteriorNode(
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
u64 iChild; /* Block id of child node to descend to */
|
||||
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
@@ -1914,8 +1913,8 @@ static int fts3ScanInteriorNode(
|
||||
** table, then there are always 20 bytes of zeroed padding following the
|
||||
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
|
||||
*/
|
||||
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -1968,20 +1967,20 @@ static int fts3ScanInteriorNode(
|
||||
*/
|
||||
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
|
||||
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
|
||||
*piFirst = (i64)iChild;
|
||||
*piFirst = iChild;
|
||||
piFirst = 0;
|
||||
}
|
||||
|
||||
if( piLast && cmp<0 ){
|
||||
*piLast = (i64)iChild;
|
||||
*piLast = iChild;
|
||||
piLast = 0;
|
||||
}
|
||||
|
||||
iChild++;
|
||||
};
|
||||
|
||||
if( piFirst ) *piFirst = (i64)iChild;
|
||||
if( piLast ) *piLast = (i64)iChild;
|
||||
if( piFirst ) *piFirst = iChild;
|
||||
if( piLast ) *piLast = iChild;
|
||||
|
||||
finish_scan:
|
||||
sqlite3_free(zBuffer);
|
||||
@@ -3587,20 +3586,14 @@ static int fts3SetHasStat(Fts3Table *p){
|
||||
*/
|
||||
static int fts3BeginMethod(sqlite3_vtab *pVtab){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
int rc;
|
||||
UNUSED_PARAMETER(pVtab);
|
||||
assert( p->pSegments==0 );
|
||||
assert( p->nPendingData==0 );
|
||||
assert( p->inTransaction!=1 );
|
||||
TESTONLY( p->inTransaction = 1 );
|
||||
TESTONLY( p->mxSavepoint = -1; );
|
||||
p->nLeafAdd = 0;
|
||||
rc = fts3SetHasStat(p);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( rc==SQLITE_OK ){
|
||||
p->inTransaction = 1;
|
||||
p->mxSavepoint = -1;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
return fts3SetHasStat(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4013,12 +4006,9 @@ static const sqlite3_module fts3Module = {
|
||||
** allocated for the tokenizer hash table.
|
||||
*/
|
||||
static void hashDestroy(void *p){
|
||||
Fts3HashWrapper *pHash = (Fts3HashWrapper *)p;
|
||||
pHash->nRef--;
|
||||
if( pHash->nRef<=0 ){
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
Fts3Hash *pHash = (Fts3Hash *)p;
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4048,7 +4038,7 @@ void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
||||
*/
|
||||
int sqlite3Fts3Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
Fts3HashWrapper *pHash = 0;
|
||||
Fts3Hash *pHash = 0;
|
||||
const sqlite3_tokenizer_module *pSimple = 0;
|
||||
const sqlite3_tokenizer_module *pPorter = 0;
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
@@ -4076,24 +4066,23 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
sqlite3Fts3PorterTokenizerModule(&pPorter);
|
||||
|
||||
/* Allocate and initialize the hash-table used to store tokenizers. */
|
||||
pHash = sqlite3_malloc(sizeof(Fts3HashWrapper));
|
||||
pHash = sqlite3_malloc(sizeof(Fts3Hash));
|
||||
if( !pHash ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1);
|
||||
pHash->nRef = 0;
|
||||
sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
|
||||
}
|
||||
|
||||
/* Load the built-in tokenizers into the hash table */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter)
|
||||
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode)
|
||||
|| sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
|| (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
|
||||
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -4102,7 +4091,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4111,26 +4100,23 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
** module with sqlite.
|
||||
*/
|
||||
if( SQLITE_OK==rc
|
||||
&& SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
|
||||
){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts4", &fts3Module, (void *)pHash, hashDestroy
|
||||
db, "fts4", &fts3Module, (void *)pHash, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -4139,7 +4125,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
/* An error has occurred. Delete the hash table and return the error code. */
|
||||
assert( rc!=SQLITE_OK );
|
||||
if( pHash ){
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
return rc;
|
||||
@@ -4486,7 +4472,7 @@ void sqlite3Fts3DoclistPrev(
|
||||
|
||||
assert( nDoclist>0 );
|
||||
assert( *pbEof==0 );
|
||||
assert_fts3_nc( p || *piDocid==0 );
|
||||
assert( p || *piDocid==0 );
|
||||
assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
|
||||
|
||||
if( p==0 ){
|
||||
@@ -5136,15 +5122,16 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
|
||||
Fts3TokenAndCost *aTC;
|
||||
Fts3Expr **apOr;
|
||||
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
|
||||
sizeof(Fts3TokenAndCost) * nToken
|
||||
+ sizeof(Fts3Expr *) * nOr * 2
|
||||
);
|
||||
apOr = (Fts3Expr **)&aTC[nToken];
|
||||
|
||||
if( !aTC ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
|
||||
int ii;
|
||||
Fts3TokenAndCost *pTC = aTC;
|
||||
Fts3Expr **ppOr = apOr;
|
||||
@@ -5225,9 +5212,9 @@ static int fts3EvalNearTrim(
|
||||
);
|
||||
if( res ){
|
||||
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
|
||||
assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
|
||||
if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
|
||||
if( nNew>=0 ){
|
||||
assert( pPhrase->doclist.pList[nNew]=='\0' );
|
||||
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
|
||||
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
|
||||
pPhrase->doclist.nList = nNew;
|
||||
}
|
||||
@@ -5350,8 +5337,8 @@ static void fts3EvalNextRow(
|
||||
Fts3Expr *pRight = pExpr->pRight;
|
||||
sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
|
||||
|
||||
assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
|
||||
|
||||
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||
@@ -5989,9 +5976,6 @@ int sqlite3Fts3EvalPhrasePoslist(
|
||||
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
|
||||
}
|
||||
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
|
||||
if( rc==SQLITE_OK && pNear->bEof!=bEofSave ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
if( bTreeEof ){
|
||||
while( rc==SQLITE_OK && !pNear->bEof ){
|
||||
|
||||
+12
-14
@@ -134,7 +134,7 @@ SQLITE_EXTENSION_INIT3
|
||||
** is used for assert() conditions that are true only if it can be
|
||||
** guranteed that the database is not corrupt.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
extern int sqlite3_fts3_may_be_corrupt;
|
||||
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
|
||||
#else
|
||||
@@ -151,18 +151,17 @@ extern int sqlite3_fts3_may_be_corrupt;
|
||||
** Macros indicating that conditional expressions are always true or
|
||||
** false.
|
||||
*/
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
# define ALWAYS(x) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif defined(SQLITE_DEBUG)
|
||||
# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
|
||||
# define NEVER(x) sqlite3Fts3Never((x)!=0)
|
||||
int sqlite3Fts3Always(int b);
|
||||
int sqlite3Fts3Never(int b);
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
# define ALWAYS(x) (x)
|
||||
# define NEVER(x) (x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -621,7 +620,6 @@ void sqlite3Fts3ExprFree(Fts3Expr *);
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
|
||||
int sqlite3Fts3InitTerm(sqlite3 *db);
|
||||
#endif
|
||||
void *sqlite3Fts3MallocZero(i64 nByte);
|
||||
|
||||
int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
|
||||
sqlite3_tokenizer_cursor **
|
||||
@@ -641,7 +639,7 @@ int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
||||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
|
||||
/* fts3_tokenize_vtab.c */
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
|
||||
|
||||
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|
||||
+1
-6
@@ -297,7 +297,6 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
|
||||
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
|
||||
iCol = 0;
|
||||
rc = SQLITE_OK;
|
||||
|
||||
while( i<nDoclist ){
|
||||
sqlite3_int64 v = 0;
|
||||
@@ -341,10 +340,6 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
/* State 3. The integer just read is a column number. */
|
||||
default: assert( eState==3 );
|
||||
iCol = (int)v;
|
||||
if( iCol<1 ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
|
||||
pCsr->aStat[iCol+1].nDoc++;
|
||||
eState = 2;
|
||||
@@ -353,6 +348,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
|
||||
pCsr->iCol = 0;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
pCsr->isEof = 1;
|
||||
}
|
||||
@@ -410,7 +406,6 @@ static int fts3auxFilterMethod(
|
||||
sqlite3Fts3SegReaderFinish(&pCsr->csr);
|
||||
sqlite3_free((void *)pCsr->filter.zTerm);
|
||||
sqlite3_free(pCsr->aStat);
|
||||
sqlite3_free(pCsr->zStop);
|
||||
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
|
||||
|
||||
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
|
||||
|
||||
+5
-10
@@ -122,7 +122,7 @@ static int fts3isspace(char c){
|
||||
** zero the memory before returning a pointer to it. If unsuccessful,
|
||||
** return NULL.
|
||||
*/
|
||||
void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){
|
||||
static void *fts3MallocZero(sqlite3_int64 nByte){
|
||||
void *pRet = sqlite3_malloc64(nByte);
|
||||
if( pRet ) memset(pRet, 0, nByte);
|
||||
return pRet;
|
||||
@@ -203,7 +203,7 @@ static int getNextToken(
|
||||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
|
||||
pRet = (Fts3Expr *)fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -458,7 +458,7 @@ static int getNextNode(
|
||||
if( fts3isspace(cNext)
|
||||
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
|
||||
){
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pRet ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -493,11 +493,6 @@ static int getNextNode(
|
||||
if( *zInput=='(' ){
|
||||
int nConsumed = 0;
|
||||
pParse->nNest++;
|
||||
#if !defined(SQLITE_MAX_EXPR_DEPTH)
|
||||
if( pParse->nNest>1000 ) return SQLITE_ERROR;
|
||||
#elif SQLITE_MAX_EXPR_DEPTH>0
|
||||
if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR;
|
||||
#endif
|
||||
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
|
||||
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
|
||||
return rc;
|
||||
@@ -637,7 +632,7 @@ static int fts3ExprParse(
|
||||
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
|
||||
){
|
||||
/* Create an implicit NOT operator. */
|
||||
Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pNot ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -671,7 +666,7 @@ static int fts3ExprParse(
|
||||
/* Insert an implicit AND operator. */
|
||||
Fts3Expr *pAnd;
|
||||
assert( pRet && pPrev );
|
||||
pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
|
||||
pAnd = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pAnd ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
|
||||
+22
-25
@@ -17,10 +17,6 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
typedef sqlite3_int64 i64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Characters that may appear in the second argument to matchinfo().
|
||||
*/
|
||||
@@ -71,9 +67,9 @@ struct SnippetIter {
|
||||
struct SnippetPhrase {
|
||||
int nToken; /* Number of tokens in phrase */
|
||||
char *pList; /* Pointer to start of phrase position list */
|
||||
i64 iHead; /* Next value in position list */
|
||||
int iHead; /* Next value in position list */
|
||||
char *pHead; /* Position list data following iHead */
|
||||
i64 iTail; /* Next value in trailing position list */
|
||||
int iTail; /* Next value in trailing position list */
|
||||
char *pTail; /* Position list data following iTail */
|
||||
};
|
||||
|
||||
@@ -138,8 +134,9 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
+ sizeof(MatchinfoBuffer);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
|
||||
pRet = sqlite3_malloc64(nByte + nStr+1);
|
||||
if( pRet ){
|
||||
memset(pRet, 0, nByte);
|
||||
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
|
||||
+ sizeof(u32)*((int)nElem+1);
|
||||
@@ -237,7 +234,7 @@ void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
|
||||
** After it returns, *piPos contains the value of the next element of the
|
||||
** list and *pp is advanced to the following varint.
|
||||
*/
|
||||
static void fts3GetDeltaPosition(char **pp, i64 *piPos){
|
||||
static void fts3GetDeltaPosition(char **pp, int *piPos){
|
||||
int iVal;
|
||||
*pp += fts3GetVarint32(*pp, &iVal);
|
||||
*piPos += (iVal-2);
|
||||
@@ -346,10 +343,10 @@ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
|
||||
** arguments so that it points to the first element with a value greater
|
||||
** than or equal to parameter iNext.
|
||||
*/
|
||||
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
|
||||
static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
|
||||
char *pIter = *ppIter;
|
||||
if( pIter ){
|
||||
i64 iIter = *piIter;
|
||||
int iIter = *piIter;
|
||||
|
||||
while( iIter<iNext ){
|
||||
if( 0==(*pIter & 0xFE) ){
|
||||
@@ -432,7 +429,7 @@ static void fts3SnippetDetails(
|
||||
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
|
||||
if( pPhrase->pTail ){
|
||||
char *pCsr = pPhrase->pTail;
|
||||
i64 iCsr = pPhrase->iTail;
|
||||
int iCsr = pPhrase->iTail;
|
||||
|
||||
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
|
||||
int j;
|
||||
@@ -478,7 +475,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
|
||||
assert( rc==SQLITE_OK || pCsr==0 );
|
||||
if( pCsr ){
|
||||
i64 iFirst = 0;
|
||||
int iFirst = 0;
|
||||
pPhrase->pList = pCsr;
|
||||
fts3GetDeltaPosition(&pCsr, &iFirst);
|
||||
if( iFirst<0 ){
|
||||
@@ -543,10 +540,11 @@ static int fts3BestSnippet(
|
||||
** the required space using malloc().
|
||||
*/
|
||||
nByte = sizeof(SnippetPhrase) * nList;
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte);
|
||||
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
|
||||
if( !sIter.aPhrase ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(sIter.aPhrase, 0, nByte);
|
||||
|
||||
/* Initialize the contents of the SnippetIter object. Then iterate through
|
||||
** the set of phrases in the expression to populate the aPhrase[] array.
|
||||
@@ -1110,12 +1108,10 @@ static int fts3MatchinfoLcsCb(
|
||||
** position list for the next column.
|
||||
*/
|
||||
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
|
||||
char *pRead;
|
||||
char *pRead = pIter->pRead;
|
||||
sqlite3_int64 iRead;
|
||||
int rc = 0;
|
||||
|
||||
if( NEVER(pIter==0) ) return 1;
|
||||
pRead = pIter->pRead;
|
||||
pRead += sqlite3Fts3GetVarint(pRead, &iRead);
|
||||
if( iRead==0 || iRead==1 ){
|
||||
pRead = 0;
|
||||
@@ -1149,8 +1145,9 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
|
||||
/* Allocate and populate the array of LcsIterator objects. The array
|
||||
** contains one element for each matchable phrase in the query.
|
||||
**/
|
||||
aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
if( !aIter ) return SQLITE_NOMEM;
|
||||
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
|
||||
|
||||
for(i=0; i<pInfo->nPhrase; i++){
|
||||
@@ -1542,8 +1539,8 @@ typedef struct TermOffsetCtx TermOffsetCtx;
|
||||
|
||||
struct TermOffset {
|
||||
char *pList; /* Position-list */
|
||||
i64 iPos; /* Position just read from pList */
|
||||
i64 iOff; /* Offset of this term from read positions */
|
||||
int iPos; /* Position just read from pList */
|
||||
int iOff; /* Offset of this term from read positions */
|
||||
};
|
||||
|
||||
struct TermOffsetCtx {
|
||||
@@ -1562,7 +1559,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
int nTerm; /* Number of tokens in phrase */
|
||||
int iTerm; /* For looping through nTerm phrase terms */
|
||||
char *pList; /* Pointer to position list for phrase */
|
||||
i64 iPos = 0; /* First position in position-list */
|
||||
int iPos = 0; /* First position in position-list */
|
||||
int rc;
|
||||
|
||||
UNUSED_PARAMETER(iPhrase);
|
||||
@@ -1611,7 +1608,7 @@ void sqlite3Fts3Offsets(
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Allocate the array of TermOffset iterators. */
|
||||
sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
|
||||
sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
|
||||
if( 0==sCtx.aTerm ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto offsets_out;
|
||||
@@ -1632,13 +1629,13 @@ void sqlite3Fts3Offsets(
|
||||
const char *zDoc;
|
||||
int nDoc;
|
||||
|
||||
/* Initialize the contents of sCtx.aTerm[] for column iCol. This
|
||||
** operation may fail if the database contains corrupt records.
|
||||
/* Initialize the contents of sCtx.aTerm[] for column iCol. There is
|
||||
** no way that this operation can fail, so the return code from
|
||||
** fts3ExprIterate() can be discarded.
|
||||
*/
|
||||
sCtx.iCol = iCol;
|
||||
sCtx.iTerm = 0;
|
||||
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
|
||||
|
||||
/* Retreive the text stored in column iCol. If an SQL NULL is stored
|
||||
** in column iCol, jump immediately to the next iteration of the loop.
|
||||
|
||||
@@ -585,7 +585,6 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
#ifdef SQLITE_DEBUG
|
||||
int bOld = sqlite3_fts3_may_be_corrupt;
|
||||
|
||||
if( objc!=2 && objc!=1 ){
|
||||
@@ -599,7 +598,6 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,7 +420,7 @@ static int fts3tokRowidMethod(
|
||||
** Register the fts3tok module with database connection db. Return SQLITE_OK
|
||||
** if successful or an error code if sqlite3_create_module() fails.
|
||||
*/
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
||||
static const sqlite3_module fts3tok_module = {
|
||||
0, /* iVersion */
|
||||
fts3tokConnectMethod, /* xCreate */
|
||||
@@ -449,9 +449,7 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
|
||||
);
|
||||
rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,6 @@ static int unicodeOpen(
|
||||
pCsr->aInput = (const unsigned char *)aInput;
|
||||
if( aInput==0 ){
|
||||
pCsr->nInput = 0;
|
||||
pCsr->aInput = (const unsigned char*)"";
|
||||
}else if( nInput<0 ){
|
||||
pCsr->nInput = (int)strlen(aInput);
|
||||
}else{
|
||||
|
||||
+15
-30
@@ -1335,18 +1335,8 @@ static int fts3SegReaderNext(
|
||||
char *aCopy;
|
||||
PendingList *pList = (PendingList *)fts3HashData(pElem);
|
||||
int nCopy = pList->nData+1;
|
||||
|
||||
int nTerm = fts3HashKeysize(pElem);
|
||||
if( (nTerm+1)>pReader->nTermAlloc ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
pReader->zTerm = (char*)sqlite3_malloc((nTerm+1)*2);
|
||||
if( !pReader->zTerm ) return SQLITE_NOMEM;
|
||||
pReader->nTermAlloc = (nTerm+1)*2;
|
||||
}
|
||||
memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
|
||||
pReader->zTerm[nTerm] = '\0';
|
||||
pReader->nTerm = nTerm;
|
||||
|
||||
pReader->zTerm = (char *)fts3HashKey(pElem);
|
||||
pReader->nTerm = fts3HashKeysize(pElem);
|
||||
aCopy = (char*)sqlite3_malloc(nCopy);
|
||||
if( !aCopy ) return SQLITE_NOMEM;
|
||||
memcpy(aCopy, pList->aData, nCopy);
|
||||
@@ -1599,7 +1589,9 @@ int sqlite3Fts3MsrOvfl(
|
||||
*/
|
||||
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
|
||||
if( pReader ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
if( !fts3SegReaderIsPending(pReader) ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
}
|
||||
if( !fts3SegReaderIsRootOnly(pReader) ){
|
||||
sqlite3_free(pReader->aNode);
|
||||
}
|
||||
@@ -1815,7 +1807,7 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
|
||||
if( rc==0 ){
|
||||
rc = pRhs->iIdx - pLhs->iIdx;
|
||||
}
|
||||
assert_fts3_nc( rc!=0 );
|
||||
assert( rc!=0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2011,8 +2003,8 @@ static int fts3PrefixCompress(
|
||||
int nNext /* Size of buffer zNext in bytes */
|
||||
){
|
||||
int n;
|
||||
for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
|
||||
assert_fts3_nc( n<nNext );
|
||||
UNUSED_PARAMETER(nNext);
|
||||
for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -3011,7 +3003,7 @@ int sqlite3Fts3SegReaderStep(
|
||||
|
||||
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
|
||||
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist+FTS3_NODE_PADDING);
|
||||
rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
|
||||
if( rc ) return rc;
|
||||
|
||||
if( isFirst ){
|
||||
@@ -3791,7 +3783,7 @@ static int nodeReaderNext(NodeReader *p){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
|
||||
if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
|
||||
p->term.n = nPrefix+nSuffix;
|
||||
p->iOff += nSuffix;
|
||||
@@ -4185,11 +4177,7 @@ static int fts3TermCmp(
|
||||
int nCmp = MIN(nLhs, nRhs);
|
||||
int res;
|
||||
|
||||
if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){
|
||||
res = memcmp(zLhs, zRhs, nCmp);
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
|
||||
if( res==0 ) res = nLhs - nRhs;
|
||||
|
||||
return res;
|
||||
@@ -4347,20 +4335,17 @@ static int fts3IncrmergeLoad(
|
||||
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
|
||||
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
|
||||
if( reader.term.n>0 ){
|
||||
memcpy(pNode->key.a, reader.term.a, reader.term.n);
|
||||
}
|
||||
memcpy(pNode->key.a, reader.term.a, reader.term.n);
|
||||
pNode->key.n = reader.term.n;
|
||||
if( i>0 ){
|
||||
char *aBlock = 0;
|
||||
int nBlock = 0;
|
||||
pNode = &pWriter->aNodeWriter[i-1];
|
||||
pNode->iBlock = reader.iChild;
|
||||
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
|
||||
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
|
||||
blobGrowBuffer(&pNode->block,
|
||||
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
|
||||
);
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(pNode->block.a, aBlock, nBlock);
|
||||
pNode->block.n = nBlock;
|
||||
@@ -4833,7 +4818,7 @@ static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
|
||||
if( aHint ){
|
||||
blobGrowBuffer(pHint, nHint, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint);
|
||||
memcpy(pHint->a, aHint, nHint);
|
||||
pHint->n = nHint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# This script builds a single C code file holding all of FTS3 code.
|
||||
# The name of the output file is fts3amal.c. To build this file,
|
||||
# first do:
|
||||
#
|
||||
# make target_source
|
||||
#
|
||||
# The make target above moves all of the source code files into
|
||||
# a subdirectory named "tsrc". (This script expects to find the files
|
||||
# there and will not work if they are not found.)
|
||||
#
|
||||
# After the "tsrc" directory has been created and populated, run
|
||||
# this script:
|
||||
#
|
||||
# tclsh mkfts3amal.tcl
|
||||
#
|
||||
# The amalgamated FTS3 code will be written into fts3amal.c
|
||||
#
|
||||
|
||||
# Open the output file and write a header comment at the beginning
|
||||
# of the file.
|
||||
#
|
||||
set out [open fts3amal.c w]
|
||||
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
|
||||
puts $out [subst \
|
||||
{/******************************************************************************
|
||||
** This file is an amalgamation of separate C source files from the SQLite
|
||||
** Full Text Search extension 2 (fts3). By combining all the individual C
|
||||
** code files into this single large file, the entire code can be compiled
|
||||
** as a one translation unit. This allows many compilers to do optimizations
|
||||
** that would not be possible if the files were compiled separately. It also
|
||||
** makes the code easier to import into other projects.
|
||||
**
|
||||
** This amalgamation was generated on $today.
|
||||
*/}]
|
||||
|
||||
# These are the header files used by FTS3. The first time any of these
|
||||
# files are seen in a #include statement in the C code, include the complete
|
||||
# text of the file in-line. The file only needs to be included once.
|
||||
#
|
||||
foreach hdr {
|
||||
fts3.h
|
||||
fts3_hash.h
|
||||
fts3_tokenizer.h
|
||||
sqlite3.h
|
||||
sqlite3ext.h
|
||||
} {
|
||||
set available_hdr($hdr) 1
|
||||
}
|
||||
|
||||
# 78 stars used for comment formatting.
|
||||
set s78 \
|
||||
{*****************************************************************************}
|
||||
|
||||
# Insert a comment into the code
|
||||
#
|
||||
proc section_comment {text} {
|
||||
global out s78
|
||||
set n [string length $text]
|
||||
set nstar [expr {60 - $n}]
|
||||
set stars [string range $s78 0 $nstar]
|
||||
puts $out "/************** $text $stars/"
|
||||
}
|
||||
|
||||
# Read the source file named $filename and write it into the
|
||||
# sqlite3.c output file. If any #include statements are seen,
|
||||
# process them approprately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr out
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
set in [open $filename r]
|
||||
while {![eof $in]} {
|
||||
set line [gets $in]
|
||||
if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
|
||||
if {[info exists available_hdr($hdr)]} {
|
||||
if {$available_hdr($hdr)} {
|
||||
section_comment "Include $hdr in the middle of $tail"
|
||||
copy_file tsrc/$hdr
|
||||
section_comment "Continuing where we left off in $tail"
|
||||
}
|
||||
} elseif {![info exists seen_hdr($hdr)]} {
|
||||
set seen_hdr($hdr) 1
|
||||
puts $out $line
|
||||
}
|
||||
} elseif {[regexp {^#ifdef __cplusplus} $line]} {
|
||||
puts $out "#if 0"
|
||||
} elseif {[regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} else {
|
||||
puts $out $line
|
||||
}
|
||||
}
|
||||
close $in
|
||||
section_comment "End of $tail"
|
||||
}
|
||||
|
||||
|
||||
# Process the source files. Process files containing commonly
|
||||
# used subroutines first in order to help the compiler find
|
||||
# inlining opportunities.
|
||||
#
|
||||
foreach file {
|
||||
fts3.c
|
||||
fts3_hash.c
|
||||
fts3_porter.c
|
||||
fts3_tokenizer.c
|
||||
fts3_tokenizer1.c
|
||||
} {
|
||||
copy_file tsrc/$file
|
||||
}
|
||||
|
||||
close $out
|
||||
+3
-18
@@ -35,20 +35,8 @@ typedef sqlite3_uint64 u64;
|
||||
#endif
|
||||
|
||||
#define testcase(x)
|
||||
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#define ALWAYS(x) 1
|
||||
#define NEVER(x) 0
|
||||
|
||||
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
@@ -108,7 +96,7 @@ extern int sqlite3_fts5_may_be_corrupt;
|
||||
** A version of memcmp() that does not cause asan errors if one of the pointer
|
||||
** parameters is NULL and the number of bytes to compare is zero.
|
||||
*/
|
||||
#define fts5Memcmp(s1, s2, n) ((n)<=0 ? 0 : memcmp((s1), (s2), (n)))
|
||||
#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
|
||||
|
||||
/* Mark a function parameter as unused, to suppress nuisance compiler
|
||||
** warnings. */
|
||||
@@ -447,9 +435,6 @@ void sqlite3Fts5IndexCloseReader(Fts5Index*);
|
||||
*/
|
||||
const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
|
||||
int sqlite3Fts5IterNextScan(Fts5IndexIter*);
|
||||
void *sqlite3Fts5StructureRef(Fts5Index*);
|
||||
void sqlite3Fts5StructureRelease(void*);
|
||||
int sqlite3Fts5StructureTest(Fts5Index*, void*);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+10
-15
@@ -66,6 +66,7 @@ void sqlite3Fts5BufferAppendBlob(
|
||||
u32 nData,
|
||||
const u8 *pData
|
||||
){
|
||||
assert_nc( *pRc || nData>=0 );
|
||||
if( nData ){
|
||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||
@@ -175,7 +176,7 @@ int sqlite3Fts5PoslistNext64(
|
||||
return 1;
|
||||
}else{
|
||||
i64 iOff = *piOff;
|
||||
u32 iVal;
|
||||
int iVal;
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal<=1 ){
|
||||
if( iVal==0 ){
|
||||
@@ -184,19 +185,15 @@ int sqlite3Fts5PoslistNext64(
|
||||
}
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
iOff = ((i64)iVal) << 32;
|
||||
assert( iOff>=0 );
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal<2 ){
|
||||
/* This is a corrupt record. So stop parsing it here. */
|
||||
*piOff = -1;
|
||||
return 1;
|
||||
}
|
||||
*piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
|
||||
}else{
|
||||
*piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
|
||||
}
|
||||
*piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
|
||||
*pi = i;
|
||||
assert_nc( *piOff>=iOff );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -235,16 +232,14 @@ void sqlite3Fts5PoslistSafeAppend(
|
||||
i64 *piPrev,
|
||||
i64 iPos
|
||||
){
|
||||
if( iPos>=*piPrev ){
|
||||
static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
|
||||
if( (iPos & colmask) != (*piPrev & colmask) ){
|
||||
pBuf->p[pBuf->n++] = 1;
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
|
||||
*piPrev = (iPos & colmask);
|
||||
}
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
|
||||
*piPrev = iPos;
|
||||
static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
|
||||
if( (iPos & colmask) != (*piPrev & colmask) ){
|
||||
pBuf->p[pBuf->n++] = 1;
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
|
||||
*piPrev = (iPos & colmask);
|
||||
}
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
|
||||
*piPrev = iPos;
|
||||
}
|
||||
|
||||
int sqlite3Fts5PoslistWriterAppend(
|
||||
|
||||
@@ -537,7 +537,7 @@ int sqlite3Fts5ConfigParse(
|
||||
|
||||
nByte = nArg * (sizeof(char*) + sizeof(u8));
|
||||
pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0;
|
||||
pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
|
||||
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
|
||||
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
|
||||
pRet->bColumnsize = 1;
|
||||
@@ -562,7 +562,6 @@ int sqlite3Fts5ConfigParse(
|
||||
z = fts5ConfigSkipWhitespace(z);
|
||||
if( z && *z=='=' ){
|
||||
bOption = 1;
|
||||
assert( zOne!=0 );
|
||||
z++;
|
||||
if( bMustBeCol ) z = 0;
|
||||
}
|
||||
@@ -579,11 +578,7 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
if( bOption ){
|
||||
rc = fts5ConfigParseSpecial(pGlobal, pRet,
|
||||
ALWAYS(zOne)?zOne:"",
|
||||
zTwo?zTwo:"",
|
||||
pzErr
|
||||
);
|
||||
rc = fts5ConfigParseSpecial(pGlobal, pRet, zOne, zTwo?zTwo:"", pzErr);
|
||||
}else{
|
||||
rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
|
||||
zOne = 0;
|
||||
|
||||
+10
-27
@@ -135,7 +135,6 @@ void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
assert( pParse->zErr==0 );
|
||||
pParse->zErr = sqlite3_vmprintf(zFmt, ap);
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
@@ -434,7 +433,6 @@ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
|
||||
int bRetValid = 0;
|
||||
Fts5ExprTerm *p;
|
||||
|
||||
assert( pTerm );
|
||||
assert( pTerm->pSynonym );
|
||||
assert( bDesc==0 || bDesc==1 );
|
||||
for(p=pTerm; p; p=p->pSynonym){
|
||||
@@ -1627,9 +1625,6 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
}else{
|
||||
if( pRet->nPhrase>0 ){
|
||||
Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
|
||||
assert( pParse!=0 );
|
||||
assert( pParse->apPhrase!=0 );
|
||||
assert( pParse->nPhrase>=2 );
|
||||
assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
|
||||
if( pPhrase->nTerm==0 ){
|
||||
fts5ExprPhraseFree(pPhrase);
|
||||
@@ -1878,7 +1873,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
/* All the allocations succeeded. Put the expression object together. */
|
||||
pNew->pIndex = pExpr->pIndex;
|
||||
pNew->pConfig = pExpr->pConfig;
|
||||
@@ -2149,8 +2144,9 @@ void sqlite3Fts5ParseSetColset(
|
||||
){
|
||||
Fts5Colset *pFree = pColset;
|
||||
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
sqlite3Fts5ParseError(pParse,
|
||||
"fts5: column queries are not supported (detail=none)"
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
pParse->zErr = sqlite3_mprintf(
|
||||
"fts5: column queries are not supported (detail=none)"
|
||||
);
|
||||
}else{
|
||||
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
|
||||
@@ -2324,10 +2320,13 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
|| pPhrase->nTerm>1
|
||||
|| (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
|
||||
){
|
||||
sqlite3Fts5ParseError(pParse,
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
assert( pParse->zErr==0 );
|
||||
pParse->zErr = sqlite3_mprintf(
|
||||
"fts5: %s queries are not supported (detail!=full)",
|
||||
pNear->nPhrase==1 ? "phrase": "NEAR"
|
||||
);
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
@@ -2413,7 +2412,6 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
return pRet;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
|
||||
sqlite3_int64 nByte = 0;
|
||||
Fts5ExprTerm *p;
|
||||
@@ -2780,14 +2778,12 @@ static void fts5ExprFold(
|
||||
sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_TEST */
|
||||
|
||||
/*
|
||||
** This is called during initialization to register the fts5_expr() scalar
|
||||
** UDF with the SQLite handle passed as the only argument.
|
||||
*/
|
||||
int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
#ifdef SQLITE_TEST
|
||||
struct Fts5ExprFunc {
|
||||
const char *z;
|
||||
void (*x)(sqlite3_context*,int,sqlite3_value**);
|
||||
@@ -2805,10 +2801,6 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
struct Fts5ExprFunc *p = &aFunc[i];
|
||||
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
|
||||
}
|
||||
#else
|
||||
int rc = SQLITE_OK;
|
||||
UNUSED_PARAM2(pGlobal,db);
|
||||
#endif
|
||||
|
||||
/* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
|
||||
** sqlite3Fts5ParserFallback() are unused */
|
||||
@@ -2859,15 +2851,6 @@ struct Fts5PoslistPopulator {
|
||||
int bMiss;
|
||||
};
|
||||
|
||||
/*
|
||||
** Clear the position lists associated with all phrases in the expression
|
||||
** passed as the first argument. Argument bLive is true if the expression
|
||||
** might be pointing to a real entry, otherwise it has just been reset.
|
||||
**
|
||||
** At present this function is only used for detail=col and detail=none
|
||||
** fts5 tables. This implies that all phrases must be at most 1 token
|
||||
** in size, as phrase matches are not supported without detail=full.
|
||||
*/
|
||||
Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
|
||||
Fts5PoslistPopulator *pRet;
|
||||
pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
|
||||
@@ -2877,7 +2860,7 @@ Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
|
||||
for(i=0; i<pExpr->nPhrase; i++){
|
||||
Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
|
||||
Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
|
||||
assert( pExpr->apExprPhrase[i]->nTerm<=1 );
|
||||
assert( pExpr->apExprPhrase[i]->nTerm==1 );
|
||||
if( bLive &&
|
||||
(pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
|
||||
){
|
||||
|
||||
@@ -356,7 +356,7 @@ int sqlite3Fts5HashWrite(
|
||||
p->bContent = 1;
|
||||
}else{
|
||||
/* Append a new column value, if necessary */
|
||||
assert_nc( iCol>=p->iCol );
|
||||
assert( iCol>=p->iCol );
|
||||
if( iCol!=p->iCol ){
|
||||
if( pHash->eDetail==FTS5_DETAIL_FULL ){
|
||||
pPtr[p->nData++] = 0x01;
|
||||
|
||||
+48
-164
@@ -296,7 +296,7 @@ struct Fts5Index {
|
||||
sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */
|
||||
sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */
|
||||
sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */
|
||||
sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */
|
||||
sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */
|
||||
sqlite3_stmt *pIdxSelect;
|
||||
int nRead; /* Total number of blocks read */
|
||||
|
||||
@@ -431,7 +431,7 @@ struct Fts5SegIter {
|
||||
int iLeafPgno; /* Current leaf page number */
|
||||
Fts5Data *pLeaf; /* Current leaf data */
|
||||
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
|
||||
i64 iLeafOffset; /* Byte offset within current leaf */
|
||||
int iLeafOffset; /* Byte offset within current leaf */
|
||||
|
||||
/* Next method */
|
||||
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
|
||||
@@ -600,11 +600,8 @@ static int fts5BufferCompareBlob(
|
||||
** res = *pLeft - *pRight
|
||||
*/
|
||||
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
|
||||
int nCmp, res;
|
||||
nCmp = MIN(pLeft->n, pRight->n);
|
||||
assert( nCmp<=0 || pLeft->p!=0 );
|
||||
assert( nCmp<=0 || pRight->p!=0 );
|
||||
res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
|
||||
int nCmp = MIN(pLeft->n, pRight->n);
|
||||
int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
|
||||
return (res==0 ? (pLeft->n - pRight->n) : res);
|
||||
}
|
||||
|
||||
@@ -700,7 +697,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
return pRet;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Release a reference to data record returned by an earlier call to
|
||||
** fts5DataRead().
|
||||
@@ -825,58 +821,6 @@ static void fts5StructureRef(Fts5Structure *pStruct){
|
||||
pStruct->nRef++;
|
||||
}
|
||||
|
||||
void *sqlite3Fts5StructureRef(Fts5Index *p){
|
||||
fts5StructureRef(p->pStruct);
|
||||
return (void*)p->pStruct;
|
||||
}
|
||||
void sqlite3Fts5StructureRelease(void *p){
|
||||
if( p ){
|
||||
fts5StructureRelease((Fts5Structure*)p);
|
||||
}
|
||||
}
|
||||
int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
|
||||
if( p->pStruct!=(Fts5Structure*)pStruct ){
|
||||
return SQLITE_ABORT;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Ensure that structure object (*pp) is writable.
|
||||
**
|
||||
** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
|
||||
** an error occurs, (*pRc) is set to an SQLite error code before returning.
|
||||
*/
|
||||
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
|
||||
Fts5Structure *p = *pp;
|
||||
if( *pRc==SQLITE_OK && p->nRef>1 ){
|
||||
i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
|
||||
Fts5Structure *pNew;
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pNew ){
|
||||
int i;
|
||||
memcpy(pNew, p, nByte);
|
||||
for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0;
|
||||
for(i=0; i<p->nLevel; i++){
|
||||
Fts5StructureLevel *pLvl = &pNew->aLevel[i];
|
||||
nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg;
|
||||
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pLvl->aSeg==0 ){
|
||||
for(i=0; i<p->nLevel; i++){
|
||||
sqlite3_free(pNew->aLevel[i].aSeg);
|
||||
}
|
||||
sqlite3_free(pNew);
|
||||
return;
|
||||
}
|
||||
memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte);
|
||||
}
|
||||
p->nRef--;
|
||||
pNew->nRef = 1;
|
||||
}
|
||||
*pp = pNew;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Deserialize and return the structure record currently stored in serialized
|
||||
** form within buffer pData/nData.
|
||||
@@ -978,11 +922,9 @@ static int fts5StructureDecode(
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a level to the Fts5Structure.aLevel[] array of structure object
|
||||
** (*ppStruct).
|
||||
**
|
||||
*/
|
||||
static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
|
||||
fts5StructureMakeWritable(pRc, ppStruct);
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5Structure *pStruct = *ppStruct;
|
||||
int nLevel = pStruct->nLevel;
|
||||
@@ -1669,7 +1611,7 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
|
||||
|
||||
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
|
||||
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
|
||||
i64 iOff = pIter->iLeafOffset;
|
||||
int iOff = pIter->iLeafOffset;
|
||||
|
||||
ASSERT_SZLEAF_OK(pIter->pLeaf);
|
||||
if( iOff>=pIter->pLeaf->szLeaf ){
|
||||
@@ -1702,7 +1644,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
|
||||
*/
|
||||
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
|
||||
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
|
||||
i64 iOff = pIter->iLeafOffset; /* Offset to read at */
|
||||
int iOff = pIter->iLeafOffset; /* Offset to read at */
|
||||
int nNew; /* Bytes of new data */
|
||||
|
||||
iOff += fts5GetVarint32(&a[iOff], nNew);
|
||||
@@ -1776,7 +1718,6 @@ static void fts5SegIterInit(
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
pIter->iLeafOffset = 4;
|
||||
assert( pIter->pLeaf!=0 );
|
||||
assert_nc( pIter->pLeaf->nn>4 );
|
||||
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
|
||||
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
|
||||
@@ -1879,12 +1820,8 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
int iRowidOff;
|
||||
iRowidOff = fts5LeafFirstRowidOff(pNew);
|
||||
if( iRowidOff ){
|
||||
if( iRowidOff>=pNew->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
pIter->pLeaf = pNew;
|
||||
pIter->iLeafOffset = iRowidOff;
|
||||
}
|
||||
pIter->pLeaf = pNew;
|
||||
pIter->iLeafOffset = iRowidOff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2135,6 +2072,7 @@ static void fts5SegIterNext(
|
||||
** this block is particularly performance critical, so equivalent
|
||||
** code is inlined. */
|
||||
int nSz;
|
||||
assert( p->rc==SQLITE_OK );
|
||||
assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
|
||||
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
|
||||
pIter->bDel = (nSz & 0x0001);
|
||||
@@ -2164,7 +2102,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
if( pDlidx ){
|
||||
int iSegid = pIter->pSeg->iSegid;
|
||||
pgnoLast = fts5DlidxIterPgno(pDlidx);
|
||||
pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
|
||||
pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
|
||||
}else{
|
||||
Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
|
||||
|
||||
@@ -2191,7 +2129,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
** forward to find the page containing the last rowid. */
|
||||
for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
|
||||
i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
|
||||
Fts5Data *pNew = fts5LeafRead(p, iAbs);
|
||||
Fts5Data *pNew = fts5DataRead(p, iAbs);
|
||||
if( pNew ){
|
||||
int iRowid, bTermless;
|
||||
iRowid = fts5LeafFirstRowidOff(pNew);
|
||||
@@ -2222,10 +2160,6 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
pIter->pLeaf = pLast;
|
||||
pIter->iLeafPgno = pgnoLast;
|
||||
iOff = fts5LeafFirstRowidOff(pLast);
|
||||
if( iOff>pLast->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
|
||||
@@ -2234,6 +2168,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fts5SegIterReverseInitPage(p, pIter);
|
||||
@@ -2285,20 +2220,21 @@ static void fts5LeafSeek(
|
||||
Fts5SegIter *pIter, /* Iterator to seek */
|
||||
const u8 *pTerm, int nTerm /* Term to search for */
|
||||
){
|
||||
u32 iOff;
|
||||
int iOff;
|
||||
const u8 *a = pIter->pLeaf->p;
|
||||
u32 n = (u32)pIter->pLeaf->nn;
|
||||
int szLeaf = pIter->pLeaf->szLeaf;
|
||||
int n = pIter->pLeaf->nn;
|
||||
|
||||
u32 nMatch = 0;
|
||||
u32 nKeep = 0;
|
||||
u32 nNew = 0;
|
||||
u32 iTermOff;
|
||||
u32 iPgidx; /* Current offset in pgidx */
|
||||
int iPgidx; /* Current offset in pgidx */
|
||||
int bEndOfPage = 0;
|
||||
|
||||
assert( p->rc==SQLITE_OK );
|
||||
|
||||
iPgidx = (u32)pIter->pLeaf->szLeaf;
|
||||
iPgidx = szLeaf;
|
||||
iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
|
||||
iOff = iTermOff;
|
||||
if( iOff>n ){
|
||||
@@ -2364,15 +2300,15 @@ static void fts5LeafSeek(
|
||||
if( pIter->pLeaf==0 ) return;
|
||||
a = pIter->pLeaf->p;
|
||||
if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
|
||||
iPgidx = (u32)pIter->pLeaf->szLeaf;
|
||||
iPgidx = pIter->pLeaf->szLeaf;
|
||||
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
|
||||
if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
|
||||
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}else{
|
||||
nKeep = 0;
|
||||
iTermOff = iOff;
|
||||
n = (u32)pIter->pLeaf->nn;
|
||||
n = pIter->pLeaf->nn;
|
||||
iOff += fts5GetVarint32(&a[iOff], nNew);
|
||||
break;
|
||||
}
|
||||
@@ -2740,7 +2676,7 @@ static void fts5SegIterGotoPage(
|
||||
fts5SegIterNextPage(p, pIter);
|
||||
assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );
|
||||
|
||||
if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
int iOff;
|
||||
u8 *a = pIter->pLeaf->p;
|
||||
int n = pIter->pLeaf->szLeaf;
|
||||
@@ -3172,11 +3108,7 @@ static void fts5SegiterPoslist(
|
||||
Fts5Colset *pColset,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
assert( pBuf!=0 );
|
||||
assert( pSeg!=0 );
|
||||
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
|
||||
assert( pBuf->p!=0 );
|
||||
assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING );
|
||||
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
|
||||
if( pColset==0 ){
|
||||
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
|
||||
@@ -3252,7 +3184,7 @@ static void fts5IndexExtractColset(
|
||||
}
|
||||
fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
|
||||
}
|
||||
if( p>=pEnd ){
|
||||
if( p==pEnd ){
|
||||
pIter->base.pData = pIter->poslist.p;
|
||||
pIter->base.nData = pIter->poslist.n;
|
||||
return;
|
||||
@@ -3400,7 +3332,6 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
||||
}
|
||||
|
||||
static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
|
||||
assert( pIter!=0 || (*pRc)!=SQLITE_OK );
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5Config *pConfig = pIter->pIndex->pConfig;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -3472,10 +3403,7 @@ static void fts5MultiIterNew(
|
||||
}
|
||||
}
|
||||
*ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
|
||||
if( pNew==0 ){
|
||||
assert( p->rc!=SQLITE_OK );
|
||||
goto fts5MultiIterNew_post_check;
|
||||
}
|
||||
if( pNew==0 ) return;
|
||||
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
|
||||
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
|
||||
pNew->pColset = pColset;
|
||||
@@ -3539,10 +3467,6 @@ static void fts5MultiIterNew(
|
||||
fts5MultiIterFree(pNew);
|
||||
*ppOut = 0;
|
||||
}
|
||||
|
||||
fts5MultiIterNew_post_check:
|
||||
assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3590,8 +3514,7 @@ static void fts5MultiIterNew2(
|
||||
** False otherwise.
|
||||
*/
|
||||
static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
|
||||
assert( pIter!=0 || p->rc!=SQLITE_OK );
|
||||
assert( p->rc!=SQLITE_OK
|
||||
assert( p->rc
|
||||
|| (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof
|
||||
);
|
||||
return (p->rc || pIter->base.bEof);
|
||||
@@ -4395,7 +4318,6 @@ static void fts5IndexMergeLevel(
|
||||
** and last leaf page number at the same time. */
|
||||
fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
|
||||
|
||||
assert( pIter!=0 || p->rc!=SQLITE_OK );
|
||||
if( fts5MultiIterEof(p, pIter) ){
|
||||
int i;
|
||||
|
||||
@@ -4496,7 +4418,7 @@ static void fts5IndexAutomerge(
|
||||
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
|
||||
int nLeaf /* Number of output leaves just written */
|
||||
){
|
||||
if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){
|
||||
if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){
|
||||
Fts5Structure *pStruct = *ppStruct;
|
||||
u64 nWrite; /* Initial value of write-counter */
|
||||
int nWork; /* Number of work-quanta to perform */
|
||||
@@ -4619,14 +4541,14 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
|
||||
}else{
|
||||
i64 iRowid = 0;
|
||||
u64 iDelta = 0;
|
||||
i64 iDelta = 0;
|
||||
int iOff = 0;
|
||||
|
||||
/* The entire doclist will not fit on this leaf. The following
|
||||
** loop iterates through the poslists that make up the current
|
||||
** doclist. */
|
||||
while( p->rc==SQLITE_OK && iOff<nDoclist ){
|
||||
iOff += fts5GetVarint(&pDoclist[iOff], &iDelta);
|
||||
iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
|
||||
iRowid += iDelta;
|
||||
|
||||
if( writer.bFirstRowidInPage ){
|
||||
@@ -4900,9 +4822,6 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
|
||||
}
|
||||
|
||||
pIter->aPoslist = p;
|
||||
if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
|
||||
pIter->aPoslist = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4911,11 +4830,9 @@ static void fts5DoclistIterInit(
|
||||
Fts5DoclistIter *pIter
|
||||
){
|
||||
memset(pIter, 0, sizeof(*pIter));
|
||||
if( pBuf->n>0 ){
|
||||
pIter->aPoslist = pBuf->p;
|
||||
pIter->aEof = &pBuf->p[pBuf->n];
|
||||
fts5DoclistIterNext(pIter);
|
||||
}
|
||||
pIter->aPoslist = pBuf->p;
|
||||
pIter->aEof = &pBuf->p[pBuf->n];
|
||||
fts5DoclistIterNext(pIter);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -5058,7 +4975,7 @@ static void fts5MergePrefixLists(
|
||||
Fts5Buffer *aBuf /* Other lists to merge in */
|
||||
){
|
||||
#define fts5PrefixMergerNextPosition(p) \
|
||||
sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos)
|
||||
sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos);
|
||||
#define FTS5_MERGE_NLIST 16
|
||||
PrefixMerger aMerger[FTS5_MERGE_NLIST];
|
||||
PrefixMerger *pHead = 0;
|
||||
@@ -5157,8 +5074,7 @@ static void fts5MergePrefixLists(
|
||||
nTail = pHead->iter.nPoslist - pHead->iOff;
|
||||
|
||||
/* WRITEPOSLISTSIZE */
|
||||
assert_nc( tmp.n+nTail<=nTmp );
|
||||
assert( tmp.n+nTail<=nTmp+nMerge*10 );
|
||||
assert( tmp.n+nTail<=nTmp );
|
||||
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
|
||||
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
@@ -5565,7 +5481,7 @@ int sqlite3Fts5IndexQuery(
|
||||
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
|
||||
int iIdx = 0; /* Index to search */
|
||||
int iPrefixIdx = 0; /* +1 prefix index */
|
||||
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
|
||||
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
|
||||
|
||||
/* Figure out which index to search and set iIdx accordingly. If this
|
||||
** is a prefix query for which there is no prefix index, set iIdx to
|
||||
@@ -5606,15 +5522,11 @@ int sqlite3Fts5IndexQuery(
|
||||
/* Scan multiple terms in the main index */
|
||||
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
|
||||
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
|
||||
if( pRet==0 ){
|
||||
assert( p->rc!=SQLITE_OK );
|
||||
}else{
|
||||
assert( pRet->pColset==0 );
|
||||
fts5IterSetOutputCb(&p->rc, pRet);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
|
||||
if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
|
||||
}
|
||||
assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
|
||||
fts5IterSetOutputCb(&p->rc, pRet);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
|
||||
if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5682,9 +5594,8 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
|
||||
const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
|
||||
int n;
|
||||
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
|
||||
assert_nc( z || n<=1 );
|
||||
*pn = n-1;
|
||||
return (z ? &z[1] : 0);
|
||||
return &z[1];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5862,7 +5773,7 @@ static int fts5QueryCksum(
|
||||
Fts5IndexIter *pIter = 0;
|
||||
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
|
||||
|
||||
while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){
|
||||
while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){
|
||||
i64 rowid = pIter->iRowid;
|
||||
|
||||
if( eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -6227,7 +6138,6 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
|
||||
Fts5Iter *pIter; /* Used to iterate through entire index */
|
||||
Fts5Structure *pStruct; /* Index structure */
|
||||
int iLvl, iSeg;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Used by extra internal tests only run if NDEBUG is not defined */
|
||||
@@ -6238,16 +6148,15 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
|
||||
/* Load the FTS index structure */
|
||||
pStruct = fts5StructureRead(p);
|
||||
if( pStruct==0 ){
|
||||
assert( p->rc!=SQLITE_OK );
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
/* Check that the internal nodes of each segment match the leaves */
|
||||
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
|
||||
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
|
||||
Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
|
||||
fts5IndexIntegrityCheckSegment(p, pSeg);
|
||||
if( pStruct ){
|
||||
int iLvl, iSeg;
|
||||
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
|
||||
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
|
||||
Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
|
||||
fts5IndexIntegrityCheckSegment(p, pSeg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6311,7 +6220,6 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
** function only.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** Decode a segment-data rowid from the %_data table. This function is
|
||||
** the opposite of macro FTS5_SEGMENT_ROWID().
|
||||
@@ -6334,9 +6242,7 @@ static void fts5DecodeRowid(
|
||||
|
||||
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
|
||||
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
|
||||
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
|
||||
@@ -6354,9 +6260,7 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
static void fts5DebugStructure(
|
||||
int *pRc, /* IN/OUT: error code */
|
||||
Fts5Buffer *pBuf,
|
||||
@@ -6378,9 +6282,7 @@ static void fts5DebugStructure(
|
||||
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** This is part of the fts5_decode() debugging aid.
|
||||
**
|
||||
@@ -6405,9 +6307,7 @@ static void fts5DecodeStructure(
|
||||
fts5DebugStructure(pRc, pBuf, p);
|
||||
fts5StructureRelease(p);
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** This is part of the fts5_decode() debugging aid.
|
||||
**
|
||||
@@ -6430,9 +6330,7 @@ static void fts5DecodeAverages(
|
||||
zSpace = " ";
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
|
||||
** each varint and append its string representation to buffer pBuf. Return
|
||||
@@ -6449,9 +6347,7 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
|
||||
}
|
||||
return iOff;
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** The start of buffer (a/n) contains the start of a doclist. The doclist
|
||||
** may or may not finish within the buffer. This function appends a text
|
||||
@@ -6484,9 +6380,7 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
|
||||
|
||||
return iOff;
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** This function is part of the fts5_decode() debugging function. It is
|
||||
** only ever used with detail=none tables.
|
||||
@@ -6527,9 +6421,7 @@ static void fts5DecodeRowidList(
|
||||
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** The implementation of user-defined scalar function fts5_decode().
|
||||
*/
|
||||
@@ -6738,9 +6630,7 @@ static void fts5DecodeFunction(
|
||||
}
|
||||
fts5BufferFree(&s);
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** The implementation of user-defined scalar function fts5_rowid().
|
||||
*/
|
||||
@@ -6774,7 +6664,6 @@ static void fts5RowidFunction(
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
|
||||
/*
|
||||
** This is called as part of registering the FTS5 module with database
|
||||
@@ -6785,7 +6674,6 @@ static void fts5RowidFunction(
|
||||
** SQLite error code is returned instead.
|
||||
*/
|
||||
int sqlite3Fts5IndexInit(sqlite3 *db){
|
||||
#ifdef SQLITE_TEST
|
||||
int rc = sqlite3_create_function(
|
||||
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
|
||||
);
|
||||
@@ -6803,10 +6691,6 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
#else
|
||||
return SQLITE_OK;
|
||||
UNUSED_PARAM(db);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-16
@@ -22,9 +22,7 @@
|
||||
** assert() conditions in the fts5 code are activated - conditions that are
|
||||
** only true if it is guaranteed that the fts5 database is not corrupt.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3_fts5_may_be_corrupt = 1;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct Fts5Auxdata Fts5Auxdata;
|
||||
@@ -804,7 +802,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
|
||||
rc = sqlite3_step(pSorter->pStmt);
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
}else if( rc==SQLITE_ROW ){
|
||||
const u8 *a;
|
||||
const u8 *aBlob;
|
||||
@@ -1374,8 +1372,7 @@ static int fts5FilterMethod(
|
||||
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pRowidEq!=0 ){
|
||||
assert( pCsr->ePlan==FTS5_PLAN_ROWID );
|
||||
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
|
||||
sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
|
||||
}else{
|
||||
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
|
||||
@@ -1950,15 +1947,13 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
|
||||
|
||||
nInst++;
|
||||
if( nInst>=pCsr->nInstAlloc ){
|
||||
int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
|
||||
pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
|
||||
aInst = (int*)sqlite3_realloc64(
|
||||
pCsr->aInst, nNewSize*sizeof(int)*3
|
||||
pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
|
||||
);
|
||||
if( aInst ){
|
||||
pCsr->aInst = aInst;
|
||||
pCsr->nInstAlloc = nNewSize;
|
||||
}else{
|
||||
nInst--;
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
@@ -2182,8 +2177,7 @@ static int fts5ApiPhraseFirst(
|
||||
int n;
|
||||
int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pIter->a || n==0 );
|
||||
pIter->b = (pIter->a ? &pIter->a[n] : 0);
|
||||
pIter->b = &pIter->a[n];
|
||||
*piCol = 0;
|
||||
*piOff = 0;
|
||||
fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
|
||||
@@ -2242,8 +2236,7 @@ static int fts5ApiPhraseFirstColumn(
|
||||
rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pIter->a || n==0 );
|
||||
pIter->b = (pIter->a ? &pIter->a[n] : 0);
|
||||
pIter->b = &pIter->a[n];
|
||||
*piCol = 0;
|
||||
fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
|
||||
}
|
||||
@@ -2251,8 +2244,7 @@ static int fts5ApiPhraseFirstColumn(
|
||||
int n;
|
||||
rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pIter->a || n==0 );
|
||||
pIter->b = (pIter->a ? &pIter->a[n] : 0);
|
||||
pIter->b = &pIter->a[n];
|
||||
if( n<=0 ){
|
||||
*piCol = -1;
|
||||
}else if( pIter->a[0]==0x01 ){
|
||||
@@ -2730,7 +2722,7 @@ int sqlite3Fts5GetTokenizer(
|
||||
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
}else{
|
||||
rc = pMod->x.xCreate(
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
|
||||
pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
|
||||
);
|
||||
pConfig->pTokApi = &pMod->x;
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
||||
@@ -417,16 +417,12 @@ static int fts5StorageDeleteFromIndex(
|
||||
if( pConfig->abUnindexed[iCol-1]==0 ){
|
||||
const char *zText;
|
||||
int nText;
|
||||
assert( pSeek==0 || apVal==0 );
|
||||
assert( pSeek!=0 || apVal!=0 );
|
||||
if( pSeek ){
|
||||
zText = (const char*)sqlite3_column_text(pSeek, iCol);
|
||||
nText = sqlite3_column_bytes(pSeek, iCol);
|
||||
}else if( ALWAYS(apVal) ){
|
||||
}else{
|
||||
zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
|
||||
nText = sqlite3_value_bytes(apVal[iCol-1]);
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
ctx.szCol = 0;
|
||||
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
|
||||
@@ -1062,9 +1058,8 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
|
||||
|
||||
assert( p->pConfig->bColumnsize );
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
|
||||
if( pLookup ){
|
||||
if( rc==SQLITE_OK ){
|
||||
int bCorrupt = 1;
|
||||
assert( rc==SQLITE_OK );
|
||||
sqlite3_bind_int64(pLookup, 1, iRowid);
|
||||
if( SQLITE_ROW==sqlite3_step(pLookup) ){
|
||||
const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
|
||||
@@ -1077,8 +1072,6 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
|
||||
if( bCorrupt && rc==SQLITE_OK ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
}else{
|
||||
assert( rc!=SQLITE_OK );
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -29,9 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
extern int sqlite3_fts5_may_be_corrupt;
|
||||
#endif
|
||||
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
|
||||
extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*);
|
||||
|
||||
@@ -1013,7 +1011,6 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
#ifdef SQLITE_DEBUG
|
||||
int bOld = sqlite3_fts5_may_be_corrupt;
|
||||
|
||||
if( objc!=2 && objc!=1 ){
|
||||
@@ -1027,7 +1024,6 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ static int fts5tokConnectMethod(
|
||||
|
||||
rc = pApi->xFindTokenizer(pApi, zModule, &pTokCtx, &pTab->tok);
|
||||
if( rc==SQLITE_OK ){
|
||||
const char **azArg = (nDequote>1 ? (const char **)&azDequote[1] : 0);
|
||||
const char **azArg = (const char **)&azDequote[1];
|
||||
int nArg = nDequote>0 ? nDequote-1 : 0;
|
||||
rc = pTab->tok.xCreate(pTokCtx, azArg, nArg, &pTab->pTok);
|
||||
}
|
||||
|
||||
+2
-10
@@ -60,7 +60,6 @@ struct Fts5VocabCursor {
|
||||
|
||||
int bEof; /* True if this cursor is at EOF */
|
||||
Fts5IndexIter *pIter; /* Term/rowid iterator object */
|
||||
void *pStruct; /* From sqlite3Fts5StructureRef() */
|
||||
|
||||
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
@@ -374,7 +373,7 @@ static int fts5VocabOpenMethod(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
|
||||
int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
|
||||
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
}
|
||||
|
||||
@@ -394,8 +393,6 @@ static int fts5VocabOpenMethod(
|
||||
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
||||
pCsr->rowid = 0;
|
||||
sqlite3Fts5IterClose(pCsr->pIter);
|
||||
sqlite3Fts5StructureRelease(pCsr->pStruct);
|
||||
pCsr->pStruct = 0;
|
||||
pCsr->pIter = 0;
|
||||
sqlite3_free(pCsr->zLeTerm);
|
||||
pCsr->nLeTerm = -1;
|
||||
@@ -473,11 +470,9 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
|
||||
static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
int nCol = pCsr->pFts5->pConfig->nCol;
|
||||
int rc;
|
||||
|
||||
rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
pCsr->rowid++;
|
||||
|
||||
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
|
||||
@@ -651,9 +646,6 @@ static int fts5VocabFilterMethod(
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5Index *pIndex = pCsr->pFts5->pIndex;
|
||||
rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||
if( rc==SQLITE_OK ){
|
||||
pCsr->pStruct = sqlite3Fts5StructureRef(pIndex);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
|
||||
rc = fts5VocabInstanceNewTerm(pCsr);
|
||||
|
||||
@@ -165,7 +165,7 @@ do_execsql_test 4.0 {
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE p1 USING fts5(a, b, detail=%DETAIL%);
|
||||
CREATE VIRTUAL TABLE p1 USING fts5(a, b);
|
||||
INSERT INTO p1 VALUES(
|
||||
'x a a a a a a a a a a',
|
||||
'a a a a a a a a a a a a a a a a a a a x'
|
||||
@@ -184,12 +184,6 @@ do_execsql_test 5.3 {
|
||||
do_execsql_test 5.4 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x');
|
||||
} {{[x a a a a a...}}
|
||||
do_execsql_test 5.5 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ""');
|
||||
} {{[x a a a a a...}}
|
||||
do_execsql_test 5.6 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB');
|
||||
} {{[x a a a a a...}}
|
||||
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,798 +0,0 @@
|
||||
# 2015 Apr 24
|
||||
#
|
||||
# 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 tests that FTS5 handles corrupt databases (i.e. internal
|
||||
# inconsistencies in the backing tables) correctly. In this case
|
||||
# "correctly" means without crashing.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
database_may_be_corrupt
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# dbsqlfuzz crash-0f47112aa7520cf08c6a835a88fdff8c2a32a188
|
||||
#
|
||||
reset_db
|
||||
do_test 1.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename crash-0f47112aa7520c.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53 ...............S
|
||||
| 112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00 .....3..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
|
||||
| 3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62 ......1tablebbbb
|
||||
| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb
|
||||
| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table
|
||||
| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf
|
||||
| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE
|
||||
| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR
|
||||
| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI
|
||||
| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...!
|
||||
| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs
|
||||
| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR
|
||||
| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 EATE TABLE 't1_d
|
||||
| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
|
||||
| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i.......
|
||||
| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i
|
||||
| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE
|
||||
| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid,
|
||||
| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM
|
||||
| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t
|
||||
| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO
|
||||
| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl
|
||||
| 3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 et1_datat1_data.
|
||||
| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
|
||||
| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
|
||||
| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11 lock BLOB)T.....
|
||||
| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA
|
||||
| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
|
||||
| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a
|
||||
| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3
|
||||
| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L....
|
||||
| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........
|
||||
| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........
|
||||
| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........
|
||||
| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........
|
||||
| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 00 00 00 00 ...~.H..........
|
||||
| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................
|
||||
| 2384: 30 00 00 00 01 01 03 35 00 03 01 11 12 02 01 12 0......5........
|
||||
| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>...
|
||||
| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
|
||||
| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
|
||||
| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
|
||||
| 2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
|
||||
| 2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04 .<.....3the.....
|
||||
| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
|
||||
| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
|
||||
| 2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80 ....tab.........
|
||||
| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02 .....8.....2wh..
|
||||
| 2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80 ...3fts.........
|
||||
| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
|
||||
| 2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80 ...h............
|
||||
| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
|
||||
| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
|
||||
| 2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
|
||||
| 2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80 ....is..........
|
||||
| 2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
|
||||
| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
|
||||
| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
|
||||
| 2720: 01 02 05 01 00 6f 03 06 01 01 06 04 09 18 8c 80 .....o..........
|
||||
| 2736: 80 80 80 06 03 00 36 00 00 00 03 04 02 31 66 03 ......6......1f.
|
||||
| 2752: 02 02 01 01 69 03 06 01 01 03 04 f6 1c 8c 80 80 ....i...........
|
||||
| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
|
||||
| 2784: f6 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
|
||||
| 2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........0.......
|
||||
| 2816: 06 30 74 61 62 6c 65 0f 42 03 07 1c 8c 81 80 80 .0table.B.......
|
||||
| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
|
||||
| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
|
||||
| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02 .......,........
|
||||
| 2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03 0n..............
|
||||
| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
|
||||
| 2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00 ....is........*.
|
||||
| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
|
||||
| 2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80 ................
|
||||
| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
|
||||
| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
|
||||
| 2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01 .........0......
|
||||
| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
|
||||
| 3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
|
||||
| 3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88 .......the......
|
||||
| 3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04 .......<........
|
||||
| 3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08 3are.....bet....
|
||||
| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 13 32 .........<.....2
|
||||
| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
|
||||
| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
|
||||
| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
|
||||
| 3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .............6..
|
||||
| 3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
|
||||
| 3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 9e 00 ............<...
|
||||
| 3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
|
||||
| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
|
||||
| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
|
||||
| 3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00 ..............4.
|
||||
| 3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
|
||||
| 3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00 ............8...
|
||||
| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
|
||||
| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
|
||||
| 3328: 16 06 30 74 68 65 72 65 02 02 02 00 02 31 31 02 ..0there.....11.
|
||||
| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
|
||||
| 3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07 .......0the.....
|
||||
| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
|
||||
| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
|
||||
| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00 .............<..
|
||||
| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
|
||||
| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
|
||||
| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
|
||||
| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
|
||||
| 3488: 34 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2
|
||||
| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
|
||||
| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
|
||||
| 3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65 ...4tabl.......e
|
||||
| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
|
||||
| 3568: 00 00 00 16 05 34 65 61 63 68 01 02 03 01 04 70 .....4each.....p
|
||||
| 3584: 72 65 73 01 02 05 04 08 1a 84 80 80 80 80 0f 03 res.............
|
||||
| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
|
||||
| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
|
||||
| 3632: 03 00 3c 00 00 00 16 04 33 80 72 65 01 02 05 01 ..<.....3.re....
|
||||
| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
|
||||
| 3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02 ....:.....3for..
|
||||
| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
|
||||
| 3696: 80 80 0c 03 00 3c 00 00 00 17 03 32 74 68 01 06 .....<.....2th..
|
||||
| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84 .....3eac.......
|
||||
| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
|
||||
| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
|
||||
| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01 ......8.....2in.
|
||||
| 3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80 ......pr........
|
||||
| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
|
||||
| 3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
|
||||
| 3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04 .....<.....1t...
|
||||
| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
|
||||
| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
|
||||
| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
|
||||
| 3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03 .....6.....1e...
|
||||
| 3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80 ..f.............
|
||||
| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
|
||||
| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
|
||||
| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 64 61 62 ............0dab
|
||||
| 3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03 le..............
|
||||
| 3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74 .0......0present
|
||||
| 4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00 .............<..
|
||||
| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
|
||||
| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
|
||||
| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 13 66 .....0each.....f
|
||||
| 4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00 or..............
|
||||
| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
|
||||
| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
|
||||
| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
|
||||
| 48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13 .V.M.A.8./.&....
|
||||
| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
|
||||
| 80: 0e c3 0e ba 0e 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
|
||||
| 3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e .....4t ......4.
|
||||
| 3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
|
||||
| 3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10 3n.......2w.....
|
||||
| 3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
|
||||
| 3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08 ....2.......1t..
|
||||
| 3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
|
||||
| 3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
|
||||
| 3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
|
||||
| 3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
|
||||
| 3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04 ...4r.......4 ..
|
||||
| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
|
||||
| 3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
|
||||
| 3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01 2i.......2ar....
|
||||
| 3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08 ...1t.......1n..
|
||||
| 3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
|
||||
| 3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01 .......0ther....
|
||||
| 3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08 ...0t.......0n..
|
||||
| 3936: 14 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61 .....0b.......0a
|
||||
| 3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22 .............4t.
|
||||
| 3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e .....4 .....3te.
|
||||
| 3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a .....3p......3f.
|
||||
| 4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74 .....2th......2t
|
||||
| 4016: 16 01 64 09 10 01 32 69 14 07 04 09 10 01 32 66 ..d...2i......2f
|
||||
| 4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69 ......1t......1i
|
||||
| 4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65 ......1......0te
|
||||
| 4064: 0a 06 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
|
||||
| 4080: 06 08 04 09 12 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| page 4 offset 12288
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10 ................
|
||||
| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
|
||||
| 4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version.
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................
|
||||
| end crash-0f47112aa7520c.db
|
||||
}]
|
||||
} {}
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_test 2.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename sql047467.txt.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53 ...............S
|
||||
| 112: 0e e8 0e 8b 0e 33 0e 0f 01 00 00 00 00 00 00 00 .....3..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
|
||||
| 3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62 ......1tablebbbb
|
||||
| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb
|
||||
| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table
|
||||
| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf
|
||||
| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE
|
||||
| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR
|
||||
| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI
|
||||
| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...!
|
||||
| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs
|
||||
| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR
|
||||
| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 EATE TABLE 't1_d
|
||||
| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
|
||||
| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i.......
|
||||
| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i
|
||||
| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE
|
||||
| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid,
|
||||
| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM
|
||||
| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t
|
||||
| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO
|
||||
| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl
|
||||
| 3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 et1_datat1_data.
|
||||
| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
|
||||
| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
|
||||
| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11 lock BLOB)T.....
|
||||
| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA
|
||||
| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
|
||||
| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a
|
||||
| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3
|
||||
| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L....
|
||||
| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........
|
||||
| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........
|
||||
| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........
|
||||
| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........
|
||||
| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 00 00 00 00 ...~.H..........
|
||||
| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................
|
||||
| 2384: 30 00 00 00 01 01 03 35 00 03 01 11 12 02 01 12 0......5........
|
||||
| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>...
|
||||
| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
|
||||
| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
|
||||
| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
|
||||
| 2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
|
||||
| 2480: 00 3b ff f0 00 16 04 33 74 68 65 03 06 01 01 04 .;.....3the.....
|
||||
| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
|
||||
| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
|
||||
| 2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80 ....tab.........
|
||||
| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02 .....8.....2wh..
|
||||
| 2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80 ...3fts.........
|
||||
| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
|
||||
| 2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80 ...h............
|
||||
| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
|
||||
| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
|
||||
| 2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
|
||||
| 2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80 ....is..........
|
||||
| 2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
|
||||
| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
|
||||
| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
|
||||
| 2720: 01 02 05 01 00 6f 03 06 01 01 06 14 09 18 8c 80 .....o..........
|
||||
| 2736: 80 80 80 06 03 00 36 00 00 00 03 04 02 31 66 03 ......6......1f.
|
||||
| 2752: 02 02 01 01 69 03 06 01 01 03 04 f6 1c 8c 80 80 ....i...........
|
||||
| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
|
||||
| 2784: f6 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
|
||||
| 2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........0.......
|
||||
| 2816: 06 30 74 61 62 6c 65 0f 42 03 07 1c 8c 81 80 80 .0table.B.......
|
||||
| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
|
||||
| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
|
||||
| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02 .......,........
|
||||
| 2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03 0n..............
|
||||
| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
|
||||
| 2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00 ....is........*.
|
||||
| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
|
||||
| 2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80 ................
|
||||
| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
|
||||
| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
|
||||
| 2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01 .........0......
|
||||
| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
|
||||
| 3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
|
||||
| 3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88 .......the......
|
||||
| 3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04 .......<........
|
||||
| 3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08 3are.....bet....
|
||||
| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 13 32 .........<.....2
|
||||
| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
|
||||
| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
|
||||
| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
|
||||
| 3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .............6..
|
||||
| 3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
|
||||
| 3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 94 50 ............<..P
|
||||
| 3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
|
||||
| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
|
||||
| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
|
||||
| 3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00 ..............4.
|
||||
| 3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
|
||||
| 3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00 ............8...
|
||||
| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
|
||||
| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
|
||||
| 3328: 16 06 30 74 68 65 72 65 02 02 02 00 02 31 31 02 ..0there.....11.
|
||||
| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
|
||||
| 3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07 .......0the.....
|
||||
| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
|
||||
| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
|
||||
| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00 .............<..
|
||||
| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
|
||||
| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
|
||||
| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
|
||||
| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
|
||||
| 3488: 34 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2
|
||||
| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
|
||||
| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
|
||||
| 3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65 ...4tabl.......e
|
||||
| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
|
||||
| 3568: 00 00 00 16 05 34 65 61 63 68 01 02 03 01 04 70 .....4each.....p
|
||||
| 3584: 72 65 73 01 02 05 04 08 1a 84 80 80 80 80 0f 03 res.............
|
||||
| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
|
||||
| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
|
||||
| 3632: 03 00 3c 00 00 00 16 04 33 80 72 65 01 02 05 01 ..<.....3.re....
|
||||
| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
|
||||
| 3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02 ....:.....3for..
|
||||
| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
|
||||
| 3696: 80 80 0c 03 00 3c 00 00 00 17 03 32 74 68 01 06 .....<.....2th..
|
||||
| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84 .....3eac.......
|
||||
| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
|
||||
| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
|
||||
| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01 ......8.....2in.
|
||||
| 3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80 ......pr........
|
||||
| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
|
||||
| 3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
|
||||
| 3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04 .....<.....1t...
|
||||
| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
|
||||
| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
|
||||
| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
|
||||
| 3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03 .....6.....1e...
|
||||
| 3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80 ..f.............
|
||||
| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
|
||||
| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
|
||||
| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 64 61 62 ............0dab
|
||||
| 3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03 le..............
|
||||
| 3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74 .0......0present
|
||||
| 4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00 .............<..
|
||||
| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
|
||||
| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
|
||||
| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 13 66 .....0each.....f
|
||||
| 4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00 or..............
|
||||
| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
|
||||
| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
|
||||
| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
|
||||
| 48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13 .V.M.A.8./.&....
|
||||
| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
|
||||
| 80: 0e c3 0e ba 0e 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
|
||||
| 3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e .....4t ......4.
|
||||
| 3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
|
||||
| 3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10 3n.......2w.....
|
||||
| 3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
|
||||
| 3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08 ....2.......1t..
|
||||
| 3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
|
||||
| 3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
|
||||
| 3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
|
||||
| 3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
|
||||
| 3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04 ...4r.......4 ..
|
||||
| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
|
||||
| 3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
|
||||
| 3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01 2i.......2ar....
|
||||
| 3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08 ...1t.......1n..
|
||||
| 3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
|
||||
| 3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01 .......0ther....
|
||||
| 3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08 ...0t.......0n..
|
||||
| 3936: 14 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61 .....0b.......0a
|
||||
| 3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22 .............4t.
|
||||
| 3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e .....4 .....3te.
|
||||
| 3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a .....3p......3f.
|
||||
| 4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74 .....2th......2t
|
||||
| 4016: 16 01 64 09 10 01 32 69 14 07 04 09 10 01 32 66 ..d...2i......2f
|
||||
| 4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69 ......1t......1i
|
||||
| 4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65 ......1......0te
|
||||
| 4064: 0a 06 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
|
||||
| 4080: 06 08 04 09 12 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| page 4 offset 12288
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10 ................
|
||||
| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
|
||||
| 4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version.
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................
|
||||
| end sql047467.txt.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 3.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-c69fcaceff1e50.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 01 bb 02 30 30 01 02 06 01 02 06 01 02 06 .....00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6b b1 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 k.ble...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 05 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 1a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 01 ...omit.........
|
||||
| 3744: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 ................
|
||||
| 3760: 58 81 96 4d 01 06 01 02 02 03 06 01 02 02 03 06 X..M............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe....
|
||||
| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 c6 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 00 f6 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| end crash-c69fcaceff1e50.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 4.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename crash-ef6738247b1344.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 10 00 06 40 00 00 06 .....@ ....@...
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53 ...............S
|
||||
| 112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00 .....3..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
|
||||
| 3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62 ......1tablebbbb
|
||||
| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb
|
||||
| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table
|
||||
| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf
|
||||
| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE
|
||||
| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR
|
||||
| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI
|
||||
| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...!
|
||||
| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs
|
||||
| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR
|
||||
| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 EATE TABLE 't1_d
|
||||
| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
|
||||
| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i.......
|
||||
| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i
|
||||
| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE
|
||||
| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid,
|
||||
| 3872: 74 65 72 6d 2c 20 6f 67 6e 6f 2c 20 50 52 49 4d term, ogno, PRIM
|
||||
| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t
|
||||
| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO
|
||||
| 3920: 57 49 44 55 35 07 17 1b 1b 01 81 01 74 61 62 6c WIDU5.......tabl
|
||||
| 3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 et1_datat1_data.
|
||||
| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
|
||||
| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
|
||||
| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11 lock BLOB)T.....
|
||||
| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA
|
||||
| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
|
||||
| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a
|
||||
| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3
|
||||
| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L....
|
||||
| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........
|
||||
| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........
|
||||
| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........
|
||||
| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........
|
||||
| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 0a cc 0a 00 ...~.H..........
|
||||
| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................
|
||||
| 2384: 30 00 00 00 01 01 03 35 00 03 01 01 12 02 01 12 0......5........
|
||||
| 2400: 03 01 11 1c 8c 80 80 80 80 10 02 9c 3e 00 00 00 ............>...
|
||||
| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
|
||||
| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
|
||||
| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
|
||||
| 2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
|
||||
| 2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04 .<.....3the.....
|
||||
| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
|
||||
| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
|
||||
| 2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80 ....tab.........
|
||||
| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02 .....8.....2wh..
|
||||
| 2560: 04 00 04 33 66 74 73 03 12 02 04 07 18 8c 80 80 ...3fts.........
|
||||
| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
|
||||
| 2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80 ...h............
|
||||
| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
|
||||
| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
|
||||
| 2640: 82 d0 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
|
||||
| 2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80 ....is..........
|
||||
| 2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
|
||||
| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
|
||||
| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
|
||||
| 2720: 01 02 05 01 01 6f 03 06 01 01 06 04 09 18 8c 80 .....o..........
|
||||
| 2736: 81 80 80 06 03 00 36 00 00 00 13 04 12 31 66 03 ......6......1f.
|
||||
| 2752: 02 02 01 01 69 03 06 01 01 03 05 06 1c 8c 80 80 ....i...........
|
||||
| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
|
||||
| 2784: 06 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
|
||||
| 2800: 8c 80 65 80 80 04 03 00 30 00 00 00 11 01 01 06 ..e.....0.......
|
||||
| 2816: 06 30 74 61 62 6c 65 03 02 03 07 1c 8c 80 80 80 .0table.........
|
||||
| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
|
||||
| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
|
||||
| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f fc 01 03 02 .......,........
|
||||
| 2880: 30 6e 03 06 01 00 f2 07 1b 8c 80 80 80 80 01 03 0n..............
|
||||
| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
|
||||
| 2912: 03 02 01 02 69 73 03 06 04 0c 00 00 00 18 ea 00 ....is..........
|
||||
| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
|
||||
| 2944: 80 80 80 80 12 03 00 12 10 00 00 05 02 1c 88 80 ................
|
||||
| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
|
||||
| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
|
||||
| 2992: 15 88 80 80 80 80 10 03 00 2f ff ff f0 11 02 01 ........./......
|
||||
| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
|
||||
| 3024: 80 80 0f cf 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
|
||||
| 3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88 .......the......
|
||||
| 3056: 80 80 80 80 0d 03 00 3c 00 00 00 16 00 01 02 04 .......<........
|
||||
| 3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08 3are.....bet....
|
||||
| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 03 32 .........<.....2
|
||||
| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
|
||||
| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
|
||||
| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
|
||||
| 3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .............6..
|
||||
| 3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
|
||||
| 3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 00 00 ............<...
|
||||
| 3200: 16 12 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
|
||||
| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
|
||||
| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
|
||||
| 3248: 01 01 05 04 08 17 78 80 80 80 80 08 03 00 34 10 ......x.......4.
|
||||
| 3264: 01 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
|
||||
| 3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00 ............8...
|
||||
| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
|
||||
| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
|
||||
| 3328: 16 06 30 74 68 65 72 65 e7 02 02 00 02 31 31 02 ..0there.....11.
|
||||
| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
|
||||
| 3360: 00 00 11 01 01 05 e5 30 74 68 65 02 06 01 01 07 .......0the.....
|
||||
| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
|
||||
| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
|
||||
| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00 .............<..
|
||||
| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
|
||||
| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
|
||||
| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
|
||||
| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
|
||||
| 3488: 34 01 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2
|
||||
| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
|
||||
| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
|
||||
| 3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65 ...4tabl.......e
|
||||
| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
|
||||
| 3568: 00 00 00 16 05 34 65 61 63 68 01 02 02 01 04 70 .....4each.....p
|
||||
| 3584: 72 65 73 01 02 05 04 09 1a 84 80 80 80 80 0f 03 res.............
|
||||
| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
|
||||
| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
|
||||
| 3632: 03 00 3c 00 00 00 16 04 33 70 72 65 01 02 05 01 ..<.....3pre....
|
||||
| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
|
||||
| 3664: 80 0d 03 0d 1a 00 00 00 15 04 33 66 6e 72 01 02 ..........3fnr..
|
||||
| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
|
||||
| 3696: 80 80 0c 03 00 3c 00 00 00 16 03 32 74 68 01 06 .....<.....2th..
|
||||
| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84 .....3eac.......
|
||||
| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
|
||||
| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
|
||||
| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 30 c9 6e 01 ......8.....0.n.
|
||||
| 3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80 ......pr........
|
||||
| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
|
||||
| 3808: 02 0b e2 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
|
||||
| 3824: 86 f0 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04 .....<.....1t...
|
||||
| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
|
||||
| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
|
||||
| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
|
||||
| 3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03 .....6.....1e...
|
||||
| 3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80 ..f.............
|
||||
| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
|
||||
| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
|
||||
| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 74 61 62 ............0tab
|
||||
| 3968: 6c 65 01 06 01 01 05 04 15 84 7f 80 80 80 03 03 le..............
|
||||
| 3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74 .0......0present
|
||||
| 4000: 01 02 05 05 1b 84 80 22 80 80 02 03 00 3c 00 00 .............<..
|
||||
| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
|
||||
| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
|
||||
| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 03 66 .....0each.....f
|
||||
| 4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00 or..............
|
||||
| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
|
||||
| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
|
||||
| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
|
||||
| 48: 0f 56 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 .V..............
|
||||
| 3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
|
||||
| 3408: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e .....4t ......4.
|
||||
| 3424: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
|
||||
| 3440: 34 6e 1a 08 04 01 10 01 03 32 67 18 08 04 01 10 4n.......2g.....
|
||||
| 3456: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
|
||||
| 3472: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08 ....2.......1t..
|
||||
| 3488: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
|
||||
| 3504: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
|
||||
| 3520: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
|
||||
| 3536: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
|
||||
| 3552: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04 ...4r.......4 ..
|
||||
| 3568: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
|
||||
| 3584: 1c 18 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
|
||||
| 3600: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01 2i.......2ar....
|
||||
| 3616: 10 01 02 31 74 2a 08 04 01 0f 01 02 31 6e 12 0a ...1t*......1n..
|
||||
| 3632: d4 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
|
||||
| 3648: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01 .......0ther....
|
||||
| 3664: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08 ...0t.......0n..
|
||||
| 3680: 04 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61 .....0b.......0a
|
||||
| 3696: 04 06 03 f1 0c 01 02 02 07 04 09 10 01 34 74 22 .............4t.
|
||||
| 3712: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e .....4 .....3te.
|
||||
| 3728: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a .....3p......3f.
|
||||
| 3744: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74 .....2th......2t
|
||||
| 3760: 16 07 04 09 10 01 32 69 14 07 04 09 10 01 32 66 ......2i......2f
|
||||
| 3776: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69 ......1t......1i
|
||||
| 3792: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65 ......1......0te
|
||||
| 3808: 0a 07 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
|
||||
| 3824: 06 08 04 09 1e 61 30 66 74 04 05 00 00 00 00 00 .....a0ft.......
|
||||
| page 4 offset 12288
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10 ................
|
||||
| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
|
||||
| 4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version.
|
||||
| end crash-ef6738247b1344.db
|
||||
}]} {}
|
||||
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
BEGIN;
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(200,1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
INSERT INTO t1(t1) VALUES('delete-all');
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 4.3 {
|
||||
REPLACE INTO t1(rowid,b,rowid,a) VALUES(200,1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 4.4 {
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(0,1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 4.5 {
|
||||
REPLACE INTO t1(rowid,a,b,rowid) VALUES(200,1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# 2015 Apr 24
|
||||
#
|
||||
# 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 tests that FTS5 handles corrupt databases (i.e. internal
|
||||
# inconsistencies in the backing tables) correctly. In this case
|
||||
# "correctly" means without crashing.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
database_may_be_corrupt
|
||||
|
||||
proc editblock {block} {
|
||||
binary format Sa* 20000 [string range $block 2 end]
|
||||
}
|
||||
db func editblock editblock
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(abc, def);
|
||||
WITH a(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM a WHERE i<1000
|
||||
)
|
||||
INSERT INTO ft SELECT
|
||||
'abc abc abc abc abc abc abc abc abc abc',
|
||||
'def def def def def def def def def def'
|
||||
FROM a;
|
||||
UPDATE ft_data SET block = editblock(block) WHERE id=(
|
||||
SELECT id FROM ft_data ORDER BY id LIMIT 1 OFFSET 5
|
||||
);
|
||||
}
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
SELECT rowid FROM ft('def') ORDER BY rowid DESC LIMIT 1 OFFSET 9999;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -212,10 +212,6 @@ do_catchsql_test 4.1 {
|
||||
SELECT * FROM t4('a:a')
|
||||
} {1 {fts5: column queries are not supported (detail=none)}}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
SELECT * FROM t4('a:a &')
|
||||
} {1 {fts5: syntax error near "&"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that for the same content detail=none uses less space than
|
||||
# detail=col, and that detail=col uses less space than detail=full
|
||||
|
||||
@@ -42,26 +42,5 @@ do_execsql_test 1.2 {
|
||||
INSERT INTO ccc(ccc) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE VIRTUAL TABLE tx USING fts5(x);
|
||||
}
|
||||
|
||||
set doc [string repeat "abc " 5000]
|
||||
do_execsql_test 2.2 {
|
||||
BEGIN;
|
||||
INSERT INTO tx(rowid, x) VALUES(-9000000000000000000, $doc);
|
||||
INSERT INTO tx(rowid, x) VALUES(9000000000000000000, $doc);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT rowid FROM tx('abc');
|
||||
} {
|
||||
-9000000000000000000
|
||||
9000000000000000000
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -83,7 +83,7 @@ for {set i 0} {$i < 255} {incr i} {
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
|
||||
INSERT INTO e1 VALUES ('just a few words with a / inside');
|
||||
INSERT INTO e1 VALUES ("just a few words with a / inside");
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
|
||||
@@ -188,11 +188,11 @@ foreach {tn pgsz} {
|
||||
INSERT INTO hh(hh, rank) VALUES('pgsz', $pgsz);
|
||||
|
||||
WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
|
||||
INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
|
||||
INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
|
||||
FROM s;
|
||||
|
||||
WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
|
||||
INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
|
||||
INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
|
||||
FROM s;
|
||||
|
||||
INSERT INTO hh(hh) VALUES('optimize');
|
||||
|
||||
@@ -323,34 +323,5 @@ do_execsql_test 12.3 {
|
||||
SELECT * FROM t2 JOIN ft USING (ft)
|
||||
} {3 4 b b}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post https://sqlite.org/forum/forumpost/21127c1160
|
||||
#
|
||||
reset_db
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
|
||||
do_execsql_test 13.0 {
|
||||
CREATE TABLE a (id INTEGER PRIMARY KEY, name TEXT);
|
||||
CREATE VIRTUAL TABLE b USING fts5(name);
|
||||
CREATE TRIGGER a_trigger AFTER INSERT ON a BEGIN
|
||||
INSERT INTO b (name) VALUES ('foo');
|
||||
END;
|
||||
}
|
||||
|
||||
do_test 13.1 {
|
||||
set ::STMT [
|
||||
sqlite3_prepare db "INSERT INTO a VALUES (1, 'foo') RETURNING id;" -1 dummy
|
||||
]
|
||||
sqlite3_step $::STMT
|
||||
} {SQLITE_ROW}
|
||||
|
||||
do_test 13.2 {
|
||||
sqlite3_finalize $::STMT
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test 13.3 {
|
||||
sqlite3_errmsg db
|
||||
} {not an error}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -30,23 +30,23 @@ do_eqp_test 1.1 {
|
||||
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN f1 VIRTUAL TABLE INDEX 0:M1
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1, f1 WHERE f1 > t1.x
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN f1 VIRTUAL TABLE INDEX 0:
|
||||
`--SCAN t1
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN f1 VIRTUAL TABLE INDEX 0:M1
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
@@ -54,12 +54,12 @@ do_eqp_test 1.4 {
|
||||
SELECT * FROM f1 ORDER BY rank
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN f1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM f1 WHERE rank MATCH ?
|
||||
} {SCAN f1 VIRTUAL TABLE INDEX 0:r}
|
||||
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -192,9 +192,10 @@ do_eqp_test 6.2 {
|
||||
} {VIRTUAL TABLE INDEX 0:G0}
|
||||
do_eqp_test 6.3 {
|
||||
SELECT * FROM ci1 WHERE x LIKE ?
|
||||
} {{SCAN ci1 VIRTUAL TABLE INDEX 0:}}
|
||||
} {{SCAN TABLE ci1 VIRTUAL TABLE INDEX 0:}}
|
||||
do_eqp_test 6.4 {
|
||||
SELECT * FROM ci1 WHERE x GLOB ?
|
||||
} {VIRTUAL TABLE INDEX 0:G0}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -234,53 +234,4 @@ ifcapable fts3 {
|
||||
} {1 {no such fts5 table: main.nosuchtable}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the fts5 table cannot be written while there are vocab
|
||||
# cursors open.
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
|
||||
INSERT INTO t1 VALUES('one'), ('two'), ('three'), ('four');
|
||||
}
|
||||
|
||||
do_test 5.1 {
|
||||
list [catch {
|
||||
db eval { SELECT * FROM v1 } {
|
||||
db eval {INSERT INTO t1 VALUES('five')}
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {query aborted}}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
SELECT * FROM t1
|
||||
} {one two three four five}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the fts5 table cannot be written while there are vocab
|
||||
# cursors open.
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT
|
||||
'State Emergency Service (SES), Rural Fire Service (RFS) and Volunteers'
|
||||
FROM s;
|
||||
}
|
||||
|
||||
do_catchsql_test 5.1 {
|
||||
INSERT INTO t1 SELECT rowid FROM v1
|
||||
} {1 {query aborted}}
|
||||
|
||||
do_catchsql_test 5.2 {
|
||||
DELETE FROM t1 WHERE rowid>100;
|
||||
INSERT INTO t1 SELECT randomblob(3000) FROM v1
|
||||
} {1 {query aborted}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -60,8 +60,7 @@ proc fts5_source_id {zDir} {
|
||||
|
||||
set L [split [readfile [file join $top manifest]]]
|
||||
set date [lindex $L [expr [lsearch -exact $L D]+1]]
|
||||
set idx [expr {[string last . $date]-1}]
|
||||
set date [string range $date 0 $idx]
|
||||
set date [string range $date 0 [string last . $date]-1]
|
||||
set date [string map {T { }} $date]
|
||||
|
||||
return "fts5: $date $uuid"
|
||||
|
||||
+10
-4
@@ -153,12 +153,18 @@ SQLite. Documentation follows.
|
||||
the ICU extension LIKE operator is 50000, defined in source
|
||||
file "icu.c".
|
||||
|
||||
3.3 Collation Sequence Security
|
||||
3.3 Collation Sequence Security Issue
|
||||
|
||||
Internally, SQLite assumes that indices stored in database files
|
||||
are sorted according to the collation sequence indicated by the
|
||||
SQL schema. Changing the definition of a collation sequence after
|
||||
an index has been built is therefore equivalent to database
|
||||
corruption. The SQLite library is well tested for robustness in
|
||||
the fact of database corruption. Database corruption may well
|
||||
lead to incorrect answers, but should not cause memory errors.
|
||||
corruption. The SQLite library is not very well tested under
|
||||
these conditions, and may contain potential buffer overruns
|
||||
or other programming errors that could be exploited by a malicious
|
||||
programmer.
|
||||
|
||||
If the ICU extension is used in an environment where potentially
|
||||
malicious users may execute arbitrary SQL (i.e. gears), they
|
||||
should be prevented from invoking the icu_load_collation() function,
|
||||
possibly using the authorisation callback.
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
**
|
||||
** The virtual table contains read-only hidden columns:
|
||||
**
|
||||
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
|
||||
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
|
||||
** is BLOB or TEXT then this column is exactly the
|
||||
** same as the key. For the UINT keytype, this column
|
||||
** will be a variable-length integer encoding of the key.
|
||||
|
||||
+115
-222
@@ -14,23 +14,24 @@
|
||||
** appended onto the end of some other file, such as an executable.
|
||||
**
|
||||
** A special record must appear at the end of the file that identifies the
|
||||
** file as an appended database and provides the offset to the first page
|
||||
** of the exposed content. (Or, it is the length of the content prefix.)
|
||||
** For best performance page 1 should be located at a disk page boundary,
|
||||
** though that is not required.
|
||||
** file as an appended database and provides an offset to page 1. For
|
||||
** best performance page 1 should be located at a disk page boundary, though
|
||||
** that is not required.
|
||||
**
|
||||
** When opening a database using this VFS, the connection might treat
|
||||
** the file as an ordinary SQLite database, or it might treat it as a
|
||||
** database appended onto some other file. The decision is made by
|
||||
** applying the following rules in order:
|
||||
** the file as an ordinary SQLite database, or it might treat is as a
|
||||
** database appended onto some other file. Here are the rules:
|
||||
**
|
||||
** (1) An empty file is an ordinary database.
|
||||
** (1) When opening a new empty file, that file is treated as an ordinary
|
||||
** database.
|
||||
**
|
||||
** (2) If the file ends with the appendvfs trailer string
|
||||
** "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
|
||||
** (2) When opening a file that begins with the standard SQLite prefix
|
||||
** string "SQLite format 3", that file is treated as an ordinary
|
||||
** database.
|
||||
**
|
||||
** (3) If the file begins with the standard SQLite prefix string
|
||||
** "SQLite format 3", that file is an ordinary database.
|
||||
** (3) When opening a file that ends with the appendvfs trailer string
|
||||
** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
|
||||
** database.
|
||||
**
|
||||
** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
|
||||
** set, then a new database is appended to the already existing file.
|
||||
@@ -38,13 +39,13 @@
|
||||
** (5) Otherwise, SQLITE_CANTOPEN is returned.
|
||||
**
|
||||
** To avoid unnecessary complications with the PENDING_BYTE, the size of
|
||||
** the file containing the database is limited to 1GiB. (1073741824 bytes)
|
||||
** This VFS will not read or write past the 1GiB mark. This restriction
|
||||
** might be lifted in future versions. For now, if you need a larger
|
||||
** database, then keep it in a separate file.
|
||||
** the file containing the database is limited to 1GB. This VFS will refuse
|
||||
** to read or write past the 1GB mark. This restriction might be lifted in
|
||||
** future versions. For now, if you need a large database, then keep the
|
||||
** database in a separate file.
|
||||
**
|
||||
** If the file being opened is a plain database (not an appended one), then
|
||||
** this shim is a pass-through into the default underlying VFS. (rule 3)
|
||||
** If the file being opened is not an appended database, then this shim is
|
||||
** a pass-through into the default underlying VFS.
|
||||
**/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
@@ -57,27 +58,17 @@ SQLITE_EXTENSION_INIT1
|
||||
** 123456789 123456789 12345
|
||||
**
|
||||
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
|
||||
** the offset to page 1, and also the length of the prefix content.
|
||||
** the offset to page 1.
|
||||
*/
|
||||
#define APND_MARK_PREFIX "Start-Of-SQLite3-"
|
||||
#define APND_MARK_PREFIX_SZ 17
|
||||
#define APND_MARK_FOS_SZ 8
|
||||
#define APND_MARK_SIZE (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
|
||||
#define APND_MARK_SIZE 25
|
||||
|
||||
/*
|
||||
** Maximum size of the combined prefix + database + append-mark. This
|
||||
** must be less than 0x40000000 to avoid locking issues on Windows.
|
||||
*/
|
||||
#define APND_MAX_SIZE (0x40000000)
|
||||
|
||||
/*
|
||||
** Try to align the database to an even multiple of APND_ROUNDUP bytes.
|
||||
*/
|
||||
#ifndef APND_ROUNDUP
|
||||
#define APND_ROUNDUP 4096
|
||||
#endif
|
||||
#define APND_ALIGN_MASK ((sqlite3_int64)(APND_ROUNDUP-1))
|
||||
#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
|
||||
#define APND_MAX_SIZE (65536*15259)
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this utility
|
||||
@@ -91,45 +82,11 @@ typedef struct ApndFile ApndFile;
|
||||
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
||||
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
|
||||
|
||||
/* An open appendvfs file
|
||||
**
|
||||
** An instance of this structure describes the appended database file.
|
||||
** A separate sqlite3_file object is always appended. The appended
|
||||
** sqlite3_file object (which can be accessed using ORIGFILE()) describes
|
||||
** the entire file, including the prefix, the database, and the
|
||||
** append-mark.
|
||||
**
|
||||
** The structure of an AppendVFS database is like this:
|
||||
**
|
||||
** +-------------+---------+----------+-------------+
|
||||
** | prefix-file | padding | database | append-mark |
|
||||
** +-------------+---------+----------+-------------+
|
||||
** ^ ^
|
||||
** | |
|
||||
** iPgOne iMark
|
||||
**
|
||||
**
|
||||
** "prefix file" - file onto which the database has been appended.
|
||||
** "padding" - zero or more bytes inserted so that "database"
|
||||
** starts on an APND_ROUNDUP boundary
|
||||
** "database" - The SQLite database file
|
||||
** "append-mark" - The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
|
||||
** the offset from the start of prefix-file to the start
|
||||
** of "database".
|
||||
**
|
||||
** The size of the database is iMark - iPgOne.
|
||||
**
|
||||
** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
|
||||
** of iPgOne stored as a big-ending 64-bit integer.
|
||||
**
|
||||
** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
|
||||
** Or, iMark is -1 to indicate that it has not yet been written.
|
||||
*/
|
||||
/* An open file */
|
||||
struct ApndFile {
|
||||
sqlite3_file base; /* Subclass. MUST BE FIRST! */
|
||||
sqlite3_int64 iPgOne; /* Offset to the start of the database */
|
||||
sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */
|
||||
/* Always followed by another sqlite3_file that describes the whole file */
|
||||
sqlite3_file base; /* IO methods */
|
||||
sqlite3_int64 iPgOne; /* File offset to page 1 */
|
||||
sqlite3_int64 iMark; /* Start of the append-mark */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -221,6 +178,8 @@ static const sqlite3_io_methods apnd_io_methods = {
|
||||
apndUnfetch /* xUnfetch */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Close an apnd-file.
|
||||
*/
|
||||
@@ -238,37 +197,22 @@ static int apndRead(
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
ApndFile *paf = (ApndFile *)pFile;
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
|
||||
return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add the append-mark onto what should become the end of the file.
|
||||
* If and only if this succeeds, internal ApndFile.iMark is updated.
|
||||
* Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
|
||||
** Add the append-mark onto the end of the file.
|
||||
*/
|
||||
static int apndWriteMark(
|
||||
ApndFile *paf,
|
||||
sqlite3_file *pFile,
|
||||
sqlite_int64 iWriteEnd
|
||||
){
|
||||
sqlite_int64 iPgOne = paf->iPgOne;
|
||||
static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
|
||||
int i;
|
||||
unsigned char a[APND_MARK_SIZE];
|
||||
int i = APND_MARK_FOS_SZ;
|
||||
int rc;
|
||||
assert(pFile == ORIGFILE(paf));
|
||||
memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
|
||||
while( --i >= 0 ){
|
||||
a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
|
||||
iPgOne >>= 8;
|
||||
for(i=0; i<8; i++){
|
||||
a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
|
||||
}
|
||||
iWriteEnd += paf->iPgOne;
|
||||
if( SQLITE_OK==(rc = pFile->pMethods->xWrite
|
||||
(pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
|
||||
paf->iMark = iWriteEnd;
|
||||
}
|
||||
return rc;
|
||||
return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -280,28 +224,38 @@ static int apndWrite(
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
ApndFile *paf = (ApndFile *)pFile;
|
||||
sqlite_int64 iWriteEnd = iOfst + iAmt;
|
||||
if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
|
||||
int rc;
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
/* If append-mark is absent or will be overwritten, write it. */
|
||||
if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
|
||||
int rc = apndWriteMark(paf, pFile, iWriteEnd);
|
||||
if( SQLITE_OK!=rc ) return rc;
|
||||
if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
|
||||
rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
|
||||
if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
|
||||
sqlite3_int64 sz = 0;
|
||||
rc = pFile->pMethods->xFileSize(pFile, &sz);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iMark = sz - APND_MARK_SIZE;
|
||||
if( iOfst + iAmt + p->iPgOne > p->iMark ){
|
||||
p->iMark = p->iPgOne + iOfst + iAmt;
|
||||
rc = apndWriteMark(p, pFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an apnd-file.
|
||||
*/
|
||||
static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
ApndFile *paf = (ApndFile *)pFile;
|
||||
int rc;
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
/* The append mark goes out first so truncate failure does not lose it. */
|
||||
if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
|
||||
/* Truncate underlying file just past append mark */
|
||||
return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
|
||||
rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iMark = p->iPgOne+size;
|
||||
rc = apndWriteMark(p, pFile);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -314,12 +268,16 @@ static int apndSync(sqlite3_file *pFile, int flags){
|
||||
|
||||
/*
|
||||
** Return the current file-size of an apnd-file.
|
||||
** If the append mark is not yet there, the file-size is 0.
|
||||
*/
|
||||
static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
ApndFile *paf = (ApndFile *)pFile;
|
||||
*pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
|
||||
return SQLITE_OK;
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
int rc;
|
||||
pFile = ORIGFILE(p);
|
||||
rc = pFile->pMethods->xFileSize(pFile, pSize);
|
||||
if( rc==SQLITE_OK && p->iPgOne ){
|
||||
*pSize -= p->iPgOne + APND_MARK_SIZE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -350,13 +308,12 @@ static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
** File control method. For custom operations on an apnd-file.
|
||||
*/
|
||||
static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
ApndFile *paf = (ApndFile *)pFile;
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
int rc;
|
||||
pFile = ORIGFILE(pFile);
|
||||
if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
|
||||
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
|
||||
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
|
||||
*(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
|
||||
*(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -415,9 +372,6 @@ static int apndFetch(
|
||||
void **pp
|
||||
){
|
||||
ApndFile *p = (ApndFile *)pFile;
|
||||
if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
|
||||
return SQLITE_IOERR; /* Cannot read what is not yet there. */
|
||||
}
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
|
||||
}
|
||||
@@ -429,155 +383,95 @@ static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
||||
return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the file is an ordinary SQLite database file.
|
||||
*/
|
||||
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
|
||||
int rc;
|
||||
char zHdr[16];
|
||||
static const char aSqliteHdr[] = "SQLite format 3";
|
||||
if( sz<512 ) return 0;
|
||||
rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
|
||||
if( rc ) return 0;
|
||||
return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to read the append-mark off the end of a file. Return the
|
||||
** start of the appended database if the append-mark is present.
|
||||
** If there is no valid append-mark, return -1;
|
||||
**
|
||||
** An append-mark is only valid if the NNNNNNNN start-of-database offset
|
||||
** indicates that the appended database contains at least one page. The
|
||||
** start-of-database value must be a multiple of 512.
|
||||
** start of the appended database if the append-mark is present. If
|
||||
** there is no append-mark, return -1;
|
||||
*/
|
||||
static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
|
||||
int rc, i;
|
||||
sqlite3_int64 iMark;
|
||||
int msbs = 8 * (APND_MARK_FOS_SZ-1);
|
||||
unsigned char a[APND_MARK_SIZE];
|
||||
|
||||
if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
|
||||
if( sz<=APND_MARK_SIZE ) return -1;
|
||||
rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
|
||||
if( rc ) return -1;
|
||||
if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
|
||||
iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
|
||||
for(i=1; i<8; i++){
|
||||
msbs -= 8;
|
||||
iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
|
||||
iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
|
||||
for(i=1; i<8; i++){
|
||||
iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
|
||||
}
|
||||
if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
|
||||
if( iMark & 0x1ff ) return -1;
|
||||
return iMark;
|
||||
}
|
||||
|
||||
static const char apvfsSqliteHdr[] = "SQLite format 3";
|
||||
/*
|
||||
** Check to see if the file is an appendvfs SQLite database file.
|
||||
** Return true iff it is such. Parameter sz is the file's size.
|
||||
*/
|
||||
static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
|
||||
int rc;
|
||||
char zHdr[16];
|
||||
sqlite3_int64 iMark = apndReadMark(sz, pFile);
|
||||
if( iMark>=0 ){
|
||||
/* If file has the correct end-marker, the expected odd size, and the
|
||||
** SQLite DB type marker where the end-marker puts it, then it
|
||||
** is an appendvfs database.
|
||||
*/
|
||||
rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
|
||||
if( SQLITE_OK==rc
|
||||
&& memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
|
||||
&& (sz & 0x1ff) == APND_MARK_SIZE
|
||||
&& sz>=512+APND_MARK_SIZE
|
||||
){
|
||||
return 1; /* It's an appendvfs database */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the file is an ordinary SQLite database file.
|
||||
** Return true iff so. Parameter sz is the file's size.
|
||||
*/
|
||||
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
|
||||
char zHdr[16];
|
||||
if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
|
||||
|| (sz & 0x1ff) != 0
|
||||
|| SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
|
||||
|| memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
|
||||
){
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Open an apnd file handle.
|
||||
*/
|
||||
static int apndOpen(
|
||||
sqlite3_vfs *pApndVfs,
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
ApndFile *pApndFile = (ApndFile*)pFile;
|
||||
sqlite3_file *pBaseFile = ORIGFILE(pFile);
|
||||
sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
|
||||
ApndFile *p;
|
||||
sqlite3_file *pSubFile;
|
||||
sqlite3_vfs *pSubVfs;
|
||||
int rc;
|
||||
sqlite3_int64 sz = 0;
|
||||
sqlite3_int64 sz;
|
||||
pSubVfs = ORIGVFS(pVfs);
|
||||
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
|
||||
/* The appendvfs is not to be used for transient or temporary databases.
|
||||
** Just use the base VFS open to initialize the given file object and
|
||||
** open the underlying file. (Appendvfs is then unused for this file.)
|
||||
*/
|
||||
return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
|
||||
return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
|
||||
}
|
||||
memset(pApndFile, 0, sizeof(ApndFile));
|
||||
p = (ApndFile*)pFile;
|
||||
memset(p, 0, sizeof(*p));
|
||||
pSubFile = ORIGFILE(pFile);
|
||||
pFile->pMethods = &apnd_io_methods;
|
||||
pApndFile->iMark = -1; /* Append mark not yet written */
|
||||
|
||||
rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
|
||||
if( rc ){
|
||||
pBaseFile->pMethods->xClose(pBaseFile);
|
||||
}
|
||||
}
|
||||
rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
|
||||
if( rc ) goto apnd_open_done;
|
||||
rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
|
||||
if( rc ){
|
||||
pFile->pMethods = 0;
|
||||
return rc;
|
||||
pSubFile->pMethods->xClose(pSubFile);
|
||||
goto apnd_open_done;
|
||||
}
|
||||
if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
|
||||
/* The file being opened appears to be just an ordinary DB. Copy
|
||||
** the base dispatch-table so this instance mimics the base VFS.
|
||||
*/
|
||||
memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
|
||||
if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
|
||||
memmove(pFile, pSubFile, pSubVfs->szOsFile);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pApndFile->iPgOne = apndReadMark(sz, pFile);
|
||||
if( pApndFile->iPgOne>=0 ){
|
||||
pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
|
||||
p->iMark = 0;
|
||||
p->iPgOne = apndReadMark(sz, pFile);
|
||||
if( p->iPgOne>0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( (flags & SQLITE_OPEN_CREATE)==0 ){
|
||||
pBaseFile->pMethods->xClose(pBaseFile);
|
||||
pSubFile->pMethods->xClose(pSubFile);
|
||||
rc = SQLITE_CANTOPEN;
|
||||
pFile->pMethods = 0;
|
||||
}else{
|
||||
/* Round newly added appendvfs location to #define'd page boundary.
|
||||
** Note that nothing has yet been written to the underlying file.
|
||||
** The append mark will be written along with first content write.
|
||||
** Until then, paf->iMark value indicates it is not yet written.
|
||||
*/
|
||||
pApndFile->iPgOne = APND_START_ROUNDUP(sz);
|
||||
}
|
||||
p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
|
||||
apnd_open_done:
|
||||
if( rc ) pFile->pMethods = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete an apnd file.
|
||||
** For an appendvfs, this could mean delete the appendvfs portion,
|
||||
** leaving the appendee as it was before it gained an appendvfs.
|
||||
** For now, this code deletes the underlying file too.
|
||||
*/
|
||||
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
|
||||
}
|
||||
|
||||
/*
|
||||
** All other VFS methods are pass-thrus.
|
||||
*/
|
||||
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
|
||||
}
|
||||
static int apndAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
@@ -657,7 +551,6 @@ int sqlite3_appendvfs_init(
|
||||
(void)pzErrMsg;
|
||||
(void)db;
|
||||
pOrig = sqlite3_vfs_find(0);
|
||||
if( pOrig==0 ) return SQLITE_ERROR;
|
||||
apnd_vfs.iVersion = pOrig->iVersion;
|
||||
apnd_vfs.pAppData = pOrig;
|
||||
apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
|
||||
|
||||
+14
-18
@@ -56,24 +56,14 @@
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
|
||||
** Must exactly match the definitions in carray.h.
|
||||
*/
|
||||
#ifndef CARRAY_INT32
|
||||
# define CARRAY_INT32 0 /* Data is 32-bit signed integers */
|
||||
# define CARRAY_INT64 1 /* Data is 64-bit signed integers */
|
||||
# define CARRAY_DOUBLE 2 /* Data is doubles */
|
||||
# define CARRAY_TEXT 3 /* Data is char* */
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_API
|
||||
# ifdef _WIN32
|
||||
# define SQLITE_API __declspec(dllexport)
|
||||
# else
|
||||
# define SQLITE_API
|
||||
# endif
|
||||
#endif
|
||||
#define CARRAY_INT32 0 /* Data is 32-bit signed integers */
|
||||
#define CARRAY_INT64 1 /* Data is 64-bit signed integers */
|
||||
#define CARRAY_DOUBLE 2 /* Data is doubles */
|
||||
#define CARRAY_TEXT 3 /* Data is char* */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
@@ -410,7 +400,10 @@ static void carrayBindDel(void *pPtr){
|
||||
** Invoke this interface in order to bind to the single-argument
|
||||
** version of CARRAY().
|
||||
*/
|
||||
SQLITE_API int sqlite3_carray_bind(
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_carray_bind(
|
||||
sqlite3_stmt *pStmt,
|
||||
int idx,
|
||||
void *aData,
|
||||
@@ -464,7 +457,7 @@ SQLITE_API int sqlite3_carray_bind(
|
||||
z += n+1;
|
||||
}
|
||||
}else{
|
||||
memcpy(pNew->aData, aData, sz);
|
||||
memcpy(pNew->aData, aData, sz*nData);
|
||||
}
|
||||
pNew->xDel = sqlite3_free;
|
||||
}else{
|
||||
@@ -505,7 +498,10 @@ static void inttoptrFunc(
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
SQLITE_API int sqlite3_carray_init(
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_carray_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
|
||||
+1
-28
@@ -1,32 +1,12 @@
|
||||
/*
|
||||
** 2020-11-17
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** Interface definitions for the CARRAY table-valued function
|
||||
** extension.
|
||||
*/
|
||||
|
||||
#ifndef _CARRAY_H
|
||||
#define _CARRAY_H
|
||||
|
||||
#include "sqlite3.h" /* Required for error code definitions */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Use this interface to bind an array to the single-argument version
|
||||
** of CARRAY().
|
||||
*/
|
||||
SQLITE_API int sqlite3_carray_bind(
|
||||
int sqlite3_carray_bind(
|
||||
sqlite3_stmt *pStmt, /* Statement to be bound */
|
||||
int i, /* Parameter index */
|
||||
void *aData, /* Pointer to array data */
|
||||
@@ -41,10 +21,3 @@ SQLITE_API int sqlite3_carray_bind(
|
||||
#define CARRAY_INT64 1 /* Data is 64-bit signed integers */
|
||||
#define CARRAY_DOUBLE 2 /* Data is doubles */
|
||||
#define CARRAY_TEXT 3 /* Data is char* */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
#endif
|
||||
|
||||
#endif /* ifndef _CARRAY_H */
|
||||
|
||||
|
||||
+3
-15
@@ -579,18 +579,6 @@ static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
}else if( op==SQLITE_FCNTL_CKPT_START || op==SQLITE_FCNTL_CKPT_DONE ){
|
||||
p->inCkpt = op==SQLITE_FCNTL_CKPT_START;
|
||||
if( p->pPartner ) p->pPartner->inCkpt = p->inCkpt;
|
||||
}else if( op==SQLITE_FCNTL_CKSM_FILE ){
|
||||
/* This VFS needs to obtain a pointer to the corresponding database
|
||||
** file handle from within xOpen() calls to open wal files. To do this,
|
||||
** it uses the sqlite3_database_file_object() API to obtain a pointer
|
||||
** to the file-handle used by SQLite to access the db file. This is
|
||||
** fine if cksmvfs happens to be the top-level VFS, but not if there
|
||||
** are one or more wrapper VFS. To handle this case, this file-control
|
||||
** is used to extract the cksmvfs file-handle from any wrapper file
|
||||
** handle. */
|
||||
sqlite3_file **ppFile = (sqlite3_file**)pArg;
|
||||
*ppFile = (sqlite3_file*)p;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
|
||||
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
|
||||
@@ -700,8 +688,6 @@ static int cksmOpen(
|
||||
if( rc ) goto cksm_open_done;
|
||||
if( flags & SQLITE_OPEN_WAL ){
|
||||
sqlite3_file *pDb = sqlite3_database_file_object(zName);
|
||||
rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
|
||||
assert( rc==SQLITE_OK );
|
||||
p->pPartner = (CksmFile*)pDb;
|
||||
assert( p->pPartner->pPartner==0 );
|
||||
p->pPartner->pPartner = p;
|
||||
@@ -823,7 +809,6 @@ static int cksmRegisterVfs(void){
|
||||
sqlite3_vfs *pOrig;
|
||||
if( sqlite3_vfs_find("cksmvfs")!=0 ) return SQLITE_OK;
|
||||
pOrig = sqlite3_vfs_find(0);
|
||||
if( pOrig==0 ) return SQLITE_ERROR;
|
||||
cksm_vfs.iVersion = pOrig->iVersion;
|
||||
cksm_vfs.pAppData = pOrig;
|
||||
cksm_vfs.szOsFile = pOrig->szOsFile + sizeof(CksmFile);
|
||||
@@ -871,6 +856,9 @@ int sqlite3_cksumvfs_init(
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* not used */
|
||||
rc = cksmRegisterFunc(db, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = cksmRegisterVfs();
|
||||
}
|
||||
|
||||
+1
-1
@@ -941,7 +941,7 @@ int sqlite3_csv_init(
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
int rc;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
rc = sqlite3_create_module(db, "csv", &CsvModule, 0);
|
||||
|
||||
+4
-5
@@ -459,11 +459,10 @@ static void decimalSubFunc(
|
||||
Decimal *pA = decimal_new(context, argv[0], 0, 0);
|
||||
Decimal *pB = decimal_new(context, argv[1], 0, 0);
|
||||
UNUSED_PARAMETER(argc);
|
||||
if( pB ){
|
||||
pB->sign = !pB->sign;
|
||||
decimal_add(pA, pB);
|
||||
decimal_result(context, pA);
|
||||
}
|
||||
if( pB==0 ) return;
|
||||
pB->sign = !pB->sign;
|
||||
decimal_add(pA, pB);
|
||||
decimal_result(context, pA);
|
||||
decimal_free(pA);
|
||||
decimal_free(pB);
|
||||
}
|
||||
|
||||
+1
-31
@@ -72,11 +72,6 @@
|
||||
** $path is a relative path, then $path is interpreted relative to $dir.
|
||||
** And the paths returned in the "name" column of the table are also
|
||||
** relative to directory $dir.
|
||||
**
|
||||
** Notes on building this extension for Windows:
|
||||
** Unless linked statically with the SQLite library, a preprocessor
|
||||
** symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
|
||||
** DLL form of this extension for WIN32. See its use below for details.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
@@ -230,22 +225,6 @@ static sqlite3_uint64 fileTimeToUnixTime(
|
||||
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
|
||||
}
|
||||
|
||||
|
||||
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
|
||||
# /* To allow a standalone DLL, use this next replacement function: */
|
||||
# undef sqlite3_win32_utf8_to_unicode
|
||||
# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
|
||||
#
|
||||
LPWSTR utf8_to_utf16(const char *z){
|
||||
int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
|
||||
LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
|
||||
if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
|
||||
return rv;
|
||||
sqlite3_free(rv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function attempts to normalize the time values found in the stat()
|
||||
** buffer to UTC. This is necessary on Win32, where the runtime library
|
||||
@@ -368,11 +347,10 @@ static int writeFile(
|
||||
mode_t mode, /* MODE parameter passed to writefile() */
|
||||
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
|
||||
){
|
||||
if( zFile==0 ) return 1;
|
||||
#if !defined(_WIN32) && !defined(WIN32)
|
||||
if( S_ISLNK(mode) ){
|
||||
const char *zTo = (const char*)sqlite3_value_text(pData);
|
||||
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
|
||||
if( symlink(zTo, zFile)<0 ) return 1;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
@@ -1020,11 +998,3 @@ int sqlite3_fileio_init(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
|
||||
/* To allow a standalone DLL, make test_windirent.c use the same
|
||||
* redefined SQLite API calls as the above extension code does.
|
||||
* Just pull in this .c to accomplish this. As a beneficial side
|
||||
* effect, this extension becomes a single translation unit. */
|
||||
# include "test_windirent.c"
|
||||
#endif
|
||||
|
||||
+2
-14
@@ -167,14 +167,6 @@ static void ieee754func(
|
||||
int isNeg = 0;
|
||||
m = sqlite3_value_int64(argv[0]);
|
||||
e = sqlite3_value_int64(argv[1]);
|
||||
|
||||
/* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */
|
||||
if( e>10000 ){
|
||||
e = 10000;
|
||||
}else if( e<-10000 ){
|
||||
e = -10000;
|
||||
}
|
||||
|
||||
if( m<0 ){
|
||||
isNeg = 1;
|
||||
m = -m;
|
||||
@@ -194,11 +186,7 @@ static void ieee754func(
|
||||
e += 1075;
|
||||
if( e<=0 ){
|
||||
/* Subnormal */
|
||||
if( 1-e >= 64 ){
|
||||
m = 0;
|
||||
}else{
|
||||
m >>= 1-e;
|
||||
}
|
||||
m >>= 1-e;
|
||||
e = 0;
|
||||
}else if( e>0x7ff ){
|
||||
e = 0x7ff;
|
||||
@@ -284,7 +272,7 @@ int sqlite3_ieee_init(
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
|
||||
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
(void*)&aFunc[i].iAux,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
|
||||
+227
-295
File diff suppressed because it is too large
Load Diff
@@ -559,7 +559,6 @@ int sqlite3_memvfs_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
mem_vfs.pAppData = sqlite3_vfs_find(0);
|
||||
if( mem_vfs.pAppData==0 ) return SQLITE_ERROR;
|
||||
mem_vfs.szOsFile = sizeof(MemFile);
|
||||
rc = sqlite3_vfs_register(&mem_vfs, 1);
|
||||
#ifdef MEMVFS_TEST
|
||||
|
||||
@@ -1,461 +0,0 @@
|
||||
/*
|
||||
** 2022-01-19
|
||||
**
|
||||
** 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 a virtual-table that returns information about
|
||||
** how the query planner called the xBestIndex method. This virtual table
|
||||
** is intended for testing and debugging only.
|
||||
**
|
||||
** The schema of the virtual table is this:
|
||||
**
|
||||
** CREATE TABLE qpvtab(
|
||||
** vn TEXT, -- Name of an sqlite3_index_info field
|
||||
** ix INTEGER, -- Array index or value
|
||||
** cn TEXT, -- Column name
|
||||
** op INTEGER, -- operator
|
||||
** ux BOOLEAN, -- "usable" field
|
||||
** rhs TEXT, -- sqlite3_vtab_rhs_value()
|
||||
**
|
||||
** a, b, c, d, e, -- Extra columns to attach constraints to
|
||||
**
|
||||
** flags INTEGER HIDDEN -- control flags
|
||||
** );
|
||||
**
|
||||
** The virtual table returns a description of the sqlite3_index_info object
|
||||
** that was provided to the (successful) xBestIndex method. There is one
|
||||
** row in the result table for each field in the sqlite3_index_info object.
|
||||
**
|
||||
** The values of the "a" through "e" columns are one of:
|
||||
**
|
||||
** 1. TEXT - the same as the column name
|
||||
** 2. INTEGER - 1 for "a", 2 for "b", and so forth
|
||||
**
|
||||
** Option 1 is the default behavior. 2 is use if there is a usable
|
||||
** constraint on "flags" with an integer right-hand side that where the
|
||||
** value of the right-hand side has its 0x001 bit set.
|
||||
**
|
||||
** All constraints on columns "a" through "e" are marked as "omit".
|
||||
**
|
||||
** If there is a usable constraint on "flags" that has a RHS value that
|
||||
** is an integer and that integer has its 0x02 bit set, then the
|
||||
** orderByConsumed flag is set.
|
||||
**
|
||||
** FLAGS SUMMARY:
|
||||
**
|
||||
** 0x001 Columns 'a' through 'e' have INT values
|
||||
** 0x002 orderByConsumed is set
|
||||
** 0x004 OFFSET and LIMIT have omit set
|
||||
**
|
||||
** COMPILE:
|
||||
**
|
||||
** gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
|
||||
**
|
||||
** EXAMPLE USAGE:
|
||||
**
|
||||
** .load ./qpvtab
|
||||
** SELECT rowid, *, flags FROM qpvtab(102)
|
||||
** WHERE a=19
|
||||
** AND b BETWEEN 4.5 and 'hello'
|
||||
** AND c<>x'aabbcc'
|
||||
** ORDER BY d, e DESC;
|
||||
*/
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
|
||||
/* qpvtab_vtab is a subclass of sqlite3_vtab which is
|
||||
** underlying representation of the virtual table
|
||||
*/
|
||||
typedef struct qpvtab_vtab qpvtab_vtab;
|
||||
struct qpvtab_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
};
|
||||
|
||||
/* qpvtab_cursor is a subclass of sqlite3_vtab_cursor which will
|
||||
** serve as the underlying representation of a cursor that scans
|
||||
** over rows of the result
|
||||
*/
|
||||
typedef struct qpvtab_cursor qpvtab_cursor;
|
||||
struct qpvtab_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3_int64 iRowid; /* The rowid */
|
||||
const char *zData; /* Data to return */
|
||||
int nData; /* Number of bytes of data */
|
||||
int flags; /* Flags value */
|
||||
};
|
||||
|
||||
/*
|
||||
** Names of columns
|
||||
*/
|
||||
static const char *azColname[] = {
|
||||
"vn",
|
||||
"ix",
|
||||
"cn",
|
||||
"op",
|
||||
"ux",
|
||||
"rhs",
|
||||
"a", "b", "c", "d", "e",
|
||||
"flags",
|
||||
""
|
||||
};
|
||||
|
||||
/*
|
||||
** The qpvtabConnect() method is invoked to create a new
|
||||
** qpvtab virtual table.
|
||||
*/
|
||||
static int qpvtabConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
qpvtab_vtab *pNew;
|
||||
int rc;
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x("
|
||||
" vn TEXT,"
|
||||
" ix INT,"
|
||||
" cn TEXT,"
|
||||
" op INT,"
|
||||
" ux BOOLEAN,"
|
||||
" rhs TEXT,"
|
||||
" a, b, c, d, e,"
|
||||
" flags INT HIDDEN)"
|
||||
);
|
||||
#define QPVTAB_VN 0
|
||||
#define QPVTAB_IX 1
|
||||
#define QPVTAB_CN 2
|
||||
#define QPVTAB_OP 3
|
||||
#define QPVTAB_UX 4
|
||||
#define QPVTAB_RHS 5
|
||||
#define QPVTAB_A 6
|
||||
#define QPVTAB_B 7
|
||||
#define QPVTAB_C 8
|
||||
#define QPVTAB_D 9
|
||||
#define QPVTAB_E 10
|
||||
#define QPVTAB_FLAGS 11
|
||||
#define QPVTAB_NONE 12
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for qpvtab_vtab objects.
|
||||
*/
|
||||
static int qpvtabDisconnect(sqlite3_vtab *pVtab){
|
||||
qpvtab_vtab *p = (qpvtab_vtab*)pVtab;
|
||||
sqlite3_free(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new qpvtab_cursor object.
|
||||
*/
|
||||
static int qpvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
qpvtab_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a qpvtab_cursor.
|
||||
*/
|
||||
static int qpvtabClose(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance a qpvtab_cursor to its next row of output.
|
||||
*/
|
||||
static int qpvtabNext(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
if( pCur->iRowid<pCur->nData ){
|
||||
const char *z = &pCur->zData[pCur->iRowid];
|
||||
const char *zEnd = strchr(z, '\n');
|
||||
if( zEnd ) zEnd++;
|
||||
pCur->iRowid = (int)(zEnd - pCur->zData);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the qpvtab_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int qpvtabColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int i /* Which column to return */
|
||||
){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
if( i>=QPVTAB_VN && i<=QPVTAB_RHS && pCur->iRowid<pCur->nData ){
|
||||
const char *z = &pCur->zData[pCur->iRowid];
|
||||
const char *zEnd;
|
||||
int j;
|
||||
j = QPVTAB_VN;
|
||||
while(1){
|
||||
zEnd = strchr(z, j==QPVTAB_RHS ? '\n' : ',');
|
||||
if( j==i || zEnd==0 ) break;
|
||||
z = zEnd+1;
|
||||
j++;
|
||||
}
|
||||
if( zEnd==z ){
|
||||
sqlite3_result_null(ctx);
|
||||
}else if( i==QPVTAB_IX || i==QPVTAB_OP || i==QPVTAB_UX ){
|
||||
sqlite3_result_int(ctx, atoi(z));
|
||||
}else{
|
||||
sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
|
||||
}
|
||||
}else if( i>=QPVTAB_A && i<=QPVTAB_E ){
|
||||
if( pCur->flags & 0x001 ){
|
||||
sqlite3_result_int(ctx, i-QPVTAB_A+1);
|
||||
}else{
|
||||
char x = 'a'+i-QPVTAB_A;
|
||||
sqlite3_result_text64(ctx, &x, 1, SQLITE_TRANSIENT, SQLITE_UTF8);
|
||||
}
|
||||
}else if( i==QPVTAB_FLAGS ){
|
||||
sqlite3_result_int(ctx, pCur->flags);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the rowid for the current row. In this implementation, the
|
||||
** rowid is the same as the output value.
|
||||
*/
|
||||
static int qpvtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int qpvtabEof(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
return pCur->iRowid>=pCur->nData;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the qpvtab_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
** once prior to any call to qpvtabColumn() or qpvtabRowid() or
|
||||
** qpvtabEof().
|
||||
*/
|
||||
static int qpvtabFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor *)pVtabCursor;
|
||||
pCur->iRowid = 0;
|
||||
pCur->zData = idxStr;
|
||||
pCur->nData = (int)strlen(idxStr);
|
||||
pCur->flags = idxNum;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append the text of a value to pStr
|
||||
*/
|
||||
static void qpvtabStrAppendValue(
|
||||
sqlite3_str *pStr,
|
||||
sqlite3_value *pVal
|
||||
){
|
||||
switch( sqlite3_value_type(pVal) ){
|
||||
case SQLITE_NULL:
|
||||
sqlite3_str_appendf(pStr, "NULL");
|
||||
break;
|
||||
case SQLITE_INTEGER:
|
||||
sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pVal));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
sqlite3_str_appendf(pStr, "%!f", sqlite3_value_double(pVal));
|
||||
break;
|
||||
case SQLITE_TEXT: {
|
||||
int i;
|
||||
const char *a = (const char*)sqlite3_value_text(pVal);
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
for(i=0; i<n; i++){
|
||||
char c = a[i];
|
||||
if( c=='\n' ) c = ' ';
|
||||
sqlite3_str_append(pStr, &c, 1);
|
||||
if( c=='\'' ) sqlite3_str_append(pStr, &c, 1);
|
||||
}
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
int i;
|
||||
const unsigned char *a = sqlite3_value_blob(pVal);
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
sqlite3_str_append(pStr, "x'", 2);
|
||||
for(i=0; i<n; i++){
|
||||
sqlite3_str_appendf(pStr, "%02x", a[i]);
|
||||
}
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the virtual table. This routine needs to create
|
||||
** a query plan for each invocation and compute an estimated cost for that
|
||||
** plan.
|
||||
*/
|
||||
static int qpvtabBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
sqlite3_str *pStr = sqlite3_str_new(0);
|
||||
int i, k = 0;
|
||||
int rc;
|
||||
sqlite3_str_appendf(pStr, "nConstraint,%d,,,,\n", pIdxInfo->nConstraint);
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
sqlite3_value *pVal;
|
||||
int iCol = pIdxInfo->aConstraint[i].iColumn;
|
||||
int op = pIdxInfo->aConstraint[i].op;
|
||||
if( iCol==QPVTAB_FLAGS && pIdxInfo->aConstraint[i].usable ){
|
||||
pVal = 0;
|
||||
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
|
||||
assert( rc==SQLITE_OK || pVal==0 );
|
||||
if( pVal ){
|
||||
pIdxInfo->idxNum = sqlite3_value_int(pVal);
|
||||
if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
}
|
||||
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
iCol = QPVTAB_NONE;
|
||||
}
|
||||
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
|
||||
i,
|
||||
azColname[iCol],
|
||||
op,
|
||||
pIdxInfo->aConstraint[i].usable);
|
||||
pVal = 0;
|
||||
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
|
||||
assert( rc==SQLITE_OK || pVal==0 );
|
||||
if( pVal ){
|
||||
qpvtabStrAppendValue(pStr, pVal);
|
||||
}
|
||||
sqlite3_str_append(pStr, "\n", 1);
|
||||
}
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
int iCol = pIdxInfo->aConstraint[i].iColumn;
|
||||
int op = pIdxInfo->aConstraint[i].op;
|
||||
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
iCol = QPVTAB_NONE;
|
||||
}
|
||||
if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
|
||||
if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
|
||||
for(i=0; i<pIdxInfo->nOrderBy; i++){
|
||||
int iCol = pIdxInfo->aOrderBy[i].iColumn;
|
||||
sqlite3_str_appendf(pStr, "aOrderBy,%d,%s,%d,,\n",i,
|
||||
iCol>=0 ? azColname[iCol] : "rowid",
|
||||
pIdxInfo->aOrderBy[i].desc
|
||||
);
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "sqlite3_vtab_distinct,%d,,,,\n",
|
||||
sqlite3_vtab_distinct(pIdxInfo));
|
||||
sqlite3_str_appendf(pStr, "idxFlags,%d,,,,\n", pIdxInfo->idxFlags);
|
||||
sqlite3_str_appendf(pStr, "colUsed,%d,,,,\n", (int)pIdxInfo->colUsed);
|
||||
pIdxInfo->estimatedCost = (double)10;
|
||||
pIdxInfo->estimatedRows = 10;
|
||||
sqlite3_str_appendf(pStr, "idxNum,%d,,,,\n", pIdxInfo->idxNum);
|
||||
sqlite3_str_appendf(pStr, "orderByConsumed,%d,,,,\n",
|
||||
pIdxInfo->orderByConsumed);
|
||||
pIdxInfo->idxStr = sqlite3_str_finish(pStr);
|
||||
pIdxInfo->needToFreeIdxStr = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** virtual table.
|
||||
*/
|
||||
static sqlite3_module qpvtabModule = {
|
||||
/* iVersion */ 0,
|
||||
/* xCreate */ 0,
|
||||
/* xConnect */ qpvtabConnect,
|
||||
/* xBestIndex */ qpvtabBestIndex,
|
||||
/* xDisconnect */ qpvtabDisconnect,
|
||||
/* xDestroy */ 0,
|
||||
/* xOpen */ qpvtabOpen,
|
||||
/* xClose */ qpvtabClose,
|
||||
/* xFilter */ qpvtabFilter,
|
||||
/* xNext */ qpvtabNext,
|
||||
/* xEof */ qpvtabEof,
|
||||
/* xColumn */ qpvtabColumn,
|
||||
/* xRowid */ qpvtabRowid,
|
||||
/* xUpdate */ 0,
|
||||
/* xBegin */ 0,
|
||||
/* xSync */ 0,
|
||||
/* xCommit */ 0,
|
||||
/* xRollback */ 0,
|
||||
/* xFindMethod */ 0,
|
||||
/* xRename */ 0,
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
};
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_qpvtab_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3_create_module(db, "qpvtab", &qpvtabModule, 0);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
+15
-28
@@ -248,7 +248,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
break;
|
||||
}
|
||||
case RE_OP_ANY: {
|
||||
if( c!=0 ) re_add_state(pNext, x+1);
|
||||
re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_WORD: {
|
||||
@@ -256,7 +256,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTWORD: {
|
||||
if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
|
||||
if( !re_word_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_DIGIT: {
|
||||
@@ -264,7 +264,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTDIGIT: {
|
||||
if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
|
||||
if( !re_digit_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_SPACE: {
|
||||
@@ -272,7 +272,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTSPACE: {
|
||||
if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
|
||||
if( !re_space_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_BOUNDARY: {
|
||||
@@ -297,11 +297,8 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
rc = 1;
|
||||
goto re_match_end;
|
||||
}
|
||||
case RE_OP_CC_INC:
|
||||
case RE_OP_CC_EXC: {
|
||||
if( c==0 ) break;
|
||||
/* fall-through */ goto re_op_cc_inc;
|
||||
}
|
||||
case RE_OP_CC_INC: re_op_cc_inc: {
|
||||
int j = 1;
|
||||
int n = pRe->aArg[x];
|
||||
int hit = 0;
|
||||
@@ -322,7 +319,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
}
|
||||
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
|
||||
if( hit ) re_add_state(pNext, x+n);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -483,7 +480,7 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
iStart = p->nState;
|
||||
switch( c ){
|
||||
case '|':
|
||||
case '$':
|
||||
case '$':
|
||||
case ')': {
|
||||
p->sIn.i--;
|
||||
return 0;
|
||||
@@ -499,7 +496,7 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
if( rePeek(p)=='*' ){
|
||||
re_append(p, RE_OP_ANYSTAR, 0);
|
||||
p->sIn.i++;
|
||||
}else{
|
||||
}else{
|
||||
re_append(p, RE_OP_ANY, 0);
|
||||
}
|
||||
break;
|
||||
@@ -676,8 +673,8 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
** regex engine over the string. Do not worry able trying to match
|
||||
** unicode characters beyond plane 0 - those are very rare and this is
|
||||
** just an optimization. */
|
||||
if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
|
||||
for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
|
||||
if( pRe->aOp[0]==RE_OP_ANYSTAR ){
|
||||
for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
|
||||
unsigned x = pRe->aArg[i];
|
||||
if( x<=127 ){
|
||||
pRe->zInit[j++] = (unsigned char)x;
|
||||
@@ -708,8 +705,8 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
** is implemented as regexp(B,A).
|
||||
*/
|
||||
static void re_sql_func(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
ReCompiled *pRe; /* Compiled regular expression */
|
||||
@@ -718,12 +715,11 @@ static void re_sql_func(
|
||||
const char *zErr; /* Compile error message */
|
||||
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
|
||||
|
||||
(void)argc; /* Unused */
|
||||
pRe = sqlite3_get_auxdata(context, 0);
|
||||
if( pRe==0 ){
|
||||
zPattern = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zPattern==0 ) return;
|
||||
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
|
||||
zErr = re_compile(&pRe, zPattern, 0);
|
||||
if( zErr ){
|
||||
re_free(pRe);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
@@ -758,16 +754,7 @@ int sqlite3_regexp_init(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused */
|
||||
rc = sqlite3_create_function(db, "regexp", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
0, re_sql_func, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
|
||||
** of regexp(PATTERN,STRING). */
|
||||
rc = sqlite3_create_function(db, "regexpi", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
(void*)db, re_sql_func, 0, 0);
|
||||
}
|
||||
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, re_sql_func, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
+4
-18
@@ -323,12 +323,11 @@ static int seriesFilter(
|
||||
** (8) output in descending order
|
||||
*/
|
||||
static int seriesBestIndex(
|
||||
sqlite3_vtab *pVTab,
|
||||
sqlite3_vtab *tabUnused,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i, j; /* Loop over constraints */
|
||||
int idxNum = 0; /* The query plan bitmask */
|
||||
int bStartSeen = 0; /* EQ constraint seen on the START column */
|
||||
int unusableMask = 0; /* Mask of unusable constraints */
|
||||
int nArg = 0; /* Number of arguments that seriesFilter() expects */
|
||||
int aIdx[3]; /* Constraints on start, stop, and step */
|
||||
@@ -338,7 +337,7 @@ static int seriesBestIndex(
|
||||
** are the last three columns in the virtual table. */
|
||||
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
|
||||
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
|
||||
|
||||
(void)tabUnused;
|
||||
aIdx[0] = aIdx[1] = aIdx[2] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
@@ -348,7 +347,6 @@ static int seriesBestIndex(
|
||||
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
|
||||
assert( iCol>=0 && iCol<=2 );
|
||||
iMask = 1 << iCol;
|
||||
if( iCol==0 ) bStartSeen = 1;
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
continue;
|
||||
@@ -363,18 +361,6 @@ static int seriesBestIndex(
|
||||
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||
}
|
||||
}
|
||||
/* The current generate_column() implementation requires at least one
|
||||
** argument (the START value). Legacy versions assumed START=0 if the
|
||||
** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
|
||||
** to obtain the legacy behavior */
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
if( !bStartSeen ){
|
||||
sqlite3_free(pVTab->zErrMsg);
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"first argument to \"generate_series()\" missing or unusable");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
if( (unusableMask & ~idxNum)!=0 ){
|
||||
/* The start, stop, and step columns are inputs. Therefore if there
|
||||
** are unusable constraints on any of start, stop, or step then
|
||||
@@ -386,7 +372,7 @@ static int seriesBestIndex(
|
||||
** the preferred case */
|
||||
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
|
||||
pIdxInfo->estimatedRows = 1000;
|
||||
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
|
||||
if( pIdxInfo->nOrderBy==1 ){
|
||||
if( pIdxInfo->aOrderBy[0].desc ){
|
||||
idxNum |= 8;
|
||||
}else{
|
||||
@@ -448,7 +434,7 @@ int sqlite3_series_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){
|
||||
if( sqlite3_libversion_number()<3008012 ){
|
||||
*pzErrMsg = sqlite3_mprintf(
|
||||
"generate_series() requires SQLite 3.8.12 or later");
|
||||
return SQLITE_ERROR;
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ struct SHA1Context {
|
||||
/*
|
||||
* Hash a single 512-bit block. This is the core of the algorithm.
|
||||
*/
|
||||
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
|
||||
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
|
||||
unsigned int qq[5]; /* a, b, c, d, e; */
|
||||
static int one = 1;
|
||||
unsigned int block[16];
|
||||
|
||||
+1
-2
@@ -19,7 +19,7 @@
|
||||
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
|
||||
** X is NULL.
|
||||
**
|
||||
** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
|
||||
** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
|
||||
** and returns a hash of their results.
|
||||
**
|
||||
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
|
||||
@@ -436,7 +436,6 @@ static void SHA3Update(
|
||||
unsigned int nData
|
||||
){
|
||||
unsigned int i = 0;
|
||||
if( aData==0 ) return;
|
||||
#if SHA3_BYTEORDER==1234
|
||||
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
|
||||
for(; i+7<nData; i+=8){
|
||||
|
||||
@@ -754,7 +754,6 @@ static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
||||
*/
|
||||
int sqlite3_register_vfslog(const char *zArg){
|
||||
vlog_vfs.pVfs = sqlite3_vfs_find(0);
|
||||
if( vlog_vfs.pVfs==0 ) return SQLITE_ERROR;
|
||||
vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
|
||||
return sqlite3_vfs_register(&vlog_vfs.base, 1);
|
||||
}
|
||||
|
||||
@@ -806,7 +806,6 @@ int sqlite3_vfsstat_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
vstat_vfs.pVfs = sqlite3_vfs_find(0);
|
||||
if( vstat_vfs.pVfs==0 ) return SQLITE_ERROR;
|
||||
vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
|
||||
rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
@@ -220,7 +220,7 @@ static int wholenumberBestIndex(
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
if( (idxNum & 12)==0 ){
|
||||
pIdxInfo->estimatedCost = 1e99;
|
||||
pIdxInfo->estimatedCost = (double)100000000;
|
||||
}else if( (idxNum & 3)==0 ){
|
||||
pIdxInfo->estimatedCost = (double)5;
|
||||
}else{
|
||||
|
||||
+33
-55
@@ -36,30 +36,13 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
|
||||
#ifndef UINT32_TYPE
|
||||
# ifdef HAVE_UINT32_T
|
||||
# define UINT32_TYPE uint32_t
|
||||
# else
|
||||
# define UINT32_TYPE unsigned int
|
||||
# endif
|
||||
#endif
|
||||
#ifndef UINT16_TYPE
|
||||
# ifdef HAVE_UINT16_T
|
||||
# define UINT16_TYPE uint16_t
|
||||
# else
|
||||
# define UINT16_TYPE unsigned short int
|
||||
# endif
|
||||
#endif
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef unsigned char u8;
|
||||
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
|
||||
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned long u32;
|
||||
#define MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
@@ -564,7 +547,6 @@ static u16 zipfileGetU16(const u8 *aBuf){
|
||||
** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
|
||||
*/
|
||||
static u32 zipfileGetU32(const u8 *aBuf){
|
||||
if( aBuf==0 ) return 0;
|
||||
return ((u32)(aBuf[3]) << 24)
|
||||
+ ((u32)(aBuf[2]) << 16)
|
||||
+ ((u32)(aBuf[1]) << 8)
|
||||
@@ -724,24 +706,34 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
|
||||
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
|
||||
*/
|
||||
static u32 zipfileMtime(ZipfileCDS *pCDS){
|
||||
int Y,M,D,X1,X2,A,B,sec,min,hr;
|
||||
i64 JDsec;
|
||||
Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
|
||||
M = ((pCDS->mDate >> 5) & 0x0F);
|
||||
D = (pCDS->mDate & 0x1F);
|
||||
sec = (pCDS->mTime & 0x1F)*2;
|
||||
min = (pCDS->mTime >> 5) & 0x3F;
|
||||
hr = (pCDS->mTime >> 11) & 0x1F;
|
||||
if( M<=2 ){
|
||||
Y--;
|
||||
M += 12;
|
||||
int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
|
||||
int M = ((pCDS->mDate >> 5) & 0x0F);
|
||||
int D = (pCDS->mDate & 0x1F);
|
||||
int B = -13;
|
||||
|
||||
int sec = (pCDS->mTime & 0x1F)*2;
|
||||
int min = (pCDS->mTime >> 5) & 0x3F;
|
||||
int hr = (pCDS->mTime >> 11) & 0x1F;
|
||||
i64 JD;
|
||||
|
||||
/* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
|
||||
|
||||
/* Calculate the JD in seconds for noon on the day in question */
|
||||
if( M<3 ){
|
||||
Y = Y-1;
|
||||
M = M+12;
|
||||
}
|
||||
X1 = 36525*(Y+4716)/100;
|
||||
X2 = 306001*(M+1)/10000;
|
||||
A = Y/100;
|
||||
B = 2 - A + (A/4);
|
||||
JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
|
||||
return (u32)(JDsec - (i64)24405875*(i64)8640);
|
||||
JD = (i64)(24*60*60) * (
|
||||
(int)(365.25 * (Y + 4716))
|
||||
+ (int)(30.6001 * (M + 1))
|
||||
+ D + B - 1524
|
||||
);
|
||||
|
||||
/* Correct the JD for the time within the day */
|
||||
JD += (hr-12) * 3600 + min * 60 + sec;
|
||||
|
||||
/* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
|
||||
return (u32)(JD - (i64)(24405875) * 24*60*6);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -867,7 +859,7 @@ static int zipfileGetEntry(
|
||||
aRead = (u8*)&aBlob[pNew->cds.iOffset];
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
|
||||
rc = zipfileReadLFH(aRead, &lfh);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
|
||||
pNew->iDataOff += lfh.nFile + lfh.nExtra;
|
||||
@@ -1143,13 +1135,13 @@ static int zipfileReadEOCD(
|
||||
int nRead; /* Bytes to read from file */
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
memset(pEOCD, 0, sizeof(ZipfileEOCD));
|
||||
if( aBlob==0 ){
|
||||
i64 iOff; /* Offset to read from */
|
||||
i64 szFile; /* Total size of file in bytes */
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
szFile = (i64)ftell(pFile);
|
||||
if( szFile==0 ){
|
||||
memset(pEOCD, 0, sizeof(ZipfileEOCD));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
|
||||
@@ -1262,14 +1254,9 @@ static int zipfileFilter(
|
||||
zipfileCursorErr(pCsr, "zipfile() function requires an argument");
|
||||
return SQLITE_ERROR;
|
||||
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
|
||||
static const u8 aEmptyBlob = 0;
|
||||
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
assert( pTab->pFirstEntry==0 );
|
||||
if( aBlob==0 ){
|
||||
aBlob = &aEmptyBlob;
|
||||
nBlob = 0;
|
||||
}
|
||||
rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
|
||||
pCsr->pFreeEntry = pTab->pFirstEntry;
|
||||
pTab->pFirstEntry = pTab->pLastEntry = 0;
|
||||
@@ -1495,7 +1482,6 @@ static int zipfileBegin(sqlite3_vtab *pVtab){
|
||||
static u32 zipfileTime(void){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
u32 ret;
|
||||
if( pVfs==0 ) return 0;
|
||||
if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
|
||||
i64 ms;
|
||||
pVfs->xCurrentTimeInt64(pVfs, &ms);
|
||||
@@ -1943,7 +1929,7 @@ static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
|
||||
** SELECT zipfile(name,mode,mtime,data) ...
|
||||
** SELECT zipfile(name,mode,mtime,data,method) ...
|
||||
*/
|
||||
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
ZipfileCtx *p; /* Aggregate function context */
|
||||
ZipfileEntry e; /* New entry to add to zip archive */
|
||||
|
||||
@@ -2118,7 +2104,7 @@ static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
/*
|
||||
** xFinalize() callback for zipfile aggregate function.
|
||||
*/
|
||||
static void zipfileFinal(sqlite3_context *pCtx){
|
||||
void zipfileFinal(sqlite3_context *pCtx){
|
||||
ZipfileCtx *p;
|
||||
ZipfileEOCD eocd;
|
||||
sqlite3_int64 nZip;
|
||||
@@ -2175,10 +2161,6 @@ static int zipfileRegister(sqlite3 *db){
|
||||
zipfileRollback, /* xRollback */
|
||||
zipfileFindFunction, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollback */
|
||||
0 /* xShadowName */
|
||||
};
|
||||
|
||||
int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
|
||||
@@ -2188,10 +2170,6 @@ static int zipfileRegister(sqlite3 *db){
|
||||
zipfileStep, zipfileFinal
|
||||
);
|
||||
}
|
||||
assert( sizeof(i64)==8 );
|
||||
assert( sizeof(u32)==4 );
|
||||
assert( sizeof(u16)==2 );
|
||||
assert( sizeof(u8)==1 );
|
||||
return rc;
|
||||
}
|
||||
#else /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ void usage(const char *zArgv0){
|
||||
|
||||
void report_default_vfs(){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
fprintf(stdout, "default vfs is \"%s\"\n", pVfs ? pVfs->zName : "NULL");
|
||||
fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
|
||||
}
|
||||
|
||||
void report_rbu_vfs(sqlite3rbu *pRbu){
|
||||
|
||||
@@ -132,11 +132,6 @@ foreach {tn3 create_vfs destroy_vfs} {
|
||||
} {
|
||||
sqlite3rbu_destroy_vfs myrbu
|
||||
}
|
||||
3 {
|
||||
sqlite3_register_cksumvfs
|
||||
} {
|
||||
sqlite3_unregister_cksumvfs
|
||||
}
|
||||
} {
|
||||
|
||||
eval $create_vfs
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ do_test 1.1 {
|
||||
#
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 2.0 {
|
||||
create virtual TABLE ft USING fts4(a, b, languageid='langid');
|
||||
CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid');
|
||||
}
|
||||
do_test 2.1 {
|
||||
apply_rbu {
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# 2014 August 30
|
||||
#
|
||||
# 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]] rbu_common.tcl]
|
||||
set ::testprefix rbubusy
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log xLog
|
||||
reset_db
|
||||
|
||||
set db_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1000, 2000, 3000);
|
||||
}
|
||||
|
||||
set rbu_sql {
|
||||
CREATE TABLE data_t1(a, b, c, rbu_control);
|
||||
INSERT INTO data_t1 VALUES(1, 2, 3, 0);
|
||||
INSERT INTO data_t1 VALUES(4, 5, 6, 0);
|
||||
INSERT INTO data_t1 VALUES(7, 8, 9, 0);
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
forcedelete rbu.db
|
||||
sqlite3 rbu rbu.db
|
||||
rbu eval $rbu_sql
|
||||
rbu close
|
||||
|
||||
db eval $db_sql
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
BEGIN;
|
||||
SELECT * FROM t1
|
||||
} {1000 2000 3000}
|
||||
|
||||
do_test 1.3 {
|
||||
sqlite3rbu rbu test.db rbu.db
|
||||
rbu step
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test 1.4 {
|
||||
while 1 {
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
}
|
||||
set rc
|
||||
} {SQLITE_BUSY}
|
||||
|
||||
do_test 1.5 {
|
||||
rbu step
|
||||
} {SQLITE_BUSY}
|
||||
|
||||
do_test 1.6 {
|
||||
db eval COMMIT
|
||||
rbu step
|
||||
} {SQLITE_BUSY}
|
||||
catch { rbu close }
|
||||
|
||||
do_test 1.7 {
|
||||
sqlite3rbu rbu test.db rbu.db
|
||||
while 1 {
|
||||
set rc [rbu step]
|
||||
if {$rc!="SQLITE_OK"} break
|
||||
}
|
||||
set rc
|
||||
} {SQLITE_DONE}
|
||||
|
||||
rbu close
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
|
||||
@@ -268,14 +268,6 @@ tablE t1 USING FTs5(c);
|
||||
DELETE FROM t1 WHERE rowid = 1;
|
||||
INSERT INTO t1 VALUES('a b c');
|
||||
}
|
||||
4 {
|
||||
creAte virTUal tablE t1 USING FTs5(c);
|
||||
INSERT INTO t1 VALUES('a b c');
|
||||
INSERT INTO t1 VALUES('a b c');
|
||||
} {
|
||||
DELETE FROM t1 WHERE rowid = 1;
|
||||
INSERT INTO t1 VALUES('a b c');
|
||||
}
|
||||
|
||||
} {
|
||||
forcedelete test.db test.db2
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
# 2021 November 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set ::testprefix rbuexlock
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
# Create a simple RBU database. That expects to write to a table:
|
||||
#
|
||||
# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
#
|
||||
proc create_rbu {filename} {
|
||||
forcedelete $filename
|
||||
sqlite3 rbu1 $filename
|
||||
rbu1 eval {
|
||||
CREATE TABLE data_t1(a, b, c, rbu_control);
|
||||
INSERT INTO data_t1 VALUES(10, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(20, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(30, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(40, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(50, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(60, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(70, random(), random(), 0);
|
||||
INSERT INTO data_t1 VALUES(80, random(), random(), 0);
|
||||
}
|
||||
rbu1 close
|
||||
return $filename
|
||||
}
|
||||
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b INT, c INT);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
}
|
||||
create_rbu rbu1.db
|
||||
|
||||
do_test 1.1.0 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=1 rbu1.db
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 1.1.1 { SELECT * FROM t1 } {0 {1 2 3}}
|
||||
|
||||
do_test 1.2.0 {
|
||||
for {set ii 0} {$ii < 10} {incr ii} {
|
||||
rbu step
|
||||
}
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 1.2.1 { SELECT * FROM t1 } {0 {1 2 3}}
|
||||
do_test 1.2.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
do_test 1.3.0 {
|
||||
while {[file exists test.db-wal]==0} {
|
||||
rbu step
|
||||
}
|
||||
} {}
|
||||
do_catchsql_test 1.3.1 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
do_test 1.3.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
|
||||
do_test 1.4.0 {
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 1.4.1 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
do_test 1.4.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
|
||||
rbu close
|
||||
|
||||
do_test 1.5.0 {
|
||||
file exists test.db-wal
|
||||
} {1}
|
||||
do_test 1.5.1 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=1 rbu1.db
|
||||
file exists test.db-wal
|
||||
} 1
|
||||
do_catchsql_test 1.5.2 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
do_test 1.5.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
|
||||
do_test 1.6.0 {
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 1.6.1 { SELECT * FROM t1 } {1 {database is locked}}
|
||||
do_test 1.6.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
do_test 1.7.0 {
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
rbu close
|
||||
} SQLITE_DONE
|
||||
do_catchsql_test 1.7.2 { SELECT count(*) FROM t1 } {0 9}
|
||||
do_test 1.7.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {delete}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b INT, c INT);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
}
|
||||
create_rbu rbu1.db
|
||||
|
||||
do_test 2.1.0 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 2.1.1 { SELECT * FROM t1 } {0 {1 2 3}}
|
||||
|
||||
do_test 2.2.0 {
|
||||
for {set ii 0} {$ii < 10} {incr ii} {
|
||||
rbu step
|
||||
}
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_catchsql_test 2.2.1 { SELECT * FROM t1 } {0 {1 2 3}}
|
||||
|
||||
do_test 2.3.0 {
|
||||
while {[file exists test.db-wal]==0} {
|
||||
rbu step
|
||||
}
|
||||
} {}
|
||||
do_test 2.3.1 {
|
||||
llength [db eval {SELECT * FROM t1}]
|
||||
} {27}
|
||||
do_test 2.3.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {wal}
|
||||
|
||||
do_test 2.4.0 {
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
do_test 2.4.1 {
|
||||
llength [db eval {SELECT * FROM t1}]
|
||||
} {27}
|
||||
do_test 2.4.2 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {wal}
|
||||
|
||||
rbu close
|
||||
|
||||
do_test 2.5.0 {
|
||||
db eval {PRAGMA journal_mode}
|
||||
} {wal}
|
||||
do_execsql_test 2.5.1 {
|
||||
DELETE FROM t1;
|
||||
} {}
|
||||
|
||||
create_rbu rbu1.db
|
||||
do_test 3.1.0 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
|
||||
rbu step
|
||||
} SQLITE_ERROR
|
||||
|
||||
do_test 3.1.1 {
|
||||
set rc [catch {rbu close} msg]
|
||||
lappend rc $msg
|
||||
} {1 {SQLITE_ERROR - cannot update wal mode database}}
|
||||
db eval {PRAGMA journal_mode=DELETE}
|
||||
|
||||
create_rbu rbu1.db
|
||||
do_test 3.2.0 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
|
||||
do_test 3.3.1 {
|
||||
set rc [catch {rbu close} msg]
|
||||
lappend rc $msg
|
||||
} {0 SQLITE_OK}
|
||||
|
||||
db close
|
||||
create_rbu rbu1.db
|
||||
do_test 3.4.0 {
|
||||
sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db
|
||||
rbu step
|
||||
} SQLITE_OK
|
||||
rbu close
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -198,11 +198,7 @@ if {$::tcl_platform(platform)=="unix"} {
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test 5.$tn.2 { file exists test.db-vacuum } 1
|
||||
# The result pattern might be 00xxx or 0oxxx depending on which
|
||||
# version of TCL is being used. So make perm2 into a regexp that
|
||||
# will match either
|
||||
regsub {^00} $perm {0.} perm2
|
||||
do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} /$perm2/
|
||||
do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm
|
||||
rbu close
|
||||
}
|
||||
}
|
||||
|
||||
+57
-99
@@ -110,13 +110,6 @@
|
||||
# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Name of the URI option that causes RBU to take an exclusive lock as
|
||||
** part of the incremental checkpoint operation.
|
||||
*/
|
||||
#define RBU_EXCLUSIVE_CHECKPOINT "rbu_exclusive_checkpoint"
|
||||
|
||||
|
||||
/*
|
||||
** The rbu_state table is used to save the state of a partially applied
|
||||
** update so that it can be resumed later. The table consists of integer
|
||||
@@ -1201,9 +1194,7 @@ static void rbuTableType(
|
||||
assert( p->rc==SQLITE_OK );
|
||||
p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
|
||||
sqlite3_mprintf(
|
||||
"SELECT "
|
||||
" (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM'),"
|
||||
" rootpage"
|
||||
"SELECT (sql LIKE 'create virtual%%'), rootpage"
|
||||
" FROM sqlite_schema"
|
||||
" WHERE name=%Q", zTab
|
||||
));
|
||||
@@ -1563,7 +1554,7 @@ static char *rbuVacuumTableStart(
|
||||
** the caller has to use an OFFSET clause to extract only the required
|
||||
** rows from the sourct table, just as it does for an RBU update operation.
|
||||
*/
|
||||
static char *rbuVacuumIndexStart(
|
||||
char *rbuVacuumIndexStart(
|
||||
sqlite3rbu *p, /* RBU handle */
|
||||
RbuObjIter *pIter /* RBU iterator object */
|
||||
){
|
||||
@@ -1629,9 +1620,7 @@ static char *rbuVacuumIndexStart(
|
||||
zSep = "";
|
||||
for(iCol=0; iCol<pIter->nCol; iCol++){
|
||||
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
|
||||
if( zQuoted==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
}else if( zQuoted[0]=='N' ){
|
||||
if( zQuoted[0]=='N' ){
|
||||
bFailed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -2736,7 +2725,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
|
||||
break;
|
||||
|
||||
case RBU_STATE_OALSZ:
|
||||
pRet->iOalSz = sqlite3_column_int64(pStmt, 1);
|
||||
pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
|
||||
break;
|
||||
|
||||
case RBU_STATE_PHASEONESTEP:
|
||||
@@ -2763,19 +2752,13 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
|
||||
/*
|
||||
** Open the database handle and attach the RBU database as "rbu". If an
|
||||
** error occurs, leave an error code and message in the RBU handle.
|
||||
**
|
||||
** If argument dbMain is not NULL, then it is a database handle already
|
||||
** open on the target database. Use this handle instead of opening a new
|
||||
** one.
|
||||
*/
|
||||
static void rbuOpenDatabase(sqlite3rbu *p, sqlite3 *dbMain, int *pbRetry){
|
||||
static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
|
||||
assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
|
||||
assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
|
||||
assert( dbMain==0 || rbuIsVacuum(p)==0 );
|
||||
|
||||
/* Open the RBU database */
|
||||
p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
|
||||
p->dbMain = dbMain;
|
||||
|
||||
if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
|
||||
sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
|
||||
@@ -3141,31 +3124,15 @@ static void rbuCheckpointFrame(sqlite3rbu *p, RbuFrame *pFrame){
|
||||
|
||||
|
||||
/*
|
||||
** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if
|
||||
** successful, or an SQLite error code otherwise.
|
||||
** Take an EXCLUSIVE lock on the database file.
|
||||
*/
|
||||
static int rbuLockDatabase(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_file *fd = 0;
|
||||
sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd);
|
||||
|
||||
if( fd->pMethods ){
|
||||
rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE);
|
||||
}
|
||||
static void rbuLockDatabase(sqlite3rbu *p){
|
||||
sqlite3_file *pReal = p->pTargetFd->pReal;
|
||||
assert( p->rc==SQLITE_OK );
|
||||
p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the database handle passed as the only argument
|
||||
** was opened with the rbu_exclusive_checkpoint=1 URI parameter
|
||||
** specified. Or false otherwise.
|
||||
*/
|
||||
static int rbuExclusiveCheckpoint(sqlite3 *db){
|
||||
const char *zUri = sqlite3_db_filename(db, 0);
|
||||
return sqlite3_uri_boolean(zUri, RBU_EXCLUSIVE_CHECKPOINT, 0);
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
@@ -3223,24 +3190,18 @@ static void rbuMoveOalFile(sqlite3rbu *p){
|
||||
** In order to ensure that there are no database readers, an EXCLUSIVE
|
||||
** lock is obtained here before the *-oal is moved to *-wal.
|
||||
*/
|
||||
sqlite3 *dbMain = 0;
|
||||
rbuFileSuffix3(zBase, zWal);
|
||||
rbuFileSuffix3(zBase, zOal);
|
||||
|
||||
/* Re-open the databases. */
|
||||
rbuObjIterFinalize(&p->objiter);
|
||||
sqlite3_close(p->dbRbu);
|
||||
sqlite3_close(p->dbMain);
|
||||
p->dbMain = 0;
|
||||
p->dbRbu = 0;
|
||||
|
||||
dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
|
||||
if( dbMain ){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
p->rc = rbuLockDatabase(dbMain);
|
||||
}
|
||||
|
||||
rbuLockDatabase(p);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
rbuFileSuffix3(zBase, zWal);
|
||||
rbuFileSuffix3(zBase, zOal);
|
||||
|
||||
/* Re-open the databases. */
|
||||
rbuObjIterFinalize(&p->objiter);
|
||||
sqlite3_close(p->dbRbu);
|
||||
sqlite3_close(p->dbMain);
|
||||
p->dbMain = 0;
|
||||
p->dbRbu = 0;
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
{
|
||||
LPWSTR zWideOal;
|
||||
@@ -3267,19 +3228,11 @@ static void rbuMoveOalFile(sqlite3rbu *p){
|
||||
#else
|
||||
p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
if( p->rc!=SQLITE_OK
|
||||
|| rbuIsVacuum(p)
|
||||
|| rbuExclusiveCheckpoint(dbMain)==0
|
||||
){
|
||||
sqlite3_close(dbMain);
|
||||
dbMain = 0;
|
||||
}
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
rbuOpenDatabase(p, dbMain, 0);
|
||||
rbuSetupCheckpoint(p, 0);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
rbuOpenDatabase(p, 0);
|
||||
rbuSetupCheckpoint(p, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4030,9 +3983,9 @@ static sqlite3rbu *openRbuHandle(
|
||||
** If this is the case, it will have been checkpointed and deleted
|
||||
** when the handle was closed and a second attempt to open the
|
||||
** database may succeed. */
|
||||
rbuOpenDatabase(p, 0, &bRetry);
|
||||
rbuOpenDatabase(p, &bRetry);
|
||||
if( bRetry ){
|
||||
rbuOpenDatabase(p, 0, 0);
|
||||
rbuOpenDatabase(p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4127,14 +4080,6 @@ static sqlite3rbu *openRbuHandle(
|
||||
}else if( p->eStage==RBU_STAGE_MOVE ){
|
||||
/* no-op */
|
||||
}else if( p->eStage==RBU_STAGE_CKPT ){
|
||||
if( !rbuIsVacuum(p) && rbuExclusiveCheckpoint(p->dbMain) ){
|
||||
/* If the rbu_exclusive_checkpoint=1 URI parameter was specified
|
||||
** and an incremental checkpoint is being resumed, attempt an
|
||||
** exclusive lock on the db file. If this fails, so be it. */
|
||||
p->eStage = RBU_STAGE_DONE;
|
||||
rbuLockDatabase(p->dbMain);
|
||||
p->eStage = RBU_STAGE_CKPT;
|
||||
}
|
||||
rbuSetupCheckpoint(p, pState);
|
||||
}else if( p->eStage==RBU_STAGE_DONE ){
|
||||
p->rc = SQLITE_DONE;
|
||||
@@ -4172,6 +4117,7 @@ sqlite3rbu *sqlite3rbu_open(
|
||||
const char *zState
|
||||
){
|
||||
if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
|
||||
/* TODO: Check that zTarget and zRbu are non-NULL */
|
||||
return openRbuHandle(zTarget, zRbu, zState);
|
||||
}
|
||||
|
||||
@@ -4882,24 +4828,22 @@ static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
#endif
|
||||
|
||||
assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
|
||||
if( pRbu && (
|
||||
pRbu->eStage==RBU_STAGE_OAL
|
||||
|| pRbu->eStage==RBU_STAGE_MOVE
|
||||
|| pRbu->eStage==RBU_STAGE_DONE
|
||||
)){
|
||||
/* Prevent SQLite from taking a shm-lock on the target file when it
|
||||
** is supplying heap memory to the upper layer in place of *-shm
|
||||
** segments. */
|
||||
if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
|
||||
/* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
|
||||
** taking this lock also prevents any checkpoints from occurring.
|
||||
** todo: really, it's not clear why this might occur, as
|
||||
** wal_autocheckpoint ought to be turned off. */
|
||||
if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
|
||||
}else{
|
||||
int bCapture = 0;
|
||||
if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
|
||||
bCapture = 1;
|
||||
}
|
||||
|
||||
if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
|
||||
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
|
||||
if( bCapture && rc==SQLITE_OK ){
|
||||
pRbu->mLock |= ((1<<n) - 1) << ofst;
|
||||
pRbu->mLock |= (1 << ofst);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5046,14 +4990,28 @@ static int rbuVfsOpen(
|
||||
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
|
||||
if( pDb ){
|
||||
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
|
||||
/* This call is to open a *-wal file. Intead, open the *-oal. */
|
||||
size_t nOpen;
|
||||
/* This call is to open a *-wal file. Intead, open the *-oal. This
|
||||
** code ensures that the string passed to xOpen() is terminated by a
|
||||
** pair of '\0' bytes in case the VFS attempts to extract a URI
|
||||
** parameter from it. */
|
||||
const char *zBase = zName;
|
||||
size_t nCopy;
|
||||
char *zCopy;
|
||||
if( rbuIsVacuum(pDb->pRbu) ){
|
||||
zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
|
||||
zOpen = sqlite3_filename_wal(zOpen);
|
||||
zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
|
||||
zBase = sqlite3_filename_wal(zBase);
|
||||
}
|
||||
nCopy = strlen(zBase);
|
||||
zCopy = sqlite3_malloc64(nCopy+2);
|
||||
if( zCopy ){
|
||||
memcpy(zCopy, zBase, nCopy);
|
||||
zCopy[nCopy-3] = 'o';
|
||||
zCopy[nCopy] = '\0';
|
||||
zCopy[nCopy+1] = '\0';
|
||||
zOpen = (const char*)(pFd->zDel = zCopy);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
nOpen = strlen(zOpen);
|
||||
((char*)zOpen)[nOpen-3] = 'o';
|
||||
pFd->pRbu = pDb->pRbu;
|
||||
}
|
||||
pDb->pWalFd = pFd;
|
||||
|
||||
@@ -44,19 +44,8 @@ SQLITE_EXTENSION_INIT1
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
# endif
|
||||
# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
# elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
# else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
# endif
|
||||
# define ALWAYS(X) 1
|
||||
# define NEVER(X) 0
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
|
||||
#define SQLITE_ENABLE_DBPAGE_VTAB 1
|
||||
#define SQLITE_ENABLE_JSON1 1
|
||||
#undef SQLITE_THREADSAFE
|
||||
#define SQLITE_THREADSAFE 0
|
||||
#undef SQLITE_ENABLE_COLUMN_METADATA
|
||||
|
||||
+10
-14
@@ -26,7 +26,11 @@
|
||||
# define GEODEBUG(X)
|
||||
#endif
|
||||
|
||||
/* Character class routines */
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Versions of isspace(), isalnum() and isdigit() to which it is safe
|
||||
** to pass signed char values.
|
||||
*/
|
||||
#ifdef sqlite3Isdigit
|
||||
/* Use the SQLite core versions if this routine is part of the
|
||||
** SQLite amalgamation */
|
||||
@@ -41,7 +45,6 @@
|
||||
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
** the library isspace() function.
|
||||
@@ -64,7 +67,7 @@ static const char geopolyIsSpace[] = {
|
||||
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, 0,
|
||||
};
|
||||
#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#endif /* JSON NULL - back to original code */
|
||||
|
||||
/* Compiler and version */
|
||||
@@ -153,7 +156,7 @@ static void geopolySwab32(unsigned char *a){
|
||||
|
||||
/* Skip whitespace. Return the next non-whitespace character. */
|
||||
static char geopolySkipSpace(GeoParse *p){
|
||||
while( fast_isspace(p->z[0]) ) p->z++;
|
||||
while( safe_isspace(p->z[0]) ) p->z++;
|
||||
return p->z[0];
|
||||
}
|
||||
|
||||
@@ -302,16 +305,11 @@ static GeoPoly *geopolyFuncParam(
|
||||
){
|
||||
GeoPoly *p = 0;
|
||||
int nByte;
|
||||
testcase( pCtx==0 );
|
||||
if( sqlite3_value_type(pVal)==SQLITE_BLOB
|
||||
&& (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
|
||||
){
|
||||
const unsigned char *a = sqlite3_value_blob(pVal);
|
||||
int nVertex;
|
||||
if( a==0 ){
|
||||
if( pCtx ) sqlite3_result_error_nomem(pCtx);
|
||||
return 0;
|
||||
}
|
||||
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
|
||||
if( (a[0]==0 || a[0]==1)
|
||||
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
|
||||
@@ -685,7 +683,7 @@ static GeoPoly *geopolyBBox(
|
||||
aCoord[2].f = mnY;
|
||||
aCoord[3].f = mxY;
|
||||
}
|
||||
}else if( aCoord ){
|
||||
}else{
|
||||
memset(aCoord, 0, sizeof(RtreeCoord)*4);
|
||||
}
|
||||
return pOut;
|
||||
@@ -1136,11 +1134,11 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
|
||||
}else{
|
||||
/* Remove a segment */
|
||||
if( pActive==pThisEvent->pSeg ){
|
||||
pActive = ALWAYS(pActive) ? pActive->pNext : 0;
|
||||
pActive = pActive->pNext;
|
||||
}else{
|
||||
for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
|
||||
if( pSeg->pNext==pThisEvent->pSeg ){
|
||||
pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0;
|
||||
pSeg->pNext = pSeg->pNext->pNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1384,7 +1382,6 @@ static int geopolyFilter(
|
||||
RtreeCoord bbox[4];
|
||||
RtreeConstraint *p;
|
||||
assert( argc==1 );
|
||||
assert( argv[0]!=0 );
|
||||
geopolyBBox(0, argv[0], bbox, &rc);
|
||||
if( rc ){
|
||||
goto geopoly_filter_end;
|
||||
@@ -1612,7 +1609,6 @@ static int geopolyUpdate(
|
||||
|| !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|
||||
|| oldRowid!=newRowid) /* Rowid change */
|
||||
){
|
||||
assert( aData[2]!=0 );
|
||||
geopolyBBox(0, aData[2], cell.aCoord, &rc);
|
||||
if( rc ){
|
||||
if( rc==SQLITE_ERROR ){
|
||||
|
||||
+60
-97
@@ -64,11 +64,7 @@
|
||||
#endif
|
||||
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
|
||||
|
||||
/*
|
||||
** If building separately, we will need some setup that is normally
|
||||
** found in sqliteInt.h
|
||||
*/
|
||||
#if !defined(SQLITE_AMALGAMATION)
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
#include "sqlite3rtree.h"
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
@@ -81,20 +77,7 @@ typedef unsigned int u32;
|
||||
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
#endif
|
||||
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_AMALGAMATION) */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -152,9 +135,7 @@ struct Rtree {
|
||||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
u8 nAuxNotNull; /* Number of initial not-null aux columns */
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 bCorrupt; /* Shadow table corruption detected */
|
||||
#endif
|
||||
@@ -436,12 +417,7 @@ struct RtreeMatchArg {
|
||||
** it is not, make it a no-op.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
unsigned int sqlite3RtreeTestcase = 0;
|
||||
# define testcase(X) if( X ){ sqlite3RtreeTestcase += __LINE__; }
|
||||
# else
|
||||
# define testcase(X)
|
||||
# endif
|
||||
# define testcase(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -690,6 +666,18 @@ static void nodeBlobReset(Rtree *pRtree){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if pNode is the same as pParent or any of the parents
|
||||
** of pParent.
|
||||
*/
|
||||
static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
|
||||
do{
|
||||
if( pNode==pParent ) return 1;
|
||||
pParent = pParent->pParent;
|
||||
}while( pParent );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Obtain a reference to an r-tree node.
|
||||
*/
|
||||
@@ -706,7 +694,14 @@ static int nodeAcquire(
|
||||
** increase its reference count and return it.
|
||||
*/
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
||||
if( pParent && pParent!=pNode->pParent ){
|
||||
if( pParent && !pNode->pParent ){
|
||||
if( nodeInParentChain(pNode, pParent) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pParent->nRef++;
|
||||
pNode->pParent = pParent;
|
||||
}else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -764,7 +759,7 @@ static int nodeAcquire(
|
||||
** are the leaves, and so on. If the depth as specified on the root node
|
||||
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
|
||||
*/
|
||||
if( rc==SQLITE_OK && pNode && iNode==1 ){
|
||||
if( pNode && rc==SQLITE_OK && iNode==1 ){
|
||||
pRtree->iDepth = readInt16(pNode->zData);
|
||||
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
@@ -1287,29 +1282,20 @@ static void rtreeNonleafConstraint(
|
||||
switch( p->op ){
|
||||
case RTREE_TRUE: return; /* Always satisfied */
|
||||
case RTREE_FALSE: break; /* Never satisfied */
|
||||
case RTREE_LE:
|
||||
case RTREE_LT:
|
||||
case RTREE_EQ:
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the lower bound of the coordinate pair */
|
||||
if( p->u.rValue>=val ){
|
||||
pCellData += 4;
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the upper bound of the coordinate pair */
|
||||
if( p->u.rValue<=val ) return;
|
||||
}
|
||||
break;
|
||||
case RTREE_LE:
|
||||
case RTREE_LT:
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the lower bound of the coordinate pair */
|
||||
if( p->u.rValue>=val ) return;
|
||||
break;
|
||||
if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */
|
||||
/* Fall through for the RTREE_EQ case */
|
||||
|
||||
default:
|
||||
default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
|
||||
pCellData += 4;
|
||||
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||
/* val now holds the upper bound of the coordinate pair */
|
||||
if( p->u.rValue<=val ) return;
|
||||
break;
|
||||
}
|
||||
*peWithin = NOT_WITHIN;
|
||||
}
|
||||
@@ -1379,12 +1365,11 @@ static int nodeRowidIndex(
|
||||
*/
|
||||
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
|
||||
RtreeNode *pParent = pNode->pParent;
|
||||
if( ALWAYS(pParent) ){
|
||||
if( pParent ){
|
||||
return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
|
||||
}else{
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1507,8 +1492,7 @@ static RtreeSearchPoint *rtreeSearchPointNew(
|
||||
pNew = rtreeEnqueue(pCur, rScore, iLevel);
|
||||
if( pNew==0 ) return 0;
|
||||
ii = (int)(pNew - pCur->aPoint) + 1;
|
||||
assert( ii==1 );
|
||||
if( ALWAYS(ii<RTREE_CACHE_SZ) ){
|
||||
if( ii<RTREE_CACHE_SZ ){
|
||||
assert( pCur->aNode[ii]==0 );
|
||||
pCur->aNode[ii] = pCur->aNode[0];
|
||||
}else{
|
||||
@@ -1569,7 +1553,7 @@ static void rtreeSearchPointPop(RtreeCursor *p){
|
||||
if( p->bPoint ){
|
||||
p->anQueue[p->sPoint.iLevel]--;
|
||||
p->bPoint = 0;
|
||||
}else if( ALWAYS(p->nPoint) ){
|
||||
}else if( p->nPoint ){
|
||||
p->anQueue[p->aPoint[0].iLevel]--;
|
||||
n = --p->nPoint;
|
||||
p->aPoint[0] = p->aPoint[n];
|
||||
@@ -1710,7 +1694,7 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
|
||||
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
|
||||
int rc = SQLITE_OK;
|
||||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
if( rc==SQLITE_OK && ALWAYS(p) ){
|
||||
if( rc==SQLITE_OK && p ){
|
||||
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
|
||||
}
|
||||
return rc;
|
||||
@@ -1728,7 +1712,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
|
||||
if( rc ) return rc;
|
||||
if( NEVER(p==0) ) return SQLITE_OK;
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
if( i==0 ){
|
||||
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
}else if( i<=pRtree->nDim2 ){
|
||||
@@ -1927,11 +1911,8 @@ static int rtreeFilter(
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
RtreeSearchPoint *pNew;
|
||||
assert( pCsr->bPoint==0 ); /* Due to the resetCursor() call above */
|
||||
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
|
||||
if( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
pNew->id = 1;
|
||||
pNew->iCell = 0;
|
||||
pNew->eWithin = PARTLY_WITHIN;
|
||||
@@ -2008,7 +1989,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
|
||||
|
||||
if( bMatch==0 && p->usable
|
||||
&& p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
&& p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
/* We have an equality constraint on the rowid. Use strategy 1. */
|
||||
int jj;
|
||||
@@ -2214,7 +2195,7 @@ static int ChooseLeaf(
|
||||
|
||||
int nCell = NCELL(pNode);
|
||||
RtreeCell cell;
|
||||
RtreeNode *pChild = 0;
|
||||
RtreeNode *pChild;
|
||||
|
||||
RtreeCell *aCell = 0;
|
||||
|
||||
@@ -2261,19 +2242,12 @@ static int AdjustTree(
|
||||
){
|
||||
RtreeNode *p = pNode;
|
||||
int cnt = 0;
|
||||
int rc;
|
||||
while( p->pParent ){
|
||||
RtreeNode *pParent = p->pParent;
|
||||
RtreeCell cell;
|
||||
int iCell;
|
||||
|
||||
cnt++;
|
||||
if( NEVER(cnt>100) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
rc = nodeParentIndex(pRtree, p, &iCell);
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -2562,17 +2536,12 @@ static int updateMapping(
|
||||
xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
|
||||
if( iHeight>0 ){
|
||||
RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
|
||||
RtreeNode *p;
|
||||
for(p=pNode; p; p=p->pParent){
|
||||
if( p==pChild ) return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
if( pChild ){
|
||||
nodeRelease(pRtree, pChild->pParent);
|
||||
nodeReference(pNode);
|
||||
pChild->pParent = pNode;
|
||||
}
|
||||
}
|
||||
if( NEVER(pNode==0) ) return SQLITE_ERROR;
|
||||
return xSetMapping(pRtree, iRowid, pNode->iNode);
|
||||
}
|
||||
|
||||
@@ -2662,12 +2631,11 @@ static int SplitNode(
|
||||
RtreeNode *pParent = pLeft->pParent;
|
||||
int iCell;
|
||||
rc = nodeParentIndex(pRtree, pLeft, &iCell);
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
|
||||
rc = AdjustTree(pRtree, pParent, &leftbbox);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto splitnode_out;
|
||||
}
|
||||
}
|
||||
@@ -2742,7 +2710,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
|
||||
*/
|
||||
iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
|
||||
for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
|
||||
if( pTest==0 ){
|
||||
if( !pTest ){
|
||||
rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
|
||||
}
|
||||
}
|
||||
@@ -2773,7 +2741,6 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
|
||||
pParent = pNode->pParent;
|
||||
pNode->pParent = 0;
|
||||
rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
rc2 = nodeRelease(pRtree, pParent);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2996,7 +2963,7 @@ static int rtreeInsertCell(
|
||||
}
|
||||
}else{
|
||||
rc = AdjustTree(pRtree, pNode, pCell);
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iHeight==0 ){
|
||||
rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
|
||||
}else{
|
||||
@@ -3102,7 +3069,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
||||
int rc2;
|
||||
RtreeNode *pChild = 0;
|
||||
i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
|
||||
}
|
||||
@@ -3437,7 +3404,7 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
char *zSql;
|
||||
sqlite3_stmt *p;
|
||||
int rc;
|
||||
i64 nRow = RTREE_MIN_ROWEST;
|
||||
i64 nRow = 0;
|
||||
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
|
||||
@@ -3454,10 +3421,20 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
|
||||
rc = sqlite3_finalize(p);
|
||||
}else if( rc!=SQLITE_NOMEM ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nRow==0 ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
}else{
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3607,12 +3584,9 @@ static int rtreeSqlInit(
|
||||
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
if( ii ) sqlite3_str_append(p, ",", 1);
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
if( ii<pRtree->nAuxNotNull ){
|
||||
sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
}else{
|
||||
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
|
||||
}
|
||||
}
|
||||
@@ -3877,7 +3851,6 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
tree.nDim2 = tree.nDim*2;
|
||||
tree.nBytesPerCell = 8 + 8 * tree.nDim;
|
||||
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
|
||||
if( node.zData==0 ) return;
|
||||
nData = sqlite3_value_bytes(apArg[1]);
|
||||
if( nData<4 ) return;
|
||||
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
|
||||
@@ -3917,16 +3890,11 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
UNUSED_PARAMETER(nArg);
|
||||
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(apArg[0])<2
|
||||
|
||||
){
|
||||
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
|
||||
}else{
|
||||
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
|
||||
if( zBlob ){
|
||||
sqlite3_result_int(ctx, readInt16(zBlob));
|
||||
}else{
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
}
|
||||
sqlite3_result_int(ctx, readInt16(zBlob));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4292,10 +4260,8 @@ static int rtreeCheckTable(
|
||||
if( pStmt ){
|
||||
nAux = sqlite3_column_count(pStmt) - 2;
|
||||
sqlite3_finalize(pStmt);
|
||||
}else
|
||||
if( check.rc!=SQLITE_NOMEM ){
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Find number of dimensions in the rtree table. */
|
||||
@@ -4552,10 +4518,7 @@ int sqlite3_rtree_query_callback(
|
||||
|
||||
/* Allocate and populate the context object. */
|
||||
pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
|
||||
if( !pGeomCtx ){
|
||||
if( xDestructor ) xDestructor(pContext);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( !pGeomCtx ) return SQLITE_NOMEM;
|
||||
pGeomCtx->xGeom = 0;
|
||||
pGeomCtx->xQueryFunc = xQueryFunc;
|
||||
pGeomCtx->xDestructor = xDestructor;
|
||||
|
||||
@@ -57,12 +57,9 @@ ifcapable !rtree {
|
||||
do_test rtree-1.1.1 {
|
||||
execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2) }
|
||||
} {}
|
||||
do_test rtree-1.1.2a {
|
||||
do_test rtree-1.1.2 {
|
||||
execsql { SELECT name FROM sqlite_master ORDER BY name }
|
||||
} {t1 t1_node t1_parent t1_rowid}
|
||||
do_execsql_test rtree-1.1.2b {
|
||||
SELECT name FROM pragma_table_list WHERE type='shadow' ORDER BY name;
|
||||
} {t1_node t1_parent t1_rowid}
|
||||
do_test rtree-1.1.3 {
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
|
||||
+12
-12
@@ -79,47 +79,47 @@ do_eqp_test rtree6.2.1 {
|
||||
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.2 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.3 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.4.1 {
|
||||
SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH t2 USING AUTOMATIC COVERING INDEX (v=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
|
||||
}
|
||||
do_eqp_test rtree6.2.4.2 {
|
||||
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.5 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii AND x1<v
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_execsql_test rtree6-3.1 {
|
||||
|
||||
@@ -36,7 +36,7 @@ do_execsql_test rtree9-1.4 {
|
||||
DELETE FROM rt;
|
||||
} {}
|
||||
|
||||
unset -nocomplain x
|
||||
|
||||
for {set i 0} {$i < 1000} {incr i} {
|
||||
set x [expr $i%10]
|
||||
set y [expr ($i/10)%10]
|
||||
|
||||
@@ -145,7 +145,7 @@ populate_t1
|
||||
do_test rtreeA-2.2.0 { truncate_node 1 200 } {}
|
||||
do_corruption_tests rtreeA-2.2 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
|
||||
}
|
||||
@@ -160,18 +160,18 @@ do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1}
|
||||
do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3}
|
||||
do_corruption_tests rtreeA-3.1 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-3.1.0.3 {
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
|
||||
do_corruption_tests rtreeA-3.2 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ do_test rtreeA-3.3.0 {
|
||||
} {65535}
|
||||
do_corruption_tests rtreeA-3.3 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ do_test rtreeA-4.1.0 {
|
||||
} {4000}
|
||||
do_corruption_tests rtreeA-4.1 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
|
||||
}
|
||||
@@ -216,12 +216,12 @@ create_t1
|
||||
populate_t1
|
||||
do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {}
|
||||
do_corruption_tests rtreeA-5.1 {
|
||||
1 "DELETE FROM t1 WHERE +rowid = 5"
|
||||
1 "DELETE FROM t1 WHERE rowid = 5"
|
||||
2 "DELETE FROM t1"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-5.2 {
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -238,7 +238,7 @@ do_corruption_tests rtreeA-6.1 {
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-6.2 {
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
+44
-44
@@ -30,8 +30,8 @@ do_eqp_test 1.1 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
@@ -39,8 +39,8 @@ do_eqp_test 1.2 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
@@ -48,16 +48,16 @@ do_eqp_test 1.3 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM t, r_tree
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN t
|
||||
|--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
@@ -87,8 +87,8 @@ do_eqp_test 2.1 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.2 {
|
||||
@@ -96,8 +96,8 @@ do_eqp_test 2.2 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.3 {
|
||||
@@ -105,16 +105,16 @@ do_eqp_test 2.3 {
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t
|
||||
`--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.5 {
|
||||
SELECT * FROM t, r_tree
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN t
|
||||
|--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -128,24 +128,24 @@ do_execsql_test 3.1 {
|
||||
|
||||
do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN t2
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
|
||||
QUERY PLAN
|
||||
|--SCAN t2
|
||||
`--SCAN t1
|
||||
|--SCAN TABLE t2
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN t3 VIRTUAL TABLE INDEX 2:
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
|
||||
}
|
||||
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
|
||||
QUERY PLAN
|
||||
|--SCAN t3 VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN t1
|
||||
|--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -203,8 +203,8 @@ do_eqp_test 5.2 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN rt VIRTUAL TABLE INDEX 1:
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
|
||||
@@ -220,8 +220,8 @@ do_eqp_test 5.4 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN rt VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
|
||||
}
|
||||
|
||||
# Delete the ANALYZE data. "t1" should be the outer loop again.
|
||||
@@ -233,8 +233,8 @@ do_eqp_test 5.6 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN rt VIRTUAL TABLE INDEX 1:
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
# This time create and attach a database that contains ANALYZE data for
|
||||
@@ -258,8 +258,8 @@ do_eqp_test 5.8 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN rt VIRTUAL TABLE INDEX 1:
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -327,9 +327,9 @@ do_eqp_execsql_test 7.1 {
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN xdir
|
||||
|--SCAN ydir
|
||||
`--SCAN rt VIRTUAL TABLE INDEX 2:B2D3B0D1
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE ydir
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
@@ -340,9 +340,9 @@ do_eqp_execsql_test 7.2 {
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN xdir
|
||||
|--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN ydir LEFT-JOIN
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
5 1 2 7 12 14 {}
|
||||
5 2 2 7 8 12 10
|
||||
@@ -355,9 +355,9 @@ do_eqp_execsql_test 7.3 {
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN xdir
|
||||
|--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN ydir
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
@@ -368,9 +368,9 @@ do_eqp_execsql_test 7.4 {
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN xdir
|
||||
|--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN ydir
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
|
||||
@@ -117,13 +117,13 @@ sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 3.2 {
|
||||
BEGIN;
|
||||
UPDATE r2_node SET data = X'123456';
|
||||
SELECT rtreecheck('r2')!='ok';
|
||||
SELECT rtreecheck('r2')!="ok";
|
||||
} {1}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
ROLLBACK;
|
||||
UPDATE r2_node SET data = X'00001234';
|
||||
SELECT rtreecheck('r2')!='ok';
|
||||
SELECT rtreecheck('r2')!="ok";
|
||||
} {1}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,346 +0,0 @@
|
||||
# 2021 September 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The focus of this file is testing the r-tree extension.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix rtreedoc2
|
||||
|
||||
ifcapable !rtree {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# Section 6 of documentation.
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
set testprefix rtreedoc2-1
|
||||
|
||||
# EVIDENCE-OF: R-35254-48865 A call to one of the above APIs creates a
|
||||
# new SQL function named by the second parameter (zQueryFunc or zGeom).
|
||||
#
|
||||
# [register_circle_geom db] registers new geometry callback "Qcircle"
|
||||
# and legacy implementation "circle". Test that these do actually appear.
|
||||
#
|
||||
do_execsql_test 1.1.0 {
|
||||
SELECT * FROM pragma_function_list WHERE name IN('circle', 'qcircle');
|
||||
} {
|
||||
}
|
||||
do_test 1.1 {
|
||||
register_circle_geom db
|
||||
} {SQLITE_OK}
|
||||
do_execsql_test 1.1.2 {
|
||||
SELECT * FROM pragma_function_list WHERE name = 'circle' AND enc='utf8';
|
||||
} {
|
||||
circle 0 s utf8 -1 0
|
||||
}
|
||||
do_execsql_test 1.1.3 {
|
||||
SELECT * FROM pragma_function_list WHERE name = 'qcircle' AND enc='utf8';
|
||||
} {
|
||||
qcircle 0 s utf8 -1 0
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.0 { SELECT circle(1, 2, 3); } {{}}
|
||||
do_execsql_test 1.2.1 { SELECT qcircle(1, 2, 3); } {{}}
|
||||
|
||||
# EVIDENCE-OF: R-61427-46983
|
||||
do_execsql_test 1.3.0 {
|
||||
CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
|
||||
INSERT INTO demo_index VALUES(10, 45,45, 24,24);
|
||||
INSERT INTO demo_index VALUES(20, 50,50, 28,28);
|
||||
INSERT INTO demo_index VALUES(30, 43,43, 22,22);
|
||||
}
|
||||
do_execsql_test 1.3.1 {
|
||||
SELECT id FROM demo_index WHERE id MATCH circle(45.3, 22.9, 5.0)
|
||||
} {10 30}
|
||||
|
||||
# EVIDENCE-OF: R-16907-50223 The SQL syntax for custom queries is the
|
||||
# same regardless of which interface, sqlite3_rtree_geometry_callback()
|
||||
# or sqlite3_rtree_query_callback(), is used to register the SQL
|
||||
# function.
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT id FROM demo_index WHERE id MATCH qcircle(45.3, 22.9, 5.0, 1)
|
||||
} {10 30}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-59634-51678 When that SQL function appears on the
|
||||
# right-hand side of the MATCH operator and the left-hand side of the
|
||||
# MATCH operator is any column in the R*Tree virtual table, then the
|
||||
# callback defined by the third argument (xQueryFunc or xGeom) is
|
||||
# invoked to determine if a particular object or subtree overlaps the
|
||||
# desired region.
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
|
||||
return ""
|
||||
}
|
||||
register_box_geom db box_geom
|
||||
set box_geom [list]
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT id FROM demo_index WHERE id MATCH box(43,46, 21,25);
|
||||
} {10 30}
|
||||
do_test 1.3.3 {
|
||||
set ::box_geom
|
||||
} [list {*}{
|
||||
{box {43.0 46.0 21.0 25.0} {45.0 45.0 24.0 24.0}}
|
||||
{box {43.0 46.0 21.0 25.0} {50.0 50.0 28.0 28.0}}
|
||||
{box {43.0 46.0 21.0 25.0} {43.0 43.0 22.0 22.0}}
|
||||
}]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# Section 6 of documentation.
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
set testprefix rtreedoc2-2
|
||||
|
||||
# EVIDENCE-OF: R-02424-24769 The second argument is the number of
|
||||
# coordinates in each r-tree entry, and is always the same for any given
|
||||
# R*Tree.
|
||||
#
|
||||
# EVIDENCE-OF: R-40260-16838 The number of coordinates is 2 for a
|
||||
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
|
||||
# 3-dimensional R*Tree, and so forth.
|
||||
#
|
||||
# The second argument refered to above is the length of the list passed
|
||||
# as the 3rd parameter to the Tcl script.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2);
|
||||
CREATE VIRTUAL TABLE rt2 USING rtree(id, x1,x2, y1,y2);
|
||||
CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2);
|
||||
|
||||
INSERT INTO rt1 DEFAULT VALUES;
|
||||
INSERT INTO rt2 DEFAULT VALUES;
|
||||
INSERT INTO rt3 DEFAULT VALUES;
|
||||
}
|
||||
foreach {tn tbl nCoord} {
|
||||
1 rt1 2
|
||||
2 rt2 4
|
||||
3 rt3 6
|
||||
} {
|
||||
set ::box_geom [list]
|
||||
do_catchsql_test 1.$tn.1 "
|
||||
SELECT id FROM $tbl WHERE id MATCH box();
|
||||
" {1 {SQL logic error}}
|
||||
|
||||
do_test 1.$tn.2 {
|
||||
llength [lindex $::box_geom 0 2]
|
||||
} $nCoord
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-28051-48608 If xGeom returns anything other than
|
||||
# SQLITE_OK, then the r-tree query will abort with an error.
|
||||
proc box_geom {args} {
|
||||
error "an error!"
|
||||
}
|
||||
do_catchsql_test 2.0 {
|
||||
SELECT * FROM rt2 WHERE id MATCH box(22,23, 24,25);
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
INSERT INTO rt1 VALUES(10, 10, 10);
|
||||
INSERT INTO rt1 VALUES(11, 11, 11);
|
||||
INSERT INTO rt1 VALUES(12, 12, 12);
|
||||
INSERT INTO rt1 VALUES(13, 13, 13);
|
||||
INSERT INTO rt1 VALUES(14, 14, 14);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-53759-57366 The exact same sqlite3_rtree_geometry
|
||||
# structure is used for every callback for same MATCH operator in the
|
||||
# same query.
|
||||
proc box_geom {args} {
|
||||
lappend ::ptr_list [lindex $args 4]
|
||||
return 0
|
||||
}
|
||||
set ::ptr_list [list]
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM rt1 WHERE id MATCH box(1,1);
|
||||
}
|
||||
do_test 3.2 {
|
||||
set val [lindex $::ptr_list 0]
|
||||
foreach p $::ptr_list {
|
||||
if {$p!=$val} {error "pointer mismatch"}
|
||||
}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-60247-35692 The contents of the sqlite3_rtree_geometry
|
||||
# structure are initialized by SQLite but are not subsequently modified.
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
|
||||
if {[llength $::box_geom]==3} {
|
||||
return "zero"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
set ::box_geom [list]
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM rt1 WHERE id MATCH box(1,1);
|
||||
} {1 {SQL logic error}}
|
||||
do_test 3.3 {
|
||||
set ::box_geom
|
||||
} [list {*}{
|
||||
{box {1.0 1.0} {0.0 0.0}}
|
||||
{box {1.0 1.0} {10.0 10.0}}
|
||||
{box {1.0 1.0} {11.0 11.0}}
|
||||
{box 0.0 {12.0 12.0}}
|
||||
}]
|
||||
|
||||
# EVIDENCE-OF: R-31246-29731 The pContext member of the
|
||||
# sqlite3_rtree_geometry structure is always set to a copy of the
|
||||
# pContext argument passed to sqlite3_rtree_geometry_callback() when the
|
||||
# callback is registered.
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE r1 USING rtree(id, minX,maxX, minY,maxY);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<120
|
||||
)
|
||||
INSERT INTO r1 SELECT i,i,i+1, 200,201 FROM s;
|
||||
}
|
||||
set ctx [register_box_geom db box_geom]
|
||||
set ::box_geom [list]
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [lindex $args 1]
|
||||
return ""
|
||||
}
|
||||
do_execsql_test 4.1 {
|
||||
SELECT count(*) FROM r1 WHERE id MATCH box(0,150,199,201)
|
||||
} 120
|
||||
do_test 4.2 {
|
||||
foreach g $::box_geom {
|
||||
if {$g!=$ctx} {error "pointer mismatch"}
|
||||
}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-09904-19077 The aParam[] array (size nParam) contains
|
||||
# the parameter values passed to the SQL function on the right-hand side
|
||||
# of the MATCH operator.
|
||||
proc box_geom {args} {
|
||||
set ::box_geom [lindex $args 2]
|
||||
}
|
||||
foreach {tn q vals} {
|
||||
1 "SELECT count(*) FROM r1 WHERE id MATCH box(1,2,3)" {1.0 2.0 3.0}
|
||||
2 "SELECT count(*) FROM r1 WHERE id MATCH box(10001)" {10001.0}
|
||||
3 "SELECT count(*) FROM r1 WHERE id MATCH box(-10001)" {-10001.0}
|
||||
} {
|
||||
do_catchsql_test 5.$tn.1 $q {1 {SQL logic error}}
|
||||
do_test 5.$tn.2 { set ::box_geom } $vals
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE myrtree USING rtree(id, x1,x2);
|
||||
INSERT INTO myrtree VALUES(1, 1, 1);
|
||||
INSERT INTO myrtree VALUES(2, 2, 2);
|
||||
INSERT INTO myrtree VALUES(3, 3, 3);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-44448-00687 The pUser and xDelUser members of the
|
||||
# sqlite3_rtree_geometry structure are initially set to NULL.
|
||||
set ::box_geom_calls 0
|
||||
proc box_geom {args} {
|
||||
incr ::box_geom_calls
|
||||
return user_is_zero
|
||||
}
|
||||
do_execsql_test 5.1.1 {
|
||||
SELECT * FROM myrtree WHERE id MATCH box(4, 5);
|
||||
}
|
||||
do_test 5.1.2 { set ::box_geom_calls } 3
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-55837-00155 The pUser variable may be set by the
|
||||
# callback implementation to any arbitrary value that may be useful to
|
||||
# subsequent invocations of the callback within the same query (for
|
||||
# example, a pointer to a complicated data structure used to test for
|
||||
# region intersection).
|
||||
#
|
||||
# EVIDENCE-OF: R-34745-08839 If the xDelUser variable is set to a
|
||||
# non-NULL value, then after the query has finished running SQLite
|
||||
# automatically invokes it with the value of the pUser variable as the
|
||||
# only argument.
|
||||
#
|
||||
set ::box_geom_calls 0
|
||||
proc box_geom {args} {
|
||||
incr ::box_geom_calls
|
||||
switch -- $::box_geom_calls {
|
||||
1 {
|
||||
return user_is_zero
|
||||
}
|
||||
2 {
|
||||
return [list user box_geom_finalizer]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
proc box_geom_finalizer {} {
|
||||
set ::box_geom_finalizer "::box_geom_calls is $::box_geom_calls"
|
||||
}
|
||||
do_execsql_test 5.1.1 {
|
||||
SELECT * FROM myrtree WHERE id MATCH box(4, 5);
|
||||
}
|
||||
do_test 5.1.2 { set ::box_geom_calls } 3
|
||||
do_test 5.1.3 {
|
||||
set ::box_geom_finalizer
|
||||
} {::box_geom_calls is 3}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-28176-28813 The xGeom callback always does a
|
||||
# depth-first search of the r-tree.
|
||||
#
|
||||
# For a breadth first search, final test case would return "B L" only.
|
||||
#
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE xyz USING rtree(x, x1,x2, y1,y2);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15
|
||||
)
|
||||
INSERT INTO xyz SELECT NULL, one.i,one.i+1, two.i,two.i+1 FROM s one, s two;
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
SELECT count(*) FROM xyz_node
|
||||
} {10}
|
||||
proc box_geom {args} {
|
||||
set coords [lindex $args 3]
|
||||
set area [expr {
|
||||
([lindex $coords 1]-[lindex $coords 0]) *
|
||||
([lindex $coords 3]-[lindex $coords 2])
|
||||
}]
|
||||
if {$area==1} {
|
||||
lappend ::box_geom_calls L
|
||||
} else {
|
||||
lappend ::box_geom_calls B
|
||||
}
|
||||
}
|
||||
set ::box_geom_calls [list]
|
||||
do_execsql_test 6.2 {
|
||||
SELECT count(*) FROM xyz WHERE x MATCH box(0,20,0,20)
|
||||
} 225
|
||||
do_test 6.3 {
|
||||
set prev ""
|
||||
set box_calls [list]
|
||||
foreach c $::box_geom_calls {
|
||||
if {$c!=$prev} {
|
||||
lappend ::box_calls $c
|
||||
set prev $c
|
||||
}
|
||||
}
|
||||
set ::box_calls
|
||||
} {B L B L B L B L B L B L B L B L B L}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
# 2021 September 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The focus of this file is testing the r-tree extension.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix rtreedoc3
|
||||
|
||||
ifcapable !rtree {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
# This command assumes that the argument is a node blob for a 2 dimensional
|
||||
# i32 r-tree table. It decodes and returns a list of cells from the node
|
||||
# as a list. Each cell is itself a list of the following form:
|
||||
#
|
||||
# {$rowid $minX $maxX $minY $maxY}
|
||||
#
|
||||
# For internal (non-leaf) nodes, the rowid is replaced by the child node
|
||||
# number.
|
||||
#
|
||||
proc rnode_cells {aData} {
|
||||
set nDim 2
|
||||
|
||||
set nData [string length $aData]
|
||||
set nBytePerCell [expr (8 + 2*$nDim*4)]
|
||||
binary scan [string range $aData 2 3] S nCell
|
||||
|
||||
set res [list]
|
||||
for {set i 0} {$i < $nCell} {incr i} {
|
||||
set iOff [expr $i*$nBytePerCell+4]
|
||||
set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]]
|
||||
binary scan $cell WIIII rowid x1 x2 y1 y2
|
||||
lappend res [list $rowid $x1 $x2 $y1 $y2]
|
||||
}
|
||||
|
||||
return $res
|
||||
}
|
||||
|
||||
# Interpret the first two bytes of the blob passed as the only parameter
|
||||
# as a 16-bit big-endian integer and return the value. If this blob is
|
||||
# the root node of an r-tree, this value is the height of the tree.
|
||||
#
|
||||
proc rnode_height {aData} {
|
||||
binary scan [string range $aData 0 1] S nHeight
|
||||
return $nHeight
|
||||
}
|
||||
|
||||
# Return a blob containing node iNode of r-tree "rt".
|
||||
#
|
||||
proc rt_node_get {iNode} {
|
||||
db one { SELECT data FROM rt_node WHERE nodeno=$iNode }
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# API:
|
||||
#
|
||||
# pq_init
|
||||
# Initialize a new test.
|
||||
#
|
||||
# pq_test_callback
|
||||
# Invoked each time the xQueryCallback function is called. This Tcl
|
||||
# command checks that the arguments that SQLite passed to xQueryCallback
|
||||
# are as expected.
|
||||
#
|
||||
# pq_test_row
|
||||
# Invoked each time a row is returned. Checks that the row returned
|
||||
# was predicted by the documentation.
|
||||
#
|
||||
# DATA STRUCTURE:
|
||||
# The priority queue is stored as a Tcl list. The order of elements in
|
||||
# the list is unimportant - it is just used as a set here. Each element
|
||||
# in the priority queue is itself a list. The first element is the
|
||||
# priority value for the entry (a real). Following this is a list of
|
||||
# key-value pairs that make up the entries fields.
|
||||
#
|
||||
proc pq_init {} {
|
||||
global Q
|
||||
set Q(pri_queue) [list]
|
||||
|
||||
set nHeight [rnode_height [rt_node_get 1]]
|
||||
set nCell [llength [rnode_cells [rt_node_get 1]]]
|
||||
|
||||
# EVIDENCE-OF: R-54708-13595 An R*Tree query is initialized by making
|
||||
# the root node the only entry in a priority queue sorted by rScore.
|
||||
lappend Q(pri_queue) [list 0.0 [list \
|
||||
iLevel [expr $nHeight+1] \
|
||||
iChild 1 \
|
||||
iCurrent 0 \
|
||||
]]
|
||||
}
|
||||
|
||||
proc pq_extract {} {
|
||||
global Q
|
||||
if {[llength $Q(pri_queue)]==0} {
|
||||
error "priority queue is empty!"
|
||||
}
|
||||
|
||||
# Find the priority queue entry with the lowest score.
|
||||
#
|
||||
# EVIDENCE-OF: R-47257-47871 Smaller scores are processed first.
|
||||
set iBest 0
|
||||
set rBestScore [lindex $Q(pri_queue) 0 0]
|
||||
for {set ii 1} {$ii < [llength $Q(pri_queue)]} {incr ii} {
|
||||
set rScore [expr [lindex $Q(pri_queue) $ii 0]]
|
||||
if {$rScore<$rBestScore} {
|
||||
set rBestScore $rScore
|
||||
set iBest $ii
|
||||
}
|
||||
}
|
||||
|
||||
# Extract the entry with the lowest score from the queue and return it.
|
||||
#
|
||||
# EVIDENCE-OF: R-60002-49798 The query proceeds by extracting the entry
|
||||
# from the priority queue that has the lowest score.
|
||||
set ret [lindex $Q(pri_queue) $iBest]
|
||||
set Q(pri_queue) [lreplace $Q(pri_queue) $iBest $iBest]
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
proc pq_new_entry {rScore iLevel cell} {
|
||||
global Q
|
||||
|
||||
set rowid_name "iChild"
|
||||
if {$iLevel==0} { set rowid_name "iRowid" }
|
||||
|
||||
set kv [list]
|
||||
lappend kv aCoord [lrange $cell 1 end]
|
||||
lappend kv iLevel $iLevel
|
||||
|
||||
if {$iLevel==0} {
|
||||
lappend kv iRowid [lindex $cell 0]
|
||||
} else {
|
||||
lappend kv iChild [lindex $cell 0]
|
||||
lappend kv iCurrent 0
|
||||
}
|
||||
|
||||
lappend Q(pri_queue) [list $rScore $kv]
|
||||
}
|
||||
|
||||
proc pq_test_callback {L res} {
|
||||
#pq_debug "pq_test_callback $L -> $res"
|
||||
global Q
|
||||
|
||||
array set G $L ;# "Got" - as in stuff passed to xQuery
|
||||
|
||||
# EVIDENCE-OF: R-65127-42665 If the extracted priority queue entry is a
|
||||
# node (a subtree), then the next child of that node is passed to the
|
||||
# xQueryFunc callback.
|
||||
#
|
||||
# If it had been a leaf, the row should have been returned, instead of
|
||||
# xQueryCallback being called on a child - as is happening here.
|
||||
foreach {rParentScore parent} [pq_extract] {}
|
||||
array set P $parent ;# "Parent" - as in parent of expected cell
|
||||
if {$P(iLevel)==0} { error "query callback mismatch (1)" }
|
||||
set child_node [rnode_cells [rt_node_get $P(iChild)]]
|
||||
set expected_cell [lindex $child_node $P(iCurrent)]
|
||||
set expected_coords [lrange $expected_cell 1 end]
|
||||
if {[llength $expected_coords] != [llength $G(aCoord)]} {
|
||||
puts [array get P]
|
||||
puts "E: $expected_coords G: $G(aCoord)"
|
||||
error "coordinate mismatch in query callback (1)"
|
||||
}
|
||||
foreach a [lrange $expected_cell 1 end] b $G(aCoord) {
|
||||
if {$a!=$b} { error "coordinate mismatch in query callback (2)" }
|
||||
}
|
||||
|
||||
# Check level is as expected
|
||||
#
|
||||
if {$G(iLevel) != $P(iLevel)-1} {
|
||||
error "iLevel mismatch in query callback (1)"
|
||||
}
|
||||
|
||||
# Unless the callback returned NOT_WITHIN, add the entry to the priority
|
||||
# queue.
|
||||
#
|
||||
# EVIDENCE-OF: R-28754-35153 Those subelements for which the xQueryFunc
|
||||
# callback sets eWithin to PARTLY_WITHIN or FULLY_WITHIN are added to
|
||||
# the priority queue using the score supplied by the callback.
|
||||
#
|
||||
# EVIDENCE-OF: R-08681-45277 Subelements that return NOT_WITHIN are
|
||||
# discarded.
|
||||
set r [lindex $res 0]
|
||||
set rScore [lindex $res 1]
|
||||
if {$r!="fully" && $r!="partly" && $r!="not"} {
|
||||
error "unknown result: $r - expected \"fully\", \"partly\" or \"not\""
|
||||
}
|
||||
if {$r!="not"} {
|
||||
pq_new_entry $rScore [expr $P(iLevel)-1] $expected_cell
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-07194-63805 If the node has more children then it is
|
||||
# returned to the priority queue. Otherwise it is discarded.
|
||||
incr P(iCurrent)
|
||||
if {$P(iCurrent)<[llength $child_node]} {
|
||||
lappend Q(pri_queue) [list $rParentScore [array get P]]
|
||||
}
|
||||
}
|
||||
|
||||
proc pq_test_result {id x1 x2 y1 y2} {
|
||||
#pq_debug "pq_test_result $id $x1 $x2 $y1 $y2"
|
||||
foreach {rScore next} [pq_extract] {}
|
||||
|
||||
# The extracted entry must be a leaf (otherwise, xQueryCallback would
|
||||
# have been called on the extracted entries children instead of just
|
||||
# returning the data).
|
||||
#
|
||||
# EVIDENCE-OF: R-13214-54017 If that entry is a leaf (meaning that it is
|
||||
# an actual R*Tree entry and not a subtree) then that entry is returned
|
||||
# as one row of the query result.
|
||||
array set N $next
|
||||
if {$N(iLevel)!=0} { error "result row mismatch (1)" }
|
||||
|
||||
if {$x1!=[lindex $N(aCoord) 0] || $x2!=[lindex $N(aCoord) 1]
|
||||
|| $y1!=[lindex $N(aCoord) 2] || $y2!=[lindex $N(aCoord) 3]
|
||||
} {
|
||||
if {$N(iLevel)!=0} { error "result row mismatch (2)" }
|
||||
}
|
||||
|
||||
if {$id!=$N(iRowid)} { error "result row mismatch (3)" }
|
||||
}
|
||||
|
||||
proc pq_done {} {
|
||||
global Q
|
||||
# EVIDENCE-OF: R-57438-45968 The query runs until the priority queue is
|
||||
# empty.
|
||||
if {[llength $Q(pri_queue)]>0} {
|
||||
error "priority queue is not empty!"
|
||||
}
|
||||
}
|
||||
|
||||
proc pq_debug {caption} {
|
||||
global Q
|
||||
|
||||
puts "**** $caption ****"
|
||||
set i 0
|
||||
foreach q [lsort -real -index 0 $Q(pri_queue)] {
|
||||
puts "PQ $i: $q"
|
||||
incr i
|
||||
}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------
|
||||
|
||||
proc box_query {a} {
|
||||
set res [list fully [expr rand()]]
|
||||
pq_test_callback $a $res
|
||||
return $res
|
||||
}
|
||||
|
||||
register_box_query db box_query
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE rt USING rtree_i32(id, x1,x2, y1,y2);
|
||||
WITH s(i) AS (
|
||||
SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<64
|
||||
)
|
||||
INSERT INTO rt SELECT NULL, a.i, a.i+1, b.i, b.i+1 FROM s a, s b;
|
||||
}
|
||||
|
||||
proc box_query {a} {
|
||||
set res [list fully [expr rand()]]
|
||||
pq_test_callback $a $res
|
||||
return $res
|
||||
}
|
||||
|
||||
pq_init
|
||||
db eval { SELECT id, x1,x2, y1,y2 FROM rt WHERE id MATCH qbox() } {
|
||||
pq_test_result $id $x1 $x2 $y1 $y2
|
||||
}
|
||||
pq_done
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1045,167 +1045,5 @@ do_test rtreefuzz001-500 {
|
||||
catchsql {UPDATE t1 SET ex= ex ISNULL}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test rtreefuzz001-600 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 20480 pagesize 4096 filename crash-7b37d80f000235.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 10 06 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 05 0e 49 00 0f 99 0f 40 ..........I....@
|
||||
| 112: 0e da 0e 8f 0e 49 00 00 00 00 00 00 00 00 00 00 .....I..........
|
||||
| 3648: 00 00 00 00 00 00 00 00 00 44 05 06 17 15 15 08 .........D......
|
||||
| 3664: 6f 74 61 62 6c 65 67 65 6f 31 67 65 6f 31 43 52 otablegeo1geo1CR
|
||||
| 3680: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 3696: 4c 45 20 67 65 6f 31 20 55 53 49 4e 47 20 67 65 LE geo1 USING ge
|
||||
| 3712: 6f 70 6f 6c 79 28 74 79 70 65 2c 63 6c 72 29 49 opoly(type,clr)I
|
||||
| 3728: 04 06 17 1f 1f 01 63 74 61 62 6c 65 71 75 65 72 ......ctablequer
|
||||
| 3744: 79 70 6f 6c 79 71 75 65 72 79 70 6f 6c 79 05 43 ypolyquerypoly.C
|
||||
| 3760: 52 45 41 54 45 20 54 41 42 4c 45 20 71 75 65 72 REATE TABLE quer
|
||||
| 3776: 79 70 6f 6c 79 28 70 6f 6c 79 20 4a 53 4f 4e 2c ypoly(poly JSON,
|
||||
| 3792: 20 63 6c 72 20 54 45 58 54 29 64 03 07 17 23 23 clr TEXT)d...##
|
||||
| 3808: 01 81 0f 74 61 62 6c 65 67 65 6f 31 5f 70 61 72 ...tablegeo1_par
|
||||
| 3824: 65 6e 74 67 65 6f 31 5f 70 61 72 65 6e 74 04 43 entgeo1_parent.C
|
||||
| 3840: 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 6f REATE TABLE .geo
|
||||
| 3856: 31 5f 70 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 1_parent.(nodeno
|
||||
| 3872: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
|
||||
| 3888: 20 4b 45 59 2c 70 61 72 65 6e 74 6e 6f 64 85 29 KEY,parentnod.)
|
||||
| 3904: 57 02 06 17 1f 1f 01 7f 74 61 62 6c 65 67 65 6f W.......tablegeo
|
||||
| 3920: 31 5f 6e 6f 64 65 67 65 6f 31 5f 6e 6f 64 65 03 1_nodegeo1_node.
|
||||
| 3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 CREATE TABLE .ge
|
||||
| 3952: 6f 31 5f 6e 6f 64 65 22 28 6e 6f 64 65 6e 6f 20 o1_node.(nodeno
|
||||
| 3968: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
|
||||
| 3984: 4b 45 59 2c 64 61 74 61 29 65 01 07 17 21 21 01 KEY,data)e...!!.
|
||||
| 4000: 81 15 74 61 62 6c 65 67 65 6f 31 5f 72 6f 77 69 ..tablegeo1_rowi
|
||||
| 4016: 64 67 65 6f 31 5f 72 6f 77 69 64 02 43 52 45 41 dgeo1_rowid.CREA
|
||||
| 4032: 54 45 20 54 41 42 4c 45 20 22 67 65 6f 31 5f 72 TE TABLE .geo1_r
|
||||
| 4048: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
|
||||
| 4064: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
|
||||
| 4080: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 2c 61 32 29 nodeno,a0,a1,a2)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 0a 0d ab 00 0f c9 0f 88 0f 48 0f 00 .............H..
|
||||
| 3488: 00 00 00 00 00 00 00 00 00 00 00 45 82 0a 06 00 ...........E....
|
||||
| 3504: 09 74 1d 13 01 00 00 06 00 80 b5 43 00 80 ac 43 .t.........C...C
|
||||
| 3520: 00 00 bd 43 8f 82 9f 43 71 fd c9 43 8f 02 a7 43 ...C...Cq..C...C
|
||||
| 3536: 71 fd c8 43 e4 bd a8 43 64 bb bd 43 f4 3d a2 43 q..C...Cd..C.=.C
|
||||
| 3552: 64 3b b7 43 00 80 ad 43 61 6e 67 6c 65 2d 33 30 d;.C...Cangle-30
|
||||
| 3568: 72 65 64 32 81 4e 06 00 09 44 23 17 01 00 00 03 red2.N...D#.....
|
||||
| 3584: 00 40 3f 44 00 c0 20 44 00 c0 46 44 00 c0 20 44 .@?D.. D..FD.. D
|
||||
| 3600: 00 00 43 44 00 40 28 44 74 72 69 61 6e 67 6c 65 ..CD.@(Dtriangle
|
||||
| 3616: 2d 33 30 62 6c 61 63 6b 35 82 3e 06 00 09 54 1d -30black5.>...T.
|
||||
| 3632: 13 01 00 00 04 00 40 54 44 00 80 1d 44 9a c9 5c ......@TD...D...
|
||||
| 3648: 44 66 36 1b 44 33 13 5f 44 00 c0 23 44 9a 89 5b Df6.D3._D..#D..[
|
||||
| 3664: 44 a4 60 1d 44 61 72 72 6f 77 2d 35 30 72 65 64 D.`.Darrow-50red
|
||||
| 3680: 36 74 06 00 09 54 1b 17 01 00 00 04 00 80 0d 44 6t...T.........D
|
||||
| 3696: 00 00 f2 42 0a d7 04 44 00 00 ca 42 0a 77 05 44 ...B...D...B.w.D
|
||||
| 3712: 0a 57 c1 42 00 20 0e 44 0a 57 e9 42 6c 69 6e 65 .W.B. .D.W.Bline
|
||||
| 3728: 2d 34 30 67 72 65 65 6e 36 72 06 00 09 54 1b 17 -40green6r...T..
|
||||
| 3744: 01 00 00 04 00 00 7b 43 00 00 ea 42 29 5c 58 43 .......C...B).XC
|
||||
| 3760: 00 00 c2 42 29 dc 5a 43 0a 57 b9 42 00 80 7d 43 ...B).ZC.W.B...C
|
||||
| 3776: 0a 57 e1 42 6c 69 6e 65 2d 34 30 67 72 65 65 6e .W.Bline-40green
|
||||
| 3792: 36 54 06 00 09 54 1b 17 01 00 00 04 00 00 a2 43 6T...T.........C
|
||||
| 3808: 00 00 24 44 00 00 b6 43 00 00 24 44 00 00 b6 43 ..$D...C..$D...C
|
||||
| 3824: 00 40 25 44 00 00 a2 43 00 40 25 44 6c 69 6e 65 .@%D...C.@%Dline
|
||||
| 3840: 2d 34 30 62 6c 61 63 6b 3e 37 06 00 09 64 1d 15 -40black>7...d..
|
||||
| 3856: 01 00 00 05 00 80 f0 43 00 00 54 43 66 16 01 44 .......C..TCf..D
|
||||
| 3872: 66 a6 30 43 cd ec 09 44 00 00 54 43 8f 0a 09 44 f.0C...D..TC...D
|
||||
| 3888: a4 d0 73 43 66 16 01 44 9a 59 77 43 68 6f 75 73 ..sCf..D.YwChous
|
||||
| 3904: 65 2d 37 30 62 6c 75 65 3e 35 06 00 09 64 1d 15 e-70blue>5...d..
|
||||
| 3920: 01 00 00 05 00 00 a2 43 00 00 5a 43 cd ac b3 43 .......C..ZC...C
|
||||
| 3936: 66 a6 36 43 9a 59 c5 43 00 00 5a 43 1f 95 c3 43 f.6C.Y.C..ZC...C
|
||||
| 3952: a4 d0 79 43 cd ac b3 43 9a 59 7d 43 68 6f 75 73 ..yC...C.Y.Chous
|
||||
| 3968: 65 2d 37 30 62 6c 75 65 3f 2c 06 00 09 64 1d 17 e-70blue?,...d..
|
||||
| 3984: 01 00 00 05 00 00 f5 43 00 00 2f 43 00 00 07 44 .......C../C...D
|
||||
| 4000: 00 00 2f 43 00 00 07 44 00 00 61 43 00 c0 00 44 ../C...D..aC...D
|
||||
| 4016: 00 00 75 43 00 00 f5 43 00 00 61 43 68 6f 75 73 ..uC...C..aChous
|
||||
| 4032: 65 2d 37 30 62 6c 61 63 6b 35 1f 06 10 09 54 19 e-70black5....T.
|
||||
| 4048: 17 01 00 00 04 00 00 9b 43 00 00 67 43 0a 57 92 ........C..gC.W.
|
||||
| 4064: 43 00 00 5d 43 0a 57 97 43 14 ae 4b 42 ff ff a0 C..]C.W.C..KB...
|
||||
| 4080: 43 14 ae 55 43 62 6f 78 2d 32 30 67 72 65 65 6e C..UCbox-20green
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 01 0b 2d 00 0b 2e 00 00 00 00 00 00 ......-.........
|
||||
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 ...............P
|
||||
| 2864: 01 04 00 93 24 00 00 00 0a 00 00 00 00 00 00 01 ....$...........
|
||||
| 2880: 0a 43 b5 80 00 43 c9 fd 71 43 9f 82 8f 43 ad 80 .C...C..qC...C..
|
||||
| 2896: 00 00 00 00 00 00 00 00 72 43 58 5c 29 43 7d 80 ........rCX.)C..
|
||||
| 2912: 00 42 b9 57 0a 42 ea 00 00 00 00 00 00 00 00 00 .B.W.B..........
|
||||
| 2928: 35 43 a2 00 00 43 c5 59 9a 43 36 a6 66 43 7d 59 5C...C.Y.C6.fC.Y
|
||||
| 2944: 9a 00 00 00 00 00 00 00 1f 43 92 57 0a 43 a0 00 .........C.W.C..
|
||||
| 2960: 00 43 4b ae 14 43 67 00 00 00 00 00 00 00 00 00 .CK..Cg.........
|
||||
| 2976: 37 43 f0 80 00 44 09 ec cd 43 30 a6 66 43 77 59 7C...D...C0.fCwY
|
||||
| 2992: 9a 00 00 00 00 00 00 00 2c 43 f5 00 00 44 07 00 ........,C...D..
|
||||
| 3008: 00 43 2f 00 00 43 75 00 00 00 00 00 00 00 00 00 .C/..Cu.........
|
||||
| 3024: 74 44 04 d7 0a 44 0e 20 00 42 c1 57 0a 42 f2 00 tD...D. .B.W.B..
|
||||
| 3040: 00 00 00 00 00 00 00 00 ce 44 3f 40 00 44 46 c0 .........D?@.DF.
|
||||
| 3056: 00 44 20 c0 00 44 28 40 00 00 00 00 00 00 00 00 .D ..D(@........
|
||||
| 3072: be 44 54 40 00 44 5f 13 33 44 1b 36 66 44 23 c0 .DT@.D_.3D.6fD#.
|
||||
| 3088: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3104: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
|
||||
| 3120: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
|
||||
| 3136: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3152: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
|
||||
| 3168: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
|
||||
| 3184: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3200: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
|
||||
| 3216: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
|
||||
| 3232: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3248: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
|
||||
| 3264: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
|
||||
| 3280: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3296: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
|
||||
| 3312: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
|
||||
| 3328: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
|
||||
| 3344: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 01 .D$..D%@........
|
||||
| 3360: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3376: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3392: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3408: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3424: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3440: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3456: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3472: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3488: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3504: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3520: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3536: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3552: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3568: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3584: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3600: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3616: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3632: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3648: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| 3664: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
|
||||
| 3680: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
|
||||
| 3696: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 01 0f 8f 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f ...............o
|
||||
| 3984: 01 04 81 57 19 5b 5b 33 30 30 2c 33 30 30 5d 2c ...W.[[300,300],
|
||||
| 4000: 5b 34 30 30 2c 33 35 30 5d 2c 5b 35 30 30 2c 32 [400,350],[500,2
|
||||
| 4016: 35 30 5d 2c 5b 34 38 30 2c 35 30 30 5d 2c 5b 34 50],[480,500],[4
|
||||
| 4032: 30 30 2c 34 38 30 5d 2c 5c 33 30 30 2c 35 35 30 00,480],.300,550
|
||||
| 4048: 5d 2c 5b 32 38 30 2c 34 35 30 5d 2c 5b 33 32 30 ],[280,450],[320
|
||||
| 4064: 2c 34 30 30 5d 2c 5b 32 38 30 2c 33 35 30 5d 2c ,400],[280,350],
|
||||
| 4080: 5b 33 30 30 2c 33 30 00 00 00 00 00 00 00 00 00 [300,30.........
|
||||
| end crash-7b37d80f000235.db
|
||||
}]} {}
|
||||
|
||||
ifcapable geopoly {
|
||||
|
||||
do_catchsql_test rtreefuzz001-601 {
|
||||
SAVEPOINT one;
|
||||
UPDATE geo1 SET clr=CASE WHEN rowid IN ( SELECT geo1.rowid FROM geo1, querypoly ) THEN 'e' ELSE 'blue' END;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test rtreefuzz001-602 {
|
||||
SELECT geopoly_svg(_shape, printf('j',geo1.clr))
|
||||
FROM geo1, querypoly WHERE geopoly_overlap(_shape, poly);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
} ;# ifcapable geopoly
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,348 +0,0 @@
|
||||
/*
|
||||
** 2010 August 28
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
** Code for testing all sorts of SQLite interfaces. This code
|
||||
** is not included in the SQLite library.
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
#endif
|
||||
|
||||
/* Solely for the UNUSED_PARAMETER() macro. */
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
|
||||
typedef struct BoxGeomCtx BoxGeomCtx;
|
||||
struct BoxGeomCtx {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
};
|
||||
|
||||
typedef struct BoxQueryCtx BoxQueryCtx;
|
||||
struct BoxQueryCtx {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
};
|
||||
|
||||
static void testDelUser(void *pCtx){
|
||||
BoxGeomCtx *p = (BoxGeomCtx*)pCtx;
|
||||
Tcl_EvalObjEx(p->interp, p->pScript, 0);
|
||||
Tcl_DecrRefCount(p->pScript);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
static int invokeTclGeomCb(
|
||||
const char *zName,
|
||||
sqlite3_rtree_geometry *p,
|
||||
int nCoord,
|
||||
sqlite3_rtree_dbl *aCoord
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->pContext ){
|
||||
char aPtr[64];
|
||||
BoxGeomCtx *pCtx = (BoxGeomCtx*)p->pContext;
|
||||
Tcl_Interp *interp = pCtx->interp;
|
||||
Tcl_Obj *pScript = 0;
|
||||
Tcl_Obj *pParam = 0;
|
||||
Tcl_Obj *pCoord = 0;
|
||||
int ii;
|
||||
Tcl_Obj *pRes;
|
||||
|
||||
|
||||
pScript = Tcl_DuplicateObj(pCtx->pScript);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zName,-1));
|
||||
|
||||
sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p->pContext);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));
|
||||
|
||||
pParam = Tcl_NewObj();
|
||||
for(ii=0; ii<p->nParam; ii++){
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pParam, Tcl_NewDoubleObj(p->aParam[ii])
|
||||
);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pScript, pParam);
|
||||
|
||||
pCoord = Tcl_NewObj();
|
||||
for(ii=0; ii<nCoord; ii++){
|
||||
Tcl_ListObjAppendElement(interp, pCoord, Tcl_NewDoubleObj(aCoord[ii]));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pScript, pCoord);
|
||||
|
||||
sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));
|
||||
|
||||
rc = Tcl_EvalObjEx(interp, pScript, 0);
|
||||
if( rc!=TCL_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int nObj = 0;
|
||||
Tcl_Obj **aObj = 0;
|
||||
|
||||
pRes = Tcl_GetObjResult(interp);
|
||||
if( Tcl_ListObjGetElements(interp, pRes, &nObj, &aObj) ) return TCL_ERROR;
|
||||
if( nObj>0 ){
|
||||
const char *zCmd = Tcl_GetString(aObj[0]);
|
||||
if( 0==sqlite3_stricmp(zCmd, "zero") ){
|
||||
p->aParam[0] = 0.0;
|
||||
p->nParam = 1;
|
||||
}
|
||||
else if( 0==sqlite3_stricmp(zCmd, "user") ){
|
||||
if( p->pUser || p->xDelUser ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
BoxGeomCtx *pBGCtx = sqlite3_malloc(sizeof(BoxGeomCtx));
|
||||
if( pBGCtx==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pBGCtx->interp = interp;
|
||||
pBGCtx->pScript = Tcl_DuplicateObj(pRes);
|
||||
Tcl_IncrRefCount(pBGCtx->pScript);
|
||||
Tcl_ListObjReplace(interp, pBGCtx->pScript, 0, 1, 0, 0);
|
||||
p->pUser = (void*)pBGCtx;
|
||||
p->xDelUser = testDelUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( 0==sqlite3_stricmp(zCmd, "user_is_zero") ){
|
||||
if( p->pUser || p->xDelUser ) rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
# EVIDENCE-OF: R-00693-36727 The legacy xGeom callback is invoked with
|
||||
# four arguments.
|
||||
|
||||
# EVIDENCE-OF: R-50437-53270 The first argument is a pointer to an
|
||||
# sqlite3_rtree_geometry structure which provides information about how
|
||||
# the SQL function was invoked.
|
||||
|
||||
# EVIDENCE-OF: R-00090-24248 The third argument, aCoord[], is an array
|
||||
# of nCoord coordinates that defines a bounding box to be tested.
|
||||
|
||||
# EVIDENCE-OF: R-28207-40885 The last argument is a pointer into which
|
||||
# the callback result should be written.
|
||||
|
||||
*/
|
||||
static int box_geom(
|
||||
sqlite3_rtree_geometry *p, /* R-50437-53270 */
|
||||
int nCoord, /* R-02424-24769 */
|
||||
sqlite3_rtree_dbl *aCoord, /* R-00090-24248 */
|
||||
int *pRes /* R-28207-40885 */
|
||||
){
|
||||
int ii;
|
||||
|
||||
if( p->nParam!=nCoord ){
|
||||
invokeTclGeomCb("box", p, nCoord, aCoord);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( invokeTclGeomCb("box", p, nCoord, aCoord) ) return SQLITE_ERROR;
|
||||
|
||||
for(ii=0; ii<nCoord; ii+=2){
|
||||
if( aCoord[ii]>p->aParam[ii+1] || aCoord[ii+1]<p->aParam[ii] ){
|
||||
/* R-28207-40885 */
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* R-28207-40885 */
|
||||
*pRes = 1;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int SQLITE_TCLAPI register_box_geom(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
|
||||
extern const char *sqlite3ErrName(int);
|
||||
sqlite3 *db;
|
||||
BoxGeomCtx *pCtx;
|
||||
char aPtr[64];
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
pCtx = (BoxGeomCtx*)ckalloc(sizeof(BoxGeomCtx*));
|
||||
pCtx->interp = interp;
|
||||
pCtx->pScript = Tcl_DuplicateObj(objv[2]);
|
||||
Tcl_IncrRefCount(pCtx->pScript);
|
||||
|
||||
sqlite3_rtree_geometry_callback(db, "box", box_geom, (void*)pCtx);
|
||||
|
||||
sqlite3_snprintf(64, aPtr, "%p", (void*)pCtx);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(aPtr, -1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int box_query(sqlite3_rtree_query_info *pInfo){
|
||||
const char *azParentWithin[] = {"not", "partly", "fully", 0};
|
||||
BoxQueryCtx *pCtx = (BoxQueryCtx*)pInfo->pContext;
|
||||
Tcl_Interp *interp = pCtx->interp;
|
||||
Tcl_Obj *pEval;
|
||||
Tcl_Obj *pArg;
|
||||
Tcl_Obj *pTmp = 0;
|
||||
int rc;
|
||||
int ii;
|
||||
|
||||
pEval = Tcl_DuplicateObj(pCtx->pScript);
|
||||
Tcl_IncrRefCount(pEval);
|
||||
pArg = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pArg);
|
||||
|
||||
/* aParam[] */
|
||||
pTmp = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pTmp);
|
||||
for(ii=0; ii<pInfo->nParam; ii++){
|
||||
Tcl_Obj *p = Tcl_NewDoubleObj(pInfo->aParam[ii]);
|
||||
Tcl_ListObjAppendElement(interp, pTmp, p);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("aParam", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, pTmp);
|
||||
Tcl_DecrRefCount(pTmp);
|
||||
|
||||
/* aCoord[] */
|
||||
pTmp = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pTmp);
|
||||
for(ii=0; ii<pInfo->nCoord; ii++){
|
||||
Tcl_Obj *p = Tcl_NewDoubleObj(pInfo->aCoord[ii]);
|
||||
Tcl_ListObjAppendElement(interp, pTmp, p);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("aCoord", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, pTmp);
|
||||
Tcl_DecrRefCount(pTmp);
|
||||
|
||||
/* anQueue[] */
|
||||
pTmp = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pTmp);
|
||||
for(ii=0; ii<=pInfo->mxLevel; ii++){
|
||||
Tcl_Obj *p = Tcl_NewIntObj((int)pInfo->anQueue[ii]);
|
||||
Tcl_ListObjAppendElement(interp, pTmp, p);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("anQueue", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, pTmp);
|
||||
Tcl_DecrRefCount(pTmp);
|
||||
|
||||
/* iLevel */
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("iLevel", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewIntObj(pInfo->iLevel));
|
||||
|
||||
/* mxLevel */
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("mxLevel", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewIntObj(pInfo->mxLevel));
|
||||
|
||||
/* iRowid */
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("iRowid", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewWideIntObj(pInfo->iRowid));
|
||||
|
||||
/* rParentScore */
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("rParentScore", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewDoubleObj(pInfo->rParentScore));
|
||||
|
||||
/* eParentWithin */
|
||||
assert( pInfo->eParentWithin==0
|
||||
|| pInfo->eParentWithin==1
|
||||
|| pInfo->eParentWithin==2
|
||||
);
|
||||
Tcl_ListObjAppendElement(interp, pArg, Tcl_NewStringObj("eParentWithin", -1));
|
||||
Tcl_ListObjAppendElement(interp, pArg,
|
||||
Tcl_NewStringObj(azParentWithin[pInfo->eParentWithin], -1)
|
||||
);
|
||||
|
||||
Tcl_ListObjAppendElement(interp, pEval, pArg);
|
||||
rc = Tcl_EvalObjEx(interp, pEval, 0) ? SQLITE_ERROR : SQLITE_OK;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
double rScore = 0.0;
|
||||
int nObj = 0;
|
||||
int eP = 0;
|
||||
Tcl_Obj **aObj = 0;
|
||||
Tcl_Obj *pRes = Tcl_GetObjResult(interp);
|
||||
|
||||
if( Tcl_ListObjGetElements(interp, pRes, &nObj, &aObj)
|
||||
|| nObj!=2
|
||||
|| Tcl_GetDoubleFromObj(interp, aObj[1], &rScore)
|
||||
|| Tcl_GetIndexFromObj(interp, aObj[0], azParentWithin, "value", 0, &eP)
|
||||
){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pInfo->rScore = rScore;
|
||||
pInfo->eParentWithin = eP;
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_DecrRefCount(pArg);
|
||||
Tcl_DecrRefCount(pEval);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void box_query_destroy(void *p){
|
||||
BoxQueryCtx *pCtx = (BoxQueryCtx*)p;
|
||||
Tcl_DecrRefCount(pCtx->pScript);
|
||||
ckfree((char*)pCtx);
|
||||
}
|
||||
|
||||
static int SQLITE_TCLAPI register_box_query(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
|
||||
extern const char *sqlite3ErrName(int);
|
||||
sqlite3 *db;
|
||||
BoxQueryCtx *pCtx;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx));
|
||||
pCtx->interp = interp;
|
||||
pCtx->pScript = Tcl_DuplicateObj(objv[2]);
|
||||
Tcl_IncrRefCount(pCtx->pScript);
|
||||
|
||||
sqlite3_rtree_query_callback(
|
||||
db, "qbox", box_query, (void*)pCtx, box_query_destroy
|
||||
);
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_RTREE */
|
||||
|
||||
|
||||
int Sqlitetestrtreedoc_Init(Tcl_Interp *interp){
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
Tcl_CreateObjCommand(interp, "register_box_geom", register_box_geom, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "register_box_query", register_box_query, 0, 0);
|
||||
#endif /* SQLITE_ENABLE_RTREE */
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -152,26 +152,6 @@ do_changeset_test $tn.2.4.2 S {}
|
||||
do_changeset_invert_test $tn.2.4.3 S {}
|
||||
do_test $tn.2.4.4 { S delete } {}
|
||||
|
||||
do_execsql_test $tn.2.5.0 {
|
||||
SELECT * FROM t1 ORDER BY x
|
||||
} {
|
||||
2 Surin
|
||||
10 Sukhothai
|
||||
20 Thapae
|
||||
}
|
||||
|
||||
do_test $tn.2.5.1 {
|
||||
sqlite3session S db main
|
||||
S attach t1
|
||||
execsql { DELETE FROM t1 }
|
||||
} {}
|
||||
do_changeset_test $tn.2.5.2 S {
|
||||
{DELETE t1 0 X. {i 10 t Sukhothai} {}}
|
||||
{DELETE t1 0 X. {i 2 t Surin} {}}
|
||||
{DELETE t1 0 X. {i 20 t Thapae} {}}
|
||||
}
|
||||
do_test $tn.2.5.3 { S delete } {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the application of simple changesets. These tests also test that
|
||||
# the conflict callback is invoked correctly. For these tests, the
|
||||
|
||||
@@ -19,7 +19,6 @@ if {![info exists testdir]} {
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
ifcapable !incrblob {finish_test; return}
|
||||
|
||||
set testprefix session6
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ proc do_then_undo {tn sql} {
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES('abc', 'xyz');
|
||||
INSERT INTO t1 VALUES("abc", "xyz");
|
||||
}
|
||||
do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); }
|
||||
do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; }
|
||||
|
||||
@@ -20,13 +20,8 @@ if {![info exists testdir]} {
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
set testprefix sessionat
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set testprefix sessionat
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
# 2014 August 16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements regression tests for sessions SQLite extension.
|
||||
# Specifically, this file contains tests for "patchset" changes.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
if {[permutation]=="session_strm" || [permutation]=="session_eec"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
if {$::tcl_platform(pointerSize)<8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix sessionbig
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
}
|
||||
do_execsql_test -db db2 1.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
do_then_apply_sql {
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
execsql { DELETE FROM t1 }
|
||||
execsql2 { DELETE FROM t1 }
|
||||
} {}
|
||||
|
||||
do_test 1.4 {
|
||||
set rc [catch {
|
||||
do_then_apply_sql {
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
|
||||
}
|
||||
} msg]
|
||||
list $rc $msg
|
||||
} {1 SQLITE_NOMEM}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
# 2021 Februar 20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionnoop
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test plan:
|
||||
#
|
||||
# 1.*: Test that concatenating changesets cannot produce a noop UPDATE.
|
||||
# 2.*: Test that rebasing changesets cannot produce a noop UPDATE.
|
||||
# 3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
|
||||
#
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c, d);
|
||||
INSERT INTO t1 VALUES(1, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3, 3);
|
||||
}
|
||||
|
||||
proc do_concat_test {tn sql1 sql2 res} {
|
||||
uplevel [list do_test $tn [subst -nocommands {
|
||||
set C1 [changeset_from_sql {$sql1}]
|
||||
set C2 [changeset_from_sql {$sql2}]
|
||||
set C3 [sqlite3changeset_concat [set C1] [set C2]]
|
||||
set got [list]
|
||||
sqlite3session_foreach elem [set C3] { lappend got [set elem] }
|
||||
set got
|
||||
}] [list {*}$res]]
|
||||
}
|
||||
|
||||
do_concat_test 1.1 {
|
||||
UPDATE t1 SET c=c+1;
|
||||
} {
|
||||
UPDATE t1 SET c=c-1;
|
||||
} {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
|
||||
proc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
|
||||
proc xConflict {args} [list return $conflict_res]
|
||||
|
||||
uplevel [list \
|
||||
do_test $tn [subst -nocommands {
|
||||
execsql BEGIN
|
||||
set c_remote [changeset_from_sql {$sql_remote}]
|
||||
execsql ROLLBACK
|
||||
|
||||
execsql BEGIN
|
||||
set c_local [changeset_from_sql {$sql_local}]
|
||||
set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
|
||||
execsql ROLLBACK
|
||||
|
||||
sqlite3rebaser_create R
|
||||
R config [set base]
|
||||
set res [list]
|
||||
sqlite3session_foreach elem [R rebase [set c_local]] {
|
||||
lappend res [set elem]
|
||||
}
|
||||
R delete
|
||||
set res
|
||||
}] [list {*}$expected]
|
||||
]
|
||||
}
|
||||
|
||||
do_rebase_test 2.1 {
|
||||
UPDATE t1 SET c=2 WHERE a=1; -- local
|
||||
} {
|
||||
UPDATE t1 SET c=3 WHERE a=1; -- remote
|
||||
} OMIT {
|
||||
{UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
|
||||
}
|
||||
|
||||
do_rebase_test 2.2 {
|
||||
UPDATE t1 SET c=2 WHERE a=1; -- local
|
||||
} {
|
||||
UPDATE t1 SET c=3 WHERE a=1; -- remote
|
||||
} REPLACE {
|
||||
}
|
||||
|
||||
do_rebase_test 2.3.1 {
|
||||
UPDATE t1 SET c=4 WHERE a=1; -- local
|
||||
} {
|
||||
UPDATE t1 SET c=4 WHERE a=1 -- remote
|
||||
} OMIT {
|
||||
{UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
|
||||
}
|
||||
|
||||
do_rebase_test 2.3.2 {
|
||||
UPDATE t1 SET c=5 WHERE a=1; -- local
|
||||
} {
|
||||
UPDATE t1 SET c=5 WHERE a=1 -- remote
|
||||
} REPLACE {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4, 4);
|
||||
}
|
||||
|
||||
# Arg $pkstr contains one character for each column in the table. An
|
||||
# "X" for PK column, or a "." for a non-PK.
|
||||
#
|
||||
proc mk_tbl_header {name pkstr} {
|
||||
set ret [binary format H2c 54 [string length $pkstr]]
|
||||
foreach i [split $pkstr {}] {
|
||||
if {$i=="X"} {
|
||||
append ret [binary format H2 01]
|
||||
} else {
|
||||
if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
|
||||
append ret [binary format H2 00]
|
||||
}
|
||||
}
|
||||
append ret $name
|
||||
append ret [binary format H2 00]
|
||||
set ret
|
||||
}
|
||||
|
||||
proc mk_update_change {args} {
|
||||
set ret [binary format H2H2 17 00]
|
||||
foreach a $args {
|
||||
if {$a==""} {
|
||||
append ret [binary format H2 00]
|
||||
} else {
|
||||
append ret [binary format H2W 01 $a]
|
||||
}
|
||||
}
|
||||
set ret
|
||||
}
|
||||
|
||||
proc xConflict {args} { return "ABORT" }
|
||||
do_test 3.1 {
|
||||
set C [mk_tbl_header t1 X..]
|
||||
append C [mk_update_change 1 {} 1 {} {} 500]
|
||||
append C [mk_update_change 2 {} {} {} {} {}]
|
||||
append C [mk_update_change 3 3 {} {} 600 {}]
|
||||
append C [mk_update_change 4 {} {} {} {} {}]
|
||||
|
||||
sqlite3changeset_apply_v2 db $C xConflict
|
||||
} {}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 1 500
|
||||
2 2 2
|
||||
3 600 3
|
||||
4 4 4
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
# 2021 April 22
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionsize
|
||||
|
||||
proc do_changeset_size_test {tn sql} {
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
db eval $sql
|
||||
|
||||
set sz [S changeset_size]
|
||||
set C [S changeset]
|
||||
set szC [string length $C]
|
||||
S delete
|
||||
|
||||
do_test $tn "expr $sz" $szC
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1, 'abc', 'def');
|
||||
INSERT INTO t1 VALUES(2, 'ghi', 'jkl');
|
||||
}
|
||||
|
||||
do_changeset_size_test 1.1 {
|
||||
INSERT INTO t1 VALUES(3, 'hello', 'world');
|
||||
}
|
||||
|
||||
do_changeset_size_test 1.2 {
|
||||
DELETE FROM t1 WHERE a=2;
|
||||
}
|
||||
|
||||
do_changeset_size_test 1.3 {
|
||||
DELETE FROM t1 WHERE a=3;
|
||||
INSERT INTO t1 VALUES(3, 1, 2);
|
||||
}
|
||||
|
||||
do_changeset_size_test 1.4 {
|
||||
UPDATE t1 SET c='hello world' WHERE a=3;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABlE t2(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
CREATE TABlE t3(a, b, c, d PRIMARY KEY);
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.1 {
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
|
||||
)
|
||||
INSERT INTO t2 SELECT i, i+1, i+2, i+3 FROM s;
|
||||
|
||||
UPDATE t2 SET c=randomblob(a) WHERE a>10
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.2 {
|
||||
DELETE FROM t2 WHERE a=1;
|
||||
INSERT INTO t2 VALUES(1, 4, 3, 4);
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.2 {
|
||||
UPDATE t2 SET b=4 WHERE a=2
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.3 {
|
||||
INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
|
||||
UPDATE t2 SET c='qwertyuiop' WHERE a='a';
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.4 {
|
||||
DELETE FROM t2 WHERE a='a';
|
||||
INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.5 {
|
||||
UPDATE t2 SET a='aa', b='bb' WHERE (a, b) = ('a', 'b');
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.6 {
|
||||
UPDATE t2 SET a='a', b='b' WHERE (a, b) = ('aa', 'bb');
|
||||
}
|
||||
|
||||
do_changeset_size_test 2.7 {
|
||||
INSERT INTO t3 DEFAULT VALUES;
|
||||
INSERT INTO t3 VALUES(1,2,3,4);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3session S db main
|
||||
S object_config_size -1
|
||||
} 1
|
||||
|
||||
do_test 3.2.1 { S object_config_size 0 } 0
|
||||
do_test 3.2.2 { S object_config_size -1 } 0
|
||||
do_test 3.2.3 { S object_config_size 1 } 1
|
||||
do_test 3.2.4 { S object_config_size -1 } 1
|
||||
|
||||
do_test 3.3 { S attach t1 } {}
|
||||
do_test 3.4 { S object_config_size 1 } {SQLITE_MISUSE}
|
||||
do_test 3.4 { S object_config_size -1 } {1}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -69,9 +69,7 @@ foreach {tn wo} {
|
||||
} {
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.$tn.0.1 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
|
||||
do_execsql_test 2.$tn.0.2 "CREATE TABLE t2(a INTEGER PRIMARY KEY, b) $wo ;"
|
||||
do_execsql_test 2.$tn.0.3 "CREATE TABLE t3(a INTEGER PRIMARY KEY, b) $wo ;"
|
||||
do_execsql_test 2.$tn.0 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
|
||||
|
||||
do_iterator_test 1.1 t1 {
|
||||
INSERT INTO t1 VALUES(1, 'two');
|
||||
@@ -96,27 +94,6 @@ foreach {tn wo} {
|
||||
} {
|
||||
{DELETE t1 0 X. {i 1 t four} {}}
|
||||
}
|
||||
|
||||
do_execsql_test 2.$tn.5 {
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
INSERT INTO t1 VALUES(3, 'three');
|
||||
}
|
||||
|
||||
do_iterator_test 2.$tn.6 t2 {
|
||||
INSERT INTO t2 SELECT a, b FROM t1
|
||||
} {
|
||||
{INSERT t2 0 X. {} {i 1 t one}}
|
||||
{INSERT t2 0 X. {} {i 2 t two}}
|
||||
{INSERT t2 0 X. {} {i 3 t three}}
|
||||
}
|
||||
do_iterator_test 2.$tn.7 t3 {
|
||||
INSERT INTO t3 SELECT * FROM t1
|
||||
} {
|
||||
{INSERT t3 0 X. {} {i 1 t one}}
|
||||
{INSERT t3 0 X. {} {i 2 t two}}
|
||||
{INSERT t3 0 X. {} {i 3 t three}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user