Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0359f0490 |
+14
-171
@@ -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
|
||||
@@ -460,7 +459,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 +467,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
|
||||
#
|
||||
@@ -503,7 +500,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/pcache1.c \
|
||||
$(TOP)/src/select.c \
|
||||
$(TOP)/src/tokenize.c \
|
||||
$(TOP)/src/treeview.c \
|
||||
$(TOP)/src/utf.c \
|
||||
$(TOP)/src/util.c \
|
||||
$(TOP)/src/vdbeapi.c \
|
||||
@@ -610,7 +606,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
|
||||
@@ -620,18 +616,18 @@ 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
|
||||
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_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
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c $(TOP)/test/fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
@@ -760,7 +756,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 .
|
||||
|
||||
@@ -875,9 +871,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 $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c
|
||||
|
||||
legacy.lo: $(TOP)/src/legacy.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c
|
||||
|
||||
@@ -1093,7 +1086,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 \
|
||||
@@ -1181,6 +1173,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
|
||||
|
||||
@@ -1253,10 +1248,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
|
||||
@@ -1281,12 +1273,6 @@ valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessio
|
||||
tcltest: ./testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
|
||||
|
||||
# Runs all the same tests cases as the "tcltest" target but uses
|
||||
# the testrunner.tcl script to run them in multiple cores
|
||||
# concurrently.
|
||||
testrunner: testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes
|
||||
#
|
||||
quicktest: ./testfixture$(TEXE)
|
||||
@@ -1476,7 +1462,6 @@ clean:
|
||||
rm -rf .libs .deps
|
||||
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) keywordhash.h
|
||||
rm -f mksourceid$(BEXE)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf tsrc .target_source
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
@@ -1501,8 +1486,7 @@ clean:
|
||||
rm -f threadtest5
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.log config.status libtool Makefile sqlite3.pc \
|
||||
$(TESTPROGS)
|
||||
rm -f config.h config.log config.status libtool Makefile sqlite3.pc
|
||||
|
||||
#
|
||||
# Windows section
|
||||
@@ -1521,144 +1505,3 @@ sqlite3.def: $(REAL_LIBOBJ)
|
||||
sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def
|
||||
$(TCC) -shared -o $@ sqlite3.def \
|
||||
-Wl,"--strip-all" $(REAL_LIBOBJ)
|
||||
|
||||
|
||||
#
|
||||
# fiddle/wasm section
|
||||
#
|
||||
# Maintenance reminder: we can/should move this into the wasm-specific
|
||||
# GNU Make makefile, but we currently need it here for access to
|
||||
# $(SHELL_OPT). The rest of the wasm-related bits are handled via GNU
|
||||
# Make in ext/wasm/...
|
||||
#
|
||||
wasm_dir = ext/wasm
|
||||
wasm_dir_abs = $(TOP)/ext/wasm
|
||||
# ^^^ some emcc opts require absolute paths
|
||||
fiddle_dir = $(wasm_dir)/fiddle
|
||||
fiddle_dir_abs = $(TOP)/$(fiddle_dir)
|
||||
fiddle_module_js = $(fiddle_dir)/fiddle-module.js
|
||||
#emcc_opt = -O0
|
||||
#emcc_opt = -O1
|
||||
#emcc_opt = -O2
|
||||
#emcc_opt = -O3
|
||||
emcc_opt = -Oz
|
||||
emcc_flags = $(emcc_opt) \
|
||||
-sALLOW_TABLE_GROWTH \
|
||||
-sABORTING_MALLOC \
|
||||
-sSTRICT_JS \
|
||||
-sENVIRONMENT=web \
|
||||
-sMODULARIZE \
|
||||
-sEXPORTED_RUNTIME_METHODS=@$(wasm_dir_abs)/EXPORTED_RUNTIME_METHODS.fiddle \
|
||||
-sDYNAMIC_EXECUTION=0 \
|
||||
--minify 0 \
|
||||
-I. $(SHELL_OPT) \
|
||||
-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_DEPRECATED
|
||||
$(fiddle_module_js): Makefile sqlite3.c shell.c \
|
||||
$(wasm_dir)/EXPORTED_RUNTIME_METHODS.fiddle \
|
||||
$(wasm_dir)/EXPORTED_FUNCTIONS.fiddle
|
||||
emcc -o $@ $(emcc_flags) \
|
||||
-sEXPORT_NAME=initFiddleModule \
|
||||
-sEXPORTED_FUNCTIONS=@$(wasm_dir_abs)/EXPORTED_FUNCTIONS.fiddle \
|
||||
-DSQLITE_SHELL_FIDDLE \
|
||||
sqlite3.c shell.c
|
||||
gzip < $@ > $@.gz
|
||||
gzip < $(fiddle_dir)/fiddle-module.wasm > $(fiddle_dir)/fiddle-module.wasm.gz
|
||||
$(fiddle_dir)/fiddle.js.gz: $(fiddle_dir)/fiddle.js
|
||||
gzip < $< > $@
|
||||
|
||||
fiddle_generated = $(fiddle_module_js) $(fiddle_module_js).gz \
|
||||
$(fiddle_dir)/fiddle-module.wasm \
|
||||
$(fiddle_dir)/fiddle-module.wasm.gz \
|
||||
$(fiddle_dir)/fiddle.js.gz
|
||||
|
||||
clean-fiddle:
|
||||
rm -f $(fiddle_generated)
|
||||
clean: clean-fiddle
|
||||
fiddle: $(fiddle_module_js) $(fiddle_dir)/fiddle.js.gz
|
||||
wasm: fiddle
|
||||
########################################################################
|
||||
# Explanation of the emcc build flags follows. Full docs for these can
|
||||
# be found at:
|
||||
#
|
||||
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
|
||||
#
|
||||
# -sENVIRONMENT=web: elides bootstrap code related to non-web JS
|
||||
# environments like node.js. Removing this makes the output a tiny
|
||||
# tick larger but hypothetically makes it more portable to
|
||||
# non-browser JS environments.
|
||||
#
|
||||
# -sMODULARIZE: changes how the generated code is structured to avoid
|
||||
# declaring a global Module object and instead installing a function
|
||||
# which loads and initializes the module. The function is named...
|
||||
#
|
||||
# -sEXPORT_NAME=jsFunctionName (see -sMODULARIZE)
|
||||
#
|
||||
# -sEXPORTED_RUNTIME_METHODS=@/absolute/path/to/file: a file
|
||||
# containing a list of emscripten-supplied APIs, one per line, which
|
||||
# must be exported into the generated JS. Must be an absolute path!
|
||||
#
|
||||
# -sEXPORTED_FUNCTIONS=@/absolute/path/to/file: a file containing a
|
||||
# list of C functions, one per line, which must be exported via wasm
|
||||
# so they're visible to JS. C symbols names in that file must all
|
||||
# start with an underscore for reasons known only to the emcc
|
||||
# developers. e.g., _sqlite3_open_v2 and _sqlite3_finalize. Must be
|
||||
# an absolute path!
|
||||
#
|
||||
# -sSTRICT_JS ensures that the emitted JS code includes the 'use
|
||||
# strict' option. Note that -sSTRICT is more broadly-scoped and
|
||||
# results in build errors.
|
||||
#
|
||||
# -sALLOW_TABLE_GROWTH is required for (at a minimum) the UDF-binding
|
||||
# feature. Without it, JS functions cannot be made to proxy C-side
|
||||
# callbacks.
|
||||
#
|
||||
# -sABORTING_MALLOC causes the JS-bound _malloc() to abort rather than
|
||||
# return 0 on OOM. If set to 0 then all code which uses _malloc()
|
||||
# must, just like in C, check the result before using it, else
|
||||
# they're likely to corrupt the JS/WASM heap by writing to its
|
||||
# address of 0. It is, as of this writing, enabled in Emscripten by
|
||||
# default but we enable it explicitly in case that default changes.
|
||||
#
|
||||
# -sDYNAMIC_EXECUTION=0 disables eval() and the Function constructor.
|
||||
# If the build runs without these, it's preferable to use this flag
|
||||
# because certain execution environments disallow those constructs.
|
||||
# This flag is not strictly necessary, however.
|
||||
#
|
||||
# -sWASM_BIGINT is UNTESTED but "should" allow the int64-using C APIs
|
||||
# to work with JS/wasm, insofar as the JS environment supports the
|
||||
# BigInt type. That support requires an extremely recent browser:
|
||||
# Safari didn't get that support until late 2020.
|
||||
#
|
||||
# --no-entry: for compiling library code with no main(). If this is
|
||||
# not supplied and the code has a main(), it is called as part of the
|
||||
# module init process. Note that main() is #if'd out of shell.c
|
||||
# (renamed) when building in wasm mode.
|
||||
#
|
||||
# --pre-js/--post-js=FILE relative or absolute paths to JS files to
|
||||
# prepend/append to the emcc-generated bootstrapping JS. It's
|
||||
# easier/faster to develop with separate JS files (reduces rebuilding
|
||||
# requirements) but certain configurations, namely -sMODULARIZE, may
|
||||
# require using at least a --pre-js file. They can be used
|
||||
# individually and need not be paired.
|
||||
#
|
||||
# -O0..-O3 and -Oz: optimization levels affect not only C-style
|
||||
# optimization but whether or not the resulting generated JS code
|
||||
# gets minified. -O0 compiles _much_ more quickly than -O3 or -Oz,
|
||||
# and doesn't minimize any JS code, so is recommended for
|
||||
# development. -O3 or -Oz are recommended for deployment, but
|
||||
# primarily because -Oz will shrink the wasm file notably. JS-side
|
||||
# minification makes little difference in terms of overall
|
||||
# distributable size.
|
||||
#
|
||||
# --minify 0: disables minification of the generated JS code,
|
||||
# regardless of optimization level. Minification of the JS has
|
||||
# minimal overall effect in the larger scheme of things and results
|
||||
# in JS files which can neither be edited nor viewed as text files in
|
||||
# Fossil (which flags them as binary because of their extreme line
|
||||
# lengths). Interestingly, whether or not the comments in the
|
||||
# generated JS file get stripped is unaffected by this setting and
|
||||
# depends entirely on the optimization level. Higher optimization
|
||||
# levels reduce the size of the JS considerably even without
|
||||
# minification.
|
||||
#
|
||||
########################################################################
|
||||
|
||||
+27
-53
@@ -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,6 +362,7 @@ 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
|
||||
@@ -579,17 +579,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 +788,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 +1247,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 +1314,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 +1444,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.
|
||||
@@ -1578,7 +1578,6 @@ 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 \
|
||||
@@ -1586,7 +1585,6 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
$(TOP)\ext\rtree\test_rtreedoc.c \
|
||||
fts5.c
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
@@ -1695,17 +1693,16 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
# <<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_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
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
@@ -1990,9 +1987,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 +2208,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 +2294,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 +2388,7 @@ 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_CKSUMVFS_STATIC=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
@@ -2437,9 +2434,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,20 +2462,10 @@ 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)
|
||||
|
||||
# Runs all the same tests cases as the "tcltest" target but uses
|
||||
# the testrunner.tcl script to run them in multiple cores
|
||||
# concurrently.
|
||||
testrunner: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\testrunner.tcl
|
||||
|
||||
smoketest: $(TESTPROGS)
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
|
||||
@@ -2599,17 +2584,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
|
||||
|
||||
@@ -2647,7 +2621,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,11 +47,11 @@ 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:
|
||||
|
||||
@@ -61,14 +61,14 @@ Then run commands like this:
|
||||
fossil open ~/Fossils/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,6 +285,7 @@ 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
|
||||
@@ -501,12 +502,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 =
|
||||
|
||||
+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:
|
||||
|
||||
@@ -173,6 +173,21 @@ else
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-json1
|
||||
#
|
||||
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
|
||||
[--enable-json1], [include json1 support [default=yes]])],
|
||||
[],[enable_json1=yes])
|
||||
AC_MSG_CHECKING([JSON functions])
|
||||
if test x"$enable_json1" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-rtree
|
||||
#
|
||||
|
||||
+74
-109
@@ -11,6 +11,8 @@
|
||||
#
|
||||
# See the file "license.terms" for information on usage and redistribution
|
||||
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
#
|
||||
# RCS: @(#) $Id: Makefile.in,v 1.59 2005/07/26 19:17:02 mdejong Exp $
|
||||
|
||||
#========================================================================
|
||||
# Add additional lines to handle any additional AC_SUBST cases that
|
||||
@@ -58,8 +60,6 @@ PKG_HEADERS = @PKG_HEADERS@
|
||||
#========================================================================
|
||||
|
||||
PKG_LIB_FILE = @PKG_LIB_FILE@
|
||||
PKG_LIB_FILE8 = @PKG_LIB_FILE8@
|
||||
PKG_LIB_FILE9 = @PKG_LIB_FILE9@
|
||||
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
|
||||
|
||||
lib_BINARIES = $(PKG_LIB_FILE)
|
||||
@@ -73,11 +73,10 @@ exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
datarootdir = @datarootdir@
|
||||
runstatedir = @runstatedir@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
|
||||
DESTDIR =
|
||||
|
||||
@@ -86,25 +85,24 @@ pkgdatadir = $(datadir)/$(PKG_DIR)
|
||||
pkglibdir = $(libdir)/$(PKG_DIR)
|
||||
pkgincludedir = $(includedir)/$(PKG_DIR)
|
||||
|
||||
top_builddir = @abs_top_builddir@
|
||||
top_builddir = .
|
||||
|
||||
INSTALL_OPTIONS =
|
||||
INSTALL = @INSTALL@ $(INSTALL_OPTIONS)
|
||||
INSTALL_DATA_DIR = @INSTALL_DATA_DIR@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_LIBRARY = @INSTALL_LIBRARY@
|
||||
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
CC = @CC@
|
||||
CCLD = @CCLD@
|
||||
CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
|
||||
CFLAGS_WARNING = @CFLAGS_WARNING@
|
||||
CLEANFILES = @CLEANFILES@
|
||||
EXEEXT = @EXEEXT@
|
||||
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
|
||||
MAKE_LIB = @MAKE_LIB@
|
||||
MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
|
||||
MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
|
||||
MAKE_STUB_LIB = @MAKE_STUB_LIB@
|
||||
OBJEXT = @OBJEXT@
|
||||
RANLIB = @RANLIB@
|
||||
@@ -119,6 +117,8 @@ TCL_SRC_DIR = @TCL_SRC_DIR@
|
||||
#TK_BIN_DIR = @TK_BIN_DIR@
|
||||
#TK_SRC_DIR = @TK_SRC_DIR@
|
||||
|
||||
# This is no longer necessary even for packages that use private Tcl headers
|
||||
#TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@
|
||||
# Not used, but retained for reference of what libs Tcl required
|
||||
#TCL_LIBS = @TCL_LIBS@
|
||||
|
||||
@@ -132,52 +132,41 @@ TCL_SRC_DIR = @TCL_SRC_DIR@
|
||||
EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
|
||||
#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
|
||||
TCLLIBPATH = $(top_builddir)
|
||||
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
|
||||
PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
|
||||
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
|
||||
@LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
|
||||
PATH="$(EXTRA_PATH):$(PATH)" \
|
||||
TCLLIBPATH="$(TCLLIBPATH)"
|
||||
# TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
|
||||
|
||||
TCLSH_PROG = @TCLSH_PROG@
|
||||
TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG)
|
||||
TCLSH = $(TCLSH_ENV) $(TCLSH_PROG)
|
||||
|
||||
#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
|
||||
#WISH_PROG = @WISH_PROG@
|
||||
#WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG)
|
||||
#WISH = $(TCLSH_ENV) $(WISH_PROG)
|
||||
|
||||
|
||||
SHARED_BUILD = @SHARED_BUILD@
|
||||
|
||||
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I. -I$(srcdir)/..
|
||||
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(srcdir)/..
|
||||
#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
|
||||
|
||||
PKG_CFLAGS = @PKG_CFLAGS@
|
||||
|
||||
# TCL_DEFS is not strictly need here, but if you remove it, then you
|
||||
# must make sure that configure.ac checks for the necessary components
|
||||
# must make sure that configure.in checks for the necessary components
|
||||
# that your library may use. TCL_DEFS can actually be a problem if
|
||||
# you do not compile with a similar machine setup as the Tcl core was
|
||||
# compiled with.
|
||||
#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
|
||||
DEFS = @DEFS@ $(PKG_CFLAGS)
|
||||
|
||||
# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
|
||||
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
|
||||
CLEANFILES = @CLEANFILES@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LIBS = @PKG_LIBS@ @LIBS@
|
||||
AR = @AR@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \
|
||||
$(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS)
|
||||
|
||||
GDB = gdb
|
||||
VALGRIND = valgrind
|
||||
VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \
|
||||
--leak-check=yes --show-reachable=yes -v
|
||||
|
||||
.SUFFIXES: .c .$(OBJEXT)
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
|
||||
#========================================================================
|
||||
# Start of user-definable TARGETS section
|
||||
@@ -185,7 +174,7 @@ VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \
|
||||
|
||||
#========================================================================
|
||||
# TEA TARGETS. Please note that the "libraries:" target refers to platform
|
||||
# independent files, and the "binaries:" target includes executable programs and
|
||||
# independent files, and the "binaries:" target inclues executable programs and
|
||||
# platform-dependent libraries. Modify these targets so that they install
|
||||
# the various pieces of your package. The make and install rules
|
||||
# for the BINARIES that you specified above have already been done.
|
||||
@@ -204,6 +193,7 @@ binaries: $(BINARIES)
|
||||
|
||||
libraries:
|
||||
|
||||
|
||||
#========================================================================
|
||||
# Your doc target should differentiate from doc builds (by the developer)
|
||||
# and doc installs (see install-doc), which just install the docs on the
|
||||
@@ -226,11 +216,11 @@ install-binaries: binaries install-lib-binaries install-bin-binaries
|
||||
#========================================================================
|
||||
|
||||
install-libraries: libraries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)"
|
||||
@mkdir -p $(DESTDIR)$(includedir)
|
||||
@echo "Installing header files in $(DESTDIR)$(includedir)"
|
||||
@list='$(PKG_HEADERS)'; for i in $$list; do \
|
||||
echo "Installing $(srcdir)/$$i" ; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
|
||||
done;
|
||||
|
||||
#========================================================================
|
||||
@@ -239,11 +229,12 @@ install-libraries: libraries
|
||||
#========================================================================
|
||||
|
||||
install-doc: doc
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann"
|
||||
@mkdir -p $(DESTDIR)$(mandir)/mann
|
||||
@echo "Installing documentation in $(DESTDIR)$(mandir)"
|
||||
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
|
||||
echo "Installing $$i"; \
|
||||
$(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \
|
||||
rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
|
||||
$(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
|
||||
done
|
||||
|
||||
test: binaries libraries
|
||||
@@ -253,21 +244,7 @@ shell: binaries libraries
|
||||
@$(TCLSH) $(SCRIPT)
|
||||
|
||||
gdb:
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT)
|
||||
|
||||
gdb-test: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(GDB) \
|
||||
--args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \
|
||||
$(TESTFLAGS) -singleproc 1 \
|
||||
-load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
|
||||
[list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]"
|
||||
|
||||
valgrind: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \
|
||||
`@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
|
||||
|
||||
valgrindshell: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
|
||||
$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
|
||||
|
||||
depend:
|
||||
|
||||
@@ -306,70 +283,49 @@ $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
|
||||
# As necessary, add $(srcdir):$(srcdir)/compat:....
|
||||
#========================================================================
|
||||
|
||||
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx
|
||||
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
|
||||
|
||||
.c.@OBJEXT@:
|
||||
$(COMPILE) -c `@CYGPATH@ $<` -o $@
|
||||
|
||||
tclsample.@OBJEXT@: sampleUuid.h
|
||||
|
||||
$(srcdir)/manifest.uuid:
|
||||
printf "git-" >$(srcdir)/manifest.uuid
|
||||
(cd $(srcdir); git rev-parse HEAD >>$(srcdir)/manifest.uuid || \
|
||||
(printf "svn-r" >$(srcdir)/manifest.uuid ; \
|
||||
svn info --show-item last-changed-revision >>$(srcdir)/manifest.uuid) || \
|
||||
printf "unknown" >$(srcdir)/manifest.uuid)
|
||||
|
||||
sampleUuid.h: $(srcdir)/manifest.uuid
|
||||
echo "#define SAMPLE_VERSION_UUID \\" >$@
|
||||
cat $(srcdir)/manifest.uuid >>$@
|
||||
echo "" >>$@
|
||||
|
||||
#========================================================================
|
||||
# Distribution creation
|
||||
# You may need to tweak this target to make it work correctly.
|
||||
#========================================================================
|
||||
|
||||
#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
|
||||
COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
|
||||
COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
|
||||
DIST_ROOT = /tmp/dist
|
||||
DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
|
||||
|
||||
DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644
|
||||
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755
|
||||
|
||||
dist-clean:
|
||||
rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
|
||||
|
||||
dist: dist-clean $(srcdir)/manifest.uuid
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)
|
||||
dist: dist-clean
|
||||
mkdir -p $(DIST_DIR)
|
||||
cp -p $(srcdir)/README* $(srcdir)/license* \
|
||||
$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
|
||||
$(DIST_DIR)/
|
||||
chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
|
||||
chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
|
||||
|
||||
# TEA files
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \
|
||||
$(srcdir)/aclocal.m4 $(srcdir)/configure.ac \
|
||||
$(DIST_DIR)/
|
||||
$(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/
|
||||
for i in $(srcdir)/*.[ch]; do \
|
||||
if [ -f $$i ]; then \
|
||||
cp -p $$i $(DIST_DIR)/ ; \
|
||||
fi; \
|
||||
done;
|
||||
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \
|
||||
$(srcdir)/manifest.uuid \
|
||||
$(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \
|
||||
$(DIST_DIR)/tclconfig/
|
||||
mkdir $(DIST_DIR)/tclconfig
|
||||
cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
|
||||
$(DIST_DIR)/tclconfig/
|
||||
chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
|
||||
chmod +x $(DIST_DIR)/tclconfig/install-sh
|
||||
|
||||
# Extension files
|
||||
$(DIST_INSTALL_DATA) \
|
||||
$(srcdir)/ChangeLog \
|
||||
$(srcdir)/README.sha \
|
||||
$(srcdir)/license.terms \
|
||||
$(srcdir)/README \
|
||||
$(srcdir)/pkgIndex.tcl.in \
|
||||
$(DIST_DIR)/
|
||||
|
||||
list='demos doc generic library macosx tests unix win'; \
|
||||
list='demos doc generic library mac tests unix win'; \
|
||||
for p in $$list; do \
|
||||
if test -d $(srcdir)/$$p ; then \
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \
|
||||
mkdir $(DIST_DIR)/$$p; \
|
||||
cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
@@ -381,10 +337,10 @@ dist: dist-clean $(srcdir)/manifest.uuid
|
||||
|
||||
#========================================================================
|
||||
# Don't modify the file to clean here. Instead, set the "CLEANFILES"
|
||||
# variable in configure.ac
|
||||
# variable in configure.in
|
||||
#========================================================================
|
||||
|
||||
clean:
|
||||
clean:
|
||||
-test -z "$(BINARIES)" || rm -f $(BINARIES)
|
||||
-rm -f *.$(OBJEXT) core *.core
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
@@ -392,7 +348,7 @@ clean:
|
||||
distclean: clean
|
||||
-rm -f *.tab.c
|
||||
-rm -f $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log config.status
|
||||
-rm -f config.h config.cache config.log config.status
|
||||
|
||||
#========================================================================
|
||||
# Install binary object libraries. On Windows this includes both .dll and
|
||||
@@ -406,17 +362,25 @@ distclean: clean
|
||||
#========================================================================
|
||||
|
||||
install-lib-binaries: binaries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)"
|
||||
@mkdir -p $(DESTDIR)$(pkglibdir)
|
||||
@list='$(lib_BINARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
|
||||
if test "x$$stub" = "xstub"; then \
|
||||
echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
else \
|
||||
echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
fi; \
|
||||
ext=`echo $$p|sed -e "s/.*\.//"`; \
|
||||
if test "x$$ext" = "xdll"; then \
|
||||
lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
|
||||
if test -f $$lib; then \
|
||||
echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
|
||||
$(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \
|
||||
$(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
|
||||
fi; \
|
||||
fi; \
|
||||
fi; \
|
||||
@@ -425,12 +389,12 @@ install-lib-binaries: binaries
|
||||
if test -f $(srcdir)/$$p; then \
|
||||
destp=`basename $$p`; \
|
||||
echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
|
||||
fi; \
|
||||
done
|
||||
@if test "x$(SHARED_BUILD)" = "x1"; then \
|
||||
echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
|
||||
$(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \
|
||||
$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
|
||||
fi
|
||||
|
||||
#========================================================================
|
||||
@@ -443,32 +407,33 @@ install-lib-binaries: binaries
|
||||
#========================================================================
|
||||
|
||||
install-bin-binaries: binaries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)"
|
||||
@mkdir -p $(DESTDIR)$(bindir)
|
||||
@list='$(bin_BINARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
|
||||
$(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.SUFFIXES: .c .$(OBJEXT)
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
uninstall-binaries:
|
||||
list='$(lib_BINARIES)'; for p in $$list; do \
|
||||
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
done
|
||||
list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
|
||||
p=`basename $$p`; \
|
||||
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
done
|
||||
list='$(bin_BINARIES)'; for p in $$list; do \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$p"; \
|
||||
rm -f $(DESTDIR)$(bindir)/$$p; \
|
||||
done
|
||||
|
||||
.PHONY: all binaries clean depend distclean doc install libraries test
|
||||
.PHONY: gdb gdb-test valgrind valgrindshell
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
||||
+34
-60
@@ -2,9 +2,11 @@
|
||||
dnl This file is an input file used by the GNU "autoconf" program to
|
||||
dnl generate the file "configure", which is run during Tcl installation
|
||||
dnl to configure the system for the local environment.
|
||||
#
|
||||
# RCS: @(#) $Id: configure.in,v 1.43 2005/07/26 19:17:05 mdejong Exp $
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Sample configure.ac for Tcl Extensions. The only places you should
|
||||
# Sample configure.in for Tcl Extensions. The only places you should
|
||||
# need to modify this file are marked by the string __CHANGE__
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
@@ -15,11 +17,9 @@ dnl to configure the system for the local environment.
|
||||
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
|
||||
# set as provided. These will also be added as -D defs in your Makefile
|
||||
# so you can encode the package version directly into the source files.
|
||||
# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.40.0])
|
||||
AC_INIT([sqlite], [3.32.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
@@ -27,7 +27,7 @@ AC_INIT([sqlite],[3.40.0])
|
||||
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_INIT()
|
||||
TEA_INIT([3.9])
|
||||
|
||||
AC_CONFIG_AUX_DIR(tclconfig)
|
||||
|
||||
@@ -55,8 +55,8 @@ TEA_PREFIX
|
||||
#-----------------------------------------------------------------------
|
||||
# Standard compiler checks.
|
||||
# This sets up CC by using the CC env var, or looks for gcc otherwise.
|
||||
# This also calls AC_PROG_CC and a few others to create the basic setup
|
||||
# necessary to compile executables.
|
||||
# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
|
||||
# the basic setup necessary to compile executables.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
TEA_SETUP_COMPILER
|
||||
@@ -73,19 +73,11 @@ TEA_SETUP_COMPILER
|
||||
|
||||
TEA_ADD_SOURCES([tclsqlite3.c])
|
||||
TEA_ADD_HEADERS([])
|
||||
TEA_ADD_INCLUDES([])
|
||||
TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}/generic`\"])
|
||||
TEA_ADD_LIBS([])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS4=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS5=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_GEOPOLY=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_MATH_FUNCTIONS=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DESERIALIZE=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBPAGE_VTAB=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_BYTECODE_VTAB=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBSTAT_VTAB=1])
|
||||
TEA_ADD_STUB_SOURCES([])
|
||||
TEA_ADD_TCL_SOURCES([])
|
||||
|
||||
@@ -107,31 +99,6 @@ if test x$with_system_sqlite != xno; then
|
||||
LIBS="$LIBS -lsqlite3"])])
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
#
|
||||
# You can add more files to clean if your extension creates any extra
|
||||
# files by extending CLEANFILES.
|
||||
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
|
||||
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
|
||||
#
|
||||
# A few miscellaneous platform-specific items:
|
||||
# TEA_ADD_* any platform specific compiler/build info here.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
#CLEANFILES="$CLEANFILES pkgIndex.tcl"
|
||||
if test "${TEA_PLATFORM}" = "windows" ; then
|
||||
# Ensure no empty if clauses
|
||||
:
|
||||
#TEA_ADD_SOURCES([win/winFile.c])
|
||||
#TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
|
||||
else
|
||||
# Ensure no empty else clauses
|
||||
:
|
||||
#TEA_ADD_SOURCES([unix/unixFile.c])
|
||||
#TEA_ADD_LIBS([-lsuperfly])
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
# Choose which headers you need. Extension authors should try very
|
||||
@@ -184,6 +151,28 @@ TEA_CONFIG_CFLAGS
|
||||
|
||||
TEA_ENABLE_SYMBOLS
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Everyone should be linking against the Tcl stub library. If you
|
||||
# can't for some reason, remove this definition. If you aren't using
|
||||
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
|
||||
# link against the non-stubbed Tcl library. Add Tk too if necessary.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
|
||||
#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Redefine fdatasync as fsync on systems that lack fdatasync
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync))
|
||||
# Check for library functions that SQLite can optionally use.
|
||||
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
|
||||
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# This macro generates a line to use when building a library. It
|
||||
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
|
||||
@@ -204,24 +193,9 @@ TEA_PROG_TCLSH
|
||||
#TEA_PROG_WISH
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Setup a *Config.sh.in configuration file.
|
||||
# Finally, substitute all of the various values into the Makefile.
|
||||
# You may alternatively have a special pkgIndex.tcl.in or other files
|
||||
# which require substituting th AC variables in. Include these here.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
#TEA_EXPORT_CONFIG([sample])
|
||||
#AC_SUBST(SAMPLE_VAR)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Specify files to substitute AC variables in. You may alternatively
|
||||
# have a special pkgIndex.tcl.in or other files which require
|
||||
# substituting the AC variables in. Include these here.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_CONFIG_FILES([Makefile pkgIndex.tcl])
|
||||
#AC_CONFIG_FILES([sampleConfig.sh])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Finally, substitute all of the various values into the files
|
||||
# specified with AC_CONFIG_FILES.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_OUTPUT
|
||||
AC_OUTPUT([Makefile pkgIndex.tcl])
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
# -*- tcl -*-
|
||||
# Tcl package index file, version 1.1
|
||||
#
|
||||
if {[package vsatisfies [package provide Tcl] 9.0-]} {
|
||||
package ifneeded sqlite3 @PACKAGE_VERSION@ \
|
||||
[list load [file join $dir @PKG_LIB_FILE9@] sqlite3]
|
||||
} else {
|
||||
package ifneeded sqlite3 @PACKAGE_VERSION@ \
|
||||
[list load [file join $dir @PKG_LIB_FILE8@] sqlite3]
|
||||
}
|
||||
# Tcl package index file
|
||||
#
|
||||
# Note sqlite*3* init specifically
|
||||
#
|
||||
package ifneeded sqlite3 @PACKAGE_VERSION@ \
|
||||
[list load [file join $dir @PKG_LIB_FILE@] Sqlite3]
|
||||
|
||||
+628
-527
File diff suppressed because it is too large
Load Diff
@@ -251,18 +251,7 @@ INCLUDES = $(SQL_INCLUDES) $(TCL_INCLUDES) -I"$(WINDIR)" \
|
||||
-I"$(GENERICDIR)" -I"$(ROOT)\.."
|
||||
BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \
|
||||
-DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
|
||||
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1 \
|
||||
-DSQLITE_ENABLE_FTS4=1 \
|
||||
-DSQLITE_ENABLE_FTS5=1 \
|
||||
-DSQLITE_3_SUFFIX_ONLY=1 \
|
||||
-DSQLITE_ENABLE_RTREE=1 \
|
||||
-DSQLITE_ENABLE_GEOPOLY=1 \
|
||||
-DSQLITE_ENABLE_MATH_FUNCTIONS=1 \
|
||||
-DSQLITE_ENABLE_DESERIALIZE=1 \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB=1 \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB=1 \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
|
||||
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
|
||||
CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE -DSQLITE_ENABLE_FTS3=1
|
||||
TCL_CFLAGS = -DBUILD_sqlite -DUSE_TCL_STUBS \
|
||||
-DPACKAGE_VERSION="\"$(DOTVERSION)\"" $(BASE_CLFAGS) \
|
||||
|
||||
+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.40.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.36.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.40.0'
|
||||
PACKAGE_STRING='sqlite 3.40.0'
|
||||
PACKAGE_VERSION='3.36.0'
|
||||
PACKAGE_STRING='sqlite 3.36.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_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.40.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.36.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.40.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.36.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-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
|
||||
--enable-memsys5 Enable MEMSYS5
|
||||
--enable-memsys3 Enable MEMSYS3
|
||||
--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.40.0
|
||||
sqlite configure 3.36.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.40.0, which was
|
||||
It was created by sqlite $as_me 3.36.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
|
||||
@@ -11497,24 +11496,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
|
||||
@@ -11719,6 +11700,24 @@ else
|
||||
$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
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON" >&5
|
||||
$as_echo_n "checking whether to support JSON... " >&6; }
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
{ $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
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
@@ -11861,17 +11860,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 +12378,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.40.0, which was
|
||||
This file was extended by sqlite $as_me 3.36.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12456,7 +12444,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.40.0
|
||||
sqlite config.status 3.36.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+12
-24
@@ -605,24 +605,12 @@ 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]))
|
||||
[Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
|
||||
|
||||
##########
|
||||
# Do we want to support memsys3 and/or memsys5
|
||||
@@ -678,6 +666,17 @@ 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]))
|
||||
AC_MSG_CHECKING([whether to support JSON])
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
@@ -792,17 +791,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.
|
||||
+2
-12
@@ -196,7 +196,7 @@ do_setup_rec_test $tn.9.1 {
|
||||
} {
|
||||
SELECT * FROM "t t" WHERE a=?
|
||||
} {
|
||||
CREATE INDEX "t t_idx_00000061" ON "t t"(a);
|
||||
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
|
||||
SEARCH t t USING INDEX t t_idx_00000061 (a=?)
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ 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);
|
||||
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
|
||||
SEARCH t t USING INDEX t t_idx_00000062 (b>? AND b<?)
|
||||
}
|
||||
|
||||
@@ -391,16 +391,6 @@ do_setup_rec_test $tn.18.1 {
|
||||
SEARCH SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
|
||||
}
|
||||
|
||||
|
||||
do_setup_rec_test $tn.19.0 {
|
||||
CREATE TABLE t1("index");
|
||||
} {
|
||||
SELECT * FROM t1 ORDER BY "index";
|
||||
} {
|
||||
CREATE INDEX t1_idx_01a7214e ON t1('index');
|
||||
SCAN t1 USING COVERING INDEX t1_idx_01a7214e
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc do_candidates_test {tn sql res} {
|
||||
|
||||
+26
-112
@@ -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;
|
||||
@@ -820,10 +789,6 @@ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
|
||||
*/
|
||||
static int idxIdentifierRequiresQuotes(const char *zId){
|
||||
int i;
|
||||
int nId = STRLEN(zId);
|
||||
|
||||
if( sqlite3_keyword_check(zId, nId) ) return 1;
|
||||
|
||||
for(i=0; zId[i]; i++){
|
||||
if( !(zId[i]=='_')
|
||||
&& !(zId[i]>='0' && zId[i]<='9')
|
||||
@@ -900,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;
|
||||
@@ -946,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,
|
||||
@@ -985,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)";
|
||||
}
|
||||
@@ -1027,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);
|
||||
@@ -1183,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) */
|
||||
){
|
||||
@@ -1312,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);
|
||||
@@ -1415,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);
|
||||
@@ -1554,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 ){
|
||||
@@ -1566,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;
|
||||
}
|
||||
@@ -1781,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;
|
||||
@@ -1848,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);
|
||||
}
|
||||
@@ -1961,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 */
|
||||
|
||||
+33
-44
@@ -308,17 +308,18 @@
|
||||
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
|
||||
@@ -1178,7 +1179,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 */
|
||||
@@ -4013,12 +4014,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 +4046,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 +4074,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 +4099,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4111,26 +4108,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 +4133,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;
|
||||
@@ -4308,7 +4302,8 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
char *aPoslist = 0; /* Position list for deferred tokens */
|
||||
int nPoslist = 0; /* Number of bytes in aPoslist */
|
||||
int iPrev = -1; /* Token number of previous deferred token */
|
||||
char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0);
|
||||
|
||||
assert( pPhrase->doclist.bFreeList==0 );
|
||||
|
||||
for(iToken=0; iToken<pPhrase->nToken; iToken++){
|
||||
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
|
||||
@@ -4322,7 +4317,6 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
|
||||
if( pList==0 ){
|
||||
sqlite3_free(aPoslist);
|
||||
sqlite3_free(aFree);
|
||||
pPhrase->doclist.pList = 0;
|
||||
pPhrase->doclist.nList = 0;
|
||||
return SQLITE_OK;
|
||||
@@ -4343,7 +4337,6 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
nPoslist = (int)(aOut - aPoslist);
|
||||
if( nPoslist==0 ){
|
||||
sqlite3_free(aPoslist);
|
||||
sqlite3_free(aFree);
|
||||
pPhrase->doclist.pList = 0;
|
||||
pPhrase->doclist.nList = 0;
|
||||
return SQLITE_OK;
|
||||
@@ -4376,14 +4369,13 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
nDistance = iPrev - nMaxUndeferred;
|
||||
}
|
||||
|
||||
aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
|
||||
aOut = (char *)sqlite3_malloc(nPoslist+8);
|
||||
if( !aOut ){
|
||||
sqlite3_free(aPoslist);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
pPhrase->doclist.pList = aOut;
|
||||
assert( p1 && p2 );
|
||||
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
|
||||
pPhrase->doclist.bFreeList = 1;
|
||||
pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
|
||||
@@ -4396,7 +4388,6 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
}
|
||||
}
|
||||
|
||||
if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
|
||||
@@ -4489,7 +4480,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 ){
|
||||
@@ -5353,8 +5344,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);
|
||||
@@ -5571,10 +5562,11 @@ static int fts3EvalTestExpr(
|
||||
|
||||
default: {
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
if( pCsr->pDeferred && (pExpr->bDeferred || (
|
||||
pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
|
||||
))){
|
||||
if( pCsr->pDeferred
|
||||
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
|
||||
){
|
||||
Fts3Phrase *pPhrase = pExpr->pPhrase;
|
||||
assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
|
||||
if( pExpr->bDeferred ){
|
||||
fts3EvalInvalidatePoslist(pPhrase);
|
||||
}
|
||||
@@ -5991,9 +5983,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 ){
|
||||
|
||||
+11
-13
@@ -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
-5
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -637,7 +637,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 +671,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;
|
||||
|
||||
+12
-11
@@ -138,8 +138,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);
|
||||
@@ -543,10 +544,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 +1112,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 +1149,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++){
|
||||
@@ -1611,7 +1612,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 +1633,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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+11
-26
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -3899,8 +3891,6 @@ static int fts3IncrmergePush(
|
||||
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
|
||||
}
|
||||
pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
|
||||
assert( nPrefix+nSuffix<=nTerm );
|
||||
assert( nPrefix>=0 );
|
||||
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
|
||||
pBlk->n += nSuffix;
|
||||
|
||||
@@ -4023,7 +4013,6 @@ static int fts3IncrmergeAppend(
|
||||
pLeaf = &pWriter->aNodeWriter[0];
|
||||
nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
|
||||
nSuffix = nTerm - nPrefix;
|
||||
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
nSpace = sqlite3Fts3VarintLen(nPrefix);
|
||||
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
|
||||
@@ -4188,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;
|
||||
@@ -4836,7 +4821,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
|
||||
+4
-19
@@ -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. */
|
||||
@@ -286,7 +274,7 @@ void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
|
||||
char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
|
||||
|
||||
#define fts5BufferZero(x) sqlite3Fts5BufferZero(x)
|
||||
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,(i64)c)
|
||||
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
|
||||
#define fts5BufferFree(a) sqlite3Fts5BufferFree(a)
|
||||
#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
|
||||
#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d)
|
||||
@@ -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(
|
||||
|
||||
@@ -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
-20
@@ -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;
|
||||
}
|
||||
@@ -2859,15 +2858,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 +2867,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;
|
||||
|
||||
+47
-134
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2164,7 +2101,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 +2128,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 +2159,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 +2167,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fts5SegIterReverseInitPage(p, pIter);
|
||||
@@ -2285,20 +2219,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 +2299,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 +2675,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 +3107,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 +3183,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 +3331,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 +3402,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 +3466,6 @@ static void fts5MultiIterNew(
|
||||
fts5MultiIterFree(pNew);
|
||||
*ppOut = 0;
|
||||
}
|
||||
|
||||
fts5MultiIterNew_post_check:
|
||||
assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3590,8 +3513,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);
|
||||
@@ -4087,9 +4009,7 @@ static void fts5WriteAppendRowid(
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
|
||||
}else{
|
||||
assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf,
|
||||
(u64)iRowid - (u64)pWriter->iPrevRowid
|
||||
);
|
||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
|
||||
}
|
||||
pWriter->iPrevRowid = iRowid;
|
||||
pWriter->bFirstRowidInDoclist = 0;
|
||||
@@ -4397,7 +4317,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;
|
||||
|
||||
@@ -4498,7 +4417,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 */
|
||||
@@ -4853,7 +4772,7 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
|
||||
|
||||
static void fts5AppendRowid(
|
||||
Fts5Index *p,
|
||||
u64 iDelta,
|
||||
i64 iDelta,
|
||||
Fts5Iter *pUnused,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
@@ -4863,7 +4782,7 @@ static void fts5AppendRowid(
|
||||
|
||||
static void fts5AppendPoslist(
|
||||
Fts5Index *p,
|
||||
u64 iDelta,
|
||||
i64 iDelta,
|
||||
Fts5Iter *pMulti,
|
||||
Fts5Buffer *pBuf
|
||||
){
|
||||
@@ -4938,10 +4857,10 @@ static void fts5MergeAppendDocid(
|
||||
}
|
||||
#endif
|
||||
|
||||
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
|
||||
assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
|
||||
fts5BufferSafeAppendVarint((pBuf), (u64)(iRowid) - (u64)(iLastRowid)); \
|
||||
(iLastRowid) = (iRowid); \
|
||||
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
|
||||
assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
|
||||
fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
|
||||
(iLastRowid) = (iRowid); \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5060,7 +4979,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;
|
||||
@@ -5212,7 +5131,7 @@ static void fts5SetupPrefixIter(
|
||||
int nMerge = 1;
|
||||
|
||||
void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
|
||||
void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
|
||||
void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
|
||||
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
xMerge = fts5MergeRowidLists;
|
||||
xAppend = fts5AppendRowid;
|
||||
@@ -5251,7 +5170,7 @@ static void fts5SetupPrefixIter(
|
||||
Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
|
||||
p1->xSetOutputs(p1, pSeg);
|
||||
if( p1->base.nData ){
|
||||
xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
|
||||
xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
|
||||
iLastRowid = p1->base.iRowid;
|
||||
}
|
||||
}
|
||||
@@ -5299,7 +5218,7 @@ static void fts5SetupPrefixIter(
|
||||
iLastRowid = 0;
|
||||
}
|
||||
|
||||
xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
|
||||
xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
|
||||
iLastRowid = p1->base.iRowid;
|
||||
}
|
||||
|
||||
@@ -5567,7 +5486,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
|
||||
@@ -5608,15 +5527,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5864,7 +5779,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 ){
|
||||
@@ -6229,7 +6144,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 */
|
||||
@@ -6240,16 +6154,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -804,7 +804,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 +1374,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+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
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
# TESTRUNNER: slow
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ah
|
||||
|
||||
@@ -14791,7 +14791,7 @@ do_test 75.0 {
|
||||
|
||||
do_catchsql_test 75.1 {
|
||||
SELECT rowid, quote(matchinfo(t1,'pcxybs')) FROM t1 WHERE t1 MATCH 'e*';
|
||||
} {1 {unable to use function matchinfo in the requested context}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -14922,603 +14922,6 @@ do_catchsql_test 76.1 {
|
||||
SELECT * FROM t4;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 77.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 24576 pagesize 4096 filename crash-53216796d7c3d8.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 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 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 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 ad ...~.H..........
|
||||
| 96: 0a 8c 0a 6d 00 00 00 00 00 00 00 00 00 00 00 00 ...m............
|
||||
| 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 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: 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 02 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 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........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: 02 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 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 0d 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 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 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: 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 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 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 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 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 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 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 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 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 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 03 .V.M.A.8./.&....
|
||||
| 64: 0f 0a 0f 00 9e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
|
||||
| 80: 0e c3 00 00 00 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 18 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 0f 01 02 31 6e 12 0a ...1t.......1n..
|
||||
| 3888: d4 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: 04 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 07 04 09 10 01 32 69 14 07 04 09 10 01 32 66 ......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 07 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
|
||||
| 4080: 06 08 04 09 1e 61 30 66 74 04 05 04 09 0c 01 02 .....a0ft.......
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 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 da 03 02 02 01 02 00 00 00 00 ................
|
||||
| end crash-53216796d7c3d8.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 77.1 {
|
||||
UPDATE t1 SET B =quote(zeroblob(200)) WHERE b MATCH 'threa*thrad*tlrad*the�d';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 78.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a,b,c);
|
||||
DELETE FROM t1_data;
|
||||
INSERT INTO t1_data VALUES(1,X'245a2424');
|
||||
INSERT INTO t1_data VALUES(10,X'000000000101010001010101');
|
||||
INSERT INTO t1_data VALUES(137438953473,X'0000032b0230300102060102060102061f0203010203010203010832303136303630390102070102070102070101340102050102050102050101350102040102040102040207303030303030301c0204010204010204010662696e6172790306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020108636f6d70696c657201200102020201020201066462737ccccccccccccccccccccccccccccccccccccccccccccbccccccccccccccccccccccccccccccccccccccccccccccca2cccccccccc461740702030102030102030204656275670402020102020102020106656e61626c6507020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020523d6763632d352e342e30203230313630363039584e4f4341534526010500430f17434f4d50494c45523d6763632d352e342e3020323031363036303958525452494d0d000000240ee00004a810000fe80fe00fd80fd00fc80fc00fb80fb00fa80fa00f980f900f880f800f780f700f680f60945736502060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020201046f6d59741f0202010202010202010572747265651945030102030102030402696d010601020203060102020306010202030601120203060102020306010202030601020203060102020306010202030601020203060102020306010202010a7468726561647361666522020201020201020201047674616207020401020401020401407801060cb102010601010201060101020106010102010601010201060101020106010102010601010201060e0102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101021106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601011201060101020106010102010601010201060101020106010102041513020c124413110f47130f0c0e11100f0e100f440f1040150f');
|
||||
}
|
||||
|
||||
do_execsql_test 78.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col');
|
||||
}
|
||||
|
||||
do_execsql_test 78.2 {
|
||||
SELECT count(rowid) FROM t3 WHERE term>='nsocse';
|
||||
} 2
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 79.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 28672 pagesize 4096 filename sql053282.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 07 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 06 0d b6 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d b5 00 00 00 00 00 00 ...k............
|
||||
| 3504: 00 00 00 00 00 00 56 07 06 17 1f 1f 01 7d 74 61 ......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 01 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 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: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 12 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 0a 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 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 01 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 05 f1 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 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 01 06 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: 01 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 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 00 00 00 00 00 .......h.O......
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 45 3d ..%..THREADSAFE=
|
||||
| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 2c 00000XRTRIM....,
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4c 45 20 4d 45 4d 5a 69 53 35 58 42 49 NABLE MEMZiS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 E MEMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 NABLE GEOPOLYXBI
|
||||
| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45 E GEOPOLYXNOCASE
|
||||
| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE
|
||||
| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 3f d8 .#..ENABLE FTS?.
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 55 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e UAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d TAT VTABXNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 46 CASE.......DEBUF
|
||||
| 3968: e8 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d .RTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 62 63 2d 35 2e 34 2e OMPILER=gbc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f bb 1f a8 0f a0 ................
|
||||
| 32: 0f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 00 00 00 00 .X.P.H.@.8.0....
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 0a 83 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| 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 sql053282.txt.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 79.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5vocab('t1','row');
|
||||
}
|
||||
|
||||
do_catchsql_test 79.2 {
|
||||
INSERT INTO t1(t1) SELECT 'merge' FROM t2;
|
||||
} {1 {query aborted}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 80.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 40960 pagesize 4096 filename crash-f928a9c1ec68dd.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 0a .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c ..........n....L
|
||||
| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
|
||||
| 128: 0b f8 0b b3 0b 6e 00 00 00 00 00 00 00 00 00 00 .....n..........
|
||||
| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
|
||||
| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
|
||||
| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
|
||||
| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
|
||||
| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
|
||||
| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
|
||||
| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
|
||||
| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
|
||||
| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
|
||||
| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
|
||||
| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
|
||||
| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
|
||||
| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
|
||||
| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
|
||||
| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
|
||||
| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
|
||||
| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
|
||||
| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
|
||||
| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
|
||||
| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
|
||||
| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
|
||||
| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
|
||||
| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
|
||||
| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
|
||||
| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
|
||||
| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
|
||||
| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
|
||||
| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
|
||||
| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
|
||||
| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
|
||||
| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
|
||||
| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
|
||||
| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
|
||||
| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
|
||||
| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
|
||||
| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
|
||||
| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
|
||||
| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
|
||||
| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
|
||||
| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
|
||||
| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
|
||||
| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
|
||||
| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
|
||||
| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
|
||||
| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
|
||||
| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
|
||||
| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
|
||||
| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
|
||||
| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
|
||||
| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
|
||||
| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
|
||||
| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
|
||||
| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
|
||||
| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
|
||||
| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
|
||||
| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
|
||||
| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
|
||||
| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
|
||||
| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
|
||||
| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
|
||||
| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
|
||||
| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
|
||||
| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
|
||||
| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
|
||||
| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
|
||||
| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
|
||||
| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
|
||||
| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
|
||||
| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
|
||||
| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
|
||||
| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 6e NG fts5(a,b unin
|
||||
| 4064: 64 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 dexed,c,tokenize
|
||||
| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
|
||||
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
|
||||
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
|
||||
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
|
||||
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
|
||||
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
|
||||
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
|
||||
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
|
||||
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
|
||||
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
|
||||
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
|
||||
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 80 01 03 ........7.......
|
||||
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
|
||||
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
|
||||
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
|
||||
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
|
||||
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
|
||||
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
|
||||
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 01 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 7 offset 24576
|
||||
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 00 00 00 00 ................
|
||||
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
|
||||
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
|
||||
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
|
||||
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
|
||||
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
|
||||
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 8 offset 28672
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 12 ................
|
||||
| page 9 offset 32768
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 10 offset 36864
|
||||
| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 00 00 00 00 ........vers....
|
||||
| end crash-f928a9c1ec68dd.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 80.1 {
|
||||
SELECT snippet(rowid, -1, '.', '..', '[', '(]'),snippet(rowid, -1, '.', '.', '', '(]'), highlight(t1, 29, 1 , '') FROM t1('g+ h') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY NOT (SELECT 1 FROM t1('g+ æ') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY rank);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,16 +16,12 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5fault4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set ::TMPDBERROR [list 1 \
|
||||
{unable to open a temporary database file for storing temporary tables}
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# An OOM while dropping an fts5 table.
|
||||
#
|
||||
@@ -395,7 +391,7 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
|
||||
} -body {
|
||||
db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} $::TMPDBERROR
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# 2022 August 9
|
||||
#
|
||||
# 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 test is focused on edge cases that cause ubsan errors.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ubsan
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
}
|
||||
|
||||
set BIG 9000000000000000000
|
||||
set SMALL -9000000000000000000
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
BEGIN;
|
||||
INSERT INTO x1 (rowid, x) VALUES($BIG, 'aaa aba acc');
|
||||
INSERT INTO x1 (rowid, x) VALUES($SMALL, 'aaa abc acb');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid, x FROM x1('ab*');
|
||||
} [list $SMALL {aaa abc acb} $BIG {aaa aba acc}]
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT rowid, x FROM x1('ac*');
|
||||
} [list $SMALL {aaa abc acb} $BIG {aaa aba acc}]
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO x1 (rowid, x) VALUES($BIG, 'aaa aba acc');
|
||||
INSERT INTO x1 (rowid, x) VALUES($SMALL, 'aaa abc acb');
|
||||
}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
INSERT INTO x1 (x1) VALUES('optimize');
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -657,7 +657,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
-1
@@ -823,7 +823,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 +870,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();
|
||||
}
|
||||
|
||||
+2
-9
@@ -280,7 +280,6 @@ static char *csv_read_one_field(CsvReader *p){
|
||||
}
|
||||
p->cTerm = (char)c;
|
||||
}
|
||||
assert( p->z==0 || p->n<p->nAlloc );
|
||||
if( p->z ) p->z[p->n] = 0;
|
||||
p->bNotFirst = 1;
|
||||
return p->z;
|
||||
@@ -751,7 +750,7 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
|
||||
i++;
|
||||
}
|
||||
}while( pCur->rdr.cTerm==',' );
|
||||
if( z==0 && i==0 ){
|
||||
if( z==0 || (pCur->rdr.cTerm==EOF && i<pTab->nCol) ){
|
||||
pCur->iRowid = -1;
|
||||
}else{
|
||||
pCur->iRowid++;
|
||||
@@ -812,12 +811,6 @@ static int csvtabFilter(
|
||||
CsvCursor *pCur = (CsvCursor*)pVtabCursor;
|
||||
CsvTable *pTab = (CsvTable*)pVtabCursor->pVtab;
|
||||
pCur->iRowid = 0;
|
||||
|
||||
/* Ensure the field buffer is always allocated. Otherwise, if the
|
||||
** first field is zero bytes in size, this may be mistaken for an OOM
|
||||
** error in csvtabNext(). */
|
||||
if( csv_append(&pCur->rdr, 0) ) return SQLITE_NOMEM;
|
||||
|
||||
if( pCur->rdr.in==0 ){
|
||||
assert( pCur->rdr.zIn==pTab->zData );
|
||||
assert( pTab->iStart>=0 );
|
||||
@@ -948,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);
|
||||
|
||||
+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
-6
@@ -194,11 +194,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 +280,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);
|
||||
|
||||
+217
-284
@@ -10,10 +10,10 @@
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite JSON functions.
|
||||
** This SQLite extension implements JSON functions. The interface is
|
||||
** modeled after MySQL JSON functions:
|
||||
**
|
||||
** This file began as an extension in ext/misc/json1.c in 2015. That
|
||||
** extension proved so useful that it has now been moved into the core.
|
||||
** https://dev.mysql.com/doc/refman/5.7/en/json.html
|
||||
**
|
||||
** For the time being, all JSON is stored as pure text. (We might add
|
||||
** a JSONB type in the future which stores a binary encoding of JSON in
|
||||
@@ -21,8 +21,48 @@
|
||||
** This implementation parses JSON text at 250 MB/s, so it is hard to see
|
||||
** how JSONB might improve on that.)
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_JSON
|
||||
#include "sqliteInt.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Mark a function parameter as unused, to suppress nuisance compiler
|
||||
** warnings. */
|
||||
#ifndef UNUSED_PARAM
|
||||
# define UNUSED_PARAM(X) (void)(X)
|
||||
#endif
|
||||
|
||||
#ifndef LARGEST_INT64
|
||||
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
|
||||
#endif
|
||||
|
||||
#ifndef deliberate_fall_through
|
||||
# define deliberate_fall_through
|
||||
#endif
|
||||
|
||||
/*
|
||||
** 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 */
|
||||
# define safe_isdigit(x) sqlite3Isdigit(x)
|
||||
# define safe_isalnum(x) sqlite3Isalnum(x)
|
||||
# define safe_isxdigit(x) sqlite3Isxdigit(x)
|
||||
#else
|
||||
/* Use the standard library for separate compilation */
|
||||
#include <ctype.h> /* amalgamator: keep */
|
||||
# define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
# define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
@@ -47,12 +87,15 @@ static const char jsonIsSpace[] = {
|
||||
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) (jsonIsSpace[(unsigned char)x])
|
||||
#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
|
||||
|
||||
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST)
|
||||
# define VVA(X)
|
||||
#else
|
||||
# define VVA(X) X
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/* Unsigned integer types. These are already defined in the sqliteInt.h,
|
||||
** but the definitions need to be repeated for separate compilation. */
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short int u16;
|
||||
typedef unsigned char u8;
|
||||
#endif
|
||||
|
||||
/* Objects */
|
||||
@@ -111,14 +154,13 @@ static const char * const jsonType[] = {
|
||||
struct JsonNode {
|
||||
u8 eType; /* One of the JSON_ type values */
|
||||
u8 jnFlags; /* JNODE flags */
|
||||
u8 eU; /* Which union element to use */
|
||||
u32 n; /* Bytes of content, or number of sub-nodes */
|
||||
union {
|
||||
const char *zJContent; /* 1: Content for INT, REAL, and STRING */
|
||||
u32 iAppend; /* 2: More terms for ARRAY and OBJECT */
|
||||
u32 iKey; /* 3: Key for ARRAY objects in json_tree() */
|
||||
u32 iReplace; /* 4: Replacement content for JNODE_REPLACE */
|
||||
JsonNode *pPatch; /* 5: Node chain of patch for JNODE_PATCH */
|
||||
const char *zJContent; /* Content for INT, REAL, and STRING */
|
||||
u32 iAppend; /* More terms for ARRAY and OBJECT */
|
||||
u32 iKey; /* Key for ARRAY objects in json_tree() */
|
||||
u32 iReplace; /* Replacement content for JNODE_REPLACE */
|
||||
JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -396,14 +438,11 @@ static void jsonRenderNode(
|
||||
JsonString *pOut, /* Write JSON here */
|
||||
sqlite3_value **aReplace /* Replacement values */
|
||||
){
|
||||
assert( pNode!=0 );
|
||||
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
|
||||
if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){
|
||||
assert( pNode->eU==4 );
|
||||
if( pNode->jnFlags & JNODE_REPLACE ){
|
||||
jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
|
||||
return;
|
||||
}
|
||||
assert( pNode->eU==5 );
|
||||
pNode = pNode->u.pPatch;
|
||||
}
|
||||
switch( pNode->eType ){
|
||||
@@ -422,7 +461,6 @@ static void jsonRenderNode(
|
||||
}
|
||||
case JSON_STRING: {
|
||||
if( pNode->jnFlags & JNODE_RAW ){
|
||||
assert( pNode->eU==1 );
|
||||
jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
|
||||
break;
|
||||
}
|
||||
@@ -430,7 +468,6 @@ static void jsonRenderNode(
|
||||
}
|
||||
case JSON_REAL:
|
||||
case JSON_INT: {
|
||||
assert( pNode->eU==1 );
|
||||
jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
|
||||
break;
|
||||
}
|
||||
@@ -446,7 +483,6 @@ static void jsonRenderNode(
|
||||
j += jsonNodeSize(&pNode[j]);
|
||||
}
|
||||
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
|
||||
assert( pNode->eU==2 );
|
||||
pNode = &pNode[pNode->u.iAppend];
|
||||
j = 1;
|
||||
}
|
||||
@@ -467,7 +503,6 @@ static void jsonRenderNode(
|
||||
j += 1 + jsonNodeSize(&pNode[j+1]);
|
||||
}
|
||||
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
|
||||
assert( pNode->eU==2 );
|
||||
pNode = &pNode[pNode->u.iAppend];
|
||||
j = 1;
|
||||
}
|
||||
@@ -512,10 +547,10 @@ static u8 jsonHexToInt(int h){
|
||||
*/
|
||||
static u32 jsonHexToInt4(const char *z){
|
||||
u32 v;
|
||||
assert( sqlite3Isxdigit(z[0]) );
|
||||
assert( sqlite3Isxdigit(z[1]) );
|
||||
assert( sqlite3Isxdigit(z[2]) );
|
||||
assert( sqlite3Isxdigit(z[3]) );
|
||||
assert( safe_isxdigit(z[0]) );
|
||||
assert( safe_isxdigit(z[1]) );
|
||||
assert( safe_isxdigit(z[2]) );
|
||||
assert( safe_isxdigit(z[3]) );
|
||||
v = (jsonHexToInt(z[0])<<12)
|
||||
+ (jsonHexToInt(z[1])<<8)
|
||||
+ (jsonHexToInt(z[2])<<4)
|
||||
@@ -547,9 +582,7 @@ static void jsonReturn(
|
||||
}
|
||||
case JSON_INT: {
|
||||
sqlite3_int64 i = 0;
|
||||
const char *z;
|
||||
assert( pNode->eU==1 );
|
||||
z = pNode->u.zJContent;
|
||||
const char *z = pNode->u.zJContent;
|
||||
if( z[0]=='-' ){ z++; }
|
||||
while( z[0]>='0' && z[0]<='9' ){
|
||||
unsigned v = *(z++) - '0';
|
||||
@@ -572,17 +605,14 @@ static void jsonReturn(
|
||||
sqlite3_result_int64(pCtx, i);
|
||||
int_done:
|
||||
break;
|
||||
int_as_real: ; /* no break */ deliberate_fall_through
|
||||
int_as_real: i=0; /* no break */ deliberate_fall_through
|
||||
}
|
||||
case JSON_REAL: {
|
||||
double r;
|
||||
#ifdef SQLITE_AMALGAMATION
|
||||
const char *z;
|
||||
assert( pNode->eU==1 );
|
||||
z = pNode->u.zJContent;
|
||||
const char *z = pNode->u.zJContent;
|
||||
sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
#else
|
||||
assert( pNode->eU==1 );
|
||||
r = strtod(pNode->u.zJContent, 0);
|
||||
#endif
|
||||
sqlite3_result_double(pCtx, r);
|
||||
@@ -593,7 +623,6 @@ static void jsonReturn(
|
||||
** json_insert() and json_replace() and those routines do not
|
||||
** call jsonReturn() */
|
||||
if( pNode->jnFlags & JNODE_RAW ){
|
||||
assert( pNode->eU==1 );
|
||||
sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
|
||||
SQLITE_TRANSIENT);
|
||||
}else
|
||||
@@ -601,18 +630,15 @@ static void jsonReturn(
|
||||
assert( (pNode->jnFlags & JNODE_RAW)==0 );
|
||||
if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
|
||||
/* JSON formatted without any backslash-escapes */
|
||||
assert( pNode->eU==1 );
|
||||
sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
|
||||
SQLITE_TRANSIENT);
|
||||
}else{
|
||||
/* Translate JSON formatted string into raw text */
|
||||
u32 i;
|
||||
u32 n = pNode->n;
|
||||
const char *z;
|
||||
const char *z = pNode->u.zJContent;
|
||||
char *zOut;
|
||||
u32 j;
|
||||
assert( pNode->eU==1 );
|
||||
z = pNode->u.zJContent;
|
||||
zOut = sqlite3_malloc( n+1 );
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
@@ -733,13 +759,12 @@ static int jsonParseAddNode(
|
||||
const char *zContent /* Content */
|
||||
){
|
||||
JsonNode *p;
|
||||
if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){
|
||||
if( pParse->nNode>=pParse->nAlloc ){
|
||||
return jsonParseAddNodeExpand(pParse, eType, n, zContent);
|
||||
}
|
||||
p = &pParse->aNode[pParse->nNode];
|
||||
p->eType = (u8)eType;
|
||||
p->jnFlags = 0;
|
||||
VVA( p->eU = zContent ? 1 : 0 );
|
||||
p->n = n;
|
||||
p->u.zJContent = zContent;
|
||||
return pParse->nNode++;
|
||||
@@ -750,7 +775,7 @@ static int jsonParseAddNode(
|
||||
*/
|
||||
static int jsonIs4Hex(const char *z){
|
||||
int i;
|
||||
for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0;
|
||||
for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -769,13 +794,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
int x;
|
||||
JsonNode *pNode;
|
||||
const char *z = pParse->zJson;
|
||||
while( fast_isspace(z[i]) ){ i++; }
|
||||
while( safe_isspace(z[i]) ){ i++; }
|
||||
if( (c = z[i])=='{' ){
|
||||
/* Parse object */
|
||||
iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
|
||||
if( iThis<0 ) return -1;
|
||||
for(j=i+1;;j++){
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
|
||||
x = jsonParseValue(pParse, j);
|
||||
if( x<0 ){
|
||||
@@ -788,14 +813,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
if( pNode->eType!=JSON_STRING ) return -1;
|
||||
pNode->jnFlags |= JNODE_LABEL;
|
||||
j = x;
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
if( z[j]!=':' ) return -1;
|
||||
j++;
|
||||
x = jsonParseValue(pParse, j);
|
||||
pParse->iDepth--;
|
||||
if( x<0 ) return -1;
|
||||
j = x;
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
c = z[j];
|
||||
if( c==',' ) continue;
|
||||
if( c!='}' ) return -1;
|
||||
@@ -807,9 +832,8 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
/* Parse array */
|
||||
iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
|
||||
if( iThis<0 ) return -1;
|
||||
memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u));
|
||||
for(j=i+1;;j++){
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
|
||||
x = jsonParseValue(pParse, j);
|
||||
pParse->iDepth--;
|
||||
@@ -818,7 +842,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
return -1;
|
||||
}
|
||||
j = x;
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
c = z[j];
|
||||
if( c==',' ) continue;
|
||||
if( c!=']' ) return -1;
|
||||
@@ -855,17 +879,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
return j+1;
|
||||
}else if( c=='n'
|
||||
&& strncmp(z+i,"null",4)==0
|
||||
&& !sqlite3Isalnum(z[i+4]) ){
|
||||
&& !safe_isalnum(z[i+4]) ){
|
||||
jsonParseAddNode(pParse, JSON_NULL, 0, 0);
|
||||
return i+4;
|
||||
}else if( c=='t'
|
||||
&& strncmp(z+i,"true",4)==0
|
||||
&& !sqlite3Isalnum(z[i+4]) ){
|
||||
&& !safe_isalnum(z[i+4]) ){
|
||||
jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
|
||||
return i+4;
|
||||
}else if( c=='f'
|
||||
&& strncmp(z+i,"false",5)==0
|
||||
&& !sqlite3Isalnum(z[i+5]) ){
|
||||
&& !safe_isalnum(z[i+5]) ){
|
||||
jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
|
||||
return i+5;
|
||||
}else if( c=='-' || (c>='0' && c<='9') ){
|
||||
@@ -936,7 +960,7 @@ static int jsonParse(
|
||||
if( pParse->oom ) i = -1;
|
||||
if( i>0 ){
|
||||
assert( pParse->iDepth==0 );
|
||||
while( fast_isspace(zJson[i]) ) i++;
|
||||
while( safe_isspace(zJson[i]) ) i++;
|
||||
if( zJson[i] ) i = -1;
|
||||
}
|
||||
if( i<=0 ){
|
||||
@@ -1072,7 +1096,6 @@ static JsonParse *jsonParseCached(
|
||||
** a match.
|
||||
*/
|
||||
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
|
||||
assert( pNode->eU==1 );
|
||||
if( pNode->jnFlags & JNODE_RAW ){
|
||||
if( pNode->n!=nKey ) return 0;
|
||||
return strncmp(pNode->u.zJContent, zKey, nKey)==0;
|
||||
@@ -1119,15 +1142,14 @@ static JsonNode *jsonLookupStep(
|
||||
*pzErr = zPath;
|
||||
return 0;
|
||||
}
|
||||
testcase( nKey==0 );
|
||||
}else{
|
||||
zKey = zPath;
|
||||
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
|
||||
nKey = i;
|
||||
if( nKey==0 ){
|
||||
*pzErr = zPath;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( nKey==0 ){
|
||||
*pzErr = zPath;
|
||||
return 0;
|
||||
}
|
||||
j = 1;
|
||||
for(;;){
|
||||
@@ -1139,7 +1161,6 @@ static JsonNode *jsonLookupStep(
|
||||
j += jsonNodeSize(&pRoot[j]);
|
||||
}
|
||||
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
|
||||
assert( pRoot->eU==2 );
|
||||
iRoot += pRoot->u.iAppend;
|
||||
pRoot = &pParse->aNode[iRoot];
|
||||
j = 1;
|
||||
@@ -1154,10 +1175,8 @@ static JsonNode *jsonLookupStep(
|
||||
if( pParse->oom ) return 0;
|
||||
if( pNode ){
|
||||
pRoot = &pParse->aNode[iRoot];
|
||||
assert( pRoot->eU==0 );
|
||||
pRoot->u.iAppend = iStart - iRoot;
|
||||
pRoot->jnFlags |= JNODE_APPEND;
|
||||
VVA( pRoot->eU = 2 );
|
||||
pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
|
||||
}
|
||||
return pNode;
|
||||
@@ -1165,7 +1184,7 @@ static JsonNode *jsonLookupStep(
|
||||
}else if( zPath[0]=='[' ){
|
||||
i = 0;
|
||||
j = 1;
|
||||
while( sqlite3Isdigit(zPath[j]) ){
|
||||
while( safe_isdigit(zPath[j]) ){
|
||||
i = i*10 + zPath[j] - '0';
|
||||
j++;
|
||||
}
|
||||
@@ -1180,19 +1199,18 @@ static JsonNode *jsonLookupStep(
|
||||
j += jsonNodeSize(&pBase[j]);
|
||||
}
|
||||
if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
|
||||
assert( pBase->eU==2 );
|
||||
iBase += pBase->u.iAppend;
|
||||
pBase = &pParse->aNode[iBase];
|
||||
j = 1;
|
||||
}
|
||||
j = 2;
|
||||
if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
|
||||
if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
|
||||
unsigned int x = 0;
|
||||
j = 3;
|
||||
do{
|
||||
x = x*10 + zPath[j] - '0';
|
||||
j++;
|
||||
}while( sqlite3Isdigit(zPath[j]) );
|
||||
}while( safe_isdigit(zPath[j]) );
|
||||
if( x>i ) return 0;
|
||||
i -= x;
|
||||
}
|
||||
@@ -1214,7 +1232,6 @@ static JsonNode *jsonLookupStep(
|
||||
j += jsonNodeSize(&pRoot[j]);
|
||||
}
|
||||
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
|
||||
assert( pRoot->eU==2 );
|
||||
iRoot += pRoot->u.iAppend;
|
||||
pRoot = &pParse->aNode[iRoot];
|
||||
j = 1;
|
||||
@@ -1230,10 +1247,8 @@ static JsonNode *jsonLookupStep(
|
||||
if( pParse->oom ) return 0;
|
||||
if( pNode ){
|
||||
pRoot = &pParse->aNode[iRoot];
|
||||
assert( pRoot->eU==0 );
|
||||
pRoot->u.iAppend = iStart - iRoot;
|
||||
pRoot->jnFlags |= JNODE_APPEND;
|
||||
VVA( pRoot->eU = 2 );
|
||||
}
|
||||
return pNode;
|
||||
}
|
||||
@@ -1387,13 +1402,9 @@ static void jsonParseFunc(
|
||||
}
|
||||
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
|
||||
i, zType, x.aNode[i].n, x.aUp[i]);
|
||||
assert( x.aNode[i].eU==0 || x.aNode[i].eU==1 );
|
||||
if( x.aNode[i].u.zJContent!=0 ){
|
||||
assert( x.aNode[i].eU==1 );
|
||||
jsonAppendRaw(&s, " ", 1);
|
||||
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
|
||||
}else{
|
||||
assert( x.aNode[i].eU==0 );
|
||||
}
|
||||
jsonAppendRaw(&s, "\n", 1);
|
||||
}
|
||||
@@ -1411,7 +1422,7 @@ static void jsonTest1Func(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
@@ -1432,7 +1443,7 @@ static void jsonQuoteFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString jx;
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendValue(&jx, argv[0]);
|
||||
@@ -1503,34 +1514,13 @@ static void jsonArrayLengthFunc(
|
||||
sqlite3_result_int64(ctx, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Bit values for the flags passed into jsonExtractFunc() or
|
||||
** jsonSetFunc() via the user-data value.
|
||||
*/
|
||||
#define JSON_JSON 0x01 /* Result is always JSON */
|
||||
#define JSON_SQL 0x02 /* Result is always SQL */
|
||||
#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
|
||||
#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
|
||||
|
||||
/*
|
||||
** json_extract(JSON, PATH, ...)
|
||||
** "->"(JSON,PATH)
|
||||
** "->>"(JSON,PATH)
|
||||
**
|
||||
** Return the element described by PATH. Return NULL if that PATH element
|
||||
** is not found.
|
||||
**
|
||||
** If JSON_JSON is set or if more that one PATH argument is supplied then
|
||||
** always return a JSON representation of the result. If JSON_SQL is set,
|
||||
** then always return an SQL representation of the result. If neither flag
|
||||
** is present and argc==2, then return JSON for objects and arrays and SQL
|
||||
** for all other values.
|
||||
**
|
||||
** When multiple PATH arguments are supplied, the result is a JSON array
|
||||
** containing the result of each PATH.
|
||||
**
|
||||
** Abbreviated JSON path expressions are allows if JSON_ABPATH, for
|
||||
** compatibility with PG.
|
||||
** Return the element described by PATH. Return NULL if there is no
|
||||
** PATH element. If there are multiple PATHs, then return a JSON array
|
||||
** with the result from each path. Throw an error if the JSON or any PATH
|
||||
** is malformed.
|
||||
*/
|
||||
static void jsonExtractFunc(
|
||||
sqlite3_context *ctx,
|
||||
@@ -1540,77 +1530,35 @@ static void jsonExtractFunc(
|
||||
JsonParse *p; /* The parse */
|
||||
JsonNode *pNode;
|
||||
const char *zPath;
|
||||
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
|
||||
JsonString jx;
|
||||
int i;
|
||||
|
||||
if( argc<2 ) return;
|
||||
p = jsonParseCached(ctx, argv, ctx);
|
||||
if( p==0 ) return;
|
||||
if( argc==2 ){
|
||||
/* With a single PATH argument */
|
||||
zPath = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( zPath==0 ) return;
|
||||
if( flags & JSON_ABPATH ){
|
||||
if( zPath[0]!='$' ){
|
||||
/* The -> and ->> operators accept abbreviated PATH arguments. This
|
||||
** is mostly for compatibility with PostgreSQL, but also for
|
||||
** convenience.
|
||||
**
|
||||
** NUMBER ==> $[NUMBER] // PG compatible
|
||||
** LABEL ==> $.LABEL // PG compatible
|
||||
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
|
||||
*/
|
||||
jsonInit(&jx, ctx);
|
||||
if( sqlite3Isdigit(zPath[0]) ){
|
||||
jsonAppendRaw(&jx, "$[", 2);
|
||||
jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
|
||||
jsonAppendRaw(&jx, "]", 2);
|
||||
}else{
|
||||
jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='['));
|
||||
jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
|
||||
jsonAppendChar(&jx, 0);
|
||||
}
|
||||
pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx);
|
||||
jsonReset(&jx);
|
||||
}else{
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
}
|
||||
if( pNode ){
|
||||
if( flags & JSON_JSON ){
|
||||
jsonReturnJson(pNode, ctx, 0);
|
||||
}else{
|
||||
jsonReturn(pNode, ctx, 0);
|
||||
sqlite3_result_subtype(ctx, 0);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0);
|
||||
}
|
||||
}else{
|
||||
/* Two or more PATH arguments results in a JSON array with each
|
||||
** element of the array being the value selected by one of the PATHs */
|
||||
int i;
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendChar(&jx, '[');
|
||||
for(i=1; i<argc; i++){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr ) break;
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendChar(&jx, '[');
|
||||
for(i=1; i<argc; i++){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr ) break;
|
||||
if( argc>2 ){
|
||||
jsonAppendSeparator(&jx);
|
||||
if( pNode ){
|
||||
jsonRenderNode(pNode, &jx, 0);
|
||||
}else{
|
||||
jsonAppendRaw(&jx, "null", 4);
|
||||
}
|
||||
}else if( pNode ){
|
||||
jsonReturn(pNode, ctx, 0);
|
||||
}
|
||||
if( i==argc ){
|
||||
jsonAppendChar(&jx, ']');
|
||||
jsonResult(&jx);
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
jsonReset(&jx);
|
||||
}
|
||||
if( argc>2 && i==argc ){
|
||||
jsonAppendChar(&jx, ']');
|
||||
jsonResult(&jx);
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
jsonReset(&jx);
|
||||
}
|
||||
|
||||
/* This is the RFC 7396 MergePatch algorithm.
|
||||
@@ -1626,7 +1574,7 @@ static JsonNode *jsonMergePatch(
|
||||
if( pPatch->eType!=JSON_OBJECT ){
|
||||
return pPatch;
|
||||
}
|
||||
assert( iTarget<pParse->nNode );
|
||||
assert( iTarget>=0 && iTarget<pParse->nNode );
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
|
||||
if( pTarget->eType!=JSON_OBJECT ){
|
||||
@@ -1639,7 +1587,6 @@ static JsonNode *jsonMergePatch(
|
||||
const char *zKey;
|
||||
assert( pPatch[i].eType==JSON_STRING );
|
||||
assert( pPatch[i].jnFlags & JNODE_LABEL );
|
||||
assert( pPatch[i].eU==1 );
|
||||
nKey = pPatch[i].n;
|
||||
zKey = pPatch[i].u.zJContent;
|
||||
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
|
||||
@@ -1656,12 +1603,6 @@ static JsonNode *jsonMergePatch(
|
||||
if( pNew==0 ) return 0;
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
if( pNew!=&pTarget[j+1] ){
|
||||
assert( pTarget[j+1].eU==0
|
||||
|| pTarget[j+1].eU==1
|
||||
|| pTarget[j+1].eU==2 );
|
||||
testcase( pTarget[j+1].eU==1 );
|
||||
testcase( pTarget[j+1].eU==2 );
|
||||
VVA( pTarget[j+1].eU = 5 );
|
||||
pTarget[j+1].u.pPatch = pNew;
|
||||
pTarget[j+1].jnFlags |= JNODE_PATCH;
|
||||
}
|
||||
@@ -1677,14 +1618,9 @@ static JsonNode *jsonMergePatch(
|
||||
if( pParse->oom ) return 0;
|
||||
jsonRemoveAllNulls(pPatch);
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 );
|
||||
testcase( pParse->aNode[iRoot].eU==2 );
|
||||
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
|
||||
VVA( pParse->aNode[iRoot].eU = 2 );
|
||||
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
|
||||
iRoot = iStart;
|
||||
assert( pParse->aNode[iPatch].eU==0 );
|
||||
VVA( pParse->aNode[iPatch].eU = 5 );
|
||||
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
|
||||
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
|
||||
}
|
||||
@@ -1706,7 +1642,7 @@ static void jsonPatchFunc(
|
||||
JsonParse y; /* The patch */
|
||||
JsonNode *pResult; /* The result of the merge */
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
|
||||
if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
|
||||
jsonParseReset(&x);
|
||||
@@ -1826,15 +1762,11 @@ static void jsonReplaceFunc(
|
||||
pNode = jsonLookup(&x, zPath, 0, ctx);
|
||||
if( x.nErr ) goto replace_err;
|
||||
if( pNode ){
|
||||
assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
|
||||
testcase( pNode->eU!=0 && pNode->eU!=1 );
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
VVA( pNode->eU = 4 );
|
||||
pNode->u.iReplace = i + 1;
|
||||
}
|
||||
}
|
||||
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
|
||||
assert( x.aNode[0].eU==4 );
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
|
||||
}else{
|
||||
jsonReturnJson(x.aNode, ctx, argv);
|
||||
@@ -1843,7 +1775,6 @@ replace_err:
|
||||
jsonParseReset(&x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** json_set(JSON, PATH, VALUE, ...)
|
||||
**
|
||||
@@ -1866,7 +1797,7 @@ static void jsonSetFunc(
|
||||
const char *zPath;
|
||||
u32 i;
|
||||
int bApnd;
|
||||
int bIsSet = sqlite3_user_data(ctx)!=0;
|
||||
int bIsSet = *(int*)sqlite3_user_data(ctx);
|
||||
|
||||
if( argc<1 ) return;
|
||||
if( (argc&1)==0 ) {
|
||||
@@ -1885,15 +1816,11 @@ static void jsonSetFunc(
|
||||
}else if( x.nErr ){
|
||||
goto jsonSetDone;
|
||||
}else if( pNode && (bApnd || bIsSet) ){
|
||||
testcase( pNode->eU!=0 && pNode->eU!=1 );
|
||||
assert( pNode->eU!=3 && pNode->eU!=5 );
|
||||
VVA( pNode->eU = 4 );
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
pNode->u.iReplace = i + 1;
|
||||
}
|
||||
}
|
||||
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
|
||||
assert( x.aNode[0].eU==4 );
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
|
||||
}else{
|
||||
jsonReturnJson(x.aNode, ctx, argv);
|
||||
@@ -1906,8 +1833,8 @@ jsonSetDone:
|
||||
** json_type(JSON)
|
||||
** json_type(JSON, PATH)
|
||||
**
|
||||
** Return the top-level "type" of a JSON string. json_type() raises an
|
||||
** error if either the JSON or PATH inputs are not well-formed.
|
||||
** Return the top-level "type" of a JSON string. Throw an error if
|
||||
** either the JSON or PATH inputs are not well-formed.
|
||||
*/
|
||||
static void jsonTypeFunc(
|
||||
sqlite3_context *ctx,
|
||||
@@ -1943,7 +1870,7 @@ static void jsonValidFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonParse *p; /* The parse */
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
p = jsonParseCached(ctx, argv, 0);
|
||||
sqlite3_result_int(ctx, p!=0);
|
||||
}
|
||||
@@ -1963,7 +1890,7 @@ static void jsonArrayStep(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString *pStr;
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
@@ -2023,8 +1950,8 @@ static void jsonGroupInverse(
|
||||
char *z;
|
||||
char c;
|
||||
JsonString *pStr;
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAM(argv);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
#ifdef NEVER
|
||||
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
||||
@@ -2068,7 +1995,7 @@ static void jsonObjectStep(
|
||||
JsonString *pStr;
|
||||
const char *z;
|
||||
u32 n;
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(argc);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
@@ -2159,10 +2086,10 @@ static int jsonEachConnect(
|
||||
#define JEACH_JSON 8
|
||||
#define JEACH_ROOT 9
|
||||
|
||||
UNUSED_PARAMETER(pzErr);
|
||||
UNUSED_PARAMETER(argv);
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(pAux);
|
||||
UNUSED_PARAM(pzErr);
|
||||
UNUSED_PARAM(argv);
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAM(pAux);
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
|
||||
"json HIDDEN,root HIDDEN)");
|
||||
@@ -2185,7 +2112,7 @@ static int jsonEachDisconnect(sqlite3_vtab *pVtab){
|
||||
static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
JsonEachCursor *pCur;
|
||||
|
||||
UNUSED_PARAMETER(p);
|
||||
UNUSED_PARAM(p);
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
@@ -2244,9 +2171,6 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
|
||||
JsonNode *pUp = &p->sParse.aNode[iUp];
|
||||
p->eType = pUp->eType;
|
||||
if( pUp->eType==JSON_ARRAY ){
|
||||
assert( pUp->eU==0 || pUp->eU==3 );
|
||||
testcase( pUp->eU==3 );
|
||||
VVA( pUp->eU = 3 );
|
||||
if( iUp==p->i-1 ){
|
||||
pUp->u.iKey = 0;
|
||||
}else{
|
||||
@@ -2275,33 +2199,6 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Append an object label to the JSON Path being constructed
|
||||
** in pStr.
|
||||
*/
|
||||
static void jsonAppendObjectPathElement(
|
||||
JsonString *pStr,
|
||||
JsonNode *pNode
|
||||
){
|
||||
int jj, nn;
|
||||
const char *z;
|
||||
assert( pNode->eType==JSON_STRING );
|
||||
assert( pNode->jnFlags & JNODE_LABEL );
|
||||
assert( pNode->eU==1 );
|
||||
z = pNode->u.zJContent;
|
||||
nn = pNode->n;
|
||||
assert( nn>=2 );
|
||||
assert( z[0]=='"' );
|
||||
assert( z[nn-1]=='"' );
|
||||
if( nn>2 && sqlite3Isalpha(z[1]) ){
|
||||
for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){}
|
||||
if( jj==nn-1 ){
|
||||
z++;
|
||||
nn -= 2;
|
||||
}
|
||||
}
|
||||
jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
|
||||
}
|
||||
|
||||
/* Append the name of the path for element i to pStr
|
||||
*/
|
||||
static void jsonEachComputePath(
|
||||
@@ -2320,13 +2217,13 @@ static void jsonEachComputePath(
|
||||
pNode = &p->sParse.aNode[i];
|
||||
pUp = &p->sParse.aNode[iUp];
|
||||
if( pUp->eType==JSON_ARRAY ){
|
||||
assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
|
||||
testcase( pUp->eU==0 );
|
||||
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
|
||||
}else{
|
||||
assert( pUp->eType==JSON_OBJECT );
|
||||
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
|
||||
jsonAppendObjectPathElement(pStr, pNode);
|
||||
assert( pNode->eType==JSON_STRING );
|
||||
assert( pNode->jnFlags & JNODE_LABEL );
|
||||
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2347,7 +2244,6 @@ static int jsonEachColumn(
|
||||
u32 iKey;
|
||||
if( p->bRecursive ){
|
||||
if( p->iRowid==0 ) break;
|
||||
assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 );
|
||||
iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
|
||||
}else{
|
||||
iKey = p->iRowid;
|
||||
@@ -2397,7 +2293,7 @@ static int jsonEachColumn(
|
||||
if( p->eType==JSON_ARRAY ){
|
||||
jsonPrintf(30, &x, "[%d]", p->iRowid);
|
||||
}else if( p->eType==JSON_OBJECT ){
|
||||
jsonAppendObjectPathElement(&x, pThis);
|
||||
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
|
||||
}
|
||||
}
|
||||
jsonResult(&x);
|
||||
@@ -2455,7 +2351,7 @@ static int jsonEachBestIndex(
|
||||
/* This implementation assumes that JSON and ROOT are the last two
|
||||
** columns in the table */
|
||||
assert( JEACH_ROOT == JEACH_JSON+1 );
|
||||
UNUSED_PARAMETER(tab);
|
||||
UNUSED_PARAM(tab);
|
||||
aIdx[0] = aIdx[1] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
@@ -2464,7 +2360,6 @@ static int jsonEachBestIndex(
|
||||
if( pConstraint->iColumn < JEACH_JSON ) continue;
|
||||
iCol = pConstraint->iColumn - JEACH_JSON;
|
||||
assert( iCol==0 || iCol==1 );
|
||||
testcase( iCol==0 );
|
||||
iMask = 1 << iCol;
|
||||
if( pConstraint->usable==0 ){
|
||||
unusableMask |= iMask;
|
||||
@@ -2511,8 +2406,8 @@ static int jsonEachFilter(
|
||||
const char *zRoot = 0;
|
||||
sqlite3_int64 n;
|
||||
|
||||
UNUSED_PARAMETER(idxStr);
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAM(idxStr);
|
||||
UNUSED_PARAM(argc);
|
||||
jsonEachCursorReset(p);
|
||||
if( idxNum==0 ) return SQLITE_OK;
|
||||
z = (const char*)sqlite3_value_text(argv[0]);
|
||||
@@ -2562,8 +2457,6 @@ static int jsonEachFilter(
|
||||
p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
|
||||
p->eType = pNode->eType;
|
||||
if( p->eType>=JSON_ARRAY ){
|
||||
assert( pNode->eU==0 );
|
||||
VVA( pNode->eU = 3 );
|
||||
pNode->u.iKey = 0;
|
||||
p->iEnd = p->i + pNode->n + 1;
|
||||
if( p->bRecursive ){
|
||||
@@ -2637,63 +2530,103 @@ static sqlite3_module jsonTreeModule = {
|
||||
0 /* xShadowName */
|
||||
};
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
#endif /* !defined(SQLITE_OMIT_JSON) */
|
||||
|
||||
/*
|
||||
** Register JSON functions.
|
||||
*/
|
||||
void sqlite3RegisterJsonFunctions(void){
|
||||
#ifndef SQLITE_OMIT_JSON
|
||||
static FuncDef aJsonFunc[] = {
|
||||
JFUNCTION(json, 1, 0, jsonRemoveFunc),
|
||||
JFUNCTION(json_array, -1, 0, jsonArrayFunc),
|
||||
JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc),
|
||||
JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc),
|
||||
JFUNCTION(json_extract, -1, 0, jsonExtractFunc),
|
||||
JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc),
|
||||
JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc),
|
||||
JFUNCTION(json_insert, -1, 0, jsonSetFunc),
|
||||
JFUNCTION(json_object, -1, 0, jsonObjectFunc),
|
||||
JFUNCTION(json_patch, 2, 0, jsonPatchFunc),
|
||||
JFUNCTION(json_quote, 1, 0, jsonQuoteFunc),
|
||||
JFUNCTION(json_remove, -1, 0, jsonRemoveFunc),
|
||||
JFUNCTION(json_replace, -1, 0, jsonReplaceFunc),
|
||||
JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc),
|
||||
JFUNCTION(json_type, 1, 0, jsonTypeFunc),
|
||||
JFUNCTION(json_type, 2, 0, jsonTypeFunc),
|
||||
JFUNCTION(json_valid, 1, 0, jsonValidFunc),
|
||||
#if SQLITE_DEBUG
|
||||
JFUNCTION(json_parse, 1, 0, jsonParseFunc),
|
||||
JFUNCTION(json_test1, 1, 0, jsonTest1Func),
|
||||
#endif
|
||||
WAGGREGATE(json_group_array, 1, 0, 0,
|
||||
jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
|
||||
SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS),
|
||||
WAGGREGATE(json_group_object, 2, 0, 0,
|
||||
jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
|
||||
SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
|
||||
};
|
||||
sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
|
||||
#endif
|
||||
}
|
||||
/****************************************************************************
|
||||
** The following routines are the only publically visible identifiers in this
|
||||
** file. Call the following routines in order to register the various SQL
|
||||
** functions and the virtual table implemented by this file.
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
||||
/*
|
||||
** Register the JSON table-valued functions
|
||||
*/
|
||||
int sqlite3JsonTableFunctions(sqlite3 *db){
|
||||
int sqlite3Json1Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
static const struct {
|
||||
const char *zName;
|
||||
sqlite3_module *pModule;
|
||||
const char *zName;
|
||||
int nArg;
|
||||
int flag;
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} aFunc[] = {
|
||||
{ "json", 1, 0, jsonRemoveFunc },
|
||||
{ "json_array", -1, 0, jsonArrayFunc },
|
||||
{ "json_array_length", 1, 0, jsonArrayLengthFunc },
|
||||
{ "json_array_length", 2, 0, jsonArrayLengthFunc },
|
||||
{ "json_extract", -1, 0, jsonExtractFunc },
|
||||
{ "json_insert", -1, 0, jsonSetFunc },
|
||||
{ "json_object", -1, 0, jsonObjectFunc },
|
||||
{ "json_patch", 2, 0, jsonPatchFunc },
|
||||
{ "json_quote", 1, 0, jsonQuoteFunc },
|
||||
{ "json_remove", -1, 0, jsonRemoveFunc },
|
||||
{ "json_replace", -1, 0, jsonReplaceFunc },
|
||||
{ "json_set", -1, 1, jsonSetFunc },
|
||||
{ "json_type", 1, 0, jsonTypeFunc },
|
||||
{ "json_type", 2, 0, jsonTypeFunc },
|
||||
{ "json_valid", 1, 0, jsonValidFunc },
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
/* DEBUG and TESTING functions */
|
||||
{ "json_parse", 1, 0, jsonParseFunc },
|
||||
{ "json_test1", 1, 0, jsonTest1Func },
|
||||
#endif
|
||||
};
|
||||
static const struct {
|
||||
const char *zName;
|
||||
int nArg;
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
|
||||
void (*xFinal)(sqlite3_context*);
|
||||
void (*xValue)(sqlite3_context*);
|
||||
} aAgg[] = {
|
||||
{ "json_group_array", 1,
|
||||
jsonArrayStep, jsonArrayFinal, jsonArrayValue },
|
||||
{ "json_group_object", 2,
|
||||
jsonObjectStep, jsonObjectFinal, jsonObjectValue },
|
||||
};
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
static const struct {
|
||||
const char *zName;
|
||||
sqlite3_module *pModule;
|
||||
} aMod[] = {
|
||||
{ "json_each", &jsonEachModule },
|
||||
{ "json_tree", &jsonTreeModule },
|
||||
};
|
||||
unsigned int i;
|
||||
#endif
|
||||
static const int enc =
|
||||
SQLITE_UTF8 |
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_INNOCUOUS;
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, enc,
|
||||
(void*)&aFunc[i].flag,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
|
||||
SQLITE_SUBTYPE | enc, 0,
|
||||
aAgg[i].xStep, aAgg[i].xFinal,
|
||||
aAgg[i].xValue, jsonGroupInverse, 0);
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */
|
||||
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_json_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return sqlite3Json1Init(db);
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
|
||||
@@ -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;
|
||||
}
|
||||
+24
-144
@@ -72,7 +72,6 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
/* The end-of-input character */
|
||||
#define RE_EOF 0 /* End of input */
|
||||
#define RE_START 0xfffffff /* Start of input - larger than an UTF-8 */
|
||||
|
||||
/* The NFA is implemented as sequence of opcodes taken from the following
|
||||
** set. Each opcode has a single integer argument.
|
||||
@@ -94,33 +93,6 @@ SQLITE_EXTENSION_INIT1
|
||||
#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
|
||||
#define RE_OP_NOTSPACE 16 /* Not a digit */
|
||||
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
|
||||
#define RE_OP_ATSTART 18 /* Currently at the start of the string */
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/* Opcode names used for symbolic debugging */
|
||||
static const char *ReOpName[] = {
|
||||
"EOF",
|
||||
"MATCH",
|
||||
"ANY",
|
||||
"ANYSTAR",
|
||||
"FORK",
|
||||
"GOTO",
|
||||
"ACCEPT",
|
||||
"CC_INC",
|
||||
"CC_EXC",
|
||||
"CC_VALUE",
|
||||
"CC_RANGE",
|
||||
"WORD",
|
||||
"NOTWORD",
|
||||
"DIGIT",
|
||||
"NOTDIGIT",
|
||||
"SPACE",
|
||||
"NOTSPACE",
|
||||
"BOUNDARY",
|
||||
"ATSTART",
|
||||
};
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
|
||||
/* Each opcode is a "state" in the NFA */
|
||||
typedef unsigned short ReStateNumber;
|
||||
@@ -155,7 +127,7 @@ struct ReCompiled {
|
||||
int *aArg; /* Arguments to each operator */
|
||||
unsigned (*xNextChar)(ReInput*); /* Next character function */
|
||||
unsigned char zInit[12]; /* Initial text to match */
|
||||
int nInit; /* Number of bytes in zInit */
|
||||
int nInit; /* Number of characters in zInit */
|
||||
unsigned nState; /* Number of entries in aOp[] and aArg[] */
|
||||
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
|
||||
};
|
||||
@@ -228,7 +200,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
ReStateNumber *pToFree;
|
||||
unsigned int i = 0;
|
||||
unsigned int iSwap = 0;
|
||||
int c = RE_START;
|
||||
int c = RE_EOF+1;
|
||||
int cPrev = 0;
|
||||
int rc = 0;
|
||||
ReInput in;
|
||||
@@ -247,7 +219,6 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
in.i++;
|
||||
}
|
||||
if( in.i+pRe->nInit>in.mx ) return 0;
|
||||
c = RE_START-1;
|
||||
}
|
||||
|
||||
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
|
||||
@@ -276,12 +247,8 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_ATSTART: {
|
||||
if( cPrev==RE_START ) re_add_state(pThis, x+1);
|
||||
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: {
|
||||
@@ -289,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: {
|
||||
@@ -297,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: {
|
||||
@@ -305,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: {
|
||||
@@ -330,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;
|
||||
@@ -355,15 +319,13 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<pNext->nState; i++){
|
||||
int x = pNext->aState[i];
|
||||
while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
|
||||
if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
|
||||
if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
|
||||
}
|
||||
re_match_end:
|
||||
sqlite3_free(pToFree);
|
||||
@@ -518,6 +480,7 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
iStart = p->nState;
|
||||
switch( c ){
|
||||
case '|':
|
||||
case '$':
|
||||
case ')': {
|
||||
p->sIn.i--;
|
||||
return 0;
|
||||
@@ -533,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;
|
||||
@@ -554,14 +517,6 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
|
||||
break;
|
||||
}
|
||||
case '$': {
|
||||
re_append(p, RE_OP_MATCH, RE_EOF);
|
||||
break;
|
||||
}
|
||||
case '^': {
|
||||
re_append(p, RE_OP_ATSTART, 0);
|
||||
break;
|
||||
}
|
||||
case '{': {
|
||||
int m = 0, n = 0;
|
||||
int sz, j;
|
||||
@@ -580,7 +535,6 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
if( m==0 ){
|
||||
if( n==0 ) return "both m and n are zero in '{m,n}'";
|
||||
re_insert(p, iPrev, RE_OP_FORK, sz+1);
|
||||
iPrev++;
|
||||
n--;
|
||||
}else{
|
||||
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
|
||||
@@ -699,7 +653,11 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
re_free(pRe);
|
||||
return zErr;
|
||||
}
|
||||
if( pRe->sIn.i>=pRe->sIn.mx ){
|
||||
if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
|
||||
re_append(pRe, RE_OP_MATCH, RE_EOF);
|
||||
re_append(pRe, RE_OP_ACCEPT, 0);
|
||||
*ppRe = pRe;
|
||||
}else if( pRe->sIn.i>=pRe->sIn.mx ){
|
||||
re_append(pRe, RE_OP_ACCEPT, 0);
|
||||
*ppRe = pRe;
|
||||
}else{
|
||||
@@ -715,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;
|
||||
@@ -724,7 +682,7 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else if( x<=0xffff ){
|
||||
pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
|
||||
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
|
||||
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else{
|
||||
@@ -747,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 */
|
||||
@@ -757,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);
|
||||
@@ -783,67 +740,6 @@ static void re_sql_func(
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** This function is used for testing and debugging only. It is only available
|
||||
** if the SQLITE_DEBUG compile-time option is used.
|
||||
**
|
||||
** Compile a regular expression and then convert the compiled expression into
|
||||
** text and return that text.
|
||||
*/
|
||||
static void re_bytecode_func(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zPattern;
|
||||
const char *zErr;
|
||||
ReCompiled *pRe;
|
||||
sqlite3_str *pStr;
|
||||
int i;
|
||||
int n;
|
||||
char *z;
|
||||
|
||||
zPattern = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zPattern==0 ) return;
|
||||
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
|
||||
if( zErr ){
|
||||
re_free(pRe);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
return;
|
||||
}
|
||||
if( pRe==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
pStr = sqlite3_str_new(0);
|
||||
if( pStr==0 ) goto re_bytecode_func_err;
|
||||
if( pRe->nInit>0 ){
|
||||
sqlite3_str_appendf(pStr, "INIT ");
|
||||
for(i=0; i<pRe->nInit; i++){
|
||||
sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "\n");
|
||||
}
|
||||
for(i=0; (unsigned)i<pRe->nState; i++){
|
||||
sqlite3_str_appendf(pStr, "%-8s %4d\n",
|
||||
ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
|
||||
}
|
||||
n = sqlite3_str_length(pStr);
|
||||
z = sqlite3_str_finish(pStr);
|
||||
if( n==0 ){
|
||||
sqlite3_free(z);
|
||||
}else{
|
||||
sqlite3_result_text(context, z, n-1, sqlite3_free);
|
||||
}
|
||||
|
||||
re_bytecode_func_err:
|
||||
re_free(pRe);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
|
||||
/*
|
||||
** Invoke this routine to register the regexp() function with the
|
||||
** SQLite database connection.
|
||||
@@ -858,23 +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);
|
||||
#if defined(SQLITE_DEBUG)
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "regexp_bytecode", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
0, re_bytecode_func, 0, 0);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
}
|
||||
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){
|
||||
|
||||
+44
-81
@@ -30,16 +30,6 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
||||
#define STMT_NUM_INTEGER_COLUMN 10
|
||||
typedef struct StmtRow StmtRow;
|
||||
struct StmtRow {
|
||||
sqlite3_int64 iRowid; /* Rowid value */
|
||||
char *zSql; /* column "sql" */
|
||||
int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */
|
||||
StmtRow *pNext; /* Next row to return */
|
||||
};
|
||||
|
||||
/* stmt_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a stmt virtual table
|
||||
*/
|
||||
@@ -57,7 +47,8 @@ typedef struct stmt_cursor stmt_cursor;
|
||||
struct stmt_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this cursor */
|
||||
StmtRow *pRow; /* Current row */
|
||||
sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */
|
||||
sqlite3_int64 iRowid; /* The rowid */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -101,7 +92,7 @@ static int stmtConnect(
|
||||
"CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
|
||||
"reprep,run,mem)");
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc64( sizeof(*pNew) );
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
@@ -123,7 +114,7 @@ static int stmtDisconnect(sqlite3_vtab *pVtab){
|
||||
*/
|
||||
static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
stmt_cursor *pCur;
|
||||
pCur = sqlite3_malloc64( sizeof(*pCur) );
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
pCur->db = ((stmt_vtab*)p)->db;
|
||||
@@ -131,21 +122,10 @@ static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static void stmtCsrReset(stmt_cursor *pCur){
|
||||
StmtRow *pRow = 0;
|
||||
StmtRow *pNext = 0;
|
||||
for(pRow=pCur->pRow; pRow; pRow=pNext){
|
||||
pNext = pRow->pNext;
|
||||
sqlite3_free(pRow);
|
||||
}
|
||||
pCur->pRow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a stmt_cursor.
|
||||
*/
|
||||
static int stmtClose(sqlite3_vtab_cursor *cur){
|
||||
stmtCsrReset((stmt_cursor*)cur);
|
||||
sqlite3_free(cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -156,9 +136,8 @@ static int stmtClose(sqlite3_vtab_cursor *cur){
|
||||
*/
|
||||
static int stmtNext(sqlite3_vtab_cursor *cur){
|
||||
stmt_cursor *pCur = (stmt_cursor*)cur;
|
||||
StmtRow *pNext = pCur->pRow->pNext;
|
||||
sqlite3_free(pCur->pRow);
|
||||
pCur->pRow = pNext;
|
||||
pCur->iRowid++;
|
||||
pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -172,11 +151,39 @@ static int stmtColumn(
|
||||
int i /* Which column to return */
|
||||
){
|
||||
stmt_cursor *pCur = (stmt_cursor*)cur;
|
||||
StmtRow *pRow = pCur->pRow;
|
||||
if( i==STMT_COLUMN_SQL ){
|
||||
sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_int(ctx, pRow->aCol[i]);
|
||||
switch( i ){
|
||||
case STMT_COLUMN_SQL: {
|
||||
sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case STMT_COLUMN_NCOL: {
|
||||
sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMT_COLUMN_RO: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMT_COLUMN_BUSY: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( i==STMT_COLUMN_MEM );
|
||||
i = SQLITE_STMTSTATUS_MEMUSED +
|
||||
STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
||||
/* Fall thru */
|
||||
}
|
||||
case STMT_COLUMN_NSCAN:
|
||||
case STMT_COLUMN_NSORT:
|
||||
case STMT_COLUMN_NAIDX:
|
||||
case STMT_COLUMN_NSTEP:
|
||||
case STMT_COLUMN_REPREP:
|
||||
case STMT_COLUMN_RUN: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
|
||||
i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -187,7 +194,7 @@ static int stmtColumn(
|
||||
*/
|
||||
static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
stmt_cursor *pCur = (stmt_cursor*)cur;
|
||||
*pRowid = pCur->pRow->iRowid;
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -197,7 +204,7 @@ static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
*/
|
||||
static int stmtEof(sqlite3_vtab_cursor *cur){
|
||||
stmt_cursor *pCur = (stmt_cursor*)cur;
|
||||
return pCur->pRow==0;
|
||||
return pCur->pStmt==0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -212,53 +219,9 @@ static int stmtFilter(
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
|
||||
sqlite3_stmt *p = 0;
|
||||
sqlite3_int64 iRowid = 1;
|
||||
StmtRow **ppRow = 0;
|
||||
|
||||
stmtCsrReset(pCur);
|
||||
ppRow = &pCur->pRow;
|
||||
for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){
|
||||
const char *zSql = sqlite3_sql(p);
|
||||
sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0;
|
||||
StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql);
|
||||
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(StmtRow));
|
||||
if( zSql ){
|
||||
pNew->zSql = (char*)&pNew[1];
|
||||
memcpy(pNew->zSql, zSql, nSql);
|
||||
}
|
||||
pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p);
|
||||
pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p);
|
||||
pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p);
|
||||
pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_SORT, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_AUTOINDEX, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_VM_STEP, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_REPREPARE, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_RUN, 0
|
||||
);
|
||||
pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status(
|
||||
p, SQLITE_STMTSTATUS_MEMUSED, 0
|
||||
);
|
||||
pNew->iRowid = iRowid++;
|
||||
*ppRow = pNew;
|
||||
ppRow = &pNew->pNext;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
pCur->pStmt = 0;
|
||||
pCur->iRowid = 0;
|
||||
return stmtNext(pVtabCursor);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 ){
|
||||
|
||||
+4
-18
@@ -57,9 +57,6 @@ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
|
||||
#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 +561,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)
|
||||
@@ -867,7 +863,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 +1139,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 +1258,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 +1486,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 +1933,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 +2108,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 +2165,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);
|
||||
|
||||
+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){
|
||||
|
||||
+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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+29
-81
@@ -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 */
|
||||
){
|
||||
@@ -2736,7 +2727,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 +2754,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 +3126,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 +3192,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 +3230,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 +3985,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 +4082,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 +4119,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+11
-11
@@ -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,14 +305,13 @@ 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);
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return 0;
|
||||
}
|
||||
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
|
||||
@@ -1136,11 +1138,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 +1386,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 +1613,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 ){
|
||||
@@ -1695,7 +1695,7 @@ static int geopolyUpdate(
|
||||
sqlite3_free(p);
|
||||
nChange = 1;
|
||||
}
|
||||
for(jj=1; jj<nData-2; jj++){
|
||||
for(jj=1; jj<pRtree->nAux; jj++){
|
||||
nChange++;
|
||||
sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
|
||||
}
|
||||
|
||||
+59
-91
@@ -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;
|
||||
@@ -4292,10 +4265,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 +4523,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;
|
||||
|
||||
+1
-27
@@ -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;
|
||||
@@ -733,27 +730,4 @@ do_execsql_test 19.1 {
|
||||
SELECT v0.x FROM v0, rt0 WHERE v0.x = rt0.b;
|
||||
} {0.0}
|
||||
|
||||
# 2022-06-20 https://sqlite.org/forum/forumpost/57bdf2217d
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE VIRTUAL TABLE rt0 USING rtree(id, x0, x1);
|
||||
CREATE TABLE t0(a INT);
|
||||
CREATE TABLE t1(b INT);
|
||||
INSERT INTO rt0 VALUES(0, 0, 0);
|
||||
}
|
||||
do_catchsql_test 20.1 {
|
||||
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE +x0 = 0;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
do_catchsql_test 20.2 {
|
||||
SELECT * FROM t1 JOIN t0 ON x0>a RIGHT JOIN rt0 ON true WHERE x0 = 0;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
db null -
|
||||
do_execsql_test 20.3 {
|
||||
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE +x0 = 0;
|
||||
} {- - 0 0.0 0.0}
|
||||
do_execsql_test 20.4 {
|
||||
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
|
||||
} {- - 0 0.0 0.0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -23,10 +23,6 @@ ifcapable !rtree {
|
||||
return
|
||||
}
|
||||
|
||||
set ::TMPDBERROR [list 1 \
|
||||
{unable to open a temporary database file for storing temporary tables}
|
||||
]
|
||||
|
||||
# Test summary:
|
||||
#
|
||||
# rtree3-1: Test OOM in simple CREATE TABLE, INSERT, DELETE and SELECT
|
||||
@@ -200,9 +196,9 @@ do_test rtree3-7.prep {
|
||||
do_faultsim_test rtree3-7 -faults oom-* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql { ALTER TABLE rt RENAME TO rt2 }
|
||||
execsql { ALTER TABLE rt RENAME TO rt2 }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} $::TMPDBERROR
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
do_faultsim_test rtree3-8 -faults oom-* -prep {
|
||||
|
||||
@@ -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}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -342,7 +342,7 @@ do_eqp_execsql_test 7.2 {
|
||||
QUERY PLAN
|
||||
|--SCAN xdir
|
||||
|--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN ydir LEFT-JOIN
|
||||
`--SCAN ydir
|
||||
} {
|
||||
5 1 2 7 12 14 {}
|
||||
5 2 2 7 8 12 10
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,11 +25,6 @@ if {[permutation]=="session_strm" || [permutation]=="session_eec"} {
|
||||
return
|
||||
}
|
||||
|
||||
if {$::tcl_platform(pointerSize)<8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix sessionbig
|
||||
|
||||
forcedelete test.db2
|
||||
|
||||
@@ -420,7 +420,7 @@ static int sessionSerializeValue(
|
||||
|
||||
if( aBuf ){
|
||||
sessionVarintPut(&aBuf[1], n);
|
||||
if( n>0 ) memcpy(&aBuf[nVarint + 1], z, n);
|
||||
if( n ) memcpy(&aBuf[nVarint + 1], z, n);
|
||||
}
|
||||
|
||||
nByte = 1 + nVarint + n;
|
||||
@@ -1025,32 +1025,16 @@ static int sessionTableInfo(
|
||||
}else if( rc==SQLITE_ERROR ){
|
||||
zPragma = sqlite3_mprintf("");
|
||||
}else{
|
||||
*pazCol = 0;
|
||||
*pabPK = 0;
|
||||
*pnCol = 0;
|
||||
if( pzTab ) *pzTab = 0;
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
||||
}
|
||||
if( !zPragma ){
|
||||
*pazCol = 0;
|
||||
*pabPK = 0;
|
||||
*pnCol = 0;
|
||||
if( pzTab ) *pzTab = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( !zPragma ) return SQLITE_NOMEM;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
|
||||
sqlite3_free(zPragma);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pazCol = 0;
|
||||
*pabPK = 0;
|
||||
*pnCol = 0;
|
||||
if( pzTab ) *pzTab = 0;
|
||||
return rc;
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nByte = nThis + 1;
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
@@ -1468,11 +1452,7 @@ static int sessionFindTable(
|
||||
){
|
||||
rc = sqlite3session_attach(pSession, zName);
|
||||
if( rc==SQLITE_OK ){
|
||||
pRet = pSession->pTable;
|
||||
while( ALWAYS(pRet) && pRet->pNext ){
|
||||
pRet = pRet->pNext;
|
||||
}
|
||||
assert( pRet!=0 );
|
||||
for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext);
|
||||
assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) );
|
||||
}
|
||||
}
|
||||
@@ -2245,7 +2225,6 @@ static int sessionAppendUpdate(
|
||||
int i; /* Used to iterate through columns */
|
||||
u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */
|
||||
|
||||
assert( abPK!=0 );
|
||||
sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
|
||||
sessionAppendByte(pBuf, p->bIndirect, &rc);
|
||||
for(i=0; i<sqlite3_column_count(pStmt); i++){
|
||||
@@ -2550,14 +2529,12 @@ static int sessionGenerateChangeset(
|
||||
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
|
||||
int rc; /* Return code */
|
||||
|
||||
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
|
||||
assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
|
||||
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) );
|
||||
|
||||
/* Zero the output variables in case an error occurs. If this session
|
||||
** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
|
||||
** this call will be a no-op. */
|
||||
if( xOutput==0 ){
|
||||
assert( pnChangeset!=0 && ppChangeset!=0 );
|
||||
*pnChangeset = 0;
|
||||
*ppChangeset = 0;
|
||||
}
|
||||
@@ -2571,8 +2548,8 @@ static int sessionGenerateChangeset(
|
||||
for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
|
||||
if( pTab->nEntry ){
|
||||
const char *zName = pTab->zName;
|
||||
int nCol = 0; /* Number of columns in table */
|
||||
u8 *abPK = 0; /* Primary key array */
|
||||
int nCol; /* Number of columns in table */
|
||||
u8 *abPK; /* Primary key array */
|
||||
const char **azCol = 0; /* Table columns */
|
||||
int i; /* Used to iterate through hash buckets */
|
||||
sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */
|
||||
@@ -2610,7 +2587,6 @@ static int sessionGenerateChangeset(
|
||||
sessionAppendCol(&buf, pSel, iCol, &rc);
|
||||
}
|
||||
}else{
|
||||
assert( abPK!=0 ); /* Because sessionSelectStmt() returned ok */
|
||||
rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
|
||||
}
|
||||
}else if( p->op!=SQLITE_INSERT ){
|
||||
@@ -2671,10 +2647,7 @@ int sqlite3session_changeset(
|
||||
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
|
||||
void **ppChangeset /* OUT: Buffer containing changeset */
|
||||
){
|
||||
int rc;
|
||||
|
||||
if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE;
|
||||
rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
|
||||
int rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
|
||||
assert( rc || pnChangeset==0
|
||||
|| pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
|
||||
);
|
||||
@@ -2689,7 +2662,6 @@ int sqlite3session_changeset_strm(
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
){
|
||||
if( xOutput==0 ) return SQLITE_MISUSE;
|
||||
return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0);
|
||||
}
|
||||
|
||||
@@ -2701,7 +2673,6 @@ int sqlite3session_patchset_strm(
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
){
|
||||
if( xOutput==0 ) return SQLITE_MISUSE;
|
||||
return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0);
|
||||
}
|
||||
|
||||
@@ -2717,7 +2688,6 @@ int sqlite3session_patchset(
|
||||
int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
|
||||
void **ppPatchset /* OUT: Buffer containing changeset */
|
||||
){
|
||||
if( pnPatchset==0 || ppPatchset==0 ) return SQLITE_MISUSE;
|
||||
return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset);
|
||||
}
|
||||
|
||||
@@ -3681,11 +3651,11 @@ static int sessionChangesetInvert(
|
||||
}
|
||||
|
||||
assert( rc==SQLITE_OK );
|
||||
if( pnInverted && ALWAYS(ppInverted) ){
|
||||
if( pnInverted ){
|
||||
*pnInverted = sOut.nBuf;
|
||||
*ppInverted = sOut.aBuf;
|
||||
sOut.aBuf = 0;
|
||||
}else if( sOut.nBuf>0 && ALWAYS(xOutput!=0) ){
|
||||
}else if( sOut.nBuf>0 ){
|
||||
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
|
||||
}
|
||||
|
||||
@@ -4141,7 +4111,7 @@ static int sessionBindRow(
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nCol; i++){
|
||||
if( !abPK || abPK[i] ){
|
||||
sqlite3_value *pVal = 0;
|
||||
sqlite3_value *pVal;
|
||||
(void)xValue(pIter, i, &pVal);
|
||||
if( pVal==0 ){
|
||||
/* The value in the changeset was "undefined". This indicates a
|
||||
@@ -5284,9 +5254,9 @@ static int sessionChangegroupOutput(
|
||||
if( rc==SQLITE_OK ){
|
||||
if( xOutput ){
|
||||
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
|
||||
}else if( ppOut ){
|
||||
}else{
|
||||
*ppOut = buf.aBuf;
|
||||
if( pnOut ) *pnOut = buf.nBuf;
|
||||
*pnOut = buf.nBuf;
|
||||
buf.aBuf = 0;
|
||||
}
|
||||
}
|
||||
@@ -5686,7 +5656,7 @@ static int sessionRebase(
|
||||
if( sOut.nBuf>0 ){
|
||||
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
|
||||
}
|
||||
}else if( ppOut ){
|
||||
}else{
|
||||
*ppOut = (void*)sOut.aBuf;
|
||||
*pnOut = sOut.nBuf;
|
||||
sOut.aBuf = 0;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
_fiddle_exec
|
||||
_fiddle_interrupt
|
||||
_fiddle_experiment
|
||||
_fiddle_the_db
|
||||
_fiddle_db_arg
|
||||
_fiddle_db_filename
|
||||
_fiddle_reset_db
|
||||
@@ -1,14 +0,0 @@
|
||||
FS
|
||||
addFunction
|
||||
allocateUTF8OnStack
|
||||
ccall
|
||||
cwrap
|
||||
getValue
|
||||
intArrayFromString
|
||||
lengthBytesUTF8
|
||||
removeFunction
|
||||
setValue
|
||||
stackAlloc
|
||||
stackRestore
|
||||
stackSave
|
||||
stringToUTF8Array
|
||||
@@ -1,287 +0,0 @@
|
||||
# This GNU makefile exists primarily to simplify/speed up development
|
||||
# of the sqlite3 WASM components. It is not part of the canonical
|
||||
# build process.
|
||||
#
|
||||
# Maintenance notes: the fiddle build is currently performed in the
|
||||
# top-level ../../Makefile.in. It may be moved into this file at some
|
||||
# point, as GNU Make has been deemed acceptable for the WASM-related
|
||||
# components (whereas POSIX Make is required for the more conventional
|
||||
# components).
|
||||
SHELL := $(shell which bash 2>/dev/null)
|
||||
all:
|
||||
|
||||
.PHONY: fiddle
|
||||
ifneq (,$(wildcard /home/stephan))
|
||||
fiddle_opt ?= -O0
|
||||
else
|
||||
fiddle_opt = -Os
|
||||
endif
|
||||
fiddle:
|
||||
$(MAKE) -C ../.. fiddle -e emcc_opt=$(fiddle_opt)
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ../../ clean-fiddle
|
||||
-rm -f $(CLEAN_FILES)
|
||||
|
||||
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
dir.top := ../..
|
||||
# Reminder: some Emscripten flags require absolute paths
|
||||
dir.wasm := $(patsubst %/,%,$(dir $(abspath $(MAKEFILE))))
|
||||
dir.api := api
|
||||
dir.jacc := jaccwabyt
|
||||
dir.common := common
|
||||
CLEAN_FILES := *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~
|
||||
|
||||
SQLITE_OPT = \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
|
||||
-DSQLITE_ENABLE_STMTVTAB \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_THREADSAFE=0
|
||||
#SQLITE_OPT += -DSQLITE_ENABLE_MEMSYS5
|
||||
$(dir.top)/sqlite3.c:
|
||||
$(MAKE) -C $(dir.top) sqlite3.c
|
||||
|
||||
# SQLITE_OMIT_LOAD_EXTENSION: if this is true, sqlite3_vfs::xDlOpen
|
||||
# and friends may be NULL.
|
||||
|
||||
emcc_opt ?= -O0
|
||||
.PHONY: release
|
||||
release:
|
||||
$(MAKE) 'emcc_opt=-Os -g3'
|
||||
# ^^^^^ target-specific vars, e.g.:
|
||||
# release: emcc_opt=...
|
||||
# apparently only work for file targets, not PHONY targets?
|
||||
#
|
||||
# ^^^^ -O3, -Oz, -Os minify symbol names and there appears to be no
|
||||
# way around that except to use -g3, but -g3 causes the binary file
|
||||
# size to absolutely explode (approx. 5x larger). This minification
|
||||
# utterly breaks the resulting module, making it unsable except as
|
||||
# self-contained/self-referential-only code, as ALL of the exported
|
||||
# symbols get minified names.
|
||||
#
|
||||
# However, we have an option for using -Oz or -Os:
|
||||
#
|
||||
# Build with (-Os -g3) or (-Oz -g3) then use wasm-strip, from the wabt
|
||||
# tools package (https://github.com/WebAssembly/wabt), to strip the
|
||||
# debugging symbols. That results in a small build with unmangled
|
||||
# symbol names. -Oz gives ever-so-slightly better compression than
|
||||
# -Os: not quite 1% in some completely unscientific tests. Runtime
|
||||
# speed for the unit tests is all over the place either way so it's
|
||||
# difficult to say whether -Os gives any speed benefit over -Oz.
|
||||
########################################################################
|
||||
|
||||
# Emscripten SDK home dir and related binaries...
|
||||
EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/src/emsdk $(HOME)/emsdk))
|
||||
emcc.bin ?= $(word 1,$(wildcard $(shell which emcc) $(EMSDK_HOME)/upstream/emscripten/emcc))
|
||||
ifeq (,$(emcc.bin))
|
||||
$(error Cannot find emcc.)
|
||||
endif
|
||||
|
||||
wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
|
||||
ifeq (,$(filter clean,$(MAKECMDGOALS)))
|
||||
ifeq (,$(wasm-strip))
|
||||
$(info WARNING: *******************************************************************)
|
||||
$(info WARNING: builds using -O3/-Os/-Oz will minify WASM-exported names,)
|
||||
$(info WARNING: breaking _All The Things_. The workaround for that is to build)
|
||||
$(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
|
||||
$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
|
||||
$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
|
||||
$(info WARNING: If this build uses any optimization level higher than -O2 then)
|
||||
$(info WARNING: the ***resulting WASM binary WILL NOT BE USABLE***.)
|
||||
$(info WARNING: wasm-strip is part of the wabt package:)
|
||||
$(info WARNING: https://github.com/WebAssembly/wabt)
|
||||
$(info WARNING: on Ubuntu-like systems it can be installed with:)
|
||||
$(info WARNING: sudo apt install wabt)
|
||||
$(info WARNING: *******************************************************************)
|
||||
endif
|
||||
endif # 'make clean' check
|
||||
|
||||
ifeq (release,$(filter release,$(MAKECMDGOALS)))
|
||||
ifeq (,$(wasm-strip))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available. \
|
||||
See notes in the warning above)
|
||||
endif
|
||||
else
|
||||
$(info Development build. Use '$(MAKE) release' for a smaller release build.)
|
||||
endif
|
||||
|
||||
EXPORTED_FUNCTIONS.api.in := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api \
|
||||
$(dir.jacc)/jaccwabyt_test.exports
|
||||
|
||||
EXPORTED_FUNCTIONS.api: $(EXPORTED_FUNCTIONS.api.in) $(MAKEFILE)
|
||||
cat $(EXPORTED_FUNCTIONS.api.in) > $@
|
||||
CLEAN_FILES += EXPORTED_FUNCTIONS.api
|
||||
|
||||
sqlite3-api.jses := \
|
||||
$(dir.api)/sqlite3-api-prologue.js \
|
||||
$(dir.common)/whwasmutil.js \
|
||||
$(dir.jacc)/jaccwabyt.js \
|
||||
$(dir.api)/sqlite3-api-glue.js \
|
||||
$(dir.api)/sqlite3-api-oo1.js \
|
||||
$(dir.api)/sqlite3-api-worker.js \
|
||||
$(dir.api)/sqlite3-api-opfs.js \
|
||||
$(dir.api)/sqlite3-api-cleanup.js
|
||||
|
||||
sqlite3-api.js := $(dir.api)/sqlite3-api.js
|
||||
CLEAN_FILES += $(sqlite3-api.js)
|
||||
$(sqlite3-api.js): $(sqlite3-api.jses) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@for i in $(sqlite3-api.jses); do \
|
||||
echo "/* BEGIN FILE: $$i */"; \
|
||||
cat $$i; \
|
||||
echo "/* END FILE: $$i */"; \
|
||||
done > $@
|
||||
|
||||
post-js.js := $(dir.api)/post-js.js
|
||||
CLEAN_FILES += $(post-js.js)
|
||||
post-jses := \
|
||||
$(dir.api)/post-js-header.js \
|
||||
$(sqlite3-api.js) \
|
||||
$(dir.api)/post-js-footer.js
|
||||
|
||||
$(post-js.js): $(post-jses) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@for i in $(post-jses); do \
|
||||
echo "/* BEGIN FILE: $$i */"; \
|
||||
cat $$i; \
|
||||
echo "/* END FILE: $$i */"; \
|
||||
done > $@
|
||||
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o/.wasm.
|
||||
emcc.flags =
|
||||
#emcc.flags += -v # _very_ loud but also informative about what it's doing
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o.
|
||||
emcc.cflags :=
|
||||
emcc.cflags += -std=c99 -fPIC
|
||||
# -------------^^^^^^^^ we currently need c99 for WASM-specific sqlite3 APIs.
|
||||
emcc.cflags += -I. -I$(dir.top) # $(SQLITE_OPT)
|
||||
|
||||
########################################################################
|
||||
# emcc flags specific to building the final .js/.wasm file...
|
||||
emcc.jsflags := -fPIC
|
||||
emcc.jsflags += --no-entry
|
||||
emcc.jsflags += -sENVIRONMENT=web
|
||||
emcc.jsflags += -sMODULARIZE
|
||||
emcc.jsflags += -sSTRICT_JS
|
||||
emcc.jsflags += -sDYNAMIC_EXECUTION=0
|
||||
emcc.jsflags += -sNO_POLYFILL
|
||||
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(dir.wasm)/EXPORTED_FUNCTIONS.api
|
||||
emcc.jsflags += -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory # wasmMemory==>for -sIMPORTED_MEMORY
|
||||
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
|
||||
emcc.jsflags += -sIMPORTED_MEMORY
|
||||
#emcc.jsflags += -sINITIAL_MEMORY=13107200
|
||||
#emcc.jsflags += -sTOTAL_STACK=4194304
|
||||
emcc.jsflags += -sEXPORT_NAME=sqlite3InitModule
|
||||
emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
|
||||
emcc.jsflags +=--post-js=$(post-js.js)
|
||||
#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
|
||||
#emcc.jsflags += -sALLOW_UNIMPLEMENTED_SYSCALLS
|
||||
#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API
|
||||
#emcc.jsflags += -sABORTING_MALLOC
|
||||
emcc.jsflags += -sALLOW_MEMORY_GROWTH
|
||||
emcc.jsflags += -sALLOW_TABLE_GROWTH
|
||||
emcc.jsflags += -Wno-limited-postlink-optimizations
|
||||
# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
|
||||
#emcc.jsflags += -sMALLOC=emmalloc
|
||||
#emcc.jsflags += -sMALLOC=dlmalloc # a good 8k larger than emmalloc
|
||||
#emcc.jsflags += -sSTANDALONE_WASM # causes OOM errors, not sure why
|
||||
#emcc.jsflags += --import=foo_bar
|
||||
#emcc.jsflags += --no-gc-sections
|
||||
# https://lld.llvm.org/WebAssembly.html
|
||||
emcc.jsflags += -sERROR_ON_UNDEFINED_SYMBOLS=0
|
||||
emcc.jsflags += -sLLD_REPORT_UNDEFINED
|
||||
#emcc.jsflags += --allow-undefined
|
||||
emcc.jsflags += --import-undefined
|
||||
#emcc.jsflags += --unresolved-symbols=import-dynamic --experimental-pic
|
||||
#emcc.jsflags += --experimental-pic --unresolved-symbols=ingore-all --import-undefined
|
||||
#emcc.jsflags += --unresolved-symbols=ignore-all
|
||||
enable_bigint ?= 1
|
||||
ifneq (0,$(enable_bigint))
|
||||
emcc.jsflags += -sWASM_BIGINT
|
||||
endif
|
||||
emcc.jsflags += -sMEMORY64=0
|
||||
# ^^^^ MEMORY64=1 fails to load, erroring with:
|
||||
# invalid memory limits flags 0x5
|
||||
# (enable via --experimental-wasm-memory64)
|
||||
#
|
||||
# ^^^^ MEMORY64=2 builds and loads but dies when we do things like:
|
||||
#
|
||||
# new Uint8Array(heapWrappers().HEAP8U.buffer, ptr, n)
|
||||
#
|
||||
# because ptr is now a BigInt, so is invalid for passing to arguments
|
||||
# which have strict must-be-a-number requirements.
|
||||
########################################################################
|
||||
|
||||
|
||||
sqlite3.js := $(dir.api)/sqlite3.js
|
||||
sqlite3.wasm := $(dir.api)/sqlite3.wasm
|
||||
$(dir.api)/sqlite3-wasm.o: emcc.cflags += $(SQLITE_OPT)
|
||||
$(dir.api)/sqlite3-wasm.o: $(dir.top)/sqlite3.c
|
||||
$(dir.api)/wasm_util.o: emcc.cflags += $(SQLITE_OPT)
|
||||
sqlite3.wasm.c := $(dir.api)/sqlite3-wasm.c \
|
||||
$(dir.jacc)/jaccwabyt_test.c
|
||||
# ^^^ FIXME (how?): jaccwabyt_test.c is only needed for the test
|
||||
# apps. However, we want to test the release builds with those apps,
|
||||
# so we cannot simply elide that file in release builds. That
|
||||
# component is critical to the VFS bindings so needs to be tested
|
||||
# along with the core APIs.
|
||||
define WASM_C_COMPILE
|
||||
$(1).o := $$(subst .c,.o,$(1))
|
||||
sqlite3.wasm.obj += $$($(1).o)
|
||||
$$($(1).o): $$(MAKEFILE) $(1)
|
||||
$$(emcc.bin) $$(emcc_opt) $$(emcc.flags) $$(emcc.cflags) -c $(1) -o $$@
|
||||
CLEAN_FILES += $$($(1).o)
|
||||
endef
|
||||
$(foreach c,$(sqlite3.wasm.c),$(eval $(call WASM_C_COMPILE,$(c))))
|
||||
$(sqlite3.js):
|
||||
$(sqlite3.js): $(MAKEFILE) $(sqlite3.wasm.obj) \
|
||||
EXPORTED_FUNCTIONS.api \
|
||||
$(post-js.js)
|
||||
$(emcc.bin) -o $@ $(emcc_opt) $(emcc.flags) $(emcc.jsflags) $(sqlite3.wasm.obj)
|
||||
chmod -x $(sqlite3.wasm)
|
||||
ifneq (,$(wasm-strip))
|
||||
$(wasm-strip) $(sqlite3.wasm)
|
||||
endif
|
||||
@ls -la $@ $(sqlite3.wasm)
|
||||
|
||||
CLEAN_FILES += $(sqlite3.js) $(sqlite3.wasm)
|
||||
all: $(sqlite3.js)
|
||||
# End main Emscripten-based module build
|
||||
########################################################################
|
||||
|
||||
|
||||
########################################################################
|
||||
# fiddle_remote is the remote destination for the fiddle app. It
|
||||
# must be a [user@]HOST:/path for rsync.
|
||||
# Note that the target "should probably" contain a symlink of
|
||||
# index.html -> fiddle.html.
|
||||
fiddle_remote ?=
|
||||
ifeq (,$(fiddle_remote))
|
||||
ifneq (,$(wildcard /home/stephan))
|
||||
fiddle_remote = wh:www/wh/sqlite3/.
|
||||
else ifneq (,$(wildcard /home/drh))
|
||||
#fiddle_remote = if appropriate, add that user@host:/path here
|
||||
endif
|
||||
endif
|
||||
$(fiddle_files): default
|
||||
push-fiddle: $(fiddle_files)
|
||||
@if [ x = "x$(fiddle_remote)" ]; then \
|
||||
echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
|
||||
exit 1; \
|
||||
fi
|
||||
rsync -va fiddle/ $(fiddle_remote)
|
||||
# end fiddle remote push
|
||||
########################################################################
|
||||
@@ -1,103 +0,0 @@
|
||||
This directory houses the [Web Assembly (WASM)](https://en.wikipedia.org/wiki/WebAssembly)
|
||||
parts of the sqlite3 build.
|
||||
|
||||
It requires [emscripten][] and that the build environment be set up for
|
||||
emscripten. A mini-HOWTO for setting that up follows...
|
||||
|
||||
First, install the Emscripten SDK, as documented
|
||||
[here](https://emscripten.org/docs/getting_started/downloads.html) and summarized
|
||||
below for Linux environments:
|
||||
|
||||
```
|
||||
# Clone the emscripten repository:
|
||||
$ git clone https://github.com/emscripten-core/emsdk.git
|
||||
$ cd emsdk
|
||||
|
||||
# Download and install the latest SDK tools:
|
||||
$ ./emsdk install latest
|
||||
|
||||
# Make the "latest" SDK "active" for the current user:
|
||||
$ ./emsdk activate latest
|
||||
```
|
||||
|
||||
Those parts only need to be run once, but the SDK can be updated using:
|
||||
|
||||
```
|
||||
$ git pull
|
||||
$ ./emsdk activate latest
|
||||
```
|
||||
|
||||
The following needs to be run for each shell instance which needs the
|
||||
`emcc` compiler:
|
||||
|
||||
```
|
||||
# Activate PATH and other environment variables in the current terminal:
|
||||
$ source ./emsdk_env.sh
|
||||
|
||||
$ which emcc
|
||||
/path/to/emsdk/upstream/emscripten/emcc
|
||||
```
|
||||
|
||||
Optionally, add that to your login shell's resource file (`~/.bashrc`
|
||||
or equivalent).
|
||||
|
||||
That `env` script needs to be sourced for building this application
|
||||
from the top of the sqlite3 build tree:
|
||||
|
||||
```
|
||||
$ make fiddle
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
$ cd ext/wasm
|
||||
$ make
|
||||
```
|
||||
|
||||
That will generate the fiddle application under
|
||||
[ext/fiddle](/dir/ext/wasm/fiddle), as `fiddle.html`. That application
|
||||
cannot, due to XMLHttpRequest security limitations, run if the HTML
|
||||
file is opened directly in the browser (i.e. if it is opened using a
|
||||
`file://` URL), so it needs to be served via an HTTP server. For
|
||||
example, using [althttpd][]:
|
||||
|
||||
```
|
||||
$ cd ext/wasm/fiddle
|
||||
$ althttpd -page fiddle.html
|
||||
```
|
||||
|
||||
That will open the system's browser and run the fiddle app's page.
|
||||
|
||||
Note that when serving this app via [althttpd][], it must be a version
|
||||
from 2022-05-17 or newer so that it recognizes the `.wasm` file
|
||||
extension and responds with the mimetype `application/wasm`, as the
|
||||
WASM loader is pedantic about that detail.
|
||||
|
||||
|
||||
# Known Quirks and Limitations
|
||||
|
||||
Some "impedence mismatch" between C and WASM/JavaScript is to be
|
||||
expected.
|
||||
|
||||
## No I/O
|
||||
|
||||
sqlite3 shell commands which require file I/O or pipes are disabled in
|
||||
the WASM build.
|
||||
|
||||
## `exit()` Triggered from C
|
||||
|
||||
When C code calls `exit()`, as happens (for example) when running an
|
||||
"unsafe" command when safe mode is active, WASM's connection to the
|
||||
sqlite3 shell environment has no sensible choice but to shut down
|
||||
because `exit()` leaves it in a state we can no longer recover
|
||||
from. The JavaScript-side application attempts to recognize this and
|
||||
warn the user that restarting the application is necessary. Currently
|
||||
the only way to restart it is to reload the page. Restructuring the
|
||||
shell code such that it could be "rebooted" without restarting the
|
||||
JS app would require some invasive changes which are not currently
|
||||
on any TODO list but have not been entirely ruled out long-term.
|
||||
|
||||
|
||||
[emscripten]: https://emscripten.org
|
||||
[althttpd]: https://sqlite.org/althttpd
|
||||
@@ -1,72 +0,0 @@
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
_sqlite3_bind_int64
|
||||
_sqlite3_bind_null
|
||||
_sqlite3_bind_parameter_count
|
||||
_sqlite3_bind_parameter_index
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
_sqlite3_close_v2
|
||||
_sqlite3_column_blob
|
||||
_sqlite3_column_bytes
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_double
|
||||
_sqlite3_column_int
|
||||
_sqlite3_column_int64
|
||||
_sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_name
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
_sqlite3_errstr
|
||||
_sqlite3_exec
|
||||
_sqlite3_expanded_sql
|
||||
_sqlite3_extended_errcode
|
||||
_sqlite3_extended_result_codes
|
||||
_sqlite3_finalize
|
||||
_sqlite3_initialize
|
||||
_sqlite3_interrupt
|
||||
_sqlite3_libversion
|
||||
_sqlite3_libversion_number
|
||||
_sqlite3_open
|
||||
_sqlite3_open_v2
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_reset
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
_sqlite3_result_error_code
|
||||
_sqlite3_result_error_nomem
|
||||
_sqlite3_result_error_toobig
|
||||
_sqlite3_result_int
|
||||
_sqlite3_result_null
|
||||
_sqlite3_result_text
|
||||
_sqlite3_sourceid
|
||||
_sqlite3_sql
|
||||
_sqlite3_step
|
||||
_sqlite3_strglob
|
||||
_sqlite3_strlike
|
||||
_sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_value_blob
|
||||
_sqlite3_value_bytes
|
||||
_sqlite3_value_double
|
||||
_sqlite3_value_text
|
||||
_sqlite3_value_type
|
||||
_sqlite3_vfs_find
|
||||
_sqlite3_vfs_register
|
||||
_sqlite3_wasm_db_error
|
||||
_sqlite3_wasm_enum_json
|
||||
_malloc
|
||||
_free
|
||||
@@ -1,3 +0,0 @@
|
||||
FS
|
||||
wasmMemory
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user