Compare commits
180 Commits
sql-pipes
...
cli-stdlib
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b041fb97a | |||
| b7ceffdadf | |||
| 66b3ed318b | |||
| 878db7b099 | |||
| 7119a6c16b | |||
| 95f35b64da | |||
| 62d96919f6 | |||
| 2a9254cf2c | |||
| 9e59c06fb1 | |||
| 853520ddbf | |||
| 38b4158aba | |||
| 8f1f9ef09f | |||
| 8cd30e3f5b | |||
| f4382b2415 | |||
| 18e2ace468 | |||
| 697c3fb25b | |||
| 63558eae54 | |||
| 6ba175f0c8 | |||
| a55901a27c | |||
| 0be2dd9a1b | |||
| 29057f3d18 | |||
| 57b32ef924 | |||
| 3c90b86372 | |||
| 4e34558f1b | |||
| 118ac6a7ad | |||
| 7d24e6b080 | |||
| 415acd09d7 | |||
| 1d9db01065 | |||
| 253695caf3 | |||
| 5e419c1048 | |||
| 38f2c5f81c | |||
| 8a894cd804 | |||
| 7f0e0c7dbf | |||
| db467f5777 | |||
| f8305e4616 | |||
| 8513eb6ba8 | |||
| 0e8cbd5e78 | |||
| 704561f346 | |||
| ae2a4acf8d | |||
| 38b31a93b3 | |||
| eaa50b8660 | |||
| 87dce45f96 | |||
| ff60709d68 | |||
| 3b204ec8bb | |||
| 61e3067529 | |||
| d70fbffc1a | |||
| f8cafd7b11 | |||
| a95620c141 | |||
| d87a4f8bdd | |||
| dbff02abc5 | |||
| 11e1defc8f | |||
| 3d56d59adc | |||
| 7154803d4c | |||
| df9b488799 | |||
| 15e05eab32 | |||
| 9d3047bd0d | |||
| 2b30518804 | |||
| 33f0a3ed13 | |||
| 762946b236 | |||
| 8550e4a9f8 | |||
| 99f50dd219 | |||
| 7316b6c072 | |||
| d61d934f9b | |||
| d0d3182fa8 | |||
| e92f8e565b | |||
| 5c6dc45a10 | |||
| 74c8e234cd | |||
| 5735921b0f | |||
| 6677cfeda7 | |||
| 40b831851e | |||
| 6df1de1c73 | |||
| 0b8c8c861b | |||
| f7c96ee98b | |||
| 165daef043 | |||
| f1fb5ce10f | |||
| dc3bec34a6 | |||
| 2a4a4ec408 | |||
| 79254dc363 | |||
| 0c8144ab4f | |||
| 27119c56bd | |||
| a9c8f7cf34 | |||
| 923423c16f | |||
| 7a41b48cf9 | |||
| 38b26d82e6 | |||
| cd889c7a88 | |||
| 882aba4090 | |||
| 9c2f068ebd | |||
| dbab768d07 | |||
| a40f6eb80e | |||
| a8cf79e322 | |||
| 5600adf1b1 | |||
| cf25c16a54 | |||
| 8755e695c5 | |||
| f1c750e4ca | |||
| 6946a7fa50 | |||
| bc97630313 | |||
| c43d16d69a | |||
| deb6a60a84 | |||
| c4e84b7295 | |||
| 56a0480540 | |||
| dc181d41d5 | |||
| 934e796e43 | |||
| 6ffcdb1856 | |||
| 4987c5c3c2 | |||
| 21e7816e65 | |||
| 6aedd6d9fc | |||
| 7bd230cf4d | |||
| bb4d2edf10 | |||
| 109025c0a4 | |||
| 3c72072a6f | |||
| c81ab76cd9 | |||
| fd486258a0 | |||
| 940cdc94f3 | |||
| 23a16c8387 | |||
| e6e49bfef2 | |||
| 06638117bb | |||
| 22cd1eec5a | |||
| 7c6f2880aa | |||
| 70989b6f59 | |||
| ef7c692baf | |||
| da52f11250 | |||
| 7a29505e57 | |||
| d281889ac8 | |||
| a955ec806a | |||
| b5df31d15f | |||
| b9a6e42a55 | |||
| 1c30df3598 | |||
| ca447020ae | |||
| 7aa01a0ffc | |||
| 5d5d6194c9 | |||
| c97ad9b4e1 | |||
| 41155d8885 | |||
| df2d14b86e | |||
| a239ece378 | |||
| c1042cd133 | |||
| 65b1244781 | |||
| 49af3dfbf4 | |||
| a5315a6ece | |||
| f138110dfd | |||
| ad8ec9db63 | |||
| 129767958a | |||
| 90fa4c7b2c | |||
| 3196c349d1 | |||
| 0337b9a628 | |||
| 6cb12337b9 | |||
| c589d5ab06 | |||
| 28db1a68ba | |||
| 11397ce104 | |||
| 494ba30c9b | |||
| 6a18c9e06a | |||
| ccd34894e1 | |||
| c1547d1f7a | |||
| 50ca8af6f2 | |||
| 8db3fc5488 | |||
| ba5994b181 | |||
| 3341f5ce85 | |||
| d6b56d65a8 | |||
| 4f2f91bf08 | |||
| 242e064978 | |||
| 4a90f81a6d | |||
| a88d61824d | |||
| af43eddc23 | |||
| b5b4ca2a11 | |||
| c3c645ef46 | |||
| f5a9b58c8b | |||
| ce018f5bb3 | |||
| 1a7cfbebb0 | |||
| db05c66a16 | |||
| 71475478a1 | |||
| c8edf07ca7 | |||
| d9bc2bb638 | |||
| 3c39f1f5d6 | |||
| dac0d0b310 | |||
| 4a972bc1b8 | |||
| 8aa9135f2c | |||
| fcd65efcf1 | |||
| c013fa50db | |||
| 1321ea5010 | |||
| 3a39c44c21 | |||
| 20728a599e |
+86
-49
@@ -83,9 +83,13 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
#
|
||||
# Add OPTIONS=... on the command line to append additional options
|
||||
# to the OPT_FEATURE_FLAGS.
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ $(OPTIONS)
|
||||
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
|
||||
# Add in any optional parameters specified on the make commane line
|
||||
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
|
||||
@@ -646,6 +650,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
|
||||
FUZZCHECK_SRC += $(TOP)/test/vt02.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/percentile.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
|
||||
DBFUZZ_OPT =
|
||||
ST_OPT = -DSQLITE_OS_KV_OPTIONAL
|
||||
@@ -656,11 +661,16 @@ SQLITE3_SHELL_TARGET_ = sqlite3$(TEXE)
|
||||
SQLITE3_SHELL_TARGET_1 =
|
||||
SQLITE3_SHELL_TARGET = $(SQLITE3_SHELL_TARGET_@HAVE_WASI_SDK@)
|
||||
|
||||
# Use $(libtclsqlite3.la_$(HAVE_TCL)) to resolve to either
|
||||
# libtclsqlite3.la or an empty value.
|
||||
libtclsqlite3.la_0 =
|
||||
libtclsqlite3.la_1 = libtclsqlite3.la
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
#
|
||||
all: sqlite3.h libsqlite3.la $(SQLITE3_SHELL_TARGET) \
|
||||
$(HAVE_TCL:1=libtclsqlite3.la)
|
||||
$(libtclsqlite3.la_$(HAVE_TCL))
|
||||
|
||||
Makefile: $(TOP)/Makefile.in
|
||||
./config.status
|
||||
@@ -684,12 +694,26 @@ sqlite3$(TEXE): shell.c sqlite3.c
|
||||
shell.c sqlite3.c \
|
||||
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.lo $(TLIBS)
|
||||
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -I$(TOP)/ext/misc -o $@ $(TOP)/tool/sqldiff.c sqlite3.lo $(TLIBS)
|
||||
|
||||
dbhash$(TEXE): $(TOP)/tool/dbhash.c sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/dbhash.c sqlite3.lo $(TLIBS)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)/tool/sqlite3-rsync.c \
|
||||
sqlite3.c
|
||||
|
||||
RSYNC_OPT = \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-USQLITE_THREADSAFE \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync$(TEXE): $(RSYNC_SRC)
|
||||
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
|
||||
|
||||
scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
|
||||
$(LTLINK) -o $@ -I. -DSCRUB_STANDALONE \
|
||||
$(TOP)/ext/misc/scrub.c sqlite3.lo $(TLIBS)
|
||||
@@ -1163,8 +1187,6 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
@@ -1178,11 +1200,16 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/sha1.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.h \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/vfstrace.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
@@ -1363,9 +1390,14 @@ tcltest: ./testfixture$(TEXE)
|
||||
testrunner: testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration, regardless of how
|
||||
# ./configure was run. The devs run "make devtest" prior to each
|
||||
# check-in, at a minimum. Probably other tests too, but at least this
|
||||
# one.
|
||||
#
|
||||
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
|
||||
mdevtest: srctree-check has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
@@ -1381,16 +1413,19 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: srctree-check testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
|
||||
releasetest: srctree-check has_tclsh85 verify-source
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes
|
||||
#
|
||||
quicktest: ./testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
|
||||
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
# Try to run tests on whatever options are specified by the
|
||||
# ./configure. The developers seldom use this target. Instead
|
||||
# they use "make devtest" which runs tests on a standard set of
|
||||
# options regardless of how SQLite is configured. This "test"
|
||||
# target is provided for legacy only.
|
||||
#
|
||||
test: srctree-check fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
@@ -1407,8 +1442,8 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||
|
||||
shelltest: $(TESTPROGS)
|
||||
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
|
||||
shelltest:
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release shell
|
||||
|
||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
|
||||
@@ -1552,7 +1587,12 @@ lib_install: libsqlite3.la
|
||||
$(INSTALL) -d $(DESTDIR)$(libdir)
|
||||
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
|
||||
|
||||
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
|
||||
# Use $(tcl_install_$(HAVE_TCL)) to resolve to either tcl_install or
|
||||
# an empty value.
|
||||
tcl_install_0 =
|
||||
tcl_install_1 = tcl_install
|
||||
|
||||
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc $(tcl_install_$(HAVE_TCL))
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
$(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -d $(DESTDIR)$(includedir)
|
||||
@@ -1594,43 +1634,40 @@ tclextension-uninstall:
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
|
||||
|
||||
clean:
|
||||
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
|
||||
rm -f sqlite3.h opcodes.*
|
||||
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)
|
||||
rm -f testfixture$(TEXE) test.db
|
||||
|
||||
# Remove build products sufficient so that subsequent makes will recompile
|
||||
# everything from scratch. Do not remove:
|
||||
#
|
||||
# * test results and test logs
|
||||
# * output from ./configure
|
||||
#
|
||||
tidy:
|
||||
rm -f *.lo *.la *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
|
||||
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
|
||||
rm -rf .libs .deps tsrc .target_source
|
||||
rm -f lemon$(BEXE) sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
|
||||
rm -f parse.* fts5parse.*
|
||||
rm -f tclsqlite3$(TEXE) $(TESTPROGS)
|
||||
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
|
||||
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE)
|
||||
rm -f version-info$(TEXT)
|
||||
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
rm -f sqlite3.c
|
||||
rm -f sqlite3rc.h
|
||||
rm -f shell.c sqlite3ext.h
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
|
||||
rm -f sqlite-*-output.vsix
|
||||
rm -f mptester mptester.exe
|
||||
rm -f rbu rbu.exe
|
||||
rm -f srcck1 srcck1.exe
|
||||
rm -f fuzzershell fuzzershell.exe
|
||||
rm -f fuzzcheck fuzzcheck.exe
|
||||
rm -f sqldiff sqldiff.exe
|
||||
rm -f dbhash dbhash.exe
|
||||
rm -f fts5.* fts5parse.*
|
||||
rm -f threadtest5
|
||||
rm -f src-verify
|
||||
rm -f custom.rws
|
||||
rm -f has_tclsh84 has_tclsh85
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
|
||||
rm -f *.dll *.lib *.exp *.def *.pc *.vsix *.so *.dylib pkgIndex.tcl
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3-rsync$(TEXE)
|
||||
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
|
||||
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
|
||||
rm -f threadtest5$(TEXE)
|
||||
rm -f src-verify has_tclsh*
|
||||
|
||||
# Removes build products and test logs. Retains ./configure outputs.
|
||||
#
|
||||
clean: tidy
|
||||
rm -rf omittest* testrunner* testdir*
|
||||
|
||||
# Clean up everything. No exceptions.
|
||||
#
|
||||
distclean: clean
|
||||
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
|
||||
$(TESTPROGS)
|
||||
rm -f sqlite_cfg.h config.log config.status Makefile $(LIBTOOL)
|
||||
|
||||
#
|
||||
# Windows section
|
||||
|
||||
+58
-12
@@ -379,6 +379,7 @@ SQLITE_TCL_DEP =
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -392,6 +393,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
@@ -929,7 +938,7 @@ TCLSUFFIX =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLDIR
|
||||
TCLDIR = $(TOP)\compat\tcl
|
||||
TCLDIR = C:\Tcl
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLINCDIR
|
||||
@@ -1758,6 +1767,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
|
||||
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
@@ -1851,12 +1861,25 @@ $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLIT
|
||||
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# <<mark>>
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\consio $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\misc\sqlite3_stdio.h $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\misc $(TOP)\tool\sqldiff.c $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)\tool\sqlite3-rsync.c \
|
||||
$(SQLITE3C)
|
||||
|
||||
RSYNC_OPT = \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
|
||||
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -1884,6 +1907,10 @@ fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
fuzzcheck-asan.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) /fsanitize=address $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
run-fuzzcheck: fuzzcheck.exe fuzzcheck-asan.exe
|
||||
fuzzcheck --spinner $(FUZZDB)
|
||||
fuzzcheck-asan --spinner $(FUZZDB)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -2289,8 +2316,6 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(TOP)\ext\consio\console_io.h \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
@@ -2304,11 +2329,16 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\sha1.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\sqlar.c \
|
||||
$(TOP)\ext\misc\sqlite3_stdio.c \
|
||||
$(TOP)\ext\misc\sqlite3_stdio.h \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\misc\vfstrace.c \
|
||||
$(TOP)\ext\misc\zipfile.c \
|
||||
$(TOP)\ext\recover\dbdata.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.c \
|
||||
@@ -2535,6 +2565,13 @@ queryplantest: testfixture.exe shell
|
||||
fuzztest: fuzzcheck.exe
|
||||
.\fuzzcheck.exe $(FUZZDATA)
|
||||
|
||||
# Legacy testing target for third-party integrators. The SQLite
|
||||
# developers seldom use this target themselves. Instead
|
||||
# they use "nmake /f Makefile.msc devtest" which runs tests on
|
||||
# a standard set of options
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||
#
|
||||
quicktest: testfixture.exe sourcetest
|
||||
@@ -2544,7 +2581,6 @@ 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.
|
||||
#
|
||||
@@ -2558,17 +2594,27 @@ tcltest: testfixture.exe
|
||||
testrunner: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration. The devs run
|
||||
# "nmake /f Makefile.msc devtest" prior to each check-in, at a minimum.
|
||||
# Probably other tests too, but at least this one.
|
||||
#
|
||||
devtest: testfixture.exe fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
mdevtest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
#
|
||||
srctree-check: $(TOP)\tool\srctree-check.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: testfixture.exe
|
||||
testfixture.exe $(TOP)\test\testrunner.tcl release
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
|
||||
|
||||
|
||||
smoketest: $(TESTPROGS)
|
||||
@@ -2578,7 +2624,7 @@ smoketest: $(TESTPROGS)
|
||||
shelltest: $(TESTPROGS)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE_TCL_DEP)
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\misc\sqlite3_stdio.h $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE_TCL_DEP)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
@@ -2733,7 +2779,7 @@ clean:
|
||||
del /Q sqlite3.c sqlite3-*.c sqlite3.h 2>NUL
|
||||
del /Q sqlite3rc.h 2>NUL
|
||||
del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c sqlite3-rsync.exe 2>NUL
|
||||
del /Q sqlite-*-output.vsix 2>NUL
|
||||
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
|
||||
del /Q sqltclsh.* 2>NUL
|
||||
|
||||
@@ -73,23 +73,26 @@ 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.
|
||||
|
||||
To access sources directly using Fossil, first install Fossil version 2.0 or later.
|
||||
Source tarballs and precompiled binaries available
|
||||
[here](https://www.fossil-scm.org/home/uv/download.html). Fossil is
|
||||
To access sources directly using [Fossil](https://fossil-scm.org/home),
|
||||
first install Fossil version 2.0 or later.
|
||||
Source tarballs and precompiled binaries available at
|
||||
<https://fossil-scm.org/home/uv/download.html>. Fossil is
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
executable file and put that file someplace on your $PATH.
|
||||
Then run commands like this:
|
||||
|
||||
mkdir -p ~/sqlite ~/Fossils
|
||||
mkdir -p ~/sqlite
|
||||
cd ~/sqlite
|
||||
fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
|
||||
fossil open ~/Fossils/sqlite.fossil
|
||||
fossil open https://sqlite.org/src
|
||||
|
||||
After setting up a repository using the steps above, you can do
|
||||
bandwidth-efficient updates to the latest version using:
|
||||
The "fossil open" command will take two or three minutes. Afterwards,
|
||||
you can do fast, bandwidth-efficient updates to the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
fossil update trunk:2024-01-01 ;# First trunk check-in after 2024-01-01
|
||||
fossil update version-3.39.0 ;# Version 3.39.0
|
||||
|
||||
Or type "fossil ui" to get a web-based user interface.
|
||||
|
||||
@@ -103,17 +106,19 @@ script found at the root of the source tree. Then run "make".
|
||||
|
||||
For example:
|
||||
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make sqlite3 ;# Builds the "sqlite3" command-line tool
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make mdevtest ;# Run development tests (requires tcl-dev)
|
||||
make releasetest ;# Run full release tests (requires tcl-dev)
|
||||
make sqldiff ;# Builds the "sqldiff" command-line tool
|
||||
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool (requires tcl-dev)
|
||||
make tclextension-install ;# Build and install the SQLite TCL extension
|
||||
apt install gcc make tcl-dev ;# Make sure you have all the necessary build tools
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make sqlite3 ;# Builds the "sqlite3" command-line tool
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make sqldiff ;# Builds the "sqldiff" command-line tool
|
||||
# Makefile targets below this point require tcl-dev
|
||||
make tclextension-install ;# Build and install the SQLite TCL extension
|
||||
make devtest ;# Run development tests
|
||||
make releasetest ;# Run full release tests
|
||||
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool
|
||||
|
||||
See the makefile for additional targets. For debugging builds, the
|
||||
core developers typically run "configure" with options like this:
|
||||
@@ -124,9 +129,19 @@ For release builds, the core developers usually do:
|
||||
|
||||
../sqlite/configure --enable-all
|
||||
|
||||
Almost all makefile targets require a "tclsh" TCL interpreter
|
||||
version 8.6 or later. The targets marked with "(requires tcl-dev)" also require
|
||||
the TCL development libraries.
|
||||
Almost all makefile targets require a "tclsh" TCL interpreter version 8.6 or
|
||||
later. The "tclextension-install" target and the test targets that follow
|
||||
all require TCL development libraries too. ("apt install tcl-dev"). It is
|
||||
helpful, but is not required, to install the SQLite TCL extension (the
|
||||
"tclextension-install" target) prior to running tests. The "releasetest"
|
||||
target has additional requiremenst, such as "valgrind".
|
||||
|
||||
On "make" command-lines, one can add "OPTIONS=..." to specify additional
|
||||
compile-time options over and above those set by ./configure. For example,
|
||||
to compile with the SQLITE_OMIT_DEPRECATED compile-time option, one could say:
|
||||
|
||||
./configure --enable-all
|
||||
make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3
|
||||
|
||||
The configure script uses autoconf 2.61 and libtool. If the configure
|
||||
script does not work out for you, there is a generic makefile named
|
||||
@@ -136,7 +151,7 @@ show what changes are needed.
|
||||
|
||||
## Compiling for Windows Using MSVC
|
||||
|
||||
On Windows, all applicable build products can be compiled with MSVC.
|
||||
On Windows, everything can be compiled with MSVC.
|
||||
You will also need a working installation of TCL.
|
||||
See the [compile-for-windows.md](doc/compile-for-windows.md) document for
|
||||
additional information about how to install MSVC and TCL and configure your
|
||||
@@ -150,19 +165,30 @@ TCL library, using a command like this:
|
||||
SQLite uses "tclsh.exe" as part of the build process, and so that
|
||||
program will need to be somewhere on your %PATH%. SQLite itself
|
||||
does not contain any TCL code, but it does use TCL to help with the
|
||||
build process and to run tests.
|
||||
build process and to run tests. You may need to install TCL development
|
||||
libraries in order to successfully complete some makefile targets.
|
||||
It is helpful, but is not required, to install the SQLite TCL extension
|
||||
(the "tclextension-install" target) prior to running tests.
|
||||
|
||||
Build using Makefile.msc. Example:
|
||||
|
||||
nmake /f Makefile.msc sqlite3.exe
|
||||
nmake /f Makefile.msc sqlite3.c
|
||||
nmake /f Makefile.msc mdevtest
|
||||
nmake /f Makefile.msc releasetest
|
||||
nmake /f Makefile.msc sqldiff.exe
|
||||
# Makefile targets below this point require TCL development libraries
|
||||
nmake /f Makefile.msc tclextension-install
|
||||
nmake /f Makefile.msc devtest
|
||||
nmake /f Makefile.msc releasetest
|
||||
nmake /f Makefile.msc sqlite3_analyzer.exe
|
||||
|
||||
There are many other makefile targets. See comments in Makefile.msc for
|
||||
details.
|
||||
|
||||
As with the unix Makefile, the OPTIONS=... argument can be passed on the nmake
|
||||
command-line to enable new compile-time options. For example:
|
||||
|
||||
nmake /f Makefile.msc OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3.exe
|
||||
|
||||
## Source Tree Map
|
||||
|
||||
* **src/** - This directory contains the primary source code for the
|
||||
@@ -360,7 +386,7 @@ implementation. It will not be the easiest library in the world to hack.
|
||||
* **VERSION**, **manifest**, and **manifest.uuid** - These files define
|
||||
the current SQLite version number. The "VERSION" file is human generated,
|
||||
but the "manifest" and "manifest.uuid" files are automatically generated
|
||||
by the [Fossil version control system](https://fossil-scm/).
|
||||
by the [Fossil version control system](https://fossil-scm.org/).
|
||||
|
||||
There are many other source files. Each has a succinct header comment that
|
||||
describes its purpose and role within the larger system.
|
||||
|
||||
@@ -301,6 +301,7 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -314,6 +315,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
|
||||
@@ -57,11 +57,22 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc`
|
||||
<li> `nmake /f makefile.msc sqlite3.c`
|
||||
<li> `nmake /f makefile.msc sqlite3.exe`
|
||||
<li> `nmake /f makefile.msc sqldiff.exe`
|
||||
<li> `nmake /f makefile.msc tclextension-install`
|
||||
<li> `nmake /f makefile.msc devtest`
|
||||
<li> `nmake /f makefile.msc releasetest`
|
||||
<li> `nmake /f makefile.msc sqlite3.exe`
|
||||
<li> `nmake /f makefile.msc sqlite3_analyzer.exe`
|
||||
</ul>
|
||||
|
||||
It is not required that you run the "tclextension-install" target prior to
|
||||
running tests. However, the tests will run more smoothly if you do.
|
||||
The version of SQLite used for the TCL extension does *not* need to
|
||||
correspond to the version of SQLite under test. So you can install the
|
||||
SQLite TCL extension once, and then use it to test many different versions
|
||||
of SQLite.
|
||||
|
||||
|
||||
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
|
||||
commands work, add the DEBUG=3 argument to nmake. Like this:
|
||||
<ul>
|
||||
|
||||
+89
-2
@@ -595,6 +595,93 @@ oPutbUtf8(const char *cBuf, int nAccept){
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut){
|
||||
# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE)
|
||||
return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0;
|
||||
# else
|
||||
return fflush(pfOut);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE \
|
||||
&& !defined(SHELL_OMIT_FIO_DUPE) \
|
||||
&& defined(SQLITE_USE_ONLY_WIN32)
|
||||
static struct FileAltIds {
|
||||
int fd;
|
||||
HANDLE fh;
|
||||
} altIdsOfFile(FILE *pf){
|
||||
struct FileAltIds rv = { _fileno(pf) };
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
rv.fh = fid.fh;
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE size_t
|
||||
cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
|
||||
size_t rv = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
_setmode(fai.fd, fmode);
|
||||
while( rv < ocnt ){
|
||||
size_t nbo = osz;
|
||||
while( nbo > 0 ){
|
||||
DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo;
|
||||
BOOL wrc = TRUE;
|
||||
BOOL genCR = (fmode & _O_TEXT)!=0;
|
||||
if( genCR ){
|
||||
const char *pnl = (const char*)memchr(buf, '\n', nbo);
|
||||
if( pnl ) nbo = pnl - (const char*)buf;
|
||||
else genCR = 0;
|
||||
}
|
||||
if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0);
|
||||
if( genCR && wrc ){
|
||||
wrc = WriteFile(fai.fh, "\r\n", 2, 0,0);
|
||||
++dwno; /* Skip over the LF */
|
||||
}
|
||||
if( !wrc ) return rv;
|
||||
buf = (const char*)buf + dwno;
|
||||
nbo += dwno;
|
||||
}
|
||||
++rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* An fgets() equivalent, using Win32 file API for actual input.
|
||||
** Input ends when given buffer is filled or a newline is read.
|
||||
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
cfGets(char *cBuf, int n, FILE *pf){
|
||||
int nci = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
BOOL eatCR = (fmode & _O_TEXT)!=0;
|
||||
_setmode(fai.fd, fmode);
|
||||
while( nci < n-1 ){
|
||||
DWORD nr;
|
||||
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
|
||||
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
|
||||
nci += nr;
|
||||
if( cBuf[nci-nr]=='\n' ) break;
|
||||
}
|
||||
}
|
||||
if( nci < n ) cBuf[nci] = 0;
|
||||
return (nci>0)? cBuf : 0;
|
||||
}
|
||||
# else
|
||||
# define cfWrite(b,os,no,f) fwrite(b,os,no,f)
|
||||
# define cfGets(b,n,f) fgets(b,n,f)
|
||||
# endif
|
||||
|
||||
# ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept){
|
||||
@@ -606,7 +693,7 @@ ePutbUtf8(const char *cBuf, int nAccept){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfErr);
|
||||
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
@@ -672,7 +759,7 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return fgets(cBuf, ncMax, pfIn);
|
||||
return cfGets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
|
||||
+11
-4
@@ -176,12 +176,19 @@ SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Collect input like fgets(...) with special provisions for input
|
||||
** from the console on platforms that require same. Defers to the
|
||||
** C library fgets() when input is not from the console. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode(). As a
|
||||
** convenience, pfIn==NULL is treated as stdin.
|
||||
** from the console on such platforms as require same. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode().
|
||||
** As a convenience, pfIn==NULL is treated as stdin.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
|
||||
/* Like fGetsUtf8 except stream is always the designated input. */
|
||||
|
||||
@@ -428,6 +428,8 @@ do_execsql_test 5.0 {
|
||||
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
|
||||
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
|
||||
|
||||
CREATE INDEX i1 ON t1( lower(a) );
|
||||
}
|
||||
do_candidates_test 5.1 {
|
||||
SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
|
||||
@@ -457,6 +459,7 @@ do_execsql_test 5.3 {
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1 ORDER BY 1, 2;
|
||||
} {
|
||||
t1 i1 {100 50}
|
||||
t1 t1_idx_00000061 {100 50}
|
||||
t1 t1_idx_00000062 {100 20}
|
||||
t1 t1_idx_000123a7 {100 50 17}
|
||||
@@ -491,4 +494,17 @@ USE TEMP B-TREE FOR ORDER BY
|
||||
}}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE x1(a, b, c, d);
|
||||
CREATE INDEX x1ab ON x1(a, lower(b));
|
||||
CREATE INDEX x1dcba ON x1(d, b+c, a);
|
||||
}
|
||||
|
||||
do_candidates_test 6.1 {
|
||||
SELECT * FROM x1 WHERE b=? ORDER BY a;
|
||||
} {
|
||||
CREATE INDEX x1_idx_0001267f ON x1(b, a);
|
||||
CREATE INDEX x1_idx_00000062 ON x1(b);
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1623,6 +1623,12 @@ static int idxPopulateOneStat1(
|
||||
const char *zComma = zCols==0 ? "" : ", ";
|
||||
const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
|
||||
const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
|
||||
if( zName==0 ){
|
||||
/* This index contains an expression. Ignore it. */
|
||||
sqlite3_free(zCols);
|
||||
sqlite3_free(zOrder);
|
||||
return sqlite3_reset(pIndexXInfo);
|
||||
}
|
||||
zCols = idxAppendText(&rc, zCols,
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
|
||||
zComma, zName, nCol, zName, zColl
|
||||
|
||||
+7
-6
@@ -493,18 +493,19 @@ struct Fts5ExtensionApi {
|
||||
**
|
||||
** FTS5_TOKENIZER
|
||||
**
|
||||
** There is also an fts5_tokenizer object. This is an older version of
|
||||
** fts5_tokenizer_v2. It is similar except that:
|
||||
** There is also an fts5_tokenizer object. This is an older, deprecated,
|
||||
** version of fts5_tokenizer_v2. It is similar except that:
|
||||
**
|
||||
** <ul>
|
||||
** <li> There is no "iVersion" field, and
|
||||
** <li> The xTokenize() method does not take a locale argument.
|
||||
** </ul>
|
||||
**
|
||||
** fts5_tokenizer tokenizers should be registered with the xCreateTokenizer()
|
||||
** function, instead of xCreateTokenizer_v2(). Tokenizers implementations
|
||||
** registered using either API may be retrieved using both xFindTokenizer()
|
||||
** and xFindTokenizer_v2().
|
||||
** Legacy fts5_tokenizer tokenizers must be registered using the
|
||||
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
|
||||
**
|
||||
** Tokenizer implementations registered using either API may be retrieved
|
||||
** using both xFindTokenizer() and xFindTokenizer_v2().
|
||||
**
|
||||
** SYNONYM SUPPORT
|
||||
**
|
||||
|
||||
+6
-9
@@ -636,16 +636,13 @@ Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
|
||||
|
||||
int sqlite3Fts5FlushToDisk(Fts5Table*);
|
||||
|
||||
int sqlite3Fts5ExtractText(
|
||||
Fts5Config *pConfig,
|
||||
sqlite3_value *pVal, /* Value to extract text from */
|
||||
int bContent, /* Loaded from content table */
|
||||
int *pbResetTokenizer, /* OUT: True if ClearLocale() required */
|
||||
const char **ppText, /* OUT: Pointer to text buffer */
|
||||
int *pnText /* OUT: Size of (*ppText) in bytes */
|
||||
);
|
||||
|
||||
void sqlite3Fts5ClearLocale(Fts5Config *pConfig);
|
||||
void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc);
|
||||
|
||||
int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal);
|
||||
int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal,
|
||||
const char **ppText, int *pnText, const char **ppLoc, int *pnLoc
|
||||
);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5.c.
|
||||
|
||||
@@ -516,6 +516,15 @@ static int fts5ConfigMakeExprlist(Fts5Config *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( p->abUnindexed[i]==0 ){
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i);
|
||||
}else{
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( p->zContentExprlist==0 );
|
||||
p->zContentExprlist = (char*)buf.p;
|
||||
|
||||
@@ -2185,7 +2185,7 @@ static void fts5SegIterNext_None(
|
||||
|
||||
if( iOff<pIter->iEndofDoclist ){
|
||||
/* Next entry is on the current page */
|
||||
i64 iDelta;
|
||||
u64 iDelta;
|
||||
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
|
||||
pIter->iLeafOffset = iOff;
|
||||
pIter->iRowid += iDelta;
|
||||
|
||||
+196
-267
@@ -83,8 +83,17 @@ struct Fts5Global {
|
||||
Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */
|
||||
Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */
|
||||
Fts5Cursor *pCsr; /* First in list of all open cursors */
|
||||
u32 aLocaleHdr[4];
|
||||
};
|
||||
|
||||
/*
|
||||
** Size of header on fts5_locale() values. And macro to access a buffer
|
||||
** containing a copy of the header from an Fts5Config pointer.
|
||||
*/
|
||||
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
|
||||
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
|
||||
|
||||
|
||||
/*
|
||||
** Each auxiliary function registered with the FTS5 module is represented
|
||||
** by an object of the following type. All such objects are stored as part
|
||||
@@ -247,12 +256,6 @@ struct Fts5Cursor {
|
||||
#define BitFlagAllTest(x,y) (((x) & (y))==(y))
|
||||
#define BitFlagTest(x,y) (((x) & (y))!=0)
|
||||
|
||||
/*
|
||||
** The subtype value and header bytes used by fts5_locale().
|
||||
*/
|
||||
#define FTS5_LOCALE_SUBTYPE ((unsigned int)'L')
|
||||
#define FTS5_LOCALE_HEADER "\x00\xE0\xB2\xEB"
|
||||
|
||||
|
||||
/*
|
||||
** Macros to Set(), Clear() and Test() cursor flags.
|
||||
@@ -427,8 +430,7 @@ static int fts5InitVtab(
|
||||
|
||||
/* Load the initial configuration */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
sqlite3Fts5IndexRollback(pTab->p.pIndex);
|
||||
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
@@ -1257,7 +1259,7 @@ static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
|
||||
** valid until after the final call to sqlite3Fts5Tokenize() that will use
|
||||
** the locale.
|
||||
*/
|
||||
static void fts5SetLocale(
|
||||
static void sqlite3Fts5SetLocale(
|
||||
Fts5Config *pConfig,
|
||||
const char *zLocale,
|
||||
int nLocale
|
||||
@@ -1268,127 +1270,74 @@ static void fts5SetLocale(
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear any locale configured by an earlier call to fts5SetLocale() or
|
||||
** sqlite3Fts5ExtractText().
|
||||
** Clear any locale configured by an earlier call to sqlite3Fts5SetLocale().
|
||||
*/
|
||||
void sqlite3Fts5ClearLocale(Fts5Config *pConfig){
|
||||
fts5SetLocale(pConfig, 0, 0);
|
||||
sqlite3Fts5SetLocale(pConfig, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to extract utf-8 text from an sqlite3_value. This
|
||||
** is usually done in order to tokenize it. For example, when:
|
||||
**
|
||||
** * a value is written to an fts5 table,
|
||||
** * a value is deleted from an FTS5_CONTENT_NORMAL table,
|
||||
** * a value containing a query expression is passed to xFilter()
|
||||
**
|
||||
** and so on.
|
||||
**
|
||||
** This function handles 2 cases:
|
||||
**
|
||||
** 1) Ordinary values. The text can be extracted from these using
|
||||
** sqlite3_value_text().
|
||||
**
|
||||
** 2) Combination text/locale blobs created by fts5_locale(). There
|
||||
** are several cases for these:
|
||||
**
|
||||
** * Blobs tagged with FTS5_LOCALE_SUBTYPE.
|
||||
** * Blobs read from the content table of a locale=1 external-content
|
||||
** table, and
|
||||
** * Blobs read from the content table of a locale=1 regular
|
||||
** content table.
|
||||
**
|
||||
** The first two cases above should have the 4 byte FTS5_LOCALE_HEADER
|
||||
** header. It is an error if a blob with the subtype or a blob read
|
||||
** from the content table of an external content table does not have
|
||||
** the required header. A blob read from the content table of a regular
|
||||
** locale=1 table does not have the header. This is to save space.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned and output parameters (*ppText)
|
||||
** and (*pnText) are set to point to a buffer containing the extracted utf-8
|
||||
** text and its length in bytes, respectively. The buffer is not
|
||||
** nul-terminated. It has the same lifetime as the sqlite3_value object
|
||||
** from which it is extracted.
|
||||
**
|
||||
** Parameter bContent must be true if the value was read from an indexed
|
||||
** column (i.e. not UNINDEXED) of the on disk content.
|
||||
**
|
||||
** If pbResetTokenizer is not NULL and if case (2) is used, then
|
||||
** fts5SetLocale() is called to ensure subsequent sqlite3Fts5Tokenize() calls
|
||||
** use the locale. In this case (*pbResetTokenizer) is set to true before
|
||||
** returning, to indicate that the caller must call sqlite3Fts5ClearLocale()
|
||||
** to clear the locale after tokenizing the text.
|
||||
** Return true if the value passed as the only argument is an
|
||||
** fts5_locale() value.
|
||||
*/
|
||||
int sqlite3Fts5ExtractText(
|
||||
Fts5Config *pConfig,
|
||||
sqlite3_value *pVal, /* Value to extract text from */
|
||||
int bContent, /* True if indexed table content */
|
||||
int *pbResetTokenizer, /* OUT: True if xSetLocale(NULL) required */
|
||||
const char **ppText, /* OUT: Pointer to text buffer */
|
||||
int *pnText /* OUT: Size of (*ppText) in bytes */
|
||||
){
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int bDecodeBlob = 0;
|
||||
|
||||
assert( pbResetTokenizer==0 || *pbResetTokenizer==0 );
|
||||
assert( bContent==0 || pConfig->eContent!=FTS5_CONTENT_NONE );
|
||||
assert( bContent==0 || sqlite3_value_subtype(pVal)==0 );
|
||||
|
||||
int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){
|
||||
int ret = 0;
|
||||
if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
|
||||
if( sqlite3_value_subtype(pVal)==FTS5_LOCALE_SUBTYPE
|
||||
|| (bContent && pConfig->bLocale)
|
||||
){
|
||||
bDecodeBlob = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( bDecodeBlob ){
|
||||
const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
|
||||
/* Call sqlite3_value_bytes() after sqlite3_value_blob() in this case.
|
||||
** If the blob was created using zeroblob(), then sqlite3_value_blob()
|
||||
** may call malloc(). If this malloc() fails, then the values returned
|
||||
** by both value_blob() and value_bytes() will be 0. If value_bytes() were
|
||||
** called first, then the NULL pointer returned by value_blob() might
|
||||
** be dereferenced. */
|
||||
const u8 *pBlob = sqlite3_value_blob(pVal);
|
||||
int nBlob = sqlite3_value_bytes(pVal);
|
||||
|
||||
/* Unless this blob was read from the %_content table of an
|
||||
** FTS5_CONTENT_NORMAL table, it should have the 4 byte fts5_locale()
|
||||
** header. Check for this. If it is not found, return an error. */
|
||||
if( (!bContent || pConfig->eContent!=FTS5_CONTENT_NORMAL) ){
|
||||
if( nBlob<SZHDR || memcmp(FTS5_LOCALE_HEADER, pBlob, SZHDR) ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pBlob += 4;
|
||||
nBlob -= 4;
|
||||
}
|
||||
int nBlob = sqlite3_value_bytes(pVal);
|
||||
if( nBlob>FTS5_LOCALE_HDR_SIZE
|
||||
&& 0==memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE)
|
||||
){
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int nLocale = 0;
|
||||
|
||||
for(nLocale=0; nLocale<nBlob; nLocale++){
|
||||
if( pBlob[nLocale]==0x00 ) break;
|
||||
}
|
||||
if( nLocale==nBlob || nLocale==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pText = (const char*)&pBlob[nLocale+1];
|
||||
nText = nBlob-nLocale-1;
|
||||
|
||||
if( pbResetTokenizer ){
|
||||
fts5SetLocale(pConfig, (const char*)pBlob, nLocale);
|
||||
*pbResetTokenizer = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ppText = pText;
|
||||
*pnText = nText;
|
||||
return rc;
|
||||
/*
|
||||
** Value pVal is guaranteed to be an fts5_locale() value, according to
|
||||
** sqlite3Fts5IsLocaleValue(). This function extracts the text and locale
|
||||
** from the value and returns them separately.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned and (*ppText) and (*ppLoc) set
|
||||
** to point to buffers containing the text and locale, as utf-8,
|
||||
** respectively. In this case output parameters (*pnText) and (*pnLoc) are
|
||||
** set to the sizes in bytes of these two buffers.
|
||||
**
|
||||
** Or, if an error occurs, then an SQLite error code is returned. The final
|
||||
** value of the four output parameters is undefined in this case.
|
||||
*/
|
||||
int sqlite3Fts5DecodeLocaleValue(
|
||||
sqlite3_value *pVal,
|
||||
const char **ppText,
|
||||
int *pnText,
|
||||
const char **ppLoc,
|
||||
int *pnLoc
|
||||
){
|
||||
const char *p = sqlite3_value_blob(pVal);
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
int nLoc = 0;
|
||||
|
||||
assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
|
||||
assert( n>FTS5_LOCALE_HDR_SIZE );
|
||||
|
||||
for(nLoc=FTS5_LOCALE_HDR_SIZE; p[nLoc]; nLoc++){
|
||||
if( nLoc==(n-1) ){
|
||||
return SQLITE_MISMATCH;
|
||||
}
|
||||
}
|
||||
*ppLoc = &p[FTS5_LOCALE_HDR_SIZE];
|
||||
*pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE;
|
||||
|
||||
*ppText = &p[nLoc+1];
|
||||
*pnText = n - nLoc - 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1397,8 +1346,8 @@ int sqlite3Fts5ExtractText(
|
||||
** the text of the expression, and sets output variable (*pzText) to
|
||||
** point to a nul-terminated buffer containing the expression.
|
||||
**
|
||||
** If pVal was an fts5_locale() value, then fts5SetLocale() is called to
|
||||
** set the tokenizer to use the specified locale.
|
||||
** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called
|
||||
** to set the tokenizer to use the specified locale.
|
||||
**
|
||||
** If output variable (*pbFreeAndReset) is set to true, then the caller
|
||||
** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
|
||||
@@ -1410,24 +1359,22 @@ static int fts5ExtractExprText(
|
||||
char **pzText, /* OUT: nul-terminated buffer of text */
|
||||
int *pbFreeAndReset /* OUT: Free (*pzText) and clear locale */
|
||||
){
|
||||
const char *zText = 0;
|
||||
int nText = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int bReset = 0;
|
||||
|
||||
*pbFreeAndReset = 0;
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, 0, &bReset, &zText, &nText);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bReset ){
|
||||
*pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, zText);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}else{
|
||||
*pbFreeAndReset = 1;
|
||||
}
|
||||
}else{
|
||||
*pzText = (char*)zText;
|
||||
if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
*pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
}
|
||||
*pbFreeAndReset = 1;
|
||||
}else{
|
||||
*pzText = (char*)sqlite3_value_text(pVal);
|
||||
*pbFreeAndReset = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1967,19 +1914,14 @@ static int fts5UpdateMethod(
|
||||
else{
|
||||
int eType1 = sqlite3_value_numeric_type(apVal[1]);
|
||||
|
||||
/* Ensure that no fts5_locale() values are written to locale=0 tables.
|
||||
** And that no blobs except fts5_locale() blobs are written to indexed
|
||||
** (i.e. not UNINDEXED) columns of locale=1 tables. */
|
||||
int ii;
|
||||
for(ii=0; ii<pConfig->nCol; ii++){
|
||||
if( sqlite3_value_type(apVal[ii+2])==SQLITE_BLOB ){
|
||||
int bSub = (sqlite3_value_subtype(apVal[ii+2])==FTS5_LOCALE_SUBTYPE);
|
||||
if( (pConfig->bLocale && !bSub && pConfig->abUnindexed[ii]==0)
|
||||
|| (pConfig->bLocale==0 && bSub)
|
||||
){
|
||||
if( pConfig->bLocale==0 ){
|
||||
fts5SetVtabError(pTab, "fts5_locale() requires locale=1");
|
||||
}
|
||||
/* It is an error to write an fts5_locale() value to a table without
|
||||
** the locale=1 option. */
|
||||
if( pConfig->bLocale==0 ){
|
||||
int ii;
|
||||
for(ii=0; ii<pConfig->nCol; ii++){
|
||||
sqlite3_value *pVal = apVal[ii+2];
|
||||
if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
fts5SetVtabError(pTab, "fts5_locale() requires locale=1");
|
||||
rc = SQLITE_MISMATCH;
|
||||
goto update_out;
|
||||
}
|
||||
@@ -2068,9 +2010,11 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
|
||||
** Implementation of xBegin() method.
|
||||
*/
|
||||
static int fts5BeginMethod(sqlite3_vtab *pVtab){
|
||||
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
|
||||
fts5NewTransaction((Fts5FullTable*)pVtab);
|
||||
return SQLITE_OK;
|
||||
int rc = fts5NewTransaction((Fts5FullTable*)pVtab);
|
||||
if( rc==SQLITE_OK ){
|
||||
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2138,11 +2082,11 @@ static int fts5ApiTokenize_v2(
|
||||
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
fts5SetLocale(pTab->pConfig, pLoc, nLoc);
|
||||
sqlite3Fts5SetLocale(pTab->pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pTab->pConfig,
|
||||
FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
|
||||
);
|
||||
fts5SetLocale(pTab->pConfig, 0, 0);
|
||||
sqlite3Fts5SetLocale(pTab->pConfig, 0, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -2170,6 +2114,49 @@ static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
|
||||
return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This
|
||||
** function extracts the text value of column iCol of the current row.
|
||||
** Additionally, if there is an associated locale, it invokes
|
||||
** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller
|
||||
** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point
|
||||
** after this function returns.
|
||||
**
|
||||
** If successful, (*ppText) is set to point to a buffer containing the text
|
||||
** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that
|
||||
** buffer in bytes. It is not guaranteed to be nul-terminated. If an error
|
||||
** occurs, an SQLite error code is returned. The final values of the two
|
||||
** output parameters are undefined in this case.
|
||||
*/
|
||||
static int fts5TextFromStmt(
|
||||
Fts5Config *pConfig,
|
||||
sqlite3_stmt *pStmt,
|
||||
int iCol,
|
||||
const char **ppText,
|
||||
int *pnText
|
||||
){
|
||||
sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1);
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( pConfig->bLocale
|
||||
&& pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc);
|
||||
}else{
|
||||
*ppText = (const char*)sqlite3_value_text(pVal);
|
||||
*pnText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol);
|
||||
}
|
||||
}
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5ApiColumnText(
|
||||
Fts5Context *pCtx,
|
||||
int iCol,
|
||||
@@ -2189,10 +2176,8 @@ static int fts5ApiColumnText(
|
||||
}else{
|
||||
rc = fts5SeekCursor(pCsr, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
int bContent = (pConfig->abUnindexed[iCol]==0);
|
||||
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
|
||||
sqlite3Fts5ExtractText(pConfig, pVal, bContent, 0, pz, pn);
|
||||
rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn);
|
||||
sqlite3Fts5ClearLocale(pTab->pConfig);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -2234,17 +2219,15 @@ static int fts5CsrPoslist(
|
||||
rc = fts5SeekCursor(pCsr, 0);
|
||||
}
|
||||
for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
|
||||
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, i+1);
|
||||
const char *z = 0;
|
||||
int n = 0;
|
||||
int bReset = 0;
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &z, &n);
|
||||
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5ExprPopulatePoslists(
|
||||
pConfig, pCsr->pExpr, aPopulator, i, z, n
|
||||
);
|
||||
}
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
sqlite3_free(aPopulator);
|
||||
|
||||
@@ -2430,17 +2413,14 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
const char *z = 0;
|
||||
int n = 0;
|
||||
int bReset = 0;
|
||||
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, i+1);
|
||||
|
||||
pCsr->aColumnSize[i] = 0;
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &z, &n);
|
||||
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
|
||||
z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
|
||||
);
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2712,37 +2692,14 @@ static int fts5ApiColumnLocale(
|
||||
){
|
||||
rc = fts5SeekCursor(pCsr, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Load the value into pVal. pVal is a locale/text pair iff:
|
||||
**
|
||||
** 1) It is an SQLITE_BLOB, and
|
||||
** 2) Either the subtype is FTS5_LOCALE_SUBTYPE, or else the
|
||||
** value was loaded from an FTS5_CONTENT_NORMAL table, and
|
||||
** 3) It does not begin with an 0x00 byte.
|
||||
*/
|
||||
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
|
||||
if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
|
||||
const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal);
|
||||
int nBlob = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){
|
||||
const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
|
||||
if( nBlob<SZHDR || memcmp(FTS5_LOCALE_HEADER, pBlob, SZHDR) ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
pBlob += 4;
|
||||
nBlob -= 4;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int nLocale = 0;
|
||||
for(nLocale=0; nLocale<nBlob && pBlob[nLocale]!=0x00; nLocale++);
|
||||
if( nLocale==nBlob || nLocale==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
/* A locale/text pair */
|
||||
*pzLocale = (const char*)pBlob;
|
||||
*pnLocale = nLocale;
|
||||
}
|
||||
}
|
||||
const char *zDummy = 0;
|
||||
int nDummy = 0;
|
||||
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy);
|
||||
if( rc==SQLITE_OK ){
|
||||
*pzLocale = pConfig->t.pLocale;
|
||||
*pnLocale = pConfig->t.nLocale;
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2963,57 +2920,6 @@ static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Value pVal was read from column iCol of the FTS5 table. This function
|
||||
** returns it to the owner of pCtx via a call to an sqlite3_result_xxx()
|
||||
** function. This function deals with the same cases as
|
||||
** sqlite3Fts5ExtractText():
|
||||
**
|
||||
** 1) Ordinary values. These can be returned using sqlite3_result_value().
|
||||
**
|
||||
** 2) Blobs from fts5_locale(). The text is extracted from these and
|
||||
** returned via sqlite3_result_text(). The locale is discarded.
|
||||
*/
|
||||
static void fts5ExtractValueFromColumn(
|
||||
sqlite3_context *pCtx,
|
||||
Fts5Config *pConfig,
|
||||
int iCol,
|
||||
sqlite3_value *pVal
|
||||
){
|
||||
assert( pConfig->eContent!=FTS5_CONTENT_NONE );
|
||||
|
||||
if( pConfig->bLocale
|
||||
&& sqlite3_value_type(pVal)==SQLITE_BLOB
|
||||
&& pConfig->abUnindexed[iCol]==0
|
||||
){
|
||||
const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
|
||||
const u8 *pBlob = sqlite3_value_blob(pVal);
|
||||
int nBlob = sqlite3_value_bytes(pVal);
|
||||
int ii;
|
||||
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){
|
||||
if( nBlob<SZHDR || memcmp(pBlob, FTS5_LOCALE_HEADER, SZHDR) ){
|
||||
sqlite3_result_error_code(pCtx, SQLITE_ERROR);
|
||||
return;
|
||||
}else{
|
||||
pBlob += 4;
|
||||
nBlob -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
for(ii=0; ii<nBlob && pBlob[ii]; ii++);
|
||||
if( ii==0 || ii==nBlob ){
|
||||
sqlite3_result_error_code(pCtx, SQLITE_ERROR);
|
||||
}else{
|
||||
const char *pText = (const char*)&pBlob[ii+1];
|
||||
sqlite3_result_text(pCtx, pText, nBlob-ii-1, SQLITE_TRANSIENT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_result_value(pCtx, pVal);
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the xColumn method, called by SQLite to request a value from
|
||||
** the row that the supplied cursor currently points to.
|
||||
@@ -3070,8 +2976,22 @@ static int fts5ColumnMethod(
|
||||
rc = fts5SeekCursor(pCsr, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
|
||||
fts5ExtractValueFromColumn(pCtx, pConfig, iCol, pVal);
|
||||
if( pConfig->bLocale
|
||||
&& pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
const char *z = 0;
|
||||
int n = 0;
|
||||
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT);
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}else{
|
||||
sqlite3_result_value(pCtx, pVal);
|
||||
}
|
||||
}
|
||||
|
||||
pConfig->pzErrmsg = 0;
|
||||
}
|
||||
}
|
||||
@@ -3267,7 +3187,9 @@ static int fts5NewTokenizerModule(
|
||||
*/
|
||||
typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer;
|
||||
struct Fts5VtoVTokenizer {
|
||||
Fts5TokenizerModule *pMod;
|
||||
int bV2Native; /* True if v2 native tokenizer */
|
||||
fts5_tokenizer x1; /* Tokenizer functions */
|
||||
fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
|
||||
Fts5Tokenizer *pReal;
|
||||
};
|
||||
|
||||
@@ -3287,7 +3209,9 @@ static int fts5VtoVCreate(
|
||||
|
||||
pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pMod = pMod;
|
||||
pNew->x1 = pMod->x1;
|
||||
pNew->x2 = pMod->x2;
|
||||
pNew->bV2Native = pMod->bV2Native;
|
||||
if( pMod->bV2Native ){
|
||||
rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal);
|
||||
}else{
|
||||
@@ -3309,11 +3233,10 @@ static int fts5VtoVCreate(
|
||||
static void fts5VtoVDelete(Fts5Tokenizer *pTok){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
if( p ){
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
if( pMod->bV2Native ){
|
||||
pMod->x2.xDelete(p->pReal);
|
||||
if( p->bV2Native ){
|
||||
p->x2.xDelete(p->pReal);
|
||||
}else{
|
||||
pMod->x1.xDelete(p->pReal);
|
||||
p->x1.xDelete(p->pReal);
|
||||
}
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -3331,9 +3254,8 @@ static int fts5V1toV2Tokenize(
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
assert( pMod->bV2Native );
|
||||
return pMod->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
|
||||
assert( p->bV2Native );
|
||||
return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3348,10 +3270,9 @@ static int fts5V2toV1Tokenize(
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok;
|
||||
Fts5TokenizerModule *pMod = p->pMod;
|
||||
assert( pMod->bV2Native==0 );
|
||||
assert( p->bV2Native==0 );
|
||||
UNUSED_PARAM2(pLocale,nLocale);
|
||||
return pMod->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
|
||||
return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3632,13 +3553,12 @@ static void fts5LocaleFunc(
|
||||
if( zLocale==0 || zLocale[0]=='\0' ){
|
||||
sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx);
|
||||
u8 *pBlob = 0;
|
||||
u8 *pCsr = 0;
|
||||
int nBlob = 0;
|
||||
const int nHdr = 4;
|
||||
assert( sizeof(FTS5_LOCALE_HEADER)==nHdr+1 );
|
||||
|
||||
nBlob = nHdr + nLocale + 1 + nText;
|
||||
nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText;
|
||||
pBlob = (u8*)sqlite3_malloc(nBlob);
|
||||
if( pBlob==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
@@ -3646,8 +3566,8 @@ static void fts5LocaleFunc(
|
||||
}
|
||||
|
||||
pCsr = pBlob;
|
||||
memcpy(pCsr, FTS5_LOCALE_HEADER, nHdr);
|
||||
pCsr += nHdr;
|
||||
memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE);
|
||||
pCsr += FTS5_LOCALE_HDR_SIZE;
|
||||
memcpy(pCsr, zLocale, nLocale);
|
||||
pCsr += nLocale;
|
||||
(*pCsr++) = 0x00;
|
||||
@@ -3655,7 +3575,6 @@ static void fts5LocaleFunc(
|
||||
assert( &pCsr[nText]==&pBlob[nBlob] );
|
||||
|
||||
sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
|
||||
sqlite3_result_subtype(pCtx, FTS5_LOCALE_SUBTYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3757,6 +3676,16 @@ static int fts5Init(sqlite3 *db){
|
||||
pGlobal->api.xFindTokenizer = fts5FindTokenizer;
|
||||
pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2;
|
||||
pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2;
|
||||
|
||||
/* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector.
|
||||
** The constants below were generated randomly. */
|
||||
sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr);
|
||||
pGlobal->aLocaleHdr[0] ^= 0xF924976D;
|
||||
pGlobal->aLocaleHdr[1] ^= 0x16596E13;
|
||||
pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA;
|
||||
pGlobal->aLocaleHdr[3] ^= 0x9B03A67F;
|
||||
assert( sizeof(pGlobal->aLocaleHdr)==16 );
|
||||
|
||||
rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
|
||||
if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
|
||||
|
||||
+175
-63
@@ -73,6 +73,30 @@ struct Fts5Storage {
|
||||
#define FTS5_STMT_REPLACE_CONFIG 10
|
||||
#define FTS5_STMT_SCAN 11
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer obtained from sqlite3_malloc() that contains
|
||||
** nBind comma-separated question marks. e.g. if nBind is passed 5, this
|
||||
** function returns "?,?,?,?,?".
|
||||
**
|
||||
** If *pRc is not SQLITE_OK when this function is called, it is a no-op and
|
||||
** NULL is returned immediately. Or, if the attempt to malloc a buffer
|
||||
** fails, then *pRc is set to SQLITE_NOMEM and NULL is returned. Otherwise,
|
||||
** if it is SQLITE_OK when this function is called and the malloc() succeeds,
|
||||
** *pRc is left unchanged.
|
||||
*/
|
||||
static char *fts5BindingsList(int *pRc, int nBind){
|
||||
char *zBind = sqlite3Fts5MallocZero(pRc, 1 + nBind*2);
|
||||
if( zBind ){
|
||||
int ii;
|
||||
for(ii=0; ii<nBind; ii++){
|
||||
zBind[ii*2] = '?';
|
||||
zBind[ii*2 + 1] = ',';
|
||||
}
|
||||
zBind[ii*2-1] = '\0';
|
||||
}
|
||||
return zBind;
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare the two insert statements - Fts5Storage.pInsertContent and
|
||||
** Fts5Storage.pInsertDocsize - if they have not already been prepared.
|
||||
@@ -141,19 +165,20 @@ static int fts5StorageGetStmt(
|
||||
);
|
||||
break;
|
||||
|
||||
case FTS5_STMT_INSERT_CONTENT:
|
||||
case FTS5_STMT_REPLACE_CONTENT: {
|
||||
int nCol = pC->nCol + 1;
|
||||
case FTS5_STMT_INSERT_CONTENT: {
|
||||
int nCol = 0;
|
||||
char *zBind;
|
||||
int i;
|
||||
|
||||
zBind = sqlite3_malloc64(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
zBind[i*2 + 1] = ',';
|
||||
nCol = 1 + pC->nCol;
|
||||
if( pC->bLocale ){
|
||||
for(i=0; i<pC->nCol; i++){
|
||||
if( pC->abUnindexed[i]==0 ) nCol++;
|
||||
}
|
||||
zBind[i*2-1] = '\0';
|
||||
}
|
||||
|
||||
zBind = fts5BindingsList(&rc, nCol);
|
||||
if( zBind ){
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
|
||||
sqlite3_free(zBind);
|
||||
}
|
||||
@@ -344,7 +369,7 @@ int sqlite3Fts5StorageOpen(
|
||||
if( bCreate ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
int nDefn = 32 + pConfig->nCol*10;
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -356,6 +381,14 @@ int sqlite3Fts5StorageOpen(
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
if( pConfig->bLocale ){
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
}
|
||||
sqlite3_free(zDefn);
|
||||
@@ -507,7 +540,8 @@ static int fts5StorageDeleteFromIndex(
|
||||
sqlite3_value *pVal = 0;
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
int bReset = 0;
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
|
||||
assert( pSeek==0 || apVal==0 );
|
||||
assert( pSeek!=0 || apVal!=0 );
|
||||
@@ -517,10 +551,19 @@ static int fts5StorageDeleteFromIndex(
|
||||
pVal = apVal[iCol-1];
|
||||
}
|
||||
|
||||
rc = sqlite3Fts5ExtractText(
|
||||
pConfig, pVal, pSeek!=0, &bReset, &pText, &nText
|
||||
);
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pSeek ){
|
||||
pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
ctx.szCol = 0;
|
||||
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText, (void*)&ctx, fts5StorageInsertCallback
|
||||
@@ -529,7 +572,7 @@ static int fts5StorageDeleteFromIndex(
|
||||
if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -788,20 +831,35 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
int bReset = 0; /* True if tokenizer locale must be reset */
|
||||
int nText = 0; /* Size of pText in bytes */
|
||||
const char *pText = 0; /* Pointer to buffer containing text value */
|
||||
sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
|
||||
int nLoc = 0; /* Size of pLoc in bytes */
|
||||
const char *pLoc = 0; /* Pointer to buffer containing text value */
|
||||
|
||||
sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale ){
|
||||
int iCol = ctx.iCol + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(pScan, iCol);
|
||||
nLoc = sqlite3_column_bytes(pScan, iCol);
|
||||
}
|
||||
}
|
||||
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &pText, &nText);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
|
||||
@@ -884,29 +942,45 @@ int sqlite3Fts5StorageContentInsert(
|
||||
}else{
|
||||
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
|
||||
int i; /* Counter variable */
|
||||
int nIndexed = 0; /* Number indexed columns seen */
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
if( pInsert ) sqlite3_clear_bindings(pInsert);
|
||||
|
||||
/* Bind the rowid value */
|
||||
sqlite3_bind_value(pInsert, 1, apVal[1]);
|
||||
|
||||
/* Loop through values for user-defined columns. i=2 is the leftmost
|
||||
** user-defined column. As is column 1 of pSavedRow. */
|
||||
for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
int bUnindexed = pConfig->abUnindexed[i-2];
|
||||
sqlite3_value *pVal = apVal[i];
|
||||
|
||||
nIndexed += !bUnindexed;
|
||||
if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
|
||||
/* This is an UPDATE statement, and column (i-2) was not modified.
|
||||
** Retrieve the value from Fts5Storage.pSavedRow instead. */
|
||||
pVal = sqlite3_column_value(p->pSavedRow, i-1);
|
||||
}else if( sqlite3_value_subtype(pVal)==FTS5_LOCALE_SUBTYPE ){
|
||||
assert( pConfig->bLocale );
|
||||
assert( i>1 );
|
||||
if( pConfig->abUnindexed[i-2] ){
|
||||
/* At attempt to insert an fts5_locale() value into an UNINDEXED
|
||||
** column. Strip the locale away and just bind the text. */
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, 0, 0, &pText, &nText);
|
||||
sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal);
|
||||
int nBlob = sqlite3_value_bytes(pVal);
|
||||
assert( nBlob>4 );
|
||||
sqlite3_bind_blob(pInsert, i, pBlob+4, nBlob-4, SQLITE_TRANSIENT);
|
||||
if( pConfig->bLocale && bUnindexed==0 ){
|
||||
sqlite3_bind_value(pInsert, pConfig->nCol + 1 + nIndexed,
|
||||
sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
|
||||
);
|
||||
}
|
||||
}else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
const char *pText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nText = 0;
|
||||
int nLoc = 0;
|
||||
assert( pConfig->bLocale );
|
||||
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
|
||||
if( bUnindexed==0 ){
|
||||
int iLoc = pConfig->nCol + 1 + nIndexed;
|
||||
sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -945,23 +1019,37 @@ int sqlite3Fts5StorageIndexInsert(
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
int bReset = 0; /* True if tokenizer locale must be reset */
|
||||
int nText = 0; /* Size of pText in bytes */
|
||||
const char *pText = 0; /* Pointer to buffer containing text value */
|
||||
int nLoc = 0; /* Size of pText in bytes */
|
||||
const char *pLoc = 0; /* Pointer to buffer containing text value */
|
||||
|
||||
sqlite3_value *pVal = apVal[ctx.iCol+2];
|
||||
int bDisk = 0;
|
||||
if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
|
||||
pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
|
||||
bDisk = 1;
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
|
||||
int iCol = ctx.iCol + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
|
||||
nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
|
||||
}
|
||||
}else{
|
||||
pVal = apVal[ctx.iCol+2];
|
||||
}
|
||||
rc = sqlite3Fts5ExtractText(pConfig, pVal, bDisk, &bReset, &pText,&nText);
|
||||
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( bReset==0 || pConfig->bLocale );
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
|
||||
@@ -1126,37 +1214,61 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i] ) continue;
|
||||
ctx.iCol = i;
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int bReset = 0; /* True if tokenizer locale must be reset */
|
||||
int nText = 0; /* Size of pText in bytes */
|
||||
const char *pText = 0; /* Pointer to buffer containing text value */
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);
|
||||
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(
|
||||
pVal, &pText, &nText, &pLoc, &nLoc
|
||||
);
|
||||
}else{
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
|
||||
int iCol = i + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(pScan, iCol);
|
||||
nLoc = sqlite3_column_bytes(pScan, iCol);
|
||||
}
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
}
|
||||
|
||||
ctx.iCol = i;
|
||||
ctx.szCol = 0;
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
|
||||
rc = sqlite3Fts5ExtractText(pConfig,
|
||||
sqlite3_column_value(pScan, i+1), 1, &bReset, &pText, &nText
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageIntegrityCallback
|
||||
);
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
|
||||
/* If this is not a columnsize=0 database, check that the number
|
||||
** of tokens in the value matches the aColSize[] value read from
|
||||
** the %_docsize table. */
|
||||
if( rc==SQLITE_OK
|
||||
&& pConfig->bColumnsize
|
||||
&& ctx.szCol!=aColSize[i]
|
||||
){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
aTotalSize[i] += ctx.szCol;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
ctx.pTermset = 0;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
aTotalSize[i] += ctx.szCol;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
ctx.pTermset = 0;
|
||||
}
|
||||
}
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
|
||||
+96
-15
@@ -96,14 +96,14 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
||||
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||
sqlite3_step(pStmt);
|
||||
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
CASE(12, "xSetAuxdata") {
|
||||
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
|
||||
if( pData==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", 0);
|
||||
Tcl_AppendResult(interp, "out of memory", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pData->pObj = objv[2];
|
||||
@@ -452,7 +452,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
|
||||
rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
|
||||
@@ -683,7 +683,7 @@ static int SQLITE_TCLAPI f5tCreateFunction(
|
||||
pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy
|
||||
);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -750,7 +750,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
if( objc==5 ){
|
||||
char *zOpt = Tcl_GetString(objv[1]);
|
||||
if( strcmp("-subst", zOpt) ){
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0);
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -759,7 +759,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( nArg==0 ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", (char*)0);
|
||||
Tcl_Free((void*)azArg);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -767,13 +767,13 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
|
||||
rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], (int)(nArg-1), &pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -787,7 +787,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1049,7 +1049,7 @@ static int SQLITE_TCLAPI f5tTokenizerLocale(
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_locale may only be used by tokenizer callback", 0
|
||||
"sqlite3_fts5_locale may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1098,7 +1098,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", 0
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1250,7 +1250,7 @@ static int SQLITE_TCLAPI f5tCreateTokenizer(
|
||||
Tcl_AppendResult(interp, (
|
||||
bV2 ? "error in fts5_api.xCreateTokenizer_v2()"
|
||||
: "error in fts5_api.xCreateTokenizer()"
|
||||
), 0);
|
||||
), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1540,12 +1540,92 @@ static int SQLITE_TCLAPI f5tRegisterOriginText(
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to DROP an fts5 table. It works even if the data
|
||||
** structures fts5 stores within the database are corrupt, which sometimes
|
||||
** prevents a straight "DROP TABLE" command from succeeding.
|
||||
**
|
||||
** The first parameter is the database handle to use for the DROP TABLE
|
||||
** operation. The second is the name of the database to drop the fts5 table
|
||||
** from (i.e. "main", "temp" or the name of an attached database). The
|
||||
** third parameter is the name of the fts5 table to drop.
|
||||
**
|
||||
** SQLITE_OK is returned if the table is successfully dropped. Or, if an
|
||||
** error occurs, an SQLite error code.
|
||||
*/
|
||||
static int sqlite3_fts5_drop_corrupt_table(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const char *zDb, /* Database name ("main", "temp" etc.) */
|
||||
const char *zTab /* Name of fts5 table to drop */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int bDef = 0;
|
||||
|
||||
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDef);
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zScript = sqlite3_mprintf(
|
||||
"DELETE FROM %Q.'%q_data';"
|
||||
"DELETE FROM %Q.'%q_config';"
|
||||
"INSERT INTO %Q.'%q_data' VALUES(10, X'0000000000');"
|
||||
"INSERT INTO %Q.'%q_config' VALUES('version', 4);"
|
||||
"DROP TABLE %Q.'%q';",
|
||||
zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab
|
||||
);
|
||||
|
||||
if( zScript==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
|
||||
rc = sqlite3_exec(db, zScript, 0, 0, 0);
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
|
||||
sqlite3_free(zScript);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_drop_corrupt_table DB DATABASE TABLE
|
||||
**
|
||||
** Description...
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tDropCorruptTable(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db = 0;
|
||||
const char *zDb = 0;
|
||||
const char *zTab = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB DATABASE TABLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbPointer(interp, objv[1], &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zDb = Tcl_GetString(objv[2]);
|
||||
zTab = Tcl_GetString(objv[3]);
|
||||
|
||||
rc = sqlite3_fts5_drop_corrupt_table(db, zDb, zTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Entry point.
|
||||
*/
|
||||
@@ -1564,7 +1644,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
|
||||
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
|
||||
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 }
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
|
||||
};
|
||||
int i;
|
||||
F5tTokenizerContext *pContext;
|
||||
|
||||
@@ -103,13 +103,13 @@ do_execsql_test 3.0 {
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
INSERT INTO x1(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {1 {datatype mismatch}}
|
||||
} {0 {}}
|
||||
do_catchsql_test 3.2 {
|
||||
INSERT INTO x2(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {1 {datatype mismatch}}
|
||||
} {0 {}}
|
||||
do_catchsql_test 3.3 {
|
||||
INSERT INTO x3(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {1 {datatype mismatch}}
|
||||
} {0 {}}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
@@ -680,11 +680,11 @@ do_test 12.0 {
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 11.2 {
|
||||
INSERT INTO t1(t1, rank) VALUES('merge', 500);
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1040,7 +1040,7 @@ do_test 16.0 {
|
||||
|
||||
do_catchsql_test 16.1 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1126,7 +1126,7 @@ do_test 17.0 {
|
||||
|
||||
do_catchsql_test 17.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1630,7 +1630,7 @@ do_test 20.0 {
|
||||
|
||||
do_catchsql_test 20.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -2100,7 +2100,7 @@ do_test 22.0 {
|
||||
|
||||
do_catchsql_test 22.1 {
|
||||
INSERT INTO t1(t1) VALUES('optimize');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -3700,7 +3700,7 @@ do_catchsql_test 32.1 {
|
||||
highlight(t1, 2, '[', ']')
|
||||
FROM t1('g + h')
|
||||
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 32.2 {
|
||||
SELECT * FROM t3;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# 2024 Aug 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt8
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1_data SET block='hello world' WHERE id=10
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 1.3 {
|
||||
DROP TABLE t1
|
||||
} {0 {}}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 2.1 {
|
||||
UPDATE t1_config SET v=555 WHERE k='version'
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 2.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_test 2.4 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_execsql_test 2.5 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
DELETE FROM t1_config;
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 3.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
|
||||
|
||||
do_test 3.4 {
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
} {1}
|
||||
do_test 3.5 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_test 3.6 {
|
||||
sqlite3_db_config db DEFENSIVE -1
|
||||
} {1}
|
||||
do_execsql_test 3.7 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -90,7 +90,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
|
||||
do_faultsim_test 4 -faults oom-* -body {
|
||||
db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
|
||||
} -test {
|
||||
faultsim_test_result {0 {0 {} 3}}
|
||||
faultsim_test_result {0 {0 {} 2}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -246,7 +246,7 @@ do_execsql_test 10.1 {
|
||||
} {hello}
|
||||
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 10 -faults oom* -prep {
|
||||
do_faultsim_test 10.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
@@ -256,6 +256,39 @@ do_faultsim_test 10 -faults oom* -prep {
|
||||
faultsim_test_result {0 hello}
|
||||
}
|
||||
|
||||
breakpoint
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 10.2 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO ft VALUES(zeroblob(10000));
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(content);
|
||||
CREATE TABLE g1(id, content);
|
||||
INSERT INTO g1 VALUES(30000, 'a b c');
|
||||
INSERT INTO g1 VALUES(40000, 'd e f');
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO f1(rowid, content) SELECT id, content FROM g1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 2024 September 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests focused on the integrity-check procedure.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5integrity2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(a, detail='none');
|
||||
BEGIN;
|
||||
INSERT INTO t2(rowid, a) VALUES(-1, 'hello world');
|
||||
INSERT INTO t2(rowid, a) VALUES(9223372036854775807, 'hello world');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT rowid FROM t2('hello AND world');
|
||||
} {-1 9223372036854775807}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none');
|
||||
CREATE TABLE r1(r);
|
||||
|
||||
WITH c(x) AS (VALUES(1) UNION SELECT x<<1 FROM c)
|
||||
INSERT INTO r1(r) SELECT -1-x FROM c;
|
||||
|
||||
INSERT INTO t1(rowid, a) SELECT r, 'abc' FROM r1;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT rowid FROM t1('abc') ORDER BY +rowid;
|
||||
} [db eval {SELECT r FROM r1 ORDER BY r}]
|
||||
|
||||
|
||||
finish_test
|
||||
+106
-25
@@ -73,6 +73,7 @@ do_execsql_test 1.2 {
|
||||
SELECT rowid, a FROM t1( fts5_locale('reverse', 'abc') );
|
||||
} {2 cba}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the locale= option exists and seems to accept values. And
|
||||
# that fts5_locale() values may only be inserted into an internal-content
|
||||
@@ -99,8 +100,11 @@ do_catchsql_test 2.3 {
|
||||
INSERT INTO b1(b1, rank) VALUES('locale', 0);
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
do_execsql_test 2.4.1 {
|
||||
INSERT INTO b1 VALUES('abc', 'one two three');
|
||||
}
|
||||
|
||||
do_execsql_test 2.4.2 {
|
||||
INSERT INTO b1 VALUES('def', fts5_locale('reverse', 'four five six'));
|
||||
}
|
||||
|
||||
@@ -131,6 +135,7 @@ do_execsql_test 2.12 { SELECT quote(y) FROM b1('ruof') } {
|
||||
do_execsql_test 2.13 {
|
||||
INSERT INTO b1(b1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.14 {
|
||||
INSERT INTO b1(b1) VALUES('rebuild');
|
||||
}
|
||||
@@ -149,7 +154,6 @@ do_execsql_test 2.18 {
|
||||
INSERT INTO b1(rowid, x, y) VALUES(
|
||||
test_setsubtype(45, 76), 'abc def', 'def abc'
|
||||
);
|
||||
INSERT INTO b1(b1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -278,9 +282,9 @@ do_execsql_test 5.2 {
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
SELECT typeof(c0), typeof(c1) FROM t1_content
|
||||
SELECT typeof(c0), typeof(c1), typeof(l0) FROM t1_content
|
||||
} {
|
||||
blob text
|
||||
text text text
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -305,37 +309,37 @@ foreach {tn opt} {
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 5.$tn.3 {
|
||||
do_execsql_test 6.$tn.3 {
|
||||
SELECT fts5_test_columnsize(y1) FROM y1
|
||||
} {
|
||||
2 3 2 4
|
||||
}
|
||||
|
||||
do_execsql_test 5.$tn.4 {
|
||||
do_execsql_test 6.$tn.4 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('shall');
|
||||
} {
|
||||
2 3
|
||||
}
|
||||
|
||||
do_execsql_test 5.$tn.5 {
|
||||
do_execsql_test 6.$tn.5 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('shall');
|
||||
} {
|
||||
2 3
|
||||
}
|
||||
|
||||
do_execsql_test 5.$tn.6 {
|
||||
do_execsql_test 6.$tn.6 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('have');
|
||||
} {
|
||||
4 4
|
||||
}
|
||||
|
||||
do_execsql_test 5.$tn.7 {
|
||||
do_execsql_test 6.$tn.7 {
|
||||
SELECT rowid, highlight(y1, 0, '[', ']') FROM y1('have');
|
||||
} {
|
||||
4 {which it hath been used to [have]}
|
||||
}
|
||||
|
||||
do_execsql_test 5.$tn.8 {
|
||||
do_execsql_test 6.$tn.8 {
|
||||
SELECT rowid,
|
||||
highlight(y1, 0, '[', ']'),
|
||||
snippet(y1, 0, '[', ']', '...', 10)
|
||||
@@ -473,7 +477,7 @@ foreach_detail_mode $::testprefix {
|
||||
}
|
||||
|
||||
foreach {tn v} {
|
||||
1 X'001122'
|
||||
1 X'001152'
|
||||
2 X'0011223344'
|
||||
3 X'00E0B2EB68656c6c6f'
|
||||
4 X'00E0B2EB0068656c6c6f'
|
||||
@@ -484,33 +488,33 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 10.2.$tn.3 {
|
||||
INSERT INTO ft(ft) VALUES('rebuild');
|
||||
} {1 {SQL logic error}}
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 10.2.$tn.4 "
|
||||
SELECT * FROM ft( test_setsubtype($v, 76) );
|
||||
" {1 {SQL logic error}}
|
||||
" {1 {fts5: syntax error near ""}}
|
||||
|
||||
do_execsql_test 10.2.$tn.5 {
|
||||
INSERT INTO ft(rowid, x) VALUES(1, 'hello world');
|
||||
}
|
||||
|
||||
if {"%DETAIL%"!="full"} {
|
||||
do_catchsql_test 10.2.$tn.6 {
|
||||
if {"%DETAIL%"=="full"} {
|
||||
do_execsql_test 10.2.$tn.6 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('world');
|
||||
} {1 SQLITE_ERROR}
|
||||
} {0.0.1}
|
||||
|
||||
do_catchsql_test 10.2.$tn.7 {
|
||||
do_execsql_test 10.2.$tn.7.1 {
|
||||
SELECT fts5_test_columnsize(ft) FROM ft('world');
|
||||
} {1 SQLITE_ERROR}
|
||||
} {1}
|
||||
|
||||
do_catchsql_test 10.2.$tn.7 {
|
||||
do_execsql_test 10.2.$tn.7.2 {
|
||||
SELECT fts5_test_columnlocale(ft) FROM ft('world');
|
||||
} {1 SQLITE_ERROR}
|
||||
} {{{}}}
|
||||
}
|
||||
|
||||
do_catchsql_test 10.2.$tn.8 {
|
||||
SELECT * FROM ft('hello')
|
||||
} {1 {SQL logic error}}
|
||||
SELECT count(*) FROM ft('hello')
|
||||
} {0 1}
|
||||
|
||||
do_catchsql_test 10.2.$tn.9 {
|
||||
PRAGMA integrity_check;
|
||||
@@ -523,11 +527,11 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 10.2.$tn.11 "
|
||||
INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, test_setsubtype($v,76) )
|
||||
" {1 {SQL logic error}}
|
||||
" {0 {}}
|
||||
|
||||
do_catchsql_test 10.2.$tn.12 "
|
||||
INSERT INTO ft(rowid, x) VALUES(2, test_setsubtype($v,76) )
|
||||
" {1 {SQL logic error}}
|
||||
" {0 {}}
|
||||
|
||||
do_execsql_test 10.2.$tn.13 {
|
||||
INSERT INTO ft2(rowid, x) VALUES(1, 'hello world');
|
||||
@@ -536,7 +540,7 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 10.2.$tn.15 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {SQL logic error}}
|
||||
} {0 {{malformed inverted index for FTS5 table main.ft2}}}
|
||||
|
||||
do_execsql_test 10.2.$tn.16 {
|
||||
DELETE FROM ft2_content;
|
||||
@@ -663,5 +667,82 @@ do_catchsql_test 13.2.7 {
|
||||
FROM ft('one AND three') ORDER BY rowid
|
||||
} {1 {non-integer argument passed to function fts5_get_locale()}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that UPDATE statements that may affect more than one row work.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 14.1 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, locale=1);
|
||||
}
|
||||
|
||||
do_execsql_test 14.2 {
|
||||
INSERT INTO ft VALUES('hello', 'world');
|
||||
}
|
||||
|
||||
do_execsql_test 14.3 {
|
||||
UPDATE ft SET b = fts5_locale('en_AU', 'world');
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
INSERT INTO ft VALUES(X'abcd', X'1234');
|
||||
} {}
|
||||
|
||||
do_execsql_test 14.5 {
|
||||
SELECT quote(a), quote(b) FROM ft
|
||||
} {'hello' 'world' X'ABCD' X'1234'}
|
||||
|
||||
do_execsql_test 14.6 {
|
||||
DELETE FROM ft;
|
||||
INSERT INTO ft VALUES(NULL, 'null');
|
||||
INSERT INTO ft VALUES(123, 'int');
|
||||
INSERT INTO ft VALUES(345.0, 'real');
|
||||
INSERT INTO ft VALUES('abc', 'text');
|
||||
INSERT INTO ft VALUES(fts5_locale('abc', 'def'), 'text');
|
||||
|
||||
SELECT a, typeof(a), b FROM ft
|
||||
} {
|
||||
{} null null
|
||||
123 integer int
|
||||
345.0 real real
|
||||
abc text text
|
||||
def text text
|
||||
}
|
||||
|
||||
do_execsql_test 14.7 {
|
||||
SELECT quote(c0), typeof(c0) FROM ft_content
|
||||
} {
|
||||
NULL null
|
||||
123 integer
|
||||
345.0 real
|
||||
'abc' text
|
||||
'def' text
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that inserting UNINDEXED columns between indexed columns of a
|
||||
# locale=1 table does not cause a problem.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 15.1 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b UNINDEXED, c, locale=1, tokenize=tcl);
|
||||
}
|
||||
|
||||
do_execsql_test 15.2 {
|
||||
INSERT INTO ft VALUES('one', 'two', 'three');
|
||||
INSERT INTO ft VALUES('one', 'two', fts5_locale('loc', 'three'));
|
||||
}
|
||||
|
||||
do_execsql_test 15.3 {
|
||||
SELECT c2, l2 FROM ft_content
|
||||
} {three {} three loc}
|
||||
|
||||
do_execsql_test 15.4 {
|
||||
SELECT c, fts5_columnlocale(ft, 2) FROM ft
|
||||
} {three {} three loc}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -44,12 +44,12 @@ do_catchsql_test 1.2.2 {
|
||||
|
||||
do_catchsql_test 1.3.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
do_catchsql_test 1.3.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
@@ -57,12 +57,12 @@ sqlite3 db test.db
|
||||
do_catchsql_test 1.3.3 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 1.3.4 {
|
||||
SELECT fts5_columntext(t1) FROM t1('*reads');
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -93,15 +93,21 @@ foreach {tn cols tokens} {
|
||||
10 {b} "i e"
|
||||
11 {a} "i e"
|
||||
} {
|
||||
set fts "{$cols}:[join $tokens +]"
|
||||
set where [list]
|
||||
foreach c $cols { lappend where "pmatch($c, '$tokens')" }
|
||||
set where [join $where " OR "]
|
||||
|
||||
set res [db eval "SELECT rowid FROM t3 WHERE $where"]
|
||||
do_execsql_test "1.$tn.$fts->([llength $res] rows)" {
|
||||
SELECT rowid FROM t3($fts)
|
||||
} $res
|
||||
foreach fts [list \
|
||||
"{$cols}:[join $tokens +]" \
|
||||
"{$cols}:NEAR([join $tokens +])" \
|
||||
"{$cols}:NEAR([join $tokens +],1)" \
|
||||
"{$cols}:NEAR([join $tokens +],111)" \
|
||||
] {
|
||||
set res [db eval "SELECT rowid FROM t3 WHERE $where"]
|
||||
do_execsql_test "1.$tn.$fts->([llength $res] rows)" {
|
||||
SELECT rowid FROM t3($fts)
|
||||
} $res
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
|
||||
@@ -350,7 +350,7 @@ do_execsql_test 14.3 {
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'
|
||||
} {0 {} 3}
|
||||
} {0 {} 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
+10
-3
@@ -40,7 +40,7 @@
|
||||
** modification-time of the target file is set to this value before
|
||||
** returning.
|
||||
**
|
||||
** If three or more arguments are passed to this function and an
|
||||
** If five or more arguments are passed to this function and an
|
||||
** error is encountered, an exception is raised.
|
||||
**
|
||||
** READFILE(FILE):
|
||||
@@ -110,6 +110,13 @@ SQLITE_EXTENSION_INIT1
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* When used as part of the CLI, the sqlite3_stdio.h module will have
|
||||
** been included before this one. In that case use the sqlite3_stdio.h
|
||||
** #defines. If not, create our own for fopen().
|
||||
*/
|
||||
#ifndef _SQLITE3_STDIO_H_
|
||||
# define sqlite3_fopen fopen
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Structure of the fsdir() table-valued function
|
||||
@@ -142,7 +149,7 @@ static void readFileContents(sqlite3_context *ctx, const char *zName){
|
||||
sqlite3 *db;
|
||||
int mxBlob;
|
||||
|
||||
in = fopen(zName, "rb");
|
||||
in = sqlite3_fopen(zName, "rb");
|
||||
if( in==0 ){
|
||||
/* File does not exist or is unreadable. Leave the result set to NULL. */
|
||||
return;
|
||||
@@ -397,7 +404,7 @@ static int writeFile(
|
||||
sqlite3_int64 nWrite = 0;
|
||||
const char *z;
|
||||
int rc = 0;
|
||||
FILE *out = fopen(zFile, "wb");
|
||||
FILE *out = sqlite3_fopen(zFile, "wb");
|
||||
if( out==0 ) return 1;
|
||||
z = (const char*)sqlite3_value_blob(pData);
|
||||
if( z ){
|
||||
|
||||
+303
-89
@@ -11,7 +11,7 @@
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains code to implement the percentile(Y,P) SQL function
|
||||
** as described below:
|
||||
** and similar as described below:
|
||||
**
|
||||
** (1) The percentile(Y,P) function is an aggregate function taking
|
||||
** exactly two arguments.
|
||||
@@ -60,31 +60,105 @@
|
||||
**
|
||||
** (13) A separate median(Y) function is the equivalent percentile(Y,50).
|
||||
**
|
||||
** (14) A separate percentile_cond(Y,X) function is the equivalent of
|
||||
** percentile(Y,X*100.0).
|
||||
** (14) A separate percentile_cont(Y,P) function is equivalent to
|
||||
** percentile(Y,P/100.0). In other words, the fraction value in
|
||||
** the second argument is in the range of 0 to 1 instead of 0 to 100.
|
||||
**
|
||||
** (15) A separate percentile_disc(Y,P) function is like
|
||||
** percentile_cont(Y,P) except that instead of returning the weighted
|
||||
** average of the nearest two input values, it returns the next lower
|
||||
** value. So the percentile_disc(Y,P) will always return a value
|
||||
** that was one of the inputs.
|
||||
**
|
||||
** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and
|
||||
** percentile_disc(Y,P) can be used as window functions.
|
||||
**
|
||||
** Differences from standard SQL:
|
||||
**
|
||||
** * The percentile_cont(X,P) function is equivalent to the following in
|
||||
** standard SQL:
|
||||
**
|
||||
** (percentile_cont(P) WITHIN GROUP (ORDER BY X))
|
||||
**
|
||||
** The SQLite syntax is much more compact. The standard SQL syntax
|
||||
** is also supported if SQLite is compiled with the
|
||||
** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
|
||||
**
|
||||
** * No median(X) function exists in the SQL standard. App developers
|
||||
** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
|
||||
**
|
||||
** * No percentile(Y,P) function exists in the SQL standard. Instead of
|
||||
** percential(Y,P), developers must write this:
|
||||
** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that
|
||||
** the fraction parameter to percentile() goes from 0 to 100 whereas
|
||||
** the fraction parameter in SQL standard percentile_cont() goes from
|
||||
** 0 to 1.
|
||||
**
|
||||
** Implementation notes as of 2024-08-31:
|
||||
**
|
||||
** * The regular aggregate-function versions of these routines work
|
||||
** by accumulating all values in an array of doubles, then sorting
|
||||
** that array using quicksort before computing the answer. Thus
|
||||
** the runtime is O(NlogN) where N is the number of rows of input.
|
||||
**
|
||||
** * For the window-function versions of these routines, the array of
|
||||
** inputs is sorted as soon as the first value is computed. Thereafter,
|
||||
** the array is kept in sorted order using an insert-sort. This
|
||||
** results in O(N*K) performance where K is the size of the window.
|
||||
** One can imagine alternative implementations that give O(N*logN*logK)
|
||||
** performance, but they require more complex logic and data structures.
|
||||
** The developers have elected to keep the asymptotically slower
|
||||
** algorithm for now, for simplicity, under the theory that window
|
||||
** functions are seldom used and when they are, the window size K is
|
||||
** often small. The developers might revisit that decision later,
|
||||
** should the need arise.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#if defined(SQLITE3_H)
|
||||
/* no-op */
|
||||
#elif defined(SQLITE_STATIC_PERCENTILE)
|
||||
# include "sqlite3.h"
|
||||
#else
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The following object is the session context for a single percentile()
|
||||
** function. We have to remember all input Y values until the very end.
|
||||
/* The following object is the group context for a single percentile()
|
||||
** aggregate. Remember all input Y values until the very end.
|
||||
** Those values are accumulated in the Percentile.a[] array.
|
||||
*/
|
||||
typedef struct Percentile Percentile;
|
||||
struct Percentile {
|
||||
unsigned nAlloc; /* Number of slots allocated for a[] */
|
||||
unsigned nUsed; /* Number of slots actually used in a[] */
|
||||
double rPct; /* 1.0 more than the value for P */
|
||||
char bSorted; /* True if a[] is already in sorted order */
|
||||
char bKeepSorted; /* True if advantageous to keep a[] sorted */
|
||||
char bPctValid; /* True if rPct is valid */
|
||||
double rPct; /* Fraction. 0.0 to 1.0 */
|
||||
double *a; /* Array of Y values */
|
||||
};
|
||||
|
||||
/* Details of each function in the percentile family */
|
||||
typedef struct PercentileFunc PercentileFunc;
|
||||
struct PercentileFunc {
|
||||
const char *zName; /* Function name */
|
||||
char nArg; /* Number of arguments */
|
||||
char mxFrac; /* Maximum value of the "fraction" input */
|
||||
char bDiscrete; /* True for percentile_disc() */
|
||||
};
|
||||
static const PercentileFunc aPercentFunc[] = {
|
||||
{ "median", 1, 1, 0 },
|
||||
{ "percentile", 2, 100, 0 },
|
||||
{ "percentile_cont", 2, 1, 0 },
|
||||
{ "percentile_disc", 2, 1, 1 },
|
||||
};
|
||||
|
||||
/*
|
||||
** Return TRUE if the input floating-point number is an infinity.
|
||||
*/
|
||||
static int isInfinity(double r){
|
||||
static int percentIsInfinity(double r){
|
||||
sqlite3_uint64 u;
|
||||
assert( sizeof(u)==sizeof(r) );
|
||||
memcpy(&u, &r, sizeof(u));
|
||||
@@ -92,13 +166,64 @@ static int isInfinity(double r){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if two doubles differ by 0.001 or less
|
||||
** Return TRUE if two doubles differ by 0.001 or less.
|
||||
*/
|
||||
static int sameValue(double a, double b){
|
||||
static int percentSameValue(double a, double b){
|
||||
a -= b;
|
||||
return a>=-0.001 && a<=0.001;
|
||||
}
|
||||
|
||||
/*
|
||||
** Search p (which must have p->bSorted) looking for an entry with
|
||||
** value y. Return the index of that entry.
|
||||
**
|
||||
** If bExact is true, return -1 if the entry is not found.
|
||||
**
|
||||
** If bExact is false, return the index at which a new entry with
|
||||
** value y should be insert in order to keep the values in sorted
|
||||
** order. The smallest return value in this case will be 0, and
|
||||
** the largest return value will be p->nUsed.
|
||||
*/
|
||||
static int percentBinarySearch(Percentile *p, double y, int bExact){
|
||||
int iFirst = 0; /* First element of search range */
|
||||
int iLast = p->nUsed - 1; /* Last element of search range */
|
||||
while( iLast>=iFirst ){
|
||||
int iMid = (iFirst+iLast)/2;
|
||||
double x = p->a[iMid];
|
||||
if( x<y ){
|
||||
iFirst = iMid + 1;
|
||||
}else if( x>y ){
|
||||
iLast = iMid - 1;
|
||||
}else{
|
||||
return iMid;
|
||||
}
|
||||
}
|
||||
if( bExact ) return -1;
|
||||
return iFirst;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate an error for a percentile function.
|
||||
**
|
||||
** The error format string must have exactly one occurrance of "%%s()"
|
||||
** (with two '%' characters). That substring will be replaced by the name
|
||||
** of the function.
|
||||
*/
|
||||
static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
|
||||
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
||||
char *zMsg1;
|
||||
char *zMsg2;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, zFormat);
|
||||
zMsg1 = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
|
||||
sqlite3_result_error(pCtx, zMsg2, -1);
|
||||
sqlite3_free(zMsg1);
|
||||
sqlite3_free(zMsg2);
|
||||
}
|
||||
|
||||
/*
|
||||
** The "step" function for percentile(Y,P) is called once for each
|
||||
** input row.
|
||||
@@ -112,28 +237,20 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
|
||||
if( argc==1 ){
|
||||
/* Requirement 13: median(Y) is the same as percentile(Y,50). */
|
||||
rPct = 50.0;
|
||||
}else if( sqlite3_user_data(pCtx)==0 ){
|
||||
/* Requirement 3: P must be a number between 0 and 100 */
|
||||
eType = sqlite3_value_numeric_type(argv[1]);
|
||||
rPct = sqlite3_value_double(argv[1]);
|
||||
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|
||||
|| rPct<0.0 || rPct>100.0 ){
|
||||
sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
|
||||
"a number between 0.0 and 100.0", -1);
|
||||
return;
|
||||
}
|
||||
rPct = 0.5;
|
||||
}else{
|
||||
/* Requirement 3: P must be a number between 0 and 1 */
|
||||
/* Requirement 3: P must be a number between 0 and 100 */
|
||||
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
||||
eType = sqlite3_value_numeric_type(argv[1]);
|
||||
rPct = sqlite3_value_double(argv[1]);
|
||||
rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac;
|
||||
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|
||||
|| rPct<0.0 || rPct>1.0 ){
|
||||
sqlite3_result_error(pCtx, "2nd argument to percentile_cont() is not "
|
||||
"a number between 0.0 and 1.0", -1);
|
||||
|| rPct<0.0 || rPct>1.0
|
||||
){
|
||||
percentError(pCtx, "the fraction argument to %%s()"
|
||||
" is not between 0.0 and %.1f",
|
||||
(double)pFunc->mxFrac);
|
||||
return;
|
||||
}
|
||||
rPct *= 100.0;
|
||||
}
|
||||
|
||||
/* Allocate the session context. */
|
||||
@@ -142,11 +259,12 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
|
||||
/* Remember the P value. Throw an error if the P value is different
|
||||
** from any prior row, per Requirement (2). */
|
||||
if( p->rPct==0.0 ){
|
||||
p->rPct = rPct+1.0;
|
||||
}else if( !sameValue(p->rPct,rPct+1.0) ){
|
||||
sqlite3_result_error(pCtx, "2nd argument to percentile() is not the "
|
||||
"same for all input rows", -1);
|
||||
if( !p->bPctValid ){
|
||||
p->rPct = rPct;
|
||||
p->bPctValid = 1;
|
||||
}else if( !percentSameValue(p->rPct,rPct) ){
|
||||
percentError(pCtx, "the fraction argument to %%s()"
|
||||
" is not the same for all input rows");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,15 +275,14 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
/* If not NULL, then Y must be numeric. Otherwise throw an error.
|
||||
** Requirement 4 */
|
||||
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
|
||||
sqlite3_result_error(pCtx, "1st argument to percentile() is not "
|
||||
"numeric", -1);
|
||||
percentError(pCtx, "input to %%s() is not numeric");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Throw an error if the Y value is infinity or NaN */
|
||||
y = sqlite3_value_double(argv[0]);
|
||||
if( isInfinity(y) ){
|
||||
sqlite3_result_error(pCtx, "Inf input to percentile()", -1);
|
||||
if( percentIsInfinity(y) ){
|
||||
percentError(pCtx, "Inf input to %%s()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,50 +299,80 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
p->nAlloc = n;
|
||||
p->a = a;
|
||||
}
|
||||
p->a[p->nUsed++] = y;
|
||||
if( p->nUsed==0 ){
|
||||
p->a[p->nUsed++] = y;
|
||||
p->bSorted = 1;
|
||||
}else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
|
||||
p->a[p->nUsed++] = y;
|
||||
}else if( p->bKeepSorted ){
|
||||
int i;
|
||||
i = percentBinarySearch(p, y, 0);
|
||||
if( i<(int)p->nUsed ){
|
||||
memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
|
||||
}
|
||||
p->a[i] = y;
|
||||
p->nUsed++;
|
||||
}else{
|
||||
p->a[p->nUsed++] = y;
|
||||
p->bSorted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Sort an array of doubles.
|
||||
** Interchange two doubles.
|
||||
*/
|
||||
static void sortDoubles(double *a, int n){
|
||||
int iLt; /* Entries with index less than iLt are less than rPivot */
|
||||
int iGt; /* Entries with index iGt or more are greater than rPivot */
|
||||
#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
|
||||
|
||||
/*
|
||||
** Sort an array of doubles.
|
||||
**
|
||||
** Algorithm: quicksort
|
||||
**
|
||||
** This is implemented separately rather than using the qsort() routine
|
||||
** from the standard library because:
|
||||
**
|
||||
** (1) To avoid a dependency on qsort()
|
||||
** (2) To avoid the function call to the comparison routine for each
|
||||
** comparison.
|
||||
*/
|
||||
static void percentSort(double *a, unsigned int n){
|
||||
int iLt; /* Entries before a[iLt] are less than rPivot */
|
||||
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
|
||||
int i; /* Loop counter */
|
||||
double rPivot; /* The pivot value */
|
||||
double rTmp; /* Temporary used to swap two values */
|
||||
|
||||
if( n<2 ) return;
|
||||
if( n>5 ){
|
||||
rPivot = (a[0] + a[n/2] + a[n-1])/3.0;
|
||||
}else{
|
||||
rPivot = a[n/2];
|
||||
|
||||
assert( n>=2 );
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
iLt = i = 0;
|
||||
iGt = n;
|
||||
while( i<iGt ){
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
i = n/2;
|
||||
if( a[0]>a[i] ){
|
||||
SWAP_DOUBLE(a[0],a[i])
|
||||
}else if( a[i]>a[iGt] ){
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}
|
||||
if( n==3 ) return;
|
||||
rPivot = a[i];
|
||||
iLt = i = 1;
|
||||
do{
|
||||
if( a[i]<rPivot ){
|
||||
if( i>iLt ){
|
||||
rTmp = a[i];
|
||||
a[i] = a[iLt];
|
||||
a[iLt] = rTmp;
|
||||
}
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
rTmp = a[i];
|
||||
a[i] = a[iGt];
|
||||
a[iGt] = rTmp;
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if( iLt>=2 ) sortDoubles(a, iLt);
|
||||
if( n-iGt>=2 ) sortDoubles(a+iGt, n-iGt);
|
||||
|
||||
}while( i<iGt );
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
|
||||
/* Uncomment for testing */
|
||||
#if 0
|
||||
for(i=0; i<n-1; i++){
|
||||
@@ -234,12 +381,61 @@ static void sortDoubles(double *a, int n){
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Called to compute the final output of percentile() and to clean
|
||||
** up all allocated memory.
|
||||
** The "inverse" function for percentile(Y,P) is called to remove a
|
||||
** row that was previously inserted by "step".
|
||||
*/
|
||||
static void percentFinal(sqlite3_context *pCtx){
|
||||
static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
|
||||
Percentile *p;
|
||||
int eType;
|
||||
double y;
|
||||
int i;
|
||||
assert( argc==2 || argc==1 );
|
||||
|
||||
/* Allocate the session context. */
|
||||
p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
|
||||
assert( p!=0 );
|
||||
|
||||
/* Ignore rows for which Y is NULL */
|
||||
eType = sqlite3_value_type(argv[0]);
|
||||
if( eType==SQLITE_NULL ) return;
|
||||
|
||||
/* If not NULL, then Y must be numeric. Otherwise throw an error.
|
||||
** Requirement 4 */
|
||||
if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore the Y value if it is infinity or NaN */
|
||||
y = sqlite3_value_double(argv[0]);
|
||||
if( percentIsInfinity(y) ){
|
||||
return;
|
||||
}
|
||||
if( p->bSorted==0 ){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}
|
||||
p->bKeepSorted = 1;
|
||||
|
||||
/* Find and remove the row */
|
||||
i = percentBinarySearch(p, y, 1);
|
||||
if( i>=0 ){
|
||||
p->nUsed--;
|
||||
if( i<(int)p->nUsed ){
|
||||
memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the final output of percentile(). Clean up all allocated
|
||||
** memory if and only if bIsFinal is true.
|
||||
*/
|
||||
static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
|
||||
Percentile *p;
|
||||
PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx);
|
||||
unsigned i1, i2;
|
||||
double v1, v2;
|
||||
double ix, vx;
|
||||
@@ -247,21 +443,38 @@ static void percentFinal(sqlite3_context *pCtx){
|
||||
if( p==0 ) return;
|
||||
if( p->a==0 ) return;
|
||||
if( p->nUsed ){
|
||||
sortDoubles(p->a, p->nUsed);
|
||||
ix = (p->rPct-1.0)*(p->nUsed-1)*0.01;
|
||||
if( p->bSorted==0 ){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}
|
||||
ix = p->rPct*(p->nUsed-1);
|
||||
i1 = (unsigned)ix;
|
||||
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
|
||||
v1 = p->a[i1];
|
||||
v2 = p->a[i2];
|
||||
vx = v1 + (v2-v1)*(ix-i1);
|
||||
if( pFunc->bDiscrete ){
|
||||
vx = p->a[i1];
|
||||
}else{
|
||||
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
|
||||
v1 = p->a[i1];
|
||||
v2 = p->a[i2];
|
||||
vx = v1 + (v2-v1)*(ix-i1);
|
||||
}
|
||||
sqlite3_result_double(pCtx, vx);
|
||||
}
|
||||
sqlite3_free(p->a);
|
||||
memset(p, 0, sizeof(*p));
|
||||
if( bIsFinal ){
|
||||
sqlite3_free(p->a);
|
||||
memset(p, 0, sizeof(*p));
|
||||
}else{
|
||||
p->bKeepSorted = 1;
|
||||
}
|
||||
}
|
||||
static void percentFinal(sqlite3_context *pCtx){
|
||||
percentCompute(pCtx, 1);
|
||||
}
|
||||
static void percentValue(sqlite3_context *pCtx){
|
||||
percentCompute(pCtx, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_percentile_init(
|
||||
@@ -270,20 +483,21 @@ int sqlite3_percentile_init(
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#endif
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "percentile", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
||||
0, percentStep, percentFinal);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "median", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
||||
0, percentStep, percentFinal);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "percentile_cont", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS, &percentStep,
|
||||
0, percentStep, percentFinal);
|
||||
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
||||
rc = sqlite3_create_window_function(db,
|
||||
aPercentFunc[i].zName,
|
||||
aPercentFunc[i].nArg,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1,
|
||||
(void*)&aPercentFunc[i],
|
||||
percentStep, percentFinal, percentValue, percentInverse, 0);
|
||||
if( rc ) break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+25
-9
@@ -196,7 +196,8 @@ static void hash_step_vformat(
|
||||
** zOut[]. zOut[] must be at least 41 bytes long. */
|
||||
static void hash_finish(
|
||||
SHA1Context *p, /* The SHA1 context to finish and render */
|
||||
char *zOut /* Store hexadecimal hash here */
|
||||
char *zOut, /* Store hex or binary hash here */
|
||||
int bAsBinary /* 1 for binary hash, 0 for hex hash */
|
||||
){
|
||||
unsigned int i;
|
||||
unsigned char finalcount[8];
|
||||
@@ -215,11 +216,15 @@ static void hash_finish(
|
||||
for (i = 0; i < 20; i++){
|
||||
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
for(i=0; i<20; i++){
|
||||
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
|
||||
zOut[i*2+1] = zEncode[digest[i] & 0xf];
|
||||
if( bAsBinary ){
|
||||
memcpy(zOut, digest, 20);
|
||||
}else{
|
||||
for(i=0; i<20; i++){
|
||||
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
|
||||
zOut[i*2+1] = zEncode[digest[i] & 0xf];
|
||||
}
|
||||
zOut[i*2]= 0;
|
||||
}
|
||||
zOut[i*2]= 0;
|
||||
}
|
||||
/* End of the hashing logic
|
||||
*****************************************************************************/
|
||||
@@ -251,8 +256,13 @@ static void sha1Func(
|
||||
}else{
|
||||
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
|
||||
}
|
||||
hash_finish(&cx, zOut);
|
||||
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
|
||||
if( sqlite3_user_data(context)!=0 ){
|
||||
hash_finish(&cx, zOut, 1);
|
||||
sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
hash_finish(&cx, zOut, 0);
|
||||
sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -365,7 +375,7 @@ static void sha1QueryFunc(
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
hash_finish(&cx, zOut);
|
||||
hash_finish(&cx, zOut, 0);
|
||||
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
@@ -379,11 +389,17 @@ int sqlite3_sha_init(
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
static int one = 1;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "sha1", 1,
|
||||
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
|
||||
0, sha1Func, 0, 0);
|
||||
0, sha1Func, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "sha1b", 1,
|
||||
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
|
||||
(void*)&one, sha1Func, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "sha1_query", 1,
|
||||
SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
** 2024-09-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.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** Implementation of standard I/O interfaces for UTF-8 that are missing
|
||||
** on Windows.
|
||||
*/
|
||||
#ifdef _WIN32 /* This file is a no-op on all platforms except Windows */
|
||||
#ifndef _SQLITE3_STDIO_H_
|
||||
#include "sqlite3_stdio.h"
|
||||
#endif
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "sqlite3.h"
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/*
|
||||
** If the SQLITE_U8TEXT_ONLY option is defined, then only use
|
||||
** _O_U8TEXT, _O_WTEXT, and similar together with the UTF-16
|
||||
** interfaces to the Windows CRT. The use of ANSI-only routines
|
||||
** like fputs() and ANSI modes like _O_TEXT and _O_BINARY is
|
||||
** avoided.
|
||||
**
|
||||
** The downside of using SQLITE_U8TEXT_ONLY is that it becomes
|
||||
** impossible to output a bare newline character (0x0a) - that is,
|
||||
** a newline that is not preceded by a carriage return (0x0d).
|
||||
** And without that capability, sometimes the output will be slightly
|
||||
** incorrect, as extra 0x0d characters will have been inserted where
|
||||
** they do not belong.
|
||||
**
|
||||
** The SQLITE_U8TEXT_STDIO compile-time option is a compromise.
|
||||
** It always enables _O_WTEXT or similar for stdin, stdout, stderr,
|
||||
** but allows other streams to be _O_TEXT and/or O_BINARY. The
|
||||
** SQLITE_U8TEXT_STDIO option has the same downside as SQLITE_U8TEXT_ONLY
|
||||
** in that stray 0x0d characters might appear where they ought not, but
|
||||
** at least with this option those characters only appear on standard
|
||||
** I/O streams, and not on new streams that might be created by the
|
||||
** application using sqlite3_fopen() or sqlite3_popen().
|
||||
*/
|
||||
#if defined(SQLITE_U8TEXT_ONLY)
|
||||
# define UseWtextForOutput(fd) 1
|
||||
# define UseWtextForInput(fd) 1
|
||||
# define IsConsole(fd) _isatty(_fileno(fd))
|
||||
#elif defined(SQLITE_U8TEXT_STDIO)
|
||||
# define UseWtextForOutput(fd) ((fd)==stdout || (fd)==stderr)
|
||||
# define UseWtextForInput(fd) ((fd)==stdin)
|
||||
# define IsConsole(fd) _isatty(_fileno(fd))
|
||||
#else
|
||||
# define UseWtextForOutput(fd) _isatty(_fileno(fd))
|
||||
# define UseWtextForInput(fd) _isatty(_fileno(fd))
|
||||
# define IsConsole(fd) 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Work-alike for the fopen() routine from the standard C library.
|
||||
*/
|
||||
FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
||||
FILE *fp = 0;
|
||||
wchar_t *b1, *b2;
|
||||
int sz1, sz2;
|
||||
|
||||
sz1 = (int)strlen(zFilename);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2);
|
||||
b2[sz2] = 0;
|
||||
fp = _wfopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Work-alike for the popen() routine from the standard C library.
|
||||
*/
|
||||
FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
||||
FILE *fp = 0;
|
||||
wchar_t *b1, *b2;
|
||||
int sz1, sz2;
|
||||
|
||||
sz1 = (int)strlen(zCommand);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2);
|
||||
b2[sz2] = 0;
|
||||
fp = _wpopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
return fp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Work-alike for fgets() from the standard C library.
|
||||
*/
|
||||
char *sqlite3_fgets(char *buf, int sz, FILE *in){
|
||||
if( UseWtextForInput(in) ){
|
||||
/* When reading from the command-prompt in Windows, it is necessary
|
||||
** to use _O_WTEXT input mode to read UTF-16 characters, then translate
|
||||
** that into UTF-8. Otherwise, non-ASCII characters all get translated
|
||||
** into '?'.
|
||||
*/
|
||||
wchar_t *b1 = malloc( sz*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
||||
if( fgetws(b1, sz/4, in)==0 ){
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
}
|
||||
WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0);
|
||||
sqlite3_free(b1);
|
||||
return buf;
|
||||
}else{
|
||||
/* Reading from a file or other input source, just read bytes without
|
||||
** any translation. */
|
||||
return fgets(buf, sz, in);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Work-alike for fputs() from the standard C library.
|
||||
*/
|
||||
int sqlite3_fputs(const char *z, FILE *out){
|
||||
if( UseWtextForOutput(out) ){
|
||||
/* When writing to the command-prompt in Windows, it is necessary
|
||||
** to use _O_WTEXT input mode and write UTF-16 characters.
|
||||
*/
|
||||
int sz = (int)strlen(z);
|
||||
wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
_setmode(_fileno(out), _O_U8TEXT);
|
||||
fputws(b1, out);
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
}else{
|
||||
/* Writing to a file or other destination, just write bytes without
|
||||
** any translation. */
|
||||
return fputs(z, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Work-alike for fprintf() from the standard C library.
|
||||
*/
|
||||
int sqlite3_fprintf(FILE *out, const char *zFormat, ...){
|
||||
int rc;
|
||||
if( UseWtextForOutput(out) ){
|
||||
/* When writing to the command-prompt in Windows, it is necessary
|
||||
** to use _O_WTEXT input mode and write UTF-16 characters.
|
||||
*/
|
||||
char *z;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, zFormat);
|
||||
z = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
sqlite3_fputs(z, out);
|
||||
rc = (int)strlen(z);
|
||||
sqlite3_free(z);
|
||||
}else{
|
||||
/* Writing to a file or other destination, just write bytes without
|
||||
** any translation. */
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
rc = vfprintf(out, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the mode for an output stream. mode argument is typically _O_BINARY or
|
||||
** _O_TEXT.
|
||||
*/
|
||||
void sqlite3_fsetmode(FILE *fp, int mode){
|
||||
if( !UseWtextForOutput(fp) ){
|
||||
fflush(fp);
|
||||
_setmode(_fileno(fp), mode);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
** 2024-09-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 header file contains definitions of interfaces that provide
|
||||
** cross-platform I/O for UTF-8 content.
|
||||
**
|
||||
** On most platforms, the interfaces definitions in this file are
|
||||
** just #defines. For example sqlite3_fopen() is a macro that resolves
|
||||
** to the standard fopen() in the C-library.
|
||||
**
|
||||
** But Windows does not have a standard C-library, at least not one that
|
||||
** can handle UTF-8. So for windows build, the interfaces resolve to new
|
||||
** C-language routines contained in the separate sqlite3_stdio.c source file.
|
||||
**
|
||||
** So on all non-Windows platforms, simply #include this header file and
|
||||
** use the interfaces defined herein. Then to run your application on Windows,
|
||||
** also link in the accompanying sqlite3_stdio.c source file when compiling
|
||||
** to get compatible interfaces.
|
||||
*/
|
||||
#ifndef _SQLITE3_STDIO_H_
|
||||
#define _SQLITE3_STDIO_H_ 1
|
||||
#ifdef _WIN32
|
||||
/**** Definitions For Windows ****/
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
FILE *sqlite3_fopen(const char *zFilename, const char *zMode);
|
||||
FILE *sqlite3_popen(const char *zCommand, const char *type);
|
||||
char *sqlite3_fgets(char *s, int size, FILE *stream);
|
||||
int sqlite3_fputs(const char *s, FILE *stream);
|
||||
int sqlite3_fprintf(FILE *stream, const char *format, ...);
|
||||
void sqlite3_fsetmode(FILE *stream, int mode);
|
||||
|
||||
|
||||
#else
|
||||
/**** Definitions For All Other Platforms ****/
|
||||
#include <stdio.h>
|
||||
#define sqlite3_fopen fopen
|
||||
#define sqlite3_popen popen
|
||||
#define sqlite3_fgets fgets
|
||||
#define sqlite3_fputs fputs
|
||||
#define sqlite3_fprintf fprintf
|
||||
#define sqlite3_fsetmode(F,X) /*no-op*/
|
||||
|
||||
#endif
|
||||
#endif /* _SQLITE3_STDIO_H_ */
|
||||
@@ -182,7 +182,7 @@ static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName);
|
||||
** xyzzy.txt -> xyzzy.txt
|
||||
*/
|
||||
static const char *fileTail(const char *z){
|
||||
int i;
|
||||
size_t i;
|
||||
if( z==0 ) return 0;
|
||||
i = strlen(z)-1;
|
||||
while( i>0 && z[i-1]!='/' ){ i--; }
|
||||
@@ -207,36 +207,34 @@ static void vfstrace_printf(
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert value rc into a string and print it using zFormat. zFormat
|
||||
** should have exactly one %s
|
||||
** Try to convert an error code into a symbolic name for that error code.
|
||||
*/
|
||||
static void vfstrace_print_errcode(
|
||||
vfstrace_info *pInfo,
|
||||
const char *zFormat,
|
||||
int rc
|
||||
){
|
||||
char zBuf[50];
|
||||
char *zVal;
|
||||
static const char *vfstrace_errcode_name(int rc ){
|
||||
const char *zVal = 0;
|
||||
switch( rc ){
|
||||
case SQLITE_OK: zVal = "SQLITE_OK"; break;
|
||||
case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break;
|
||||
case SQLITE_PERM: zVal = "SQLITE_PERM"; break;
|
||||
case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break;
|
||||
case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break;
|
||||
case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break;
|
||||
case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break;
|
||||
case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break;
|
||||
case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break;
|
||||
case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break;
|
||||
case SQLITE_FULL: zVal = "SQLITE_FULL"; break;
|
||||
case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break;
|
||||
case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break;
|
||||
case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break;
|
||||
case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break;
|
||||
case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break;
|
||||
case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break;
|
||||
case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break;
|
||||
case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break;
|
||||
case SQLITE_OK: zVal = "SQLITE_OK"; break;
|
||||
case SQLITE_INTERNAL: zVal = "SQLITE_INTERNAL"; break;
|
||||
case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break;
|
||||
case SQLITE_PERM: zVal = "SQLITE_PERM"; break;
|
||||
case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break;
|
||||
case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break;
|
||||
case SQLITE_LOCKED: zVal = "SQLITE_LOCKED"; break;
|
||||
case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break;
|
||||
case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break;
|
||||
case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break;
|
||||
case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break;
|
||||
case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break;
|
||||
case SQLITE_NOTFOUND: zVal = "SQLITE_NOTFOUND"; break;
|
||||
case SQLITE_FULL: zVal = "SQLITE_FULL"; break;
|
||||
case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break;
|
||||
case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break;
|
||||
case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break;
|
||||
case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break;
|
||||
case SQLITE_TOOBIG: zVal = "SQLITE_TOOBIG"; break;
|
||||
case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break;
|
||||
case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break;
|
||||
case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break;
|
||||
case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break;
|
||||
case SQLITE_IOERR_READ: zVal = "SQLITE_IOERR_READ"; break;
|
||||
case SQLITE_IOERR_SHORT_READ: zVal = "SQLITE_IOERR_SHORT_READ"; break;
|
||||
case SQLITE_IOERR_WRITE: zVal = "SQLITE_IOERR_WRITE"; break;
|
||||
@@ -266,11 +264,30 @@ static void vfstrace_print_errcode(
|
||||
case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
|
||||
case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break;
|
||||
case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
|
||||
default: {
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
|
||||
zVal = zBuf;
|
||||
break;
|
||||
}
|
||||
return zVal;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert value rc into a string and print it using zFormat. zFormat
|
||||
** should have exactly one %s
|
||||
*/
|
||||
static void vfstrace_print_errcode(
|
||||
vfstrace_info *pInfo,
|
||||
const char *zFormat,
|
||||
int rc
|
||||
){
|
||||
const char *zVal;
|
||||
char zBuf[50];
|
||||
zVal = vfstrace_errcode_name(rc);
|
||||
if( zVal==0 ){
|
||||
zVal = vfstrace_errcode_name(rc&0xff);
|
||||
if( zVal ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%s | 0x%x", zVal, rc&0xffff00);
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d (0x%x)", rc, rc);
|
||||
}
|
||||
zVal = zBuf;
|
||||
}
|
||||
vfstrace_printf(pInfo, zFormat, zVal);
|
||||
}
|
||||
@@ -399,7 +416,7 @@ static const char *lockName(int eLock){
|
||||
const char *azLockNames[] = {
|
||||
"NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE"
|
||||
};
|
||||
if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){
|
||||
if( eLock<0 || eLock>=(int)(sizeof(azLockNames)/sizeof(azLockNames[0])) ){
|
||||
return "???";
|
||||
}else{
|
||||
return azLockNames[eLock];
|
||||
@@ -457,12 +474,14 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
char zBuf[100];
|
||||
char zBuf2[100];
|
||||
char *zOp;
|
||||
char *zRVal = 0;
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
|
||||
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
|
||||
case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
|
||||
case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
|
||||
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
|
||||
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
|
||||
case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break;
|
||||
case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break;
|
||||
case SQLITE_FCNTL_SIZE_HINT: {
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld",
|
||||
*(sqlite3_int64*)pArg);
|
||||
@@ -474,20 +493,62 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
zOp = zBuf;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break;
|
||||
case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break;
|
||||
case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break;
|
||||
case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break;
|
||||
case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
|
||||
case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break;
|
||||
case 0xca093fa0: zOp = "DB_UNCHANGED"; break;
|
||||
case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break;
|
||||
case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break;
|
||||
case SQLITE_FCNTL_PERSIST_WAL: {
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "PERSIST_WAL,%d", *(int*)pArg);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
|
||||
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_PRAGMA: {
|
||||
const char *const* a = (const char*const*)pArg;
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_BUSYHANDLER: zOp = "BUSYHANDLER"; break;
|
||||
case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break;
|
||||
case SQLITE_FCNTL_MMAP_SIZE: {
|
||||
sqlite3_int64 iMMap = *(sqlite3_int64*)pArg;
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "MMAP_SIZE,%lld",iMMap);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_TRACE: zOp = "TRACE"; break;
|
||||
case SQLITE_FCNTL_HAS_MOVED: zOp = "HAS_MOVED"; break;
|
||||
case SQLITE_FCNTL_SYNC: zOp = "SYNC"; break;
|
||||
case SQLITE_FCNTL_COMMIT_PHASETWO: zOp = "COMMIT_PHASETWO"; break;
|
||||
case SQLITE_FCNTL_WIN32_SET_HANDLE: zOp = "WIN32_SET_HANDLE"; break;
|
||||
case SQLITE_FCNTL_WAL_BLOCK: zOp = "WAL_BLOCK"; break;
|
||||
case SQLITE_FCNTL_ZIPVFS: zOp = "ZIPVFS"; break;
|
||||
case SQLITE_FCNTL_RBU: zOp = "RBU"; break;
|
||||
case SQLITE_FCNTL_VFS_POINTER: zOp = "VFS_POINTER"; break;
|
||||
case SQLITE_FCNTL_JOURNAL_POINTER: zOp = "JOURNAL_POINTER"; break;
|
||||
case SQLITE_FCNTL_WIN32_GET_HANDLE: zOp = "WIN32_GET_HANDLE"; break;
|
||||
case SQLITE_FCNTL_PDB: zOp = "PDB"; break;
|
||||
case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: zOp = "BEGIN_ATOMIC_WRITE"; break;
|
||||
case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: zOp = "COMMIT_ATOMIC_WRITE"; break;
|
||||
case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
|
||||
zOp = "ROLLBACK_ATOMIC_WRITE";
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_LOCK_TIMEOUT: {
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "LOCK_TIMEOUT,%d", *(int*)pArg);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_DATA_VERSION: zOp = "DATA_VERSION"; break;
|
||||
case SQLITE_FCNTL_SIZE_LIMIT: zOp = "SIZE_LIMIT"; break;
|
||||
case SQLITE_FCNTL_CKPT_DONE: zOp = "CKPT_DONE"; break;
|
||||
case SQLITE_FCNTL_RESERVE_BYTES: zOp = "RESERVED_BYTES"; break;
|
||||
case SQLITE_FCNTL_CKPT_START: zOp = "CKPT_START"; break;
|
||||
case SQLITE_FCNTL_EXTERNAL_READER: zOp = "EXTERNAL_READER"; break;
|
||||
case SQLITE_FCNTL_CKSM_FILE: zOp = "CKSM_FILE"; break;
|
||||
case SQLITE_FCNTL_RESET_CACHE: zOp = "RESET_CACHE"; break;
|
||||
case 0xca093fa0: zOp = "DB_UNCHANGED"; break;
|
||||
default: {
|
||||
sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
|
||||
zOp = zBuf;
|
||||
@@ -497,15 +558,37 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
|
||||
pInfo->zVfsName, p->zFName, zOp);
|
||||
rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||
*(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
|
||||
if( rc==SQLITE_OK ){
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_VFSNAME: {
|
||||
*(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
|
||||
pInfo->zVfsName, *(char**)pArg);
|
||||
zRVal = *(char**)pArg;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_MMAP_SIZE: {
|
||||
sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%lld", *(sqlite3_int64*)pArg);
|
||||
zRVal = zBuf2;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_HAS_MOVED:
|
||||
case SQLITE_FCNTL_PERSIST_WAL: {
|
||||
sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%d", *(int*)pArg);
|
||||
zRVal = zBuf2;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_PRAGMA:
|
||||
case SQLITE_FCNTL_TEMPFILENAME: {
|
||||
zRVal = *(char**)pArg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (op==SQLITE_FCNTL_PRAGMA || op==SQLITE_FCNTL_TEMPFILENAME)
|
||||
&& rc==SQLITE_OK && *(char**)pArg ){
|
||||
vfstrace_printf(pInfo, "%s.xFileControl(%s,%s) returns %s",
|
||||
pInfo->zVfsName, p->zFName, zOp, *(char**)pArg);
|
||||
if( zRVal ){
|
||||
vfstrace_print_errcode(pInfo, " -> %s", rc);
|
||||
vfstrace_printf(pInfo, ", %s\n", zRVal);
|
||||
}else{
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -840,14 +923,14 @@ int vfstrace_register(
|
||||
sqlite3_vfs *pNew;
|
||||
sqlite3_vfs *pRoot;
|
||||
vfstrace_info *pInfo;
|
||||
int nName;
|
||||
int nByte;
|
||||
size_t nName;
|
||||
size_t nByte;
|
||||
|
||||
pRoot = sqlite3_vfs_find(zOldVfsName);
|
||||
if( pRoot==0 ) return SQLITE_NOTFOUND;
|
||||
nName = strlen(zTraceName);
|
||||
nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1;
|
||||
pNew = sqlite3_malloc( nByte );
|
||||
pNew = sqlite3_malloc64( nByte );
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, nByte);
|
||||
pInfo = (vfstrace_info*)&pNew[1];
|
||||
@@ -890,3 +973,15 @@ int vfstrace_register(
|
||||
pInfo->zVfsName, pRoot->zName);
|
||||
return sqlite3_vfs_register(pNew, makeDefault);
|
||||
}
|
||||
|
||||
/*
|
||||
** Look for the named VFS. If it is a TRACEVFS, then unregister it
|
||||
** and delete it.
|
||||
*/
|
||||
void vfstrace_unregister(const char *zTraceName){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(zTraceName);
|
||||
if( pVfs==0 ) return;
|
||||
if( pVfs->xOpen!=vfstraceOpen ) return;
|
||||
sqlite3_vfs_unregister(pVfs);
|
||||
sqlite3_free(pVfs);
|
||||
}
|
||||
+10
-2
@@ -35,6 +35,14 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
/* When used as part of the CLI, the sqlite3_stdio.h module will have
|
||||
** been included before this one. In that case use the sqlite3_stdio.h
|
||||
** #defines. If not, create our own for fopen().
|
||||
*/
|
||||
#ifndef _SQLITE3_STDIO_H_
|
||||
# define sqlite3_fopen fopen
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
@@ -1291,7 +1299,7 @@ static int zipfileFilter(
|
||||
}
|
||||
|
||||
if( 0==pTab->pWriteFd && 0==bInMemory ){
|
||||
pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
|
||||
pCsr->pFile = zFile ? sqlite3_fopen(zFile, "rb") : 0;
|
||||
if( pCsr->pFile==0 ){
|
||||
zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -1481,7 +1489,7 @@ static int zipfileBegin(sqlite3_vtab *pVtab){
|
||||
** structure into memory. During the transaction any new file data is
|
||||
** appended to the archive file, but the central directory is accumulated
|
||||
** in main-memory until the transaction is committed. */
|
||||
pTab->pWriteFd = fopen(pTab->zFile, "ab+");
|
||||
pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
|
||||
if( pTab->pWriteFd==0 ){
|
||||
pTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"zipfile: failed to open file %s for writing", pTab->zFile
|
||||
|
||||
+35
-6
@@ -336,6 +336,27 @@ struct RbuFrame {
|
||||
u32 iWalFrame;
|
||||
};
|
||||
|
||||
#ifndef UNUSED_PARAMETER
|
||||
/*
|
||||
** The following macros are used to suppress compiler warnings and to
|
||||
** make it clear to human readers when a function parameter is deliberately
|
||||
** left unused within the body of a function. This usually happens when
|
||||
** a function is called via a function pointer. For example the
|
||||
** implementation of an SQL aggregate step callback may not use the
|
||||
** parameter indicating the number of arguments passed to the aggregate,
|
||||
** if it knows that this is enforced elsewhere.
|
||||
**
|
||||
** When a function parameter is not used at all within the body of a function,
|
||||
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
|
||||
** However, these macros may also be used to suppress warnings related to
|
||||
** parameters that may or may not be used depending on compilation options.
|
||||
** For example those parameters only used in assert() statements. In these
|
||||
** cases the parameters are named as per the usual conventions.
|
||||
*/
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** RBU handle.
|
||||
**
|
||||
@@ -387,7 +408,7 @@ struct sqlite3rbu {
|
||||
int rc; /* Value returned by last rbu_step() call */
|
||||
char *zErrmsg; /* Error message if rc!=SQLITE_OK */
|
||||
int nStep; /* Rows processed for current object */
|
||||
int nProgress; /* Rows processed for all objects */
|
||||
sqlite3_int64 nProgress; /* Rows processed for all objects */
|
||||
RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
|
||||
const char *zVfsName; /* Name of automatically created rbu vfs */
|
||||
rbu_file *pTargetFd; /* File handle open on target db */
|
||||
@@ -504,7 +525,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
|
||||
v = (v<<6) + c;
|
||||
}
|
||||
z--;
|
||||
*pLen -= z - zStart;
|
||||
*pLen -= (int)(z - zStart);
|
||||
*pz = (char*)z;
|
||||
return v;
|
||||
}
|
||||
@@ -689,6 +710,7 @@ static void rbuFossilDeltaFunc(
|
||||
char *aOut;
|
||||
|
||||
assert( argc==2 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
|
||||
nOrig = sqlite3_value_bytes(argv[0]);
|
||||
aOrig = (const char*)sqlite3_value_blob(argv[0]);
|
||||
@@ -2268,13 +2290,13 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
|
||||
else if( c==')' ){
|
||||
nParen--;
|
||||
if( nParen==0 ){
|
||||
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
|
||||
int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
|
||||
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}else if( c==',' && nParen==1 ){
|
||||
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
|
||||
int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
|
||||
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
|
||||
pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
|
||||
}else if( c=='"' || c=='\'' || c=='`' ){
|
||||
@@ -2964,6 +2986,8 @@ static void rbuFileSuffix3(const char *zBase, char *z){
|
||||
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
|
||||
if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER2(zBase,z);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3548,7 +3572,7 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
|
||||
"(%d, %Q), "
|
||||
"(%d, %Q), "
|
||||
"(%d, %d), "
|
||||
"(%d, %d), "
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld), "
|
||||
@@ -3906,6 +3930,7 @@ static void rbuIndexCntFunc(
|
||||
sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
|
||||
|
||||
assert( nVal==1 );
|
||||
UNUSED_PARAMETER(nVal);
|
||||
|
||||
rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
|
||||
sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
|
||||
@@ -4181,7 +4206,7 @@ sqlite3rbu *sqlite3rbu_vacuum(
|
||||
){
|
||||
if( zTarget==0 ){ return rbuMisuseError(); }
|
||||
if( zState ){
|
||||
int n = strlen(zState);
|
||||
size_t n = strlen(zState);
|
||||
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
|
||||
return rbuMisuseError();
|
||||
}
|
||||
@@ -4398,6 +4423,7 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
|
||||
*/
|
||||
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
|
||||
int rc = SQLITE_OK;
|
||||
UNUSED_PARAMETER(pArg);
|
||||
#if defined(_WIN32_WCE)
|
||||
{
|
||||
LPWSTR zWideOld;
|
||||
@@ -5302,6 +5328,9 @@ static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
** No-op.
|
||||
*/
|
||||
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
UNUSED_PARAMETER(a);
|
||||
UNUSED_PARAMETER(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ foreach {tn sql1 at sql2} {
|
||||
|
||||
sqlite3changegroup grp
|
||||
grp schema db main
|
||||
breakpoint
|
||||
grp add $C1
|
||||
grp add $C2
|
||||
set T1 [grp output]
|
||||
|
||||
@@ -56,4 +56,28 @@ do_faultsim_test 1 -faults oom* -prep {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
ALTER TABLE t1 ADD COLUMN c DEFAULT 'abcdefghijklmnopqrstuvwxyz';
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 2 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_schema}
|
||||
} -body {
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
execsql {
|
||||
DELETE FROM t1 WHERE a = 1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
catch { S delete }
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -82,6 +82,7 @@ do_execsql_test 1.5 {
|
||||
UPDATE p1 SET c=12345 WHERE a = 45;
|
||||
}
|
||||
|
||||
breakpoint
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
do_execsql_test 1.6 {
|
||||
SELECT * FROM c1
|
||||
|
||||
@@ -74,6 +74,10 @@ struct SessionBuffer {
|
||||
** input data. Input data may be supplied either as a single large buffer
|
||||
** (e.g. sqlite3changeset_start()) or using a stream function (e.g.
|
||||
** sqlite3changeset_start_strm()).
|
||||
**
|
||||
** bNoDiscard:
|
||||
** If true, then the only time data is discarded is as a result of explicit
|
||||
** sessionDiscardData() calls. Not within every sessionInputBuffer() call.
|
||||
*/
|
||||
struct SessionInput {
|
||||
int bNoDiscard; /* If true, do not discard in InputBuffer() */
|
||||
@@ -1757,16 +1761,19 @@ static void sessionPreupdateOneChange(
|
||||
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
|
||||
sqlite3_value *p = 0;
|
||||
if( op!=SQLITE_INSERT ){
|
||||
TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
assert( trc==SQLITE_OK );
|
||||
/* This may fail if the column has a non-NULL default and was added
|
||||
** using ALTER TABLE ADD COLUMN after this record was created. */
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
}else if( pTab->abPK[i] ){
|
||||
TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
|
||||
assert( trc==SQLITE_OK );
|
||||
}
|
||||
|
||||
/* This may fail if SQLite value p contains a utf-16 string that must
|
||||
** be converted to utf-8 and an OOM error occurs while doing so. */
|
||||
rc = sessionSerializeValue(0, p, &nByte);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* This may fail if SQLite value p contains a utf-16 string that must
|
||||
** be converted to utf-8 and an OOM error occurs while doing so. */
|
||||
rc = sessionSerializeValue(0, p, &nByte);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto error_out;
|
||||
}
|
||||
if( pTab->bRowid ){
|
||||
@@ -5124,15 +5131,21 @@ static int sessionChangesetApply(
|
||||
int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
|
||||
SessionApplyCtx sApply; /* changeset_apply() context object */
|
||||
int bPatchset;
|
||||
u64 savedFlag = db->flags & SQLITE_FkNoAction;
|
||||
|
||||
assert( xConflict!=0 );
|
||||
|
||||
sqlite3_mutex_enter(sqlite3_db_mutex(db));
|
||||
if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
|
||||
db->flags |= ((u64)SQLITE_FkNoAction);
|
||||
db->aDb[0].pSchema->schema_cookie -= 32;
|
||||
}
|
||||
|
||||
pIter->in.bNoDiscard = 1;
|
||||
memset(&sApply, 0, sizeof(sApply));
|
||||
sApply.bRebase = (ppRebase && pnRebase);
|
||||
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
|
||||
sqlite3_mutex_enter(sqlite3_db_mutex(db));
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
||||
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
|
||||
}
|
||||
@@ -5294,6 +5307,12 @@ static int sessionChangesetApply(
|
||||
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
|
||||
sqlite3_free((char*)sApply.constraints.aBuf);
|
||||
sqlite3_free((char*)sApply.rebase.aBuf);
|
||||
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
|
||||
assert( db->flags & SQLITE_FkNoAction );
|
||||
db->flags &= ~((u64)SQLITE_FkNoAction);
|
||||
db->aDb[0].pSchema->schema_cookie -= 32;
|
||||
}
|
||||
sqlite3_mutex_leave(sqlite3_db_mutex(db));
|
||||
return rc;
|
||||
}
|
||||
@@ -5322,12 +5341,6 @@ int sqlite3changeset_apply_v2(
|
||||
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
|
||||
int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
|
||||
u64 savedFlag = db->flags & SQLITE_FkNoAction;
|
||||
|
||||
if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){
|
||||
db->flags |= ((u64)SQLITE_FkNoAction);
|
||||
db->aDb[0].pSchema->schema_cookie -= 32;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionChangesetApply(
|
||||
@@ -5335,11 +5348,6 @@ int sqlite3changeset_apply_v2(
|
||||
);
|
||||
}
|
||||
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
|
||||
assert( db->flags & SQLITE_FkNoAction );
|
||||
db->flags &= ~((u64)SQLITE_FkNoAction);
|
||||
db->aDb[0].pSchema->schema_cookie -= 32;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5660,6 +5668,9 @@ static int sessionChangesetExtendRecord(
|
||||
sessionAppendBlob(pOut, aRec, nRec, &rc);
|
||||
if( rc==SQLITE_OK && pTab->pDfltStmt==0 ){
|
||||
rc = sessionPrepareDfltStmt(pGrp->db, pTab, &pTab->pDfltStmt);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW!=sqlite3_step(pTab->pDfltStmt) ){
|
||||
rc = sqlite3_errcode(pGrp->db);
|
||||
}
|
||||
}
|
||||
for(ii=nCol; rc==SQLITE_OK && ii<pTab->nCol; ii++){
|
||||
int eType = sqlite3_column_type(pTab->pDfltStmt, ii);
|
||||
@@ -5676,6 +5687,7 @@ static int sessionChangesetExtendRecord(
|
||||
}
|
||||
if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){
|
||||
sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal);
|
||||
pOut->nBuf += 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -5815,6 +5827,8 @@ static int sessionOneChangeToHash(
|
||||
u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2];
|
||||
int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2;
|
||||
|
||||
assert( nRec>0 );
|
||||
|
||||
/* Ensure that only changesets, or only patchsets, but not a mixture
|
||||
** of both, are being combined. It is an error to try to combine a
|
||||
** changeset and a patchset. */
|
||||
@@ -5892,6 +5906,7 @@ static int sessionChangesetToHash(
|
||||
int nRec;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pIter->in.bNoDiscard = 1;
|
||||
while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
|
||||
rc = sessionOneChangeToHash(pGrp, pIter, bRebase);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
|
||||
@@ -383,10 +383,10 @@ static int SQLITE_TCLAPI test_session_cmd(
|
||||
{ "rowid", SQLITE_SESSION_OBJCONFIG_ROWID },
|
||||
{ 0, 0 }
|
||||
};
|
||||
size_t sz = sizeof(aOpt[0]);
|
||||
int sz = (int)sizeof(aOpt[0]);
|
||||
|
||||
int iArg;
|
||||
int iOpt;
|
||||
Tcl_Size iOpt;
|
||||
if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -803,7 +803,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
if( bV2 ){
|
||||
while( objc>1 ){
|
||||
const char *z1 = Tcl_GetString(objv[1]);
|
||||
int n = strlen(z1);
|
||||
int n = (int)strlen(z1);
|
||||
if( n>3 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
|
||||
flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
|
||||
}
|
||||
@@ -1119,7 +1119,7 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
|
||||
|
||||
while( objc>1 ){
|
||||
char *zOpt = Tcl_GetString(objv[1]);
|
||||
int nOpt = strlen(zOpt);
|
||||
int nOpt = (int)strlen(zOpt);
|
||||
if( zOpt[0]!='-' ) break;
|
||||
if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){
|
||||
isInvert = 1;
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
# build the SQLite library and testing tools.
|
||||
################################################################################
|
||||
|
||||
# If OPTIONS... is specified on the command-line, append its value to OPTS
|
||||
#
|
||||
OPTS += $(OPTIONS)
|
||||
|
||||
# This is how we compile
|
||||
#
|
||||
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
|
||||
@@ -537,6 +541,7 @@ FUZZSRC += $(TOP)/test/vt02.c
|
||||
FUZZSRC += $(TOP)/test/fuzzinvariants.c
|
||||
FUZZSRC += $(TOP)/ext/recover/dbdata.c
|
||||
FUZZSRC += $(TOP)/ext/recover/sqlite3recover.c
|
||||
FUZZSRC += $(TOP)/ext/misc/percentile.c
|
||||
FUZZSRC += $(TOP)/ext/misc/randomjson.c
|
||||
DBFUZZ_OPT =
|
||||
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
@@ -555,14 +560,27 @@ sqlite3$(EXE): sqlite3.h libsqlite3.a shell.c
|
||||
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
|
||||
shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h sqlite3.c sqlite3.h
|
||||
$(TCCX) -I$(TOP)/ext/misc -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o dbhash$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/dbhash.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)/tool/sqlite3-rsync.c \
|
||||
sqlite3.c
|
||||
|
||||
RSYNC_OPT = \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync$(EXE): $(RSYNC_SRC)
|
||||
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
|
||||
|
||||
scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
|
||||
$(TCC) -I. -DSCRUB_STANDALONE -o scrub$(EXE) $(TOP)/ext/misc/scrub.c sqlite3.o $(THREADLIB)
|
||||
|
||||
@@ -745,8 +763,6 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
@@ -760,11 +776,16 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/sha1.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.h \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/vfstrace.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
@@ -958,9 +979,14 @@ tcltest: ./testfixture$(EXE)
|
||||
testrunner: testfixture$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration, regardless of how
|
||||
# ./configure was run. The devs run "make devtest" prior to each
|
||||
# check-in, at a minimum. Probably other tests too, but at least this
|
||||
# one.
|
||||
#
|
||||
devtest: testfixture$(EXE) fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
tclsh $(TOP)/test/testrunner.tcl mdevtest
|
||||
|
||||
mdevtest:
|
||||
tclsh $(TOP)/test/testrunner.tcl mdevtest
|
||||
@@ -971,10 +997,19 @@ mdevtest:
|
||||
quicktest: ./testfixture$(EXE)
|
||||
./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
|
||||
|
||||
# The default test case. Runs most of the faster standard TCL tests,
|
||||
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
|
||||
test: fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
#
|
||||
srctree-check: $(TOP)/tool/srctree-check.tcl
|
||||
tclsh $(TOP)/tool/srctree-check.tcl
|
||||
|
||||
# Try to run tests on whatever options are specified by the
|
||||
# environment variables. The SQLite developers seldom use this target.
|
||||
# Instead# they use "make devtest" which runs tests on a standard set of
|
||||
# options regardless of how SQLite is configured. This "test"
|
||||
# target is provided for legacy only.
|
||||
#
|
||||
test: fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
# Run a test using valgrind. This can take a really long time
|
||||
# because valgrind is so much slower than a native machine.
|
||||
@@ -1112,41 +1147,22 @@ install: sqlite3 libsqlite3.a sqlite3.h
|
||||
mv sqlite3.h /usr/include
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3 sqlite3.exe libsqlite3.a sqlite3.h opcodes.*
|
||||
rm -f lemon lemon.exe lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash mkkeywordhash.exe keywordhash.h
|
||||
rm -f $(PUBLISH)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf tsrc target_source
|
||||
rm -f testloadext.dll libtestloadext.so
|
||||
rm -f amalgamation-testfixture amalgamation-testfixture.exe
|
||||
rm -f fts3-testfixture fts3-testfixture.exe
|
||||
rm -f testfixture testfixture.exe
|
||||
rm -f threadtest3 threadtest3.exe
|
||||
rm -f LogEst LogEst.exe
|
||||
rm -f fts3view fts3view.exe
|
||||
rm -f rollback-test rollback-test.exe
|
||||
rm -f showdb showdb.exe
|
||||
rm -f showjournal showjournal.exe
|
||||
rm -f showstat4 showstat4.exe
|
||||
rm -f showwal showwal.exe
|
||||
rm -f changeset changeset.exe
|
||||
rm -f speedtest1 speedtest1.exe
|
||||
rm -f wordcount wordcount.exe
|
||||
rm -f rbu rbu.exe
|
||||
rm -f srcck1 srcck1.exe
|
||||
rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c
|
||||
rm -f sqlite3rc.h
|
||||
rm -f shell.c sqlite3ext.h
|
||||
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
|
||||
rm -f sqlite3_expert sqlite3_expert.exe
|
||||
rm -f sqlite-*-output.vsix
|
||||
rm -f mptester mptester.exe
|
||||
rm -f fuzzershell fuzzershell.exe
|
||||
rm -f fuzzcheck fuzzcheck.exe
|
||||
rm -f sessionfuzz
|
||||
rm -f sqldiff sqldiff.exe
|
||||
rm -f fts5.* fts5parse.*
|
||||
rm -f lsm.h lsm1.c
|
||||
rm -f threadtest5
|
||||
rm -f src-verify
|
||||
rm -f *.lo *.la *.o *.c *.h *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
|
||||
rm -rf .libs .deps tsrc libtool target_source testrunner_*
|
||||
rm -f lemon$(BEXE) sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
|
||||
rm -f parse.* fts5parse.*
|
||||
rm -rf tsrc .target_source testrunner_bld_* testdir*
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
rm -f $(TESTPROGS) testrunner.*
|
||||
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
|
||||
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
|
||||
rm -f *.dll *.lib *.exp *.def *.pc *.vsix
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3-rsync$(TEXE)
|
||||
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
|
||||
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
|
||||
rm -f threadtest5$(TEXE)
|
||||
rm -f src-verify has_tclsh*
|
||||
|
||||
distclean: clean
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C shell.c.in:\suse\seputz/oputz()\sinstead\sof\seputf/oputf()\swhere\sappropriate\sto\savoid\scompilation\serrors\sin\s-std=c99\smode\s(namely\swasm\sbuilds).
|
||||
D 2024-08-25T11:59:29.477
|
||||
C Provide\sSQLITE_U8TEXT_ONLY\sand\sSQLITE_U8TEXT_STDIO\scompile-time\soptions\nto\sthe\ssqlite3_stdio.c\smodule.
|
||||
D 2024-09-26T19:16:20.290
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 101cb90f75c16ca3f8e7088364322441f9b01d6fdcef4a9c7f5fdcf78a3601a4
|
||||
F Makefile.in 6a826facc78c3c8ad38bf00ed588f6aa3665ccd7a9749b891d20582fc290c77e
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 6c3fe8b6ce60e73f34a148c957d78b4648745c8d30e792423aa1a8d8bf12d065
|
||||
F README.md 3d47ef5758e2de29d6f4e1aca714d51424baba86c8b561fef330f6ef2dc9282c
|
||||
F Makefile.msc 9c6d80d9d103fa42e931f4c464884a5e577fae8563acc7589bff4e43fbe8f864
|
||||
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
|
||||
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -17,7 +17,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc 7ac6c331fc3b8aa57b6782db995b8c0e49230352decd4e2662fd07c06a9ed623
|
||||
F autoconf/Makefile.msc 2aced6442addab13ed115696eba28d9ed29caa3dd604a31392c2c7a5da301492
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
|
||||
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
|
||||
@@ -39,7 +39,7 @@ F configure 49523f0a070b583cea040d26eff53a65fb0893eca4663b1343a4d5a9a964da53 x
|
||||
F configure.ac a100ebf7a07f5dedd319ef547dd467d1676ed059b85a7877aa9c44ac309f7000
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/compile-for-windows.md e8635eea9153dcd6a51fd2740666ebc4492b3813cb1ac31cd8e99150df91762d
|
||||
F doc/compile-for-windows.md 4d4bfafda42a7a33f166d23aed4db1bb4ea1e5751595a5cced2bad349fd14652
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
|
||||
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
|
||||
@@ -53,12 +53,12 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c b4885dfea71ed583315de8f0792a29d5fc7c7460b4a26c0aebe5cda5da8b38f8 x
|
||||
F ext/consio/console_io.h 0548b83d7c4b7270ad544a67f2bb90cebc519637fa39b1838df4744cf0d87646
|
||||
F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c74fe5d2b13f x
|
||||
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 661f873fd451127edf822ef0d520088faa319135f6a15bd10be6801ac284ac9b
|
||||
F ext/expert/sqlite3expert.c 8b09aeb2b95a9fca8b6628b522bf4d69aa746ff64c38eb1e99a9b5fad8cf03b9
|
||||
F ext/expert/expert1.test b10f9e20f64102a015c0fcf54cb7b7680266b397e91d93cdad45f57857cdfba6
|
||||
F ext/expert/sqlite3expert.c df417a6d91873a74d35daa9259171647c23c6601415e938e8a71702703f3d677
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
|
||||
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
|
||||
@@ -92,17 +92,17 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 63db9624ccf70d4887836c320eda93ab552f21008f3be7ede551eac3ead62baa
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
|
||||
F ext/fts5/fts5.h c72759fd15179934f10b71ae51ee999e8558f696335e4ec2d049243b764354ee
|
||||
F ext/fts5/fts5Int.h 26a71a09cefa4ef6b4516b204ed48da3e1380970a19b3482eea7c5d805655360
|
||||
F ext/fts5/fts5.h efaaac0df3d3bc740383044c144b582f47921aafa21d7b10eb98f42c24c740b0
|
||||
F ext/fts5/fts5Int.h 93aba03ca417f403b07b2ab6f50aa0e0c1b8b031917a9026b81520e7047a168e
|
||||
F ext/fts5/fts5_aux.c 65a0468dd177d6093aa9ae1622e6d86b0136b8d267c62c0ad6493ad1e9a3d759
|
||||
F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
|
||||
F ext/fts5/fts5_config.c 353d2a0d12678cae6ab5b9ce54aed8dac0825667b69248b5a4ed81cbefc109ea
|
||||
F ext/fts5/fts5_config.c da21548ddbc1a457cb42545f527065221ede8ada6a734891b8c34317a7a9506b
|
||||
F ext/fts5/fts5_expr.c 9a56f53700d1860f0ee2f373c2b9074eaf2a7aa0637d0e27a6476de26a3fee33
|
||||
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
|
||||
F ext/fts5/fts5_index.c eb9a0dda3bc6ef969a6be8d2746af56856e67251810ddba08622b45be8477abe
|
||||
F ext/fts5/fts5_main.c 3d8b778f65fe5be218f6a8e4019048f092c0c09621b035ce3e8804093036b578
|
||||
F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612
|
||||
F ext/fts5/fts5_tcl.c 1dcf08028141c40a32634bdcf2d5601622ce4edc48f82ac4ce0cbe0a92a6961d
|
||||
F ext/fts5/fts5_index.c 571483823193f09439356741669aa8c81da838ae6f5e1bfa7517f7ee2fb3addd
|
||||
F ext/fts5/fts5_main.c 4503498d3453e29a3cd89dacaba029011e89cb8c481a6241611d106e7a369bd4
|
||||
F ext/fts5/fts5_storage.c 3332497823c3d171cf56379f2bd8c971ce15a19aadacff961106462022c92470
|
||||
F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
F ext/fts5/fts5_tokenize.c ae9c4fa93174ef06ffc138bd4280a1c37f7e13624d3d2706aad4b80573f23c41
|
||||
@@ -132,7 +132,7 @@ F ext/fts5/test/fts5auxdata.test 372549088ff792655f73e62b9dfaf4863ce74f5e604c06c
|
||||
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
|
||||
F ext/fts5/test/fts5bigpl.test 8f09858aab866c33593560e6480b2b6975ae7ff29ca32ad7b77e2da61402f8ef
|
||||
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
|
||||
F ext/fts5/test/fts5blob.test caa33369e93e99ff494cd1103506ae34c5afbc0bcc369ed5e58e135144e33689
|
||||
F ext/fts5/test/fts5blob.test 9644a5f917306690e08c5f89a470a3f2489376eaa52026eeca3209d149d6af74
|
||||
F ext/fts5/test/fts5cat.test bf67dd335f964482ee658287521b81e2b88697b45eb7f73933e15f198ed447cb
|
||||
F ext/fts5/test/fts5circref.test f880dfd0d99f6fb73b88ccacb0927d18e833672fd906cc47d6b4e529419eaa62
|
||||
F ext/fts5/test/fts5colset.test 544f4998cdbfe06a3123887fc0221612e8aa8192cdaff152872f1aadb10e6897
|
||||
@@ -148,11 +148,12 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
|
||||
F ext/fts5/test/fts5contentless5.test 40cdcb4fe751672450829c5a96bd32c25fc2f6076279dd2ce5c58ac9a390132a
|
||||
F ext/fts5/test/fts5corrupt.test 6485f721b88ba355ca5d701e7ee87a4efa3ea578d8e6adb26f51ef956c8328bd
|
||||
F ext/fts5/test/fts5corrupt2.test 335911e3f68b9625d850325f9e29a128db3f4276a8c9d4e32134580da8f924c4
|
||||
F ext/fts5/test/fts5corrupt3.test 621e9bca3e7299f487e1b29ff4179d9fc9560f5847dfc5b50a16010c9d2a0e5f
|
||||
F ext/fts5/test/fts5corrupt3.test 4fc3bf129f1616bea00884a23fd9d7b0e46d01791d2b57fe8d68ac36e8d3ff7c
|
||||
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
|
||||
F ext/fts5/test/fts5corrupt5.test 11b47126f5772cc37b67e3e8b2ed05895c4d07c05338bc07e4eea225bfe32c76
|
||||
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
|
||||
F ext/fts5/test/fts5corrupt7.test 4e830875c33b9ea3c4cf1ba71e692b63893cbb4faae8c69b1071889dc26e211c
|
||||
F ext/fts5/test/fts5corrupt8.test b81d802e41631e98100f49a1aadeeffef860e30a62d6ed7d743c2797c477239e
|
||||
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
|
||||
@@ -164,7 +165,7 @@ F ext/fts5/test/fts5expr.test c7e208813df7a90badc856fde3796da79569b39382e0fdb430
|
||||
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
|
||||
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
|
||||
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
|
||||
F ext/fts5/test/fts5fault4.test 87a10d0caee57da587c7588b0c8d25d2930197399b4812ad1e4d574c75324cee
|
||||
F ext/fts5/test/fts5fault4.test a5c0e849127c24e1751bc453a817f09a1b8d460e75f9ae4764017e216a870db3
|
||||
F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
|
||||
F ext/fts5/test/fts5fault6.test 40f49976c6ca8927bf7d65d0b8df46009d7ea172e1d4050b294610e7ea0a2979
|
||||
F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
|
||||
@@ -177,21 +178,22 @@ F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e
|
||||
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
|
||||
F ext/fts5/test/fts5faultG.test 0544411ffcb3e19b42866f757a8a5e0fb8fef3a62c06f61d14deebc571bb7ea9
|
||||
F ext/fts5/test/fts5faultH.test 2b2b5b8cb1b3fd7679f488c06e22af44107fbc6137eaf45b3e771dc7b149312d
|
||||
F ext/fts5/test/fts5faultI.test e1e8a927122a8c3be8614a59717e838cad0505ba0a6f404983da8430e7aeb14d
|
||||
F ext/fts5/test/fts5faultI.test 0706b307b208638554c9e65b4091e1c0dd8c92941535089a301df454ff2c56f4
|
||||
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
|
||||
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
|
||||
F ext/fts5/test/fts5integrity.test 646796671205dae46af5bb12a49b5696483cfe8e12d71d21454940b13ace95ab
|
||||
F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
|
||||
F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba1044c168db0e106f9ac92c
|
||||
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
|
||||
F ext/fts5/test/fts5locale.test 797cf6f5e017462ab11313ce884b9f1df8ff063811e74ef42190cd19ed6b600b
|
||||
F ext/fts5/test/fts5locale.test 83ba7ee12628b540d3098f39c39c1de0c0440eddff8f7512c8c698d0c4a3ae3c
|
||||
F ext/fts5/test/fts5matchinfo.test 877520582feb86bbfd95ab780099bcba4526f18ac75ee34979144cf86ba3a5a3
|
||||
F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test 60bb2be4a2d83d7a45047c1812781e2e337a27efa539d86356ef7f4acaf08eab
|
||||
F ext/fts5/test/fts5misc.test 8c3cc771f773dc4bb4973620c51e7729e324ca2cc80eb8894f1c2c605e361f0b
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
|
||||
@@ -204,7 +206,7 @@ F ext/fts5/test/fts5origintext2.test f4505ff79bf7369f2b8b10b9cef7476049d844e20b3
|
||||
F ext/fts5/test/fts5origintext3.test 45c33cf0c91a9ca0e36d298462db3edc7c8fe45fd185649a9dbfd66bb670058b
|
||||
F ext/fts5/test/fts5origintext4.test 0d3ef0a8038f471dbc83001c34fe5f7ae39b571bfc209670771eb28bc0fc50e8
|
||||
F ext/fts5/test/fts5origintext5.test ee12b440ec335e5b422d1668aca0051b52ff28b6ee67073e8bbc29f509fd562b
|
||||
F ext/fts5/test/fts5phrase.test 6260b8be40d51ec287992cd983a5e58a9be92e5dc6e01d48cbce1ad0e95a99d8
|
||||
F ext/fts5/test/fts5phrase.test bb2554bb61d15f859678c96dc89a7de415cd5fc3b7b54c29b82a0d0ad138091c
|
||||
F ext/fts5/test/fts5plan.test f8b0d752a818059a934cdc96c0f77de058a67a0a57bb3a8181d28307ab5b1626
|
||||
F ext/fts5/test/fts5porter.test 15b514fac8690b58e99c330efe5bf5615bc43f2fae4a3cca3f923dbaff55a0c0
|
||||
F ext/fts5/test/fts5porter2.test 94f0e4351e2c99b4e74f1fae05a4ddf1cb5b926620a8c14554160d075ddc7a59
|
||||
@@ -225,7 +227,7 @@ F ext/fts5/test/fts5secure6.test 74bf04733cc523bccca519bb03d3b4e2ed6f6e3db7c59bf
|
||||
F ext/fts5/test/fts5secure7.test fd03d0868d64340a1db8615b02e5508fea409de13910114e4f19eaefc120777a
|
||||
F ext/fts5/test/fts5secure8.test 808ade9d172ed07b24b85c57dd53b6d2b1aba018b4e634d267ce572221de80e0
|
||||
F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08df2d951422bcef8e2ebc5
|
||||
F ext/fts5/test/fts5simple.test ed7c3815c9fa1c16166258cb98edb2e014c63c7589958d76c5487df0df913d61
|
||||
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
|
||||
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
|
||||
F ext/fts5/test/fts5simple3.test 146ec3dc8f5763d6212641c9f0a2f1cba41679353d2add7b963beceb115dc7f4
|
||||
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
|
||||
@@ -397,7 +399,7 @@ F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f82
|
||||
F ext/misc/decimal.c 172cf81a8634e6a0f0bedaf71a8372fee63348cf5a3c4e1b78bb233c35889fdc
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
|
||||
F ext/misc/fileio.c 916638042f318701460485032e33981056747d0f92e6757aa9499f2363ea7047
|
||||
F ext/misc/fileio.c e6b34db4df4b55b96265086c0010264e257b6eab1644e665697a6da587659403
|
||||
F ext/misc/fossildelta.c 8c026e086e406e2b69947f1856fa3b848fff5379962276430d10085b8756b05a
|
||||
F ext/misc/fuzzer.c 8b28acf1a7e95d50e332bdd47e792ff27054ad99d3f9bc2e91273814d4b31a5a
|
||||
F ext/misc/ieee754.c 62a90978204d2c956d5036eb89e548e736ca5fac0e965912867ddd7bb833256d
|
||||
@@ -409,7 +411,7 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
|
||||
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
|
||||
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
|
||||
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
|
||||
F ext/misc/percentile.c af1941dc87d45dd0c2698a3087fbfe9ee0d157e5e72da521430c4b784abcbe81
|
||||
F ext/misc/percentile.c 42eb041edab407e512aaa087f99ed9287fe0b3224f7a6d194456c00fc1454312
|
||||
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
|
||||
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
@@ -418,11 +420,13 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c a6089b5e8e3002bd1e5d9877cee6aead0b9a6426e406c09a399817db9e9ae823
|
||||
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
|
||||
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
|
||||
F ext/misc/shathree.c 1821d90a0040c9accdbe3e3527d378d30569475d758aa70f6848924c0b430e8c
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd397dbea
|
||||
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
|
||||
F ext/misc/sqlite3_stdio.c f110e6f2dc97c67e89f941f82af7dbd221193fa44d1e3ef38a691454a2cbccda
|
||||
F ext/misc/sqlite3_stdio.h f05eaf5e0258f0573910324a789a9586fc360a57678c57a6d63cfaa2245b6176
|
||||
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
|
||||
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
|
||||
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
|
||||
@@ -433,10 +437,11 @@ F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917
|
||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||
F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d
|
||||
F ext/misc/vfstrace.c ac76a4ac4d907774fd423cc2b61410c756f9d0782e27cf6032e058594accaaca
|
||||
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/zipfile.c 5a3bf1b9cccb8e0da2389fe9e39e9c7f2b1351474b7e5090635f817d495eee3f
|
||||
F ext/misc/zipfile.c b62147ac4985eaac4e368d529b1f4f43ad6bc9ac13d6805d907fff3afdac64d3
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
@@ -482,7 +487,7 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
|
||||
F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
|
||||
F ext/rbu/sqlite3rbu.c c07817e89477b8fc286ab6ed87da5bc82fc3490bbbe9e9b22eb2d900e81ee5dc
|
||||
F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
|
||||
F ext/rbu/test_rbu.c b9727c3394307d058e806c1da0f8bb7b24daf3c6bb94cb10cca88ea4d5c806c0
|
||||
F ext/recover/dbdata.c 5295f4f922b60d7035b6b9fd5846b13071b9d97ed7fad8496837bb7640d24771
|
||||
@@ -572,7 +577,7 @@ F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d0
|
||||
F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
|
||||
F ext/session/session_common.tcl e5598096425486b363718e2cda48ee85d660c96b4f8ea9d9d7a4c3ef514769da
|
||||
F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
|
||||
F ext/session/sessionalter.test 460bdac2832a550519f6bc32e5db2c0cee94f335870aaf25a3a403a81ab20e17
|
||||
F ext/session/sessionalter.test e852acb3d2357aac7d0b920a2109da758c4331bfdf85b41d39aa3a8c18914f65
|
||||
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionchange.test 77c4702050f24270b58070e2cf01c95c3d232a3ef164b70f31974b386ce69903
|
||||
@@ -580,10 +585,10 @@ F ext/session/sessionconflict.test 8b8cbd98548e2e636ddc17d0986276f60e833fb865617
|
||||
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
|
||||
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
|
||||
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
|
||||
F ext/session/sessionfault3.test 7c7547202775de268f3fe6f074c4d0d165151829710b4e64f90d4a01645ba9e7
|
||||
F ext/session/sessionfault3.test ce0b5d182133935c224d72507dbf1c5be1a1febf7e85d0b0fbd6d2f724b32b96
|
||||
F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
|
||||
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
|
||||
F ext/session/sessionnoact.test 506526a5fe29421ecc50d371774ef1bb04cbd9d906a8a468f0556cdbde184c22
|
||||
F ext/session/sessionnoact.test 2563dff62a2a80dc7c88002241b2fd1578c3e5438735e180fb7e941ebbc66214
|
||||
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
|
||||
F ext/session/sessionnoop2.test de4672dce88464396ec9f30ed08c6c01643a69c53ae540fadbbf6d30642d64e8
|
||||
F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
|
||||
@@ -591,9 +596,9 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c c7473aafbd88f796391a8c25aa90975a8f3729ab7f4f8cf74ab9d3b014e10abe
|
||||
F ext/session/sqlite3session.c 3d0a7f0f7a1c946e01818c716a55a40ae30542a29a9045cb05daf7fb658cdafa
|
||||
F ext/session/sqlite3session.h 683ccbf16e2c2521661fc4c1cf918ce57002039efbcabcd8097fa4bca569104b
|
||||
F ext/session/test_session.c 6acbe67db80ab0806147eb62a12f9e3a44930f4a740b68b0a4340dddda2c10d7
|
||||
F ext/session/test_session.c aa29abdcc9011ac02f4fa38e8ede226106eaeee7c3ea7d8b2b999a124e0c368c
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
|
||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||
@@ -684,7 +689,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 9541ffdce424ddddb463e2480c3f1cb4067bbd3a6d2c84b3f083cb128a2fa721
|
||||
F main.mk 0a55ebec3508ca1bdb593d86f3aa19d7fa42a2ddd3220703e6dc0a65f1338a43
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -703,31 +708,31 @@ F src/auth.c 4c1ea890e0069ad73bead5d17a5b12c34cfa4f1a24175c8147ea439b64be271c
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c 8b42fc7d9efdb2df05c30e8f91ff6cfbd979724ae24bf90269028468b7a13333
|
||||
F src/btree.c 8c5592c618741c5fc9733e7efe3927bfafad3e999d15b0a0f3f1d3f3e17b919e
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 3a1840d9d171ce2d24f4c1f7acda7266ab796c664290c1acba65ff98ce2bd01e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 64e4b1227b4ed123146f0aa2989131d1fbd9b927b11e80c9d58c6a68f9cd5ce3
|
||||
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
|
||||
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbpage.c 12e49515d67d4a59625d71f9aa42499556cfdc2e4f1ea49086e674a7f47f46e5
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
|
||||
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
|
||||
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
|
||||
F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f
|
||||
F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
|
||||
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70
|
||||
F src/json.c 5b6a1d6015997b9ee848a32948720bdb26a0ef2de5a2127ebf7355ce66dbdc0d
|
||||
F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c a520c325c7400b249242945f2c602acb19662c40f5db1c04d88664cfaa8b85ac
|
||||
F src/main.c 4db6e3bde55ba0b24ccc83600c2b6ea11429f61ce7b3a2e7e3b42e1b45366c3e
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -737,7 +742,7 @@ F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c 16679def118b5fd75292a253166d3feba3ec9c6189205bf209643ecdb2174ecc
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
|
||||
F src/mutex.c 1b4c7e5e3621b510e0c18397210be27cd54c8084141144fbbafd003fde948e88
|
||||
F src/mutex.c 06bcd9c3dbf2d9b21fcd182606c00fafb9bfe0287983c8e17acd13d2c81a2fa9
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
|
||||
@@ -753,29 +758,29 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y 5972b7d00af4c8d96fdad781af1ea1d5d51fc3b907ad61bda60e49503274e5ed
|
||||
F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
|
||||
F src/pragma.c 52bfbf6dfd668b69b5eb9bd1186e3a67367c8453807150d6e75239229924f684
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c d99931f45416652895e502328ca49fe782cfc4e1ebdcda13b3736d991ebf42ce
|
||||
F src/prepare.c 3ba0ad907b7773ed642f66cea8a2c9c8edc18841aa1050b6218dbb3479e86225
|
||||
F src/printf.c 6a87534ebfb9e5346011191b1f3a7ebc457f5938c7e4feeea478ecf53f6a41b2
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 2c127880c0634962837f16f2f48a295e514357af959330cc038de73015d5b5e8
|
||||
F src/resolve.c 9750a281f7ba073b4e6da2be1a6c4071f5d841a7746c5fb3f70d6d793b6675ea
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
|
||||
F src/shell.c.in 5a05e1a1d187ab916afe9a628d7e9b20b5997273b595bd748db324814e0ccca9
|
||||
F src/sqlite.h.in f07bff4225a1244efd604a0ffef81ed69f29d3dbaed7e22f906f26229ba3ca9e
|
||||
F src/shell.c.in f82c16f090496e61d4b67500522dbbf8f1b37c77415aafc24a7c84bc9d0c8709
|
||||
F src/sqlite.h.in 77f55bd1978a04a14db211732f0a609077cf60ba4ccf9baf39988f508945419c
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 28c878bdf528879afefe1994ac007d094f8061f2fdacdc55d6055d7e9341151e
|
||||
F src/sqliteInt.h 5978cbb11becc3ce6471015d770d95f694ece06336c496f691df1b02460e9cd5
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c c6888598f08dee3d9112a38ef42c8f5c89ca7f3190f4694744d0b84250f4bf8c
|
||||
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
|
||||
F src/test1.c 3f18399557d954bc85f4564aec8ea1777d2161a81d98a3ff6c9e9046bf3554c1
|
||||
F src/test1.c 8d7cd219c004cd2ced60659ebf045025cc5c16ce19d12459589dacd4310f7f07
|
||||
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
|
||||
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
|
||||
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
|
||||
@@ -789,7 +794,7 @@ F src/test_backup.c bd901e3c116c7f3b3bbbd4aae4ce87d99b400c9cbb0a9e7b4610af451d97
|
||||
F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
|
||||
F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5
|
||||
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
|
||||
F src/test_config.c 46eaf39842cace9d540aeefb50fe24dd3204a622893a97952cbb49c20b2f8b21
|
||||
F src/test_config.c 345b8e383f71cecc36d0fa05f2f06639c254b188f98101c3c97749df43037086
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -821,7 +826,6 @@ F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e04
|
||||
F src/test_thread.c d7a8bcea7445f37cc2a1f7f81dd6059634f45e0c61bfe80182b02872fb0328bb
|
||||
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
|
||||
F src/test_vfs.c f298475e468c7e14945b20af885917181090c265aa3c4ade897849c9fbd396f2
|
||||
F src/test_vfstrace.c a2ea82df2ed8927e9eba49bdba1aa1aeb1dcb13dbf6558cff036da813031de9a
|
||||
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
|
||||
F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb775ebc50
|
||||
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
|
||||
@@ -832,25 +836,25 @@ F src/treeview.c 88aa39b754f5ef7214385c1bbbdd2f3dc20efafeed0cf590e8d1199b9c6e44a
|
||||
F src/trigger.c 0bb986a5b96047fd597c6aac28588853df56064e576e6b81ba777ef2ccaac461
|
||||
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
|
||||
F src/utf.c 7bc550af6f3ddd5f5dc82d092c41f728acb760c92e0b47f391963b01ae52569b
|
||||
F src/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
|
||||
F src/vdbe.c be5f58bc29f60252e041a618eae59e8d57d460ba136c5403cf0abf955560c457
|
||||
F src/vdbe.h c2549a215898a390de6669cfa32adba56f0d7e17ba5a7f7b14506d6fd5f0c36a
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
F src/vdbeaux.c 25d685cafe119ff890c94345e884ea558a6b5d823bfa52ba708eb8ff3c70aa71
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
|
||||
F src/vdbeInt.h af7d7e8291edd0b19f2cd698e60e4d4031078f9a2f2328ac8f0b7efb134f8a1d
|
||||
F src/vdbeapi.c 53c7e26a2c0821a892b20eee2cde4656e31998212f3d515576c780dfaa45fd17
|
||||
F src/vdbeaux.c 676dbee99b4febdd94bc9658667a2e3bc413c4c0e356242d90f98a1155d513e5
|
||||
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
|
||||
F src/vdbemem.c df568ef0187e4be2788c35174f6d9b8566ab9475f9aff2d73907ed05aa5684b2
|
||||
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 5fb499d20494b7eecaadb7584634af9afcb374cb0524912b475fcb1712458a1b
|
||||
F src/vtab.c 316cd48e9320660db3047cd306cd056e4361180cebb4d0f10a39244e10c11422
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||
F src/wal.c ef68130ba330ee18c1cb22da36a881c82e3a3b109badbdc6a9b9acaf788a6688
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c c046dd58c3410f7b7528e1e6317cb876398557bad346d568ed8562321a7d002d
|
||||
F src/where.c 461d41017d900d4248a268df96d2d30506c4dcc2257f4167c4f46072003ce2cf
|
||||
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
|
||||
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
|
||||
F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa
|
||||
@@ -1182,7 +1186,7 @@ F test/fts3conf.test c9cd45433b6787d48a43e84949aa2eb8b3b3d242bac7276731c1476290d
|
||||
F test/fts3corrupt.test 6732477c5ace050c5758a40a8b5706c8c0cccd416b9c558e0e15224805a40e57
|
||||
F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
|
||||
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
|
||||
F test/fts3corrupt4.test 48bd57baed9654e511709a02dbef2d22ee54c012ad466e8648f0f825233faa08
|
||||
F test/fts3corrupt4.test a451033ae31db9c5979a7612dee80fb4f221db104a2eeeabd1c9adcc8e8fe95a
|
||||
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
|
||||
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
|
||||
F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
|
||||
@@ -1265,7 +1269,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 6e87c27df3d95c556870187987dff6efdc712b5cea60abedc8ab9215f471907a
|
||||
F test/fuzzcheck.c 89b71d92b150a532e945e489d6e0721a4b15353c9255e079c198ed2a1958018b
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1277,14 +1281,14 @@ F test/fuzzdata8.db 4a53b6d077c6a5c23b609d8d3ac66996fa55ba3f8d02f9b6efdd0214a767
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
|
||||
F test/fuzzinvariants.c 81167c9a7e82c0539a1d704aeb3384046d01f4108cda160a2447cb2a149d6362
|
||||
F test/fuzzinvariants.c 057e910241d85aa4aaf75cef1a7adc45c632b173288d07d9dbbef4e6bda83d5a
|
||||
F test/gcfault.test 4ea410ac161e685f17b19e1f606f58514a2850e806c65b846d05f60d436c5b0d
|
||||
F test/gencol1.test e169bdfa11c7ed5e9f322a98a7db3afe9e66235750b68c923efee8e1876b46ec
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
|
||||
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 18cae9140fa7f9a6f346e892a3fe3e31b2ca0be1494cd01b918adb74281016a6
|
||||
F test/hook.test 3481a68009fe143e3363fca922f6fc7a1e1f3776c51e42777f1a01b26ad2a9c8
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
@@ -1344,7 +1348,7 @@ F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
|
||||
F test/join.test f7abfef3faeaf2800308872e33a57e5b6e4a2b44fb8c6b90c6068412e71a6cf4
|
||||
F test/join2.test 8561fe82ce434ac96de91544072e578dc2cadddf2d9bc9cd802f866a9b92502e
|
||||
F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 380d12a9350f99f0cc681a4f1fea999886f18b3fe0d71a9b3065bcaead1e007f
|
||||
@@ -1379,7 +1383,7 @@ F test/json106.test 4aed3afd16549045d198a8d9cea00deea96e1f2ecf55864dce96cac558b8
|
||||
F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562
|
||||
F test/json108.test 0a5f1e2d4b35a1bc33052563d2a5ede03052e2099e58cb424547656c898e0f49
|
||||
F test/json501.test b95e2d14988b682a5cadf079dd6162f0f85fb74cd59c6b1f1624110104a974eb
|
||||
F test/json502.test 84634d3dbb521d2814e43624025b760c6198456c8197bbec6c977c0236648f5b
|
||||
F test/json502.test 4ef68e4f272dfb083d4cbceb4e9e51d67ec1186a185e0c13637c50a4dc2f9796
|
||||
F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
|
||||
@@ -1516,7 +1520,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
|
||||
F test/percentile.test 74e383216a075251512d6ba98beb9dccd6da465e3f73817fc438379e3a628de7
|
||||
F test/percentile.test 52ba89d6ee6b65f770972b67dace358bab7cdbd532803d3db157845268e789cd
|
||||
F test/permutations.test 405542f1d659942994a6b38a9e024cf5cfd23eaa68c806aeb24a72d7c9186e80
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 11cb9310c42f921918f7f563e3c0b6e70f9f9c3a6a1cf12af8fccb6c574f3882
|
||||
@@ -1624,11 +1628,11 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 490bf9d0c7c9564fea318c46d49369f4690b825b584c9a544dbdccf61bc0babc
|
||||
F test/shell2.test 56da24128304c9ab67da2964cc80beff7b35761c446ec6e6e98bff2775b15026
|
||||
F test/shell1.test b02d628494fa284cdb2b7b2fecdadea96913796afd623f340a79d68f055dcb7e
|
||||
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
|
||||
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
|
||||
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
|
||||
F test/shell5.test bafa4c0b67b7a8027e729970a625c9225cb7ef854acc4e52624c45074faaaddf
|
||||
F test/shell5.test 0e5f8ce08206b9998a778cfe1989e20e47839153c05af2da29198150172e22fc
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
|
||||
@@ -1712,9 +1716,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 2c203a2dd664298f239f0ec3ce22fbc65b5f021c1e09edbae8452af8a694e052
|
||||
F test/testrunner.tcl 5d02deeba7a53baeadae6aa7641d90aac58fdfa3a7bcac85cfcfd752b1aab87c
|
||||
F test/testrunner_data.tcl c5ae2b1f9a99210b0600d002fb3af1fee350997cee9416551e83b93501360ebf
|
||||
F test/tester.tcl 7b44f1a9b9a2de8112695b908afc21dd9a68cd2d44e84b73f1b27b53492c0d59
|
||||
F test/testrunner.tcl 3dd75b45593d2afa2e3bca76121297a9f163bebb98474b13536f326829a71db1 x
|
||||
F test/testrunner_data.tcl dbc0bb1c5b912dfd1e32b25d544318e412edd6085bd5fc9e6619cb93a739b786
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -2049,7 +2053,7 @@ F test/wherelimit3.test 22d73e046870cf8bbe15573eda6b432b07ebe64a88711f9f849c6b36
|
||||
F test/widetab1.test c296a98e123762de79917350e45fa33fdf88577a2571eb3a64c8bf7e44ef74d1
|
||||
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
|
||||
F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
|
||||
F test/win32longpath.test 42210789bcfc5c0ac202643d6d0237db08df2c9218f2070d9a69e8af1eccf7d7
|
||||
F test/win32longpath.test 304006024ca47104bf5a7415ef31ca83ecfc29351af202baf8588b880cffc116
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 79dc3b9a2226f622d7e104a1fc750d1c4c3c08d6147b59085bdbe05352947ffa
|
||||
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
|
||||
@@ -2069,7 +2073,7 @@ F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af
|
||||
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
|
||||
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
|
||||
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
|
||||
F test/windowE.test c98507e0b0d95980ad25845db758557757be2d7054198ccf522c7d277057a3df
|
||||
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
|
||||
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
|
||||
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
|
||||
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
|
||||
@@ -2100,7 +2104,7 @@ F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb
|
||||
F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/build-all-msvc.bat c817b716e0edeecaf265a6775b63e5f45c34a6544f1d4114a222701ed5ac79ab x
|
||||
F tool/build-shell.sh f193b5e3eb4afcb4abbf96bf1475be6cfb74763ee2e50c82bc7ca105e8a136c5
|
||||
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
|
||||
F tool/buildtclext.tcl b64d250517b148e644d26fcbc097851867a0df52cd4bafe9bcd94b8421e1428a
|
||||
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
@@ -2130,8 +2134,8 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
|
||||
F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
|
||||
F tool/mkctimec.tcl e3af51acc2ef92062fe6d622de010a27a34b497258a248dada04388b916c61c6 x
|
||||
F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
|
||||
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
|
||||
@@ -2148,21 +2152,21 @@ F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617
|
||||
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
|
||||
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
|
||||
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
|
||||
F tool/omittest.tcl e99c9fecc3f7a8ca2fa75d8ec8bdbb5acce33dc69f0c280aae53064693387f65
|
||||
F tool/omittest.tcl 5ca5e4e01716d5f35b48b00fd351d929f01fbb98169a5a3cd00baf3d2e2019a9
|
||||
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/pagesig.c f98909b4168d9cac11a2de7f031adea0e2f3131faa7515a72807c03ec58eafeb
|
||||
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
|
||||
F tool/restore_jrnl.tcl 1079ecba47cc82fa82115b81c1f68097ab1f956f357ee8da5fc4b2589af6bd98
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
|
||||
F tool/showdb.c 0f74b54cc67076c76cba9b2b7f54d3e05b78d130c70ffc394eb84c5b41bab017
|
||||
F tool/showdb.c 81b04bfaa9a63665f75945947323aa68b820570aa156b1574f440fc8276092c6
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
|
||||
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
|
||||
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
|
||||
F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3d
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 3568b2b15b83dcaf789e787a4db0980da81eb6fa0e1e00783e4a927fdf584550
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/speed-check.sh e8d20cc2eb9c85ec1ba562226de144435456dcdff4ee618de49603c6958f6116
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
@@ -2171,8 +2175,9 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
|
||||
F tool/sqldiff.c 847fc8fcfddf5ce4797b7394cad6372f2f5dc17d8186e2ef8fb44d50fae4f44a
|
||||
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
|
||||
F tool/sqldiff.c 2a0987d183027c795ced13d6749061c1d2f38e24eddb428f56fa64c3a8f51e4b
|
||||
F tool/sqlite3-rsync.c 187b262035c1159b047dbfa1959c168b87b5a153b63465e8c8bd1b54fabf4460
|
||||
F tool/sqlite3_analyzer.c.in 348ba349bbdc93c9866439f9f935d7284866a2a4e6898bc906ae1204ade56918
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
|
||||
@@ -2210,8 +2215,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P df65d00f104f31741056686f2ba41ecb192c552012bffb17c2a8b5d4db058328
|
||||
R 8d4b348b6bf673b94cab6e107b5bbb73
|
||||
U stephan
|
||||
Z 5120e8419efd39e01384da30ed409ec4
|
||||
P 54c22bc6165affbea0d1166a0912d19939300ccc4ae33a6b2ed8c510ab61c574
|
||||
R 2b2b12aba8675f6b1c9a607cabf2b89d
|
||||
U drh
|
||||
Z a76d82025e5362f7f888a23f868f0cc8
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
9ef8317faebc29d016bdf2e8c678fb21ca2cfa95272f1f18b461fcaf0e220ac5
|
||||
f31588520e3f45b50dcaa9eecab17f52ebb56bb53d0f9bdb88cc596d1a156353
|
||||
|
||||
+1
-1
@@ -5989,7 +5989,7 @@ int sqlite3BtreeIndexMoveto(
|
||||
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
|
||||
&& pIdxKey->errCode==SQLITE_OK
|
||||
){
|
||||
pCur->curFlags &= ~BTCF_ValidOvfl;
|
||||
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
|
||||
if( !pCur->pPage->isInit ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
@@ -295,6 +295,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
"ENABLE_OFFSET_SQL_FUNC",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
"ENABLE_ORDERED_SET_AGGREGATES",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
|
||||
+73
-23
@@ -28,7 +28,13 @@
|
||||
**
|
||||
** The data field of sqlite_dbpage table can be updated. The new
|
||||
** value must be a BLOB which is the correct page size, otherwise the
|
||||
** update fails. Rows may not be deleted or inserted.
|
||||
** update fails. INSERT operations also work, and operate as if they
|
||||
** where REPLACE. The size of the database can be extended by INSERT-ing
|
||||
** new pages on the end.
|
||||
**
|
||||
** Rows may not be deleted. However, doing an INSERT to page number N
|
||||
** with NULL page data causes the N-th page and all subsequent pages to be
|
||||
** deleted and the database to be truncated.
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h" /* Requires access to internal data structures */
|
||||
@@ -51,6 +57,8 @@ struct DbpageCursor {
|
||||
struct DbpageTable {
|
||||
sqlite3_vtab base; /* Base class. Must be first */
|
||||
sqlite3 *db; /* The database */
|
||||
int nTrunc; /* Entries in aTrunc[] */
|
||||
Pgno *aTrunc; /* Truncation size for each database */
|
||||
};
|
||||
|
||||
/* Columns */
|
||||
@@ -59,7 +67,6 @@ struct DbpageTable {
|
||||
#define DBPAGE_COLUMN_SCHEMA 2
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Connect to or create a dbpagevfs virtual table.
|
||||
*/
|
||||
@@ -100,6 +107,8 @@ static int dbpageConnect(
|
||||
** Disconnect from or destroy a dbpagevfs virtual table.
|
||||
*/
|
||||
static int dbpageDisconnect(sqlite3_vtab *pVtab){
|
||||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
sqlite3_free(pTab->aTrunc);
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -321,11 +330,11 @@ static int dbpageUpdate(
|
||||
DbPage *pDbPage = 0;
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
const char *zSchema;
|
||||
int iDb;
|
||||
Btree *pBt;
|
||||
Pager *pPager;
|
||||
int szPage;
|
||||
int isInsert;
|
||||
|
||||
(void)pRowid;
|
||||
if( pTab->db->flags & SQLITE_Defensive ){
|
||||
@@ -336,21 +345,29 @@ static int dbpageUpdate(
|
||||
zErr = "cannot delete";
|
||||
goto update_fail;
|
||||
}
|
||||
pgno = sqlite3_value_int(argv[0]);
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL
|
||||
|| (Pgno)sqlite3_value_int(argv[1])!=pgno
|
||||
){
|
||||
zErr = "cannot insert";
|
||||
goto update_fail;
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
|
||||
pgno = (Pgno)sqlite3_value_int(argv[2]);
|
||||
isInsert = 1;
|
||||
}else{
|
||||
pgno = sqlite3_value_int(argv[0]);
|
||||
if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
|
||||
zErr = "cannot insert";
|
||||
goto update_fail;
|
||||
}
|
||||
isInsert = 0;
|
||||
}
|
||||
zSchema = (const char*)sqlite3_value_text(argv[4]);
|
||||
iDb = ALWAYS(zSchema) ? sqlite3FindDbName(pTab->db, zSchema) : -1;
|
||||
if( NEVER(iDb<0) ){
|
||||
zErr = "no such schema";
|
||||
goto update_fail;
|
||||
if( sqlite3_value_type(argv[4])==SQLITE_NULL ){
|
||||
iDb = 0;
|
||||
}else{
|
||||
const char *zSchema = (const char*)sqlite3_value_text(argv[4]);
|
||||
iDb = sqlite3FindDbName(pTab->db, zSchema);
|
||||
if( iDb<0 ){
|
||||
zErr = "no such schema";
|
||||
goto update_fail;
|
||||
}
|
||||
}
|
||||
pBt = pTab->db->aDb[iDb].pBt;
|
||||
if( NEVER(pgno<1) || NEVER(pBt==0) || NEVER(pgno>sqlite3BtreeLastPage(pBt)) ){
|
||||
if( pgno<1 || NEVER(pBt==0) ){
|
||||
zErr = "bad page number";
|
||||
goto update_fail;
|
||||
}
|
||||
@@ -358,18 +375,31 @@ static int dbpageUpdate(
|
||||
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(argv[3])!=szPage
|
||||
){
|
||||
zErr = "bad page value";
|
||||
goto update_fail;
|
||||
if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){
|
||||
if( iDb>=pTab->nTrunc ){
|
||||
testcase( pTab->aTrunc!=0 );
|
||||
pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno));
|
||||
if( pTab->aTrunc ){
|
||||
int j;
|
||||
for(j=pTab->nTrunc; j<iDb; j++) pTab->aTrunc[j] = 0;
|
||||
pTab->nTrunc = iDb+1;
|
||||
}else{
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
pTab->aTrunc[iDb] = pgno;
|
||||
}else{
|
||||
zErr = "bad page value";
|
||||
goto update_fail;
|
||||
}
|
||||
}
|
||||
pPager = sqlite3BtreePager(pBt);
|
||||
rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
const void *pData = sqlite3_value_blob(argv[3]);
|
||||
assert( pData!=0 || pTab->db->mallocFailed );
|
||||
if( pData
|
||||
&& (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
|
||||
){
|
||||
memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
|
||||
if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
|
||||
unsigned char *aPage = sqlite3PagerGetData(pDbPage);
|
||||
memcpy(aPage, pData, szPage);
|
||||
}
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
@@ -393,6 +423,26 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
}
|
||||
if( pTab->nTrunc>0 ){
|
||||
memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
|
||||
*/
|
||||
static int dbpageSync(sqlite3_vtab *pVtab){
|
||||
int iDb;
|
||||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
|
||||
for(iDb=0; iDb<pTab->nTrunc; iDb++){
|
||||
if( pTab->aTrunc[iDb]>0 ){
|
||||
Btree *pBt = pTab->db->aDb[iDb].pBt;
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]);
|
||||
pTab->aTrunc[iDb] = 0;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -417,7 +467,7 @@ int sqlite3DbpageRegister(sqlite3 *db){
|
||||
dbpageRowid, /* xRowid - read data */
|
||||
dbpageUpdate, /* xUpdate */
|
||||
dbpageBegin, /* xBegin */
|
||||
0, /* xSync */
|
||||
dbpageSync, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
|
||||
@@ -75,6 +75,7 @@ void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
|
||||
** is for a top-level SQL statement.
|
||||
*/
|
||||
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
assert( IsVirtual(pTab) );
|
||||
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
+6
-2
@@ -2049,7 +2049,11 @@ static void minMaxFinalize(sqlite3_context *context){
|
||||
** group_concat(EXPR, ?SEPARATOR?)
|
||||
** string_agg(EXPR, SEPARATOR)
|
||||
**
|
||||
** The SEPARATOR goes before the EXPR string. This is tragic. The
|
||||
** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
|
||||
** coming before the EXPR value, except for the first entry which
|
||||
** omits the SEPARATOR.
|
||||
**
|
||||
** It is tragic that the SEPARATOR goes before the EXPR string. The
|
||||
** groupConcatInverse() implementation would have been easier if the
|
||||
** SEPARATOR were appended after EXPR. And the order is undocumented,
|
||||
** so we could change it, in theory. But the old behavior has been
|
||||
@@ -2153,7 +2157,7 @@ static void groupConcatInverse(
|
||||
/* pGCC is always non-NULL since groupConcatStep() will have always
|
||||
** run first to initialize it */
|
||||
if( ALWAYS(pGCC) ){
|
||||
int nVS;
|
||||
int nVS; /* Number of characters to remove */
|
||||
/* Must call sqlite3_value_text() to convert the argument into text prior
|
||||
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
|
||||
(void)sqlite3_value_text(argv[0]);
|
||||
|
||||
+3
-1
@@ -2847,7 +2847,9 @@ static u32 jsonLookupStep(
|
||||
zPath++;
|
||||
if( zPath[0]=='"' ){
|
||||
zKey = zPath + 1;
|
||||
for(i=1; zPath[i] && zPath[i]!='"'; i++){}
|
||||
for(i=1; zPath[i] && zPath[i]!='"'; i++){
|
||||
if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++;
|
||||
}
|
||||
nKey = i-1;
|
||||
if( zPath[i] ){
|
||||
i++;
|
||||
|
||||
+3
-1
@@ -1926,7 +1926,8 @@ int sqlite3CreateFunc(
|
||||
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
|
||||
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
|
||||
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE);
|
||||
SQLITE_SUBTYPE|SQLITE_INNOCUOUS|
|
||||
SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1);
|
||||
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
|
||||
|
||||
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
|
||||
@@ -3481,6 +3482,7 @@ static int openDatabase(
|
||||
if( ((1<<(flags&7)) & 0x46)==0 ){
|
||||
rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
|
||||
}else{
|
||||
if( zFilename==0 ) zFilename = ":memory:";
|
||||
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
||||
+14
-1
@@ -347,15 +347,28 @@ void sqlite3_mutex_leave(sqlite3_mutex *p){
|
||||
/*
|
||||
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
||||
** intended for use inside assert() statements.
|
||||
**
|
||||
** Because these routines raise false-positive alerts in TSAN, disable
|
||||
** them (make them always return 1) when compiling with TSAN.
|
||||
*/
|
||||
int sqlite3_mutex_held(sqlite3_mutex *p){
|
||||
# if defined(__has_feature)
|
||||
# if __has_feature(thread_sanitizer)
|
||||
p = 0;
|
||||
# endif
|
||||
# endif
|
||||
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
|
||||
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
|
||||
}
|
||||
int sqlite3_mutex_notheld(sqlite3_mutex *p){
|
||||
# if defined(__has_feature)
|
||||
# if __has_feature(thread_sanitizer)
|
||||
p = 0;
|
||||
# endif
|
||||
# endif
|
||||
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
|
||||
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
|
||||
}
|
||||
#endif
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#endif /* !defined(SQLITE_MUTEX_OMIT) */
|
||||
|
||||
+71
-1
@@ -264,6 +264,9 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
|
||||
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
|
||||
EXCLUDE GROUPS OTHERS TIES
|
||||
%endif SQLITE_OMIT_WINDOWFUNC
|
||||
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
WITHIN
|
||||
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
GENERATED ALWAYS
|
||||
%endif
|
||||
@@ -1179,6 +1182,65 @@ expr(A) ::= idj(X) LP STAR RP. {
|
||||
A = sqlite3ExprFunction(pParse, 0, &X, 0);
|
||||
}
|
||||
|
||||
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
%include {
|
||||
/* Generate an expression node that represents an ordered-set aggregate function.
|
||||
**
|
||||
** SQLite does not do anything special to evaluate ordered-set aggregates. The
|
||||
** aggregate function itself is expected to do any required ordering on its own.
|
||||
** This is just syntactic sugar.
|
||||
**
|
||||
** This syntax: percentile(f) WITHIN GROUP ( ORDER BY y )
|
||||
**
|
||||
** Is equivalent to: percentile(y,f)
|
||||
**
|
||||
** The purpose of this function is to generate an Expr node from the first syntax
|
||||
** into a TK_FUNCTION node that looks like it came from the second syntax.
|
||||
**
|
||||
** Only functions that have the SQLITE_SELFORDER1 perperty are allowed to do this
|
||||
** transformation. Because DISTINCT is not allowed in the ordered-set aggregate
|
||||
** syntax, an error is raised if DISTINCT is used.
|
||||
*/
|
||||
static Expr *sqlite3ExprAddOrderedsetFunction(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Token *pFuncname, /* Name of the function */
|
||||
int isDistinct, /* DISTINCT or ALL qualifier */
|
||||
ExprList *pOrig, /* Arguments to the function */
|
||||
Expr *pOrderby /* Expression in the ORDER BY clause */
|
||||
){
|
||||
ExprList *p; /* Modified argument list */
|
||||
Expr *pExpr; /* Final result */
|
||||
p = sqlite3ExprListAppend(pParse, 0, pOrderby);
|
||||
if( pOrig ){
|
||||
int i;
|
||||
for(i=0; i<pOrig->nExpr; i++){
|
||||
p = sqlite3ExprListAppend(pParse, p, pOrig->a[i].pExpr);
|
||||
pOrig->a[i].pExpr = 0;
|
||||
}
|
||||
sqlite3ExprListDelete(pParse->db, pOrig);
|
||||
}
|
||||
pExpr = sqlite3ExprFunction(pParse, p, pFuncname, 0);
|
||||
if( pParse->nErr==0 ){
|
||||
FuncDef *pDef;
|
||||
u8 enc = ENC(pParse->db);
|
||||
assert( pExpr!=0 ); /* Because otherwise pParse->nErr would not be zero */
|
||||
assert( p!=0 ); /* Because otherwise pParse->nErr would not be zero */
|
||||
pDef = sqlite3FindFunction(pParse->db, pExpr->u.zToken, -2, enc, 0);
|
||||
if( pDef==0 || (pDef->funcFlags & SQLITE_SELFORDER1)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "%#T() is not an ordered-set aggregate", pExpr);
|
||||
}else if( isDistinct==SF_Distinct ){
|
||||
sqlite3ErrorMsg(pParse, "DISTINCT not allowed on ordered-set aggregate %T()",
|
||||
pFuncname);
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
}
|
||||
}
|
||||
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP. {
|
||||
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
|
||||
}
|
||||
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
|
||||
%ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
|
||||
A = sqlite3ExprFunction(pParse, Y, &X, D);
|
||||
@@ -1193,7 +1255,15 @@ expr(A) ::= idj(X) LP STAR RP filter_over(Z). {
|
||||
A = sqlite3ExprFunction(pParse, 0, &X, 0);
|
||||
sqlite3WindowAttach(pParse, A, Z);
|
||||
}
|
||||
%endif
|
||||
%ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
expr(A) ::= idj(X) LP distinct(D) exprlist(Y) RP WITHIN GROUP LP ORDER BY expr(E) RP
|
||||
filter_over(Z). {
|
||||
A = sqlite3ExprAddOrderedsetFunction(pParse, &X, D, Y, E);
|
||||
sqlite3WindowAttach(pParse, A, Z);
|
||||
}
|
||||
%endif SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
|
||||
%endif SQLITE_OMIT_WINDOWFUNC
|
||||
|
||||
term(A) ::= CTIME_KW(OP). {
|
||||
A = sqlite3ExprFunction(pParse, 0, &OP, 0);
|
||||
|
||||
+13
-1
@@ -1007,12 +1007,24 @@ static int sqlite3Prepare16(
|
||||
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
/* Make sure nBytes is non-negative and correct. It should be the
|
||||
** number of bytes until the end of the input buffer or until the first
|
||||
** U+0000 character. If the input nBytes is odd, convert it into
|
||||
** an even number. If the input nBytes is negative, then the input
|
||||
** must be terminated by at least one U+0000 character */
|
||||
if( nBytes>=0 ){
|
||||
int sz;
|
||||
const char *z = (const char*)zSql;
|
||||
for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
|
||||
nBytes = sz;
|
||||
}else{
|
||||
int sz;
|
||||
const char *z = (const char*)zSql;
|
||||
for(sz=0; z[sz]!=0 || z[sz+1]!=0; sz += 2){}
|
||||
nBytes = sz;
|
||||
}
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
|
||||
if( zSql8 ){
|
||||
@@ -1026,7 +1038,7 @@ static int sqlite3Prepare16(
|
||||
** the same number of characters into the UTF-16 string.
|
||||
*/
|
||||
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
|
||||
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
|
||||
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed);
|
||||
}
|
||||
sqlite3DbFree(db, zSql8);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
|
||||
+5
-3
@@ -486,7 +486,7 @@ static int lookupName(
|
||||
*/
|
||||
if( cntTab==0
|
||||
|| (cntTab==1
|
||||
&& ALWAYS(pMatch!=0)
|
||||
&& pMatch!=0
|
||||
&& ALWAYS(pMatch->pSTab!=0)
|
||||
&& (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0
|
||||
&& (pTab->tabFlags & TF_Ephemeral)==0)
|
||||
@@ -1119,8 +1119,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* Resolve function names
|
||||
*/
|
||||
case TK_FUNCTION: {
|
||||
ExprList *pList = pExpr->x.pList; /* The argument list */
|
||||
int n = pList ? pList->nExpr : 0; /* Number of arguments */
|
||||
ExprList *pList; /* The argument list */
|
||||
int n; /* Number of arguments */
|
||||
int no_such_func = 0; /* True if no such function exists */
|
||||
int wrong_num_args = 0; /* True if wrong number of arguments */
|
||||
int is_agg = 0; /* True if is an aggregate function */
|
||||
@@ -1133,6 +1133,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
#endif
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
|
||||
assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER );
|
||||
pList = pExpr->x.pList;
|
||||
n = pList ? pList->nExpr : 0;
|
||||
zId = pExpr->u.zToken;
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
|
||||
if( pDef==0 ){
|
||||
|
||||
+1053
-729
File diff suppressed because it is too large
Load Diff
@@ -5615,6 +5615,15 @@ int sqlite3_create_window_function(
|
||||
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
||||
** purpose of this property is to disable certain optimizations that are
|
||||
** incompatible with subtypes.
|
||||
**
|
||||
** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd>
|
||||
** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
|
||||
** that internally orders the values provided to the first argument. The
|
||||
** ordered-set aggregate SQL notation with a single ORDER BY term can be
|
||||
** used to invoke this function. If the ordered-set aggregate notation is
|
||||
** used on a function that lacks this flag, then an error is raised. Note
|
||||
** that the ordered-set aggregate syntax is only available if SQLite is
|
||||
** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
@@ -5623,6 +5632,7 @@ int sqlite3_create_window_function(
|
||||
#define SQLITE_SUBTYPE 0x000100000
|
||||
#define SQLITE_INNOCUOUS 0x000200000
|
||||
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
||||
#define SQLITE_SELFORDER1 0x002000000
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
|
||||
+3
-1
@@ -658,6 +658,8 @@
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
# define double sqlite_int64
|
||||
# define float sqlite_int64
|
||||
# define fabs(X) ((X)<0?-(X):(X))
|
||||
# define sqlite3IsOverflow(X) 0
|
||||
# define LONGDOUBLE_TYPE sqlite_int64
|
||||
# ifndef SQLITE_BIG_DBL
|
||||
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
|
||||
@@ -5265,7 +5267,7 @@ int sqlite3GetInt32(const char *, int*);
|
||||
int sqlite3GetUInt32(const char*, u32*);
|
||||
int sqlite3Atoi(const char*);
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
int sqlite3Utf16ByteLen(const void *pData, int nChar);
|
||||
int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
|
||||
#endif
|
||||
int sqlite3Utf8CharLen(const char *pData, int nByte);
|
||||
u32 sqlite3Utf8Read(const u8**);
|
||||
|
||||
+1
-1
@@ -2343,7 +2343,7 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
|
||||
}
|
||||
for(ii=0; ii<(int)nFlag; ii++){
|
||||
int iVal = 0;
|
||||
int res = Tcl_GetIndexFromObjStruct(
|
||||
res = Tcl_GetIndexFromObjStruct(
|
||||
interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal
|
||||
);
|
||||
if( res ) return TCL_ERROR;
|
||||
|
||||
@@ -189,6 +189,14 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
Tcl_SetVar2(interp, "sqlite_options",
|
||||
"ordered_set_aggregates","1",TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options",
|
||||
"ordered_set_aggregates","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -341,6 +349,14 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ORDEREDSETFUNC
|
||||
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "1",
|
||||
TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "ordered_set_funcs", "0",
|
||||
TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
Tcl_SetVar2(interp, "sqlite_options", "oversize_cell_check", "1",
|
||||
TCL_GLOBAL_ONLY);
|
||||
|
||||
@@ -514,20 +514,22 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
|
||||
}
|
||||
|
||||
/*
|
||||
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
|
||||
** zIn is a UTF-16 encoded unicode string at least nByte bytes long.
|
||||
** Return the number of bytes in the first nChar unicode characters
|
||||
** in pZ. nChar must be non-negative.
|
||||
** in pZ. nChar must be non-negative. Surrogate pairs count as a single
|
||||
** character.
|
||||
*/
|
||||
int sqlite3Utf16ByteLen(const void *zIn, int nChar){
|
||||
int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){
|
||||
int c;
|
||||
unsigned char const *z = zIn;
|
||||
unsigned char const *zEnd = &z[nByte-1];
|
||||
int n = 0;
|
||||
|
||||
if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
|
||||
while( n<nChar ){
|
||||
while( n<nChar && ALWAYS(z<=zEnd) ){
|
||||
c = z[0];
|
||||
z += 2;
|
||||
if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
|
||||
if( c>=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
|
||||
n++;
|
||||
}
|
||||
return (int)(z-(unsigned char const *)zIn)
|
||||
|
||||
+14
-9
@@ -162,6 +162,9 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
const char *zDbMain; /* Schema name of database to vacuum */
|
||||
const char *zOut; /* Name of output file */
|
||||
u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
|
||||
u64 iRandom; /* Random value used for zDbVacuum[] */
|
||||
char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */
|
||||
|
||||
|
||||
if( !db->autoCommit ){
|
||||
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
|
||||
@@ -202,27 +205,29 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
pMain = db->aDb[iDb].pBt;
|
||||
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
|
||||
|
||||
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
|
||||
/* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
|
||||
** can be set to 'off' for this file, as it is not recovered if a crash
|
||||
** occurs anyway. The integrity of the database is maintained by a
|
||||
** (possibly synchronous) transaction opened on the main database before
|
||||
** sqlite3BtreeCopyFile() is called.
|
||||
**
|
||||
** An optimization would be to use a non-journaled pager.
|
||||
** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
|
||||
** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
|
||||
** that actually made the VACUUM run slower. Very little journalling
|
||||
** actually occurs when doing a vacuum since the vacuum_db is initially
|
||||
** empty. Only the journal header is written. Apparently it takes more
|
||||
** time to parse and run the PRAGMA to turn journalling off than it does
|
||||
** to write the journal header file.
|
||||
*/
|
||||
sqlite3_randomness(sizeof(iRandom),&iRandom);
|
||||
sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
|
||||
nDb = db->nDb;
|
||||
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
|
||||
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
|
||||
db->openFlags = saved_openFlags;
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
assert( (db->nDb-1)==nDb );
|
||||
pDb = &db->aDb[nDb];
|
||||
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
|
||||
assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
|
||||
pTemp = pDb->pBt;
|
||||
if( pOut ){
|
||||
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
|
||||
@@ -299,11 +304,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
** the contents to the temporary database.
|
||||
*/
|
||||
rc = execSqlF(db, pzErrMsg,
|
||||
"SELECT'INSERT INTO vacuum_db.'||quote(name)"
|
||||
"SELECT'INSERT INTO %s.'||quote(name)"
|
||||
"||' SELECT*FROM\"%w\".'||quote(name)"
|
||||
"FROM vacuum_db.sqlite_schema "
|
||||
"FROM %s.sqlite_schema "
|
||||
"WHERE type='table'AND coalesce(rootpage,1)>0",
|
||||
zDbMain
|
||||
zDbVacuum, zDbMain, zDbVacuum
|
||||
);
|
||||
assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
|
||||
db->mDbFlags &= ~DBFLAG_Vacuum;
|
||||
@@ -315,11 +320,11 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
** from the schema table.
|
||||
*/
|
||||
rc = execSqlF(db, pzErrMsg,
|
||||
"INSERT INTO vacuum_db.sqlite_schema"
|
||||
"INSERT INTO %s.sqlite_schema"
|
||||
" SELECT*FROM \"%w\".sqlite_schema"
|
||||
" WHERE type IN('view','trigger')"
|
||||
" OR(type='table'AND rootpage=0)",
|
||||
zDbMain
|
||||
zDbVacuum, zDbMain
|
||||
);
|
||||
if( rc ) goto end_of_vacuum;
|
||||
|
||||
|
||||
@@ -543,6 +543,7 @@ struct PreUpdate {
|
||||
Mem *aNew; /* Array of new.* values */
|
||||
Table *pTab; /* Schema object being updated */
|
||||
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
|
||||
sqlite3_value **apDflt; /* Array of default values, if required */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+41
-1
@@ -1621,6 +1621,17 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
|
||||
**
|
||||
** The error code stored in database p->db is overwritten with the return
|
||||
** value in any case.
|
||||
**
|
||||
** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK,
|
||||
** that means all of the the following will be true:
|
||||
**
|
||||
** p!=0
|
||||
** p->pVar!=0
|
||||
** i>0
|
||||
** i<=p->nVar
|
||||
**
|
||||
** An assert() is normally added after vdbeUnbind() to help static analyzers
|
||||
** realize this.
|
||||
*/
|
||||
static int vdbeUnbind(Vdbe *p, unsigned int i){
|
||||
Mem *pVar;
|
||||
@@ -1678,6 +1689,7 @@ static int bindText(
|
||||
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
if( zData!=0 ){
|
||||
pVar = &p->aVar[i-1];
|
||||
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
|
||||
@@ -1727,6 +1739,7 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
@@ -1740,6 +1753,7 @@ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
@@ -1750,6 +1764,7 @@ int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
return rc;
|
||||
@@ -1765,6 +1780,7 @@ int sqlite3_bind_pointer(
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}else if( xDestructor ){
|
||||
@@ -1846,6 +1862,7 @@ int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
rc = vdbeUnbind(p, (u32)(i-1));
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
|
||||
#else
|
||||
@@ -2205,7 +2222,30 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
||||
if( iIdx==p->pTab->iPKey ){
|
||||
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
|
||||
}else if( iIdx>=p->pUnpacked->nField ){
|
||||
*ppValue = (sqlite3_value *)columnNullValue();
|
||||
/* This occurs when the table has been extended using ALTER TABLE
|
||||
** ADD COLUMN. The value to return is the default value of the column. */
|
||||
Column *pCol = &p->pTab->aCol[iIdx];
|
||||
if( pCol->iDflt>0 ){
|
||||
if( p->apDflt==0 ){
|
||||
int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
|
||||
p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
|
||||
if( p->apDflt==0 ) goto preupdate_old_out;
|
||||
}
|
||||
if( p->apDflt[iIdx]==0 ){
|
||||
sqlite3_value *pVal = 0;
|
||||
Expr *pDflt;
|
||||
assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
|
||||
pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
|
||||
rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
|
||||
if( rc==SQLITE_OK && pVal==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
p->apDflt[iIdx] = pVal;
|
||||
}
|
||||
*ppValue = p->apDflt[iIdx];
|
||||
}else{
|
||||
*ppValue = (sqlite3_value *)columnNullValue();
|
||||
}
|
||||
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
|
||||
if( pMem->flags & (MEM_Int|MEM_IntReal) ){
|
||||
testcase( pMem->flags & MEM_Int );
|
||||
|
||||
@@ -5543,5 +5543,12 @@ void sqlite3VdbePreUpdateHook(
|
||||
}
|
||||
sqlite3DbNNFreeNN(db, preupdate.aNew);
|
||||
}
|
||||
if( preupdate.apDflt ){
|
||||
int i;
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
sqlite3ValueFree(preupdate.apDflt[i]);
|
||||
}
|
||||
sqlite3DbFree(db, preupdate.apDflt);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
||||
|
||||
@@ -167,6 +167,11 @@ int sqlite3_blob_open(
|
||||
pTab = 0;
|
||||
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
|
||||
}
|
||||
if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
|
||||
pTab = 0;
|
||||
sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
|
||||
zTable);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
if( pTab && IsView(pTab) ){
|
||||
pTab = 0;
|
||||
|
||||
+2
-1
@@ -1534,7 +1534,8 @@ static int valueFromFunction(
|
||||
goto value_from_function_out;
|
||||
}
|
||||
for(i=0; i<nVal; i++){
|
||||
rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
|
||||
rc = sqlite3Stat4ValueFromExpr(pCtx->pParse, pList->a[i].pExpr, aff,
|
||||
&apVal[i]);
|
||||
if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,6 +867,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
Table *pNew = sParse.pNewTable;
|
||||
Index *pIdx;
|
||||
pTab->aCol = pNew->aCol;
|
||||
assert( IsOrdinaryTable(pNew) );
|
||||
sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
|
||||
pTab->nNVCol = pTab->nCol = pNew->nCol;
|
||||
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
|
||||
**
|
||||
** Immediately following the wal-header are zero or more frames. Each
|
||||
** frame consists of a 24-byte frame-header followed by a <page-size> bytes
|
||||
** frame consists of a 24-byte frame-header followed by <page-size> bytes
|
||||
** of page data. The frame-header is six big-endian 32-bit unsigned
|
||||
** integer values, as follows:
|
||||
**
|
||||
|
||||
+8
-2
@@ -1636,9 +1636,11 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
|
||||
** that this is required.
|
||||
*/
|
||||
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
||||
int rc;
|
||||
sqlite3_vtab *pVtab;
|
||||
|
||||
assert( IsVirtual(pTab) );
|
||||
pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
||||
whereTraceIndexInfoInputs(p, pTab);
|
||||
pParse->db->nSchemaLock++;
|
||||
rc = pVtab->pModule->xBestIndex(pVtab, p);
|
||||
@@ -6199,6 +6201,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
|
||||
WhereTerm *pTerm, *pEnd;
|
||||
SrcItem *pItem;
|
||||
WhereLoop *pLoop;
|
||||
Bitmask m1;
|
||||
pLoop = pWInfo->a[i].pWLoop;
|
||||
pItem = &pWInfo->pTabList->a[pLoop->iTab];
|
||||
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
|
||||
@@ -6225,7 +6228,10 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
|
||||
}
|
||||
}
|
||||
if( pTerm<pEnd ) continue;
|
||||
WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId));
|
||||
WHERETRACE(0xffffffff,("-> omit unused FROM-clause term %c\n",pLoop->cId));
|
||||
m1 = MASKBIT(i)-1;
|
||||
testcase( ((pWInfo->revMask>>1) & ~m1)!=0 );
|
||||
pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
|
||||
notReady &= ~pLoop->maskSelf;
|
||||
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
|
||||
|
||||
@@ -4376,6 +4376,8 @@ do_test 25.0 {
|
||||
| end crash-dde9e76ed8ab2d.db
|
||||
}]} {}
|
||||
|
||||
reset_prng_state
|
||||
|
||||
do_catchsql_test 25.1 {
|
||||
PRAGMA writable_schema = 1;
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237)
|
||||
|
||||
+11
-8
@@ -159,10 +159,11 @@ static struct GlobalVars {
|
||||
} g;
|
||||
|
||||
/*
|
||||
** Include the external vt02.c and randomjson.c modules.
|
||||
** Include various extensions.
|
||||
*/
|
||||
extern int sqlite3_vt02_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_randomjson_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
|
||||
|
||||
/*
|
||||
@@ -1037,17 +1038,18 @@ static int recoverDatabase(sqlite3 *db){
|
||||
static void bindDebugParameters(sqlite3_stmt *pStmt){
|
||||
int nVar = sqlite3_bind_parameter_count(pStmt);
|
||||
int i;
|
||||
for(i=0; i<nVar; i++){
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i+1);
|
||||
for(i=1; i<=nVar; i++){
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
|
||||
if( zVar==0 ) continue;
|
||||
if( strncmp(zVar, "$int_", 5)==0 ){
|
||||
sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5]));
|
||||
sqlite3_bind_int(pStmt, i, atoi(&zVar[5]));
|
||||
}else
|
||||
if( strncmp(zVar, "$text_", 6)==0 ){
|
||||
char *zBuf = sqlite3_malloc64( strlen(zVar)-5 );
|
||||
size_t szVar = strlen(zVar);
|
||||
char *zBuf = sqlite3_malloc64( szVar-5 );
|
||||
if( zBuf ){
|
||||
memcpy(zBuf, &zVar[6], strlen(zVar)-5);
|
||||
sqlite3_bind_text64(pStmt, i+1, zBuf, -1, sqlite3_free, SQLITE_UTF8);
|
||||
memcpy(zBuf, &zVar[6], szVar-5);
|
||||
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1329,7 +1331,8 @@ int runCombinedDbSqlInput(
|
||||
/* Add the vt02 virtual table */
|
||||
sqlite3_vt02_init(cx.db, 0, 0);
|
||||
|
||||
/* Add the random_json() and random_json5() functions */
|
||||
/* Activate extensions */
|
||||
sqlite3_percentile_init(cx.db, 0, 0);
|
||||
sqlite3_randomjson_init(cx.db, 0, 0);
|
||||
|
||||
/* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used
|
||||
|
||||
@@ -47,17 +47,18 @@ static void reportInvariantFailed(
|
||||
static void bindDebugParameters(sqlite3_stmt *pStmt){
|
||||
int nVar = sqlite3_bind_parameter_count(pStmt);
|
||||
int i;
|
||||
for(i=0; i<nVar; i++){
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i+1);
|
||||
for(i=1; i<=nVar; i++){
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
|
||||
if( zVar==0 ) continue;
|
||||
if( strncmp(zVar, "$int_", 5)==0 ){
|
||||
sqlite3_bind_int(pStmt, i+1, atoi(&zVar[5]));
|
||||
sqlite3_bind_int(pStmt, i, atoi(&zVar[5]));
|
||||
}else
|
||||
if( strncmp(zVar, "$text_", 6)==0 ){
|
||||
char *zBuf = sqlite3_malloc64( strlen(zVar)-5 );
|
||||
size_t szVar = strlen(zVar);
|
||||
char *zBuf = sqlite3_malloc64( szVar-5 );
|
||||
if( zBuf ){
|
||||
memcpy(zBuf, &zVar[6], strlen(zVar)-5);
|
||||
sqlite3_bind_text64(pStmt, i+1, zBuf, -1, sqlite3_free, SQLITE_UTF8);
|
||||
memcpy(zBuf, &zVar[6], szVar-5);
|
||||
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-1
@@ -706,11 +706,13 @@ ifcapable altertable {
|
||||
}
|
||||
}
|
||||
|
||||
if 0 {
|
||||
if 1 {
|
||||
# At time of writing, these two are broken. They demonstrate that the
|
||||
# sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
|
||||
# has been used to add a column with a default value other than NULL.
|
||||
#
|
||||
# 2024-09-18: These are now fixed.
|
||||
#
|
||||
do_preupdate_test 7.5.2.1 {
|
||||
DELETE FROM t8 WHERE a = 'one'
|
||||
} {
|
||||
@@ -1022,4 +1024,37 @@ do_catchsql_test 12.6 {
|
||||
INSERT INTO t4 VALUES('def', 3);
|
||||
} {1 {UNIQUE constraint failed: t4.a}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test adding non-NULL default values using ALTER TABLE.
|
||||
#
|
||||
reset_db
|
||||
db preupdate hook preupdate_hook
|
||||
do_execsql_test 13.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES(100), (200), (300), (400);
|
||||
}
|
||||
|
||||
do_execsql_test 13.1 {
|
||||
ALTER TABLE t1 ADD COLUMN b DEFAULT 1234;
|
||||
ALTER TABLE t1 ADD COLUMN c DEFAULT 'abcdef';
|
||||
ALTER TABLE t1 ADD COLUMN d DEFAULT NULL;
|
||||
}
|
||||
|
||||
do_preupdate_test 13.2 {
|
||||
DELETE FROM t1 WHERE a=300
|
||||
} {DELETE main t1 300 300 0 300 1234 abcdef {}}
|
||||
|
||||
do_preupdate_test 13.3 {
|
||||
UPDATE t1 SET d='hello world' WHERE a=200
|
||||
} {
|
||||
UPDATE main t1 200 200 0 200 1234 abcdef {}
|
||||
200 1234 abcdef {hello world}
|
||||
}
|
||||
|
||||
do_preupdate_test 13.4 {
|
||||
INSERT INTO t1 DEFAULT VALUES;
|
||||
} {
|
||||
INSERT main t1 401 401 0 401 1234 abcdef {}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -428,4 +428,25 @@ do_eqp_test 12.3 {
|
||||
`--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
}
|
||||
|
||||
# 2024-09-05 https://sqlite.org/forum/forumpost/8a1e467e905b8d27
|
||||
# When performing the Omit-Noop-Join optimization, if FROM clause terms
|
||||
# to the right of the omitted join have the reverse-order bit set in the
|
||||
# WhereInfo.revMask bitmask, those bits need to be shifted to account
|
||||
# for the omitted join.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 13.0 {
|
||||
CREATE TABLE t1(a1 INTEGER PRIMARY KEY, b1 INT);
|
||||
CREATE TABLE t2(c2 INT, d2 INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t3(e3 INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES(33,0);
|
||||
INSERT INTO t2 VALUES(33,1),(33,2);
|
||||
}
|
||||
do_execsql_test 13.1 {
|
||||
SELECT t1.a1, t2.d2
|
||||
FROM (t1 LEFT JOIN t3 ON t3.e3=t1.b1) JOIN t2 ON t2.c2=t1.a1
|
||||
WHERE t1.a1=33
|
||||
ORDER BY t2.d2 DESC;
|
||||
} {33 2 33 1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -64,4 +64,17 @@ ifcapable vtab {
|
||||
} {{\x17} 1 integer 1 1 null {$."\x17"} {$}}
|
||||
}
|
||||
|
||||
# JSON PATH parsing bug involving backslash escapes, reported via
|
||||
# private email from Florent De'Neve on 2024-09-04.
|
||||
#
|
||||
do_execsql_test 5.1 {
|
||||
SELECT json_extract('{"A\"Key":1}', '$.A"Key');
|
||||
} 1
|
||||
do_execsql_test 5.2 {
|
||||
SELECT json_extract('{"A\"Key":1}', '$."A\"Key"');
|
||||
} 1
|
||||
do_execsql_test 5.3 {
|
||||
SELECT JSON_SET('{}', '$."\"Key"', 1);
|
||||
} {{{"\"Key":1}}}
|
||||
|
||||
finish_test
|
||||
|
||||
+425
-61
@@ -9,7 +9,8 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is percentile.c extension
|
||||
# focus of this file is percentile.c extension. This also tests
|
||||
# the SQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@@ -25,35 +26,65 @@ do_test percentile-1.0 {
|
||||
}
|
||||
execsql {SELECT percentile(x,0) FROM t1}
|
||||
} {1.0}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 11.0
|
||||
89 11.0 11.0
|
||||
} {
|
||||
do_test percentile-1.1.$in {
|
||||
do_test percentile-1.1.$in.1 {
|
||||
execsql {SELECT percentile(x,$in) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.1.$in.2 {
|
||||
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.1.$in.3 {
|
||||
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.1.$in.4 {
|
||||
execsql {SELECT median(x) FROM t1}
|
||||
} $out
|
||||
}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.1.$in.5 {
|
||||
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.1.$in.6 {
|
||||
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.1.$in.7 {
|
||||
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t1}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.1.$in.8 {
|
||||
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} $out
|
||||
}
|
||||
}
|
||||
}
|
||||
do_execsql_test percentile-1.1.median {
|
||||
SELECT median(x) FROM t1;
|
||||
} 8.0
|
||||
|
||||
foreach {in out} {
|
||||
1.0 11.0
|
||||
0.5 8.0
|
||||
0.125 4.0
|
||||
0.15 4.4
|
||||
0.2 5.2
|
||||
0.8 11.0
|
||||
0.89 11.0
|
||||
} {
|
||||
do_test percentile-1.1b-$in {
|
||||
execsql {SELECT percentile_cont(x,$in) FROM t1}
|
||||
} $out
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_execsql_test percentile-1.1.median {
|
||||
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} 8.0
|
||||
do_execsql_test percentile-1.1.distinct.1 {
|
||||
SELECT median(DISTINCT x) FROM t1;
|
||||
} 7.0
|
||||
do_catchsql_test percentile-1.1.distinct.2 {
|
||||
SELECT percentile(DISTINCT 50) WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} {1 {DISTINCT not allowed on ordered-set aggregate percentile()}}
|
||||
} else {
|
||||
do_catchsql_test percentile-1.1.median {
|
||||
SELECT median() WITHIN GROUP (ORDER BY x) FROM t1;
|
||||
} {1 {near "(": syntax error}}
|
||||
}
|
||||
|
||||
# Add some NULL values.
|
||||
@@ -61,28 +92,69 @@ foreach {in out} {
|
||||
do_test percentile-1.2 {
|
||||
execsql {INSERT INTO t1 VALUES(NULL),(NULL);}
|
||||
} {}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 11.0
|
||||
89 11.0 11.0
|
||||
} {
|
||||
do_test percentile-1.3.$in {
|
||||
do_test percentile-1.3.$in.1 {
|
||||
execsql {SELECT percentile(x,$in) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.3.$in.2 {
|
||||
execsql {SELECT percentile_cont(x,$in*0.01) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.3.$in.3 {
|
||||
execsql {SELECT percentile_disc(x,$in*0.01) FROM t1}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.3.$in.4 {
|
||||
execsql {SELECT median(x) FROM t1}
|
||||
} $out
|
||||
}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.3.$in.5 {
|
||||
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.3.$in.6 {
|
||||
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t1}
|
||||
} $out
|
||||
do_test percentile-1.3.$in.7 {
|
||||
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t1}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.3.$in.8 {
|
||||
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} $out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# The second argument to percentile can change some, but not much.
|
||||
#
|
||||
do_test percentile-1.4 {
|
||||
do_test percentile-1.4.1 {
|
||||
catchsql {SELECT round(percentile(x, 15+0.000001*rowid),1) FROM t1}
|
||||
} {0 4.4}
|
||||
do_test percentile-1.5 {
|
||||
catchsql {SELECT round(percentile(x, 15+0.1*rowid),1) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not the same for all input rows}}
|
||||
do_test percentile-1.4.2 {
|
||||
catchsql {SELECT round(percentile_cont(x,(15+0.000001*rowid)*0.01),1) FROM t1}
|
||||
} {0 4.4}
|
||||
do_test percentile-1.4.3 {
|
||||
catchsql {SELECT percentile_disc(x, (15+0.000001*rowid)*0.01) FROM t1}
|
||||
} {0 4.0}
|
||||
do_test percentile-1.5.1 {
|
||||
catchsql {SELECT percentile(x, 15+0.1*rowid) FROM t1}
|
||||
} {1 {the fraction argument to percentile() is not the same for all input rows}}
|
||||
do_test percentile-1.5.2 {
|
||||
catchsql {SELECT percentile_cont(x, (15+0.1*rowid)*0.01) FROM t1}
|
||||
} {1 {the fraction argument to percentile_cont() is not the same for all input rows}}
|
||||
do_test percentile-1.5.3 {
|
||||
catchsql {SELECT percentile_disc(x, (15+0.1*rowid)*0.01) FROM t1}
|
||||
} {1 {the fraction argument to percentile_disc() is not the same for all input rows}}
|
||||
|
||||
# Input values in a random order
|
||||
#
|
||||
@@ -92,65 +164,152 @@ do_test percentile-1.6 {
|
||||
INSERT INTO t2 SELECT x+0.0 FROM t1 ORDER BY random();
|
||||
}
|
||||
} {}
|
||||
foreach {in out} {
|
||||
100 11.0
|
||||
50 8.0
|
||||
12.5 4.0
|
||||
15 4.4
|
||||
20 5.2
|
||||
80 11.0
|
||||
89 11.0
|
||||
foreach {in out disc} {
|
||||
100 11.0 11.0
|
||||
50 8.0 8.0
|
||||
12.5 4.0 4.0
|
||||
15 4.4 4.0
|
||||
20 5.2 4.0
|
||||
80 11.0 11.0
|
||||
89 11.0 11.0
|
||||
} {
|
||||
do_test percentile-1.7.$in {
|
||||
do_test percentile-1.7.$in.1 {
|
||||
execsql {SELECT percentile(x,$in) FROM t2}
|
||||
} $out
|
||||
do_test percentile-1.7.$in.2 {
|
||||
execsql {SELECT percentile_cont(x,$in*0.01) FROM t2}
|
||||
} $out
|
||||
do_test percentile-1.7.$in.3 {
|
||||
execsql {SELECT percentile_disc(x,$in*0.01) FROM t2}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.7.$in.4 {
|
||||
execsql {SELECT median(x) FROM t2}
|
||||
} $out
|
||||
}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.7.$in.5 {
|
||||
execsql {SELECT percentile($in)WITHIN GROUP(ORDER BY x) FROM t2}
|
||||
} $out
|
||||
do_test percentile-1.7.$in.6 {
|
||||
execsql {SELECT percentile_cont($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t2}
|
||||
} $out
|
||||
do_test percentile-1.7.$in.7 {
|
||||
execsql {SELECT percentile_disc($in*0.01) WITHIN GROUP(ORDER BY x)
|
||||
FROM t2}
|
||||
} $disc
|
||||
if {$in==50} {
|
||||
do_test percentile-1.7.$in.8 {
|
||||
execsql {SELECT median() WITHIN GROUP (ORDER BY x) FROM t2}
|
||||
} $out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Wrong number of arguments
|
||||
#
|
||||
do_test percentile-1.8 {
|
||||
do_test percentile-1.8.1 {
|
||||
catchsql {SELECT percentile(x,0,1) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile()}}
|
||||
do_test percentile-1.9 {
|
||||
do_test percentile-1.8.2 {
|
||||
catchsql {SELECT percentile_cont(x,0,1) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_cont()}}
|
||||
do_test percentile-1.8.3 {
|
||||
catchsql {SELECT percentile_disc(x,0,1) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_disc()}}
|
||||
do_test percentile-1.8.4 {
|
||||
catchsql {SELECT median(x,0) FROM t1}
|
||||
} {1 {wrong number of arguments to function median()}}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.8.5 {
|
||||
catchsql {SELECT percentile(0,1) WITHIN GROUP(ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile()}}
|
||||
do_test percentile-1.8.2 {
|
||||
catchsql {SELECT percentile_cont(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_cont()}}
|
||||
do_test percentile-1.8.3 {
|
||||
catchsql {SELECT percentile_disc(0,1)WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_disc()}}
|
||||
do_test percentile-1.8.4 {
|
||||
catchsql {SELECT median(x) WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function median()}}
|
||||
}
|
||||
do_test percentile-1.9.1 {
|
||||
catchsql {SELECT percentile(x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile()}}
|
||||
do_test percentile-1.9.2 {
|
||||
catchsql {SELECT percentile_cont(x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_cont()}}
|
||||
do_test percentile-1.9.3 {
|
||||
catchsql {SELECT percentile_disc(x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_disc()}}
|
||||
do_test percentile-1.9.4 {
|
||||
catchsql {SELECT median() FROM t1}
|
||||
} {1 {wrong number of arguments to function median()}}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.9.5 {
|
||||
catchsql {SELECT percentile() WITHIN GROUP(ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile()}}
|
||||
do_test percentile-1.9.6 {
|
||||
catchsql {SELECT percentile_cont()WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_cont()}}
|
||||
do_test percentile-1.9.7 {
|
||||
catchsql {SELECT percentile_disc()WITHIN GROUP (ORDER BY x) FROM t1}
|
||||
} {1 {wrong number of arguments to function percentile_disc()}}
|
||||
}
|
||||
|
||||
# Second argument must be numeric
|
||||
#
|
||||
do_test percentile-1.10 {
|
||||
catchsql {SELECT percentile(x,null) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
do_test percentile-1.11 {
|
||||
catchsql {SELECT percentile(x,'fifty') FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
do_test percentile-1.12 {
|
||||
catchsql {SELECT percentile(x,x'3530') FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
do_test percentile-1.12b {
|
||||
catchsql {SELECT percentile_cont(x,x'3530') FROM t1}
|
||||
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}}
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
|
||||
# Second argument is out of range
|
||||
#
|
||||
do_test percentile-1.13 {
|
||||
catchsql {SELECT percentile(x,-0.0000001) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
do_test percentile-1.14 {
|
||||
catchsql {SELECT percentile(x,100.0000001) FROM t1}
|
||||
} {1 {2nd argument to percentile() is not a number between 0.0 and 100.0}}
|
||||
do_test percentile-1.14b {
|
||||
} {1 {the fraction argument to percentile() is not between 0.0 and 100.0}}
|
||||
do_test percentile-1.14.2 {
|
||||
catchsql {SELECT percentile_cont(x,1.0000001) FROM t1}
|
||||
} {1 {2nd argument to percentile_cont() is not a number between 0.0 and 1.0}}
|
||||
} {1 {the fraction argument to percentile_cont() is not between 0.0 and 1.0}}
|
||||
do_test percentile-1.14.3 {
|
||||
catchsql {SELECT percentile_disc(x,1.0000001) FROM t1}
|
||||
} {1 {the fraction argument to percentile_disc() is not between 0.0 and 1.0}}
|
||||
|
||||
# First argument is not NULL and is not NUMERIC
|
||||
#
|
||||
do_test percentile-1.15 {
|
||||
do_test percentile-1.15.1 {
|
||||
catchsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET x='50' WHERE x IS NULL;
|
||||
SELECT percentile(x, 50) FROM t1;
|
||||
}
|
||||
} {1 {1st argument to percentile() is not numeric}}
|
||||
} {1 {input to percentile() is not numeric}}
|
||||
do_test percentile-1.15.2 {
|
||||
catchsql {
|
||||
SELECT percentile_cont(x, 0.50) FROM t1;
|
||||
}
|
||||
} {1 {input to percentile_cont() is not numeric}}
|
||||
do_test percentile-1.15.3 {
|
||||
catchsql {
|
||||
SELECT percentile_disc(x, 0.50) FROM t1;
|
||||
}
|
||||
} {1 {input to percentile_disc() is not numeric}}
|
||||
do_test percentile-1.15.4 {
|
||||
catchsql {
|
||||
SELECT median(x) FROM t1;
|
||||
}
|
||||
} {1 {input to median() is not numeric}}
|
||||
do_test percentile-1.16 {
|
||||
catchsql {
|
||||
ROLLBACK;
|
||||
@@ -158,7 +317,7 @@ do_test percentile-1.16 {
|
||||
UPDATE t1 SET x=x'3530' WHERE x IS NULL;
|
||||
SELECT percentile(x, 50) FROM t1;
|
||||
}
|
||||
} {1 {1st argument to percentile() is not numeric}}
|
||||
} {1 {input to percentile() is not numeric}}
|
||||
do_test percentile-1.17 {
|
||||
catchsql {
|
||||
ROLLBACK;
|
||||
@@ -186,7 +345,7 @@ do_test percentile-1.19 {
|
||||
|
||||
# Infinity as an input
|
||||
#
|
||||
do_test percentile-1.20 {
|
||||
do_test percentile-1.20.1 {
|
||||
catchsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 SELECT x+0.0 FROM t2;
|
||||
@@ -194,6 +353,43 @@ do_test percentile-1.20 {
|
||||
SELECT percentile(x,50) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile()}}
|
||||
do_test percentile-1.20.2 {
|
||||
catchsql {
|
||||
SELECT percentile_cont(x,0.50) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile_cont()}}
|
||||
do_test percentile-1.20.3 {
|
||||
catchsql {
|
||||
SELECT percentile_disc(x,0.50) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile_disc()}}
|
||||
do_test percentile-1.20.4 {
|
||||
catchsql {
|
||||
SELECT median(x) from t1;
|
||||
}
|
||||
} {1 {Inf input to median()}}
|
||||
ifcapable ordered_set_aggregates {
|
||||
do_test percentile-1.20.5 {
|
||||
catchsql {
|
||||
SELECT percentile(50) WITHIN GROUP (ORDER BY x) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile()}}
|
||||
do_test percentile-1.20.6 {
|
||||
catchsql {
|
||||
SELECT percentile_cont(0.50) WITHIN GROUP (ORDER BY x) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile_cont()}}
|
||||
do_test percentile-1.20.7 {
|
||||
catchsql {
|
||||
SELECT percentile_disc(0.50) WITHIN GROUP(ORDER BY X) from t1;
|
||||
}
|
||||
} {1 {Inf input to percentile_disc()}}
|
||||
do_test percentile-1.20.8 {
|
||||
catchsql {
|
||||
SELECT median() WITHIN GROUP (ORDER BY x) from t1;
|
||||
}
|
||||
} {1 {Inf input to median()}}
|
||||
}
|
||||
do_test percentile-1.21 {
|
||||
catchsql {
|
||||
UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5;
|
||||
@@ -229,4 +425,172 @@ ifcapable vtab {
|
||||
}
|
||||
}
|
||||
|
||||
# median() as a window function. (2024-08-31)
|
||||
#
|
||||
do_execsql_test percentile-3.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
|
||||
INSERT INTO t1 VALUES (1, 'A', 'one', 8.4),
|
||||
(2, 'B', 'two', 7.1),
|
||||
(3, 'C', 'three', 5.9),
|
||||
(4, 'D', 'one', 11.0),
|
||||
(5, 'E', 'two', 12.5),
|
||||
(6, 'F', 'three', 0.0),
|
||||
(7, 'G', 'one', 2.7);
|
||||
}
|
||||
foreach {id oba expr} {
|
||||
1 0 "median(d)"
|
||||
2 0 "percentile(d,50)"
|
||||
3 0 "percentile_cont(d,0.5)"
|
||||
4 1 "median() WITHIN GROUP (ORDER BY d)"
|
||||
5 1 "percentile(50) WITHIN GROUP (ORDER BY d)"
|
||||
6 1 "percentile_cont(0.5) WITHIN GROUP (ORDER BY d)"
|
||||
} {
|
||||
if {$oba} {
|
||||
ifcapable !ordered_set_aggregates break
|
||||
}
|
||||
set sql "SELECT a, b, c, d, \
|
||||
group_concat(b,'.') OVER w1 AS 'elements', \
|
||||
$expr OVER w1 AS 'median' \
|
||||
FROM t1 \
|
||||
WINDOW w1 AS (ORDER BY c, a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)"
|
||||
do_execsql_test percentile-3.$id.1 $sql {
|
||||
1 A one 8.4 A.D 9.7
|
||||
4 D one 11.0 A.D.G 8.4
|
||||
7 G one 2.7 D.G.C 5.9
|
||||
3 C three 5.9 G.C.F 2.7
|
||||
6 F three 0.0 C.F.B 5.9
|
||||
2 B two 7.1 F.B.E 7.1
|
||||
5 E two 12.5 B.E 9.8
|
||||
}
|
||||
|
||||
set sql "SELECT a, b, c, d, \
|
||||
group_concat(b,'.') OVER w1 AS 'elements', \
|
||||
$expr OVER w1 AS 'median' \
|
||||
FROM t1 \
|
||||
WINDOW w1 AS (ORDER BY c, a \
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING)"
|
||||
do_execsql_test percentile-3.$id.2 $sql {
|
||||
1 A one 8.4 A.D 9.7
|
||||
4 D one 11.0 A.D.G 8.4
|
||||
7 G one 2.7 A.D.G.C 7.15
|
||||
3 C three 5.9 A.D.G.C.F 5.9
|
||||
6 F three 0.0 A.D.G.C.F.B 6.5
|
||||
2 B two 7.1 A.D.G.C.F.B.E 7.1
|
||||
5 E two 12.5 A.D.G.C.F.B.E 7.1
|
||||
}
|
||||
|
||||
set sql "SELECT a, b, c, d, \
|
||||
group_concat(b,'.') OVER w1 AS 'elements', \
|
||||
$expr OVER w1 AS 'median' \
|
||||
FROM t1 \
|
||||
WINDOW w1 AS (ORDER BY c, a \
|
||||
ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING)"
|
||||
do_execsql_test percentile-3.$id.3 $sql {
|
||||
1 A one 8.4 A.D.G.C.F.B.E 7.1
|
||||
4 D one 11.0 A.D.G.C.F.B.E 7.1
|
||||
7 G one 2.7 D.G.C.F.B.E 6.5
|
||||
3 C three 5.9 G.C.F.B.E 5.9
|
||||
6 F three 0.0 C.F.B.E 6.5
|
||||
2 B two 7.1 F.B.E 7.1
|
||||
5 E two 12.5 B.E 9.8
|
||||
}
|
||||
}
|
||||
|
||||
# Test case adapted from examples shown at
|
||||
# https://database.guide/3-functions-to-calculate-the-median-in-sql/
|
||||
#
|
||||
do_execsql_test percential-4.0 {
|
||||
CREATE TABLE products(
|
||||
vendorId INT,
|
||||
productId INTEGER PRIMARY KEY,
|
||||
productName REAL,
|
||||
price REAL
|
||||
);
|
||||
INSERT INTO products VALUES
|
||||
(1001, 17, 'Left-handed screwdriver', 25.99),
|
||||
(1001, 49, 'Right-handed screwdriver', 25.99),
|
||||
(1001, 216, 'Long weight (blue)', 14.75),
|
||||
(1001, 31, 'Long weight (green)', 11.99),
|
||||
(1002, 37, 'Sledge hammer', 33.49),
|
||||
(1003, 7, 'Chainsaw', 245.00),
|
||||
(1003, 8, 'Straw dog box', 55.99),
|
||||
(1003, 12, 'Hammock', 11.01),
|
||||
(1004, 113, 'Teapot', 12.45),
|
||||
(1004, 117, 'Bottomless coffee mug', 9.99);
|
||||
}
|
||||
do_execsql_test percentile-4.1 {
|
||||
SELECT VendorId, ProductId, /* ProductName,*/ Price,
|
||||
avg(price) OVER (PARTITION BY vendorId) AS "Average",
|
||||
median(price) OVER (PARTITION BY vendorId) AS "Median"
|
||||
FROM products
|
||||
ORDER BY vendorId, productId;
|
||||
} {
|
||||
1001 17 25.99 19.68 20.37
|
||||
1001 31 11.99 19.68 20.37
|
||||
1001 49 25.99 19.68 20.37
|
||||
1001 216 14.75 19.68 20.37
|
||||
1002 37 33.49 33.49 33.49
|
||||
1003 7 245.0 104.0 55.99
|
||||
1003 8 55.99 104.0 55.99
|
||||
1003 12 11.01 104.0 55.99
|
||||
1004 113 12.45 11.22 11.22
|
||||
1004 117 9.99 11.22 11.22
|
||||
}
|
||||
do_execsql_test percentile-4.2 {
|
||||
SELECT vendorId, median(price) FROM products
|
||||
GROUP BY 1 ORDER BY 1;
|
||||
} {1001 20.37 1002 33.49 1003 55.99 1004 11.22}
|
||||
|
||||
do_execsql_test percentile-5.0 {
|
||||
CREATE TABLE user(name TEXT, class TEXT, cost REAL);
|
||||
INSERT INTO user VALUES
|
||||
('Alice', 'Y', 3578.27),
|
||||
('Bob', 'X', 3399.99),
|
||||
('Cindy', 'Z', 699.10),
|
||||
('Dave', 'Y', 3078.27),
|
||||
('Emma', 'Z', 2319.99),
|
||||
('Fred', 'Y', 539.99),
|
||||
('Gina', 'X', 2320.49),
|
||||
('Hank', 'W', 24.99),
|
||||
('Irma', 'W', 24.99),
|
||||
('Jake', 'X', 2234.99),
|
||||
('Kim', 'Y', 4319.99),
|
||||
('Liam', 'X', 4968.59),
|
||||
('Mia', 'W', 59.53),
|
||||
('Nate', 'W', 23.50);
|
||||
}
|
||||
do_execsql_test percentile-5.1 {
|
||||
SELECT name, class, cost,
|
||||
percentile(cost, 0) OVER w1 AS 'P0',
|
||||
percentile(cost, 25) OVER w1 AS 'P1',
|
||||
percentile(cost, 50) OVER w1 AS 'P2',
|
||||
percentile(cost, 75) OVER w1 AS 'P3',
|
||||
percentile(cost, 100) OVER w1 AS 'P4'
|
||||
FROM user
|
||||
WINDOW w1 AS (PARTITION BY class)
|
||||
ORDER BY class, cost;
|
||||
} {
|
||||
Nate W 23.5 23.5 24.6175 24.99 33.625 59.53
|
||||
Hank W 24.99 23.5 24.6175 24.99 33.625 59.53
|
||||
Irma W 24.99 23.5 24.6175 24.99 33.625 59.53
|
||||
Mia W 59.53 23.5 24.6175 24.99 33.625 59.53
|
||||
Jake X 2234.99 2234.99 2299.115 2860.24 3792.14 4968.59
|
||||
Gina X 2320.49 2234.99 2299.115 2860.24 3792.14 4968.59
|
||||
Bob X 3399.99 2234.99 2299.115 2860.24 3792.14 4968.59
|
||||
Liam X 4968.59 2234.99 2299.115 2860.24 3792.14 4968.59
|
||||
Fred Y 539.99 539.99 2443.7 3328.27 3763.7 4319.99
|
||||
Dave Y 3078.27 539.99 2443.7 3328.27 3763.7 4319.99
|
||||
Alice Y 3578.27 539.99 2443.7 3328.27 3763.7 4319.99
|
||||
Kim Y 4319.99 539.99 2443.7 3328.27 3763.7 4319.99
|
||||
Cindy Z 699.1 699.1 1104.3225 1509.545 1914.7675 2319.99
|
||||
Emma Z 2319.99 699.1 1104.3225 1509.545 1914.7675 2319.99
|
||||
}
|
||||
|
||||
# Fuzzer find.
|
||||
do_execsql_test percentile-6.0 {
|
||||
WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<12)
|
||||
SELECT median(iif(n%2,0.1,1.0)) FROM c;
|
||||
} 0.55
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -516,6 +516,8 @@ do_test shell1-3.15.3 {
|
||||
Options:
|
||||
--bom Prefix output with a UTF8 byte-order mark
|
||||
-e Send output to the system text editor
|
||||
--plain Use text/plain for -w option
|
||||
-w Send output to a web browser
|
||||
-x Send output as CSV to a spreadsheet
|
||||
child process exited abnormally}}
|
||||
|
||||
@@ -532,6 +534,8 @@ do_test shell1-3.16.2 {
|
||||
Options:
|
||||
--bom Prefix output with a UTF8 byte-order mark
|
||||
-e Send output to the system text editor
|
||||
--plain Use text/plain for -w option
|
||||
-w Send output to a web browser
|
||||
-x Send output as CSV to a spreadsheet
|
||||
child process exited abnormally}}
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ do_test shell2-1.4.9 {
|
||||
done
|
||||
2}}
|
||||
|
||||
ifcapable vtab {
|
||||
# Verify that generate_series stays sane near 64-bit range boundaries.
|
||||
# See overflow report at https://sqlite.org/forum/forumpost/5d34ce5280
|
||||
do_test shell2-1.4.10 {
|
||||
@@ -247,7 +248,9 @@ do_test shell2-1.4.10 {
|
||||
0
|
||||
1
|
||||
2}}
|
||||
} ;# ifcapable vtab
|
||||
|
||||
ifcapable vtab {
|
||||
# Bug discovered while messing around, .import hangs with
|
||||
# bit 7 set in column separator.
|
||||
do_test shell2-1.4.11 {
|
||||
@@ -262,6 +265,7 @@ do_test shell2-1.4.11 {
|
||||
.import dummy.csv t
|
||||
SELECT count(*) FROM t;}]]
|
||||
} {0 1}
|
||||
} ;# ifcapable vtab
|
||||
|
||||
# Bug from forum post 7cbe081746dd3803
|
||||
# Keywords as column names were producing an error message.
|
||||
|
||||
@@ -84,6 +84,14 @@ do_test shell5-1.4.1 {
|
||||
.import FOO t1}]
|
||||
} {1 {Error: cannot open "FOO"}}
|
||||
|
||||
# the remainder of these test cases require virtual tables.
|
||||
#
|
||||
ifcapable !vtab {
|
||||
puts "Skipping subsequent tests due to SQLITE_OMIT_VIRTUALTABLE"
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# empty import file
|
||||
do_test shell5-1.4.2 {
|
||||
forcedelete shell5.csv
|
||||
|
||||
+7
-2
@@ -1279,10 +1279,15 @@ proc finalize_testing {} {
|
||||
out of $nTest tests"
|
||||
} else {
|
||||
set cpuinfo {}
|
||||
if {[catch {exec hostname} hname]==0} {set cpuinfo [string trim $hname]}
|
||||
if {[catch {exec hostname} hname]==0} {
|
||||
regsub {\.local$} $hname {} hname
|
||||
set cpuinfo [string trim $hname]
|
||||
}
|
||||
append cpuinfo " $::tcl_platform(os)"
|
||||
append cpuinfo " [expr {$::tcl_platform(pointerSize)*8}]-bit"
|
||||
append cpuinfo " [string map {E -e} $::tcl_platform(byteOrder)]"
|
||||
if {[string match big* $::tcl_platform(byteOrder)]} {
|
||||
append cpuinfo " [string map {E -e} $::tcl_platform(byteOrder)]"
|
||||
}
|
||||
output2 "SQLite [sqlite3 -sourceid]"
|
||||
output2 "$nErr errors out of $nTest tests on $cpuinfo"
|
||||
}
|
||||
|
||||
Regular → Executable
+259
-59
@@ -1,3 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Script to runs tests for SQLite. Run with option "help" for more info. \
|
||||
exec tclsh "$0" "$@"
|
||||
|
||||
set dir [pwd]
|
||||
set testdir [file normalize [file dirname $argv0]]
|
||||
@@ -14,8 +17,14 @@ cd $dir
|
||||
# recommend that the user build one.
|
||||
#
|
||||
proc find_interpreter {} {
|
||||
global dir
|
||||
set interpreter [file tail [info nameofexec]]
|
||||
set rc [catch { package require sqlite3 }]
|
||||
if {$rc} {
|
||||
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
|
||||
set rc [catch { package require sqlite3 }]
|
||||
}
|
||||
}
|
||||
if {$rc} {
|
||||
if { [string match -nocase testfixture* $interpreter]==0
|
||||
&& [file executable ./testfixture]
|
||||
@@ -28,8 +37,30 @@ proc find_interpreter {} {
|
||||
}
|
||||
}
|
||||
if {$rc} {
|
||||
puts stderr "Failed to find tcl package sqlite3"
|
||||
puts stderr "Run \"make testfixture\" and then try again..."
|
||||
puts "Cannot find tcl package sqlite3: Trying to build it now..."
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
set bat [open make-tcl-extension.bat w]
|
||||
puts $bat "nmake /f Makefile.msc tclextension"
|
||||
close $bat
|
||||
catch {exec -ignorestderr -- make-tcl-extension.bat}
|
||||
} else {
|
||||
catch {exec make tclextension}
|
||||
}
|
||||
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
|
||||
set rc [catch { package require sqlite3 }]
|
||||
}
|
||||
if {$rc==0} {
|
||||
puts "The SQLite tcl extension was successfully built and loaded."
|
||||
puts "Run \"make tclextension-install\" to avoid having to rebuild\
|
||||
it in the future."
|
||||
} else {
|
||||
puts "Unable to build the SQLite tcl extension"
|
||||
}
|
||||
}
|
||||
if {$rc} {
|
||||
puts stderr "Cannot find a working instance of the SQLite tcl extension."
|
||||
puts stderr "Run \"make tclextension\" or \"make testfixture\" and\
|
||||
try again..."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
@@ -54,8 +85,9 @@ proc usage {} {
|
||||
Usage:
|
||||
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
|
||||
$a0 PERMUTATION FILE
|
||||
$a0 errors ?-v|--verbose?
|
||||
$a0 errors ?-v|--verbose? ?-s|--summary? ?PATTERN?
|
||||
$a0 help
|
||||
$a0 joblist ?PATTERN?
|
||||
$a0 njob ?NJOB?
|
||||
$a0 script ?-msvc? CONFIG
|
||||
$a0 status ?-d SECS? ?--cls?
|
||||
@@ -89,7 +121,9 @@ Other PERMUTATION arguments must be run using testfixture, not tclsh:
|
||||
If no PATTERN arguments are present, all tests specified by the PERMUTATION
|
||||
are run. Otherwise, each pattern is interpreted as a glob pattern. Only
|
||||
those tcl tests for which the final component of the filename matches at
|
||||
least one specified pattern are run.
|
||||
least one specified pattern are run. The glob wildcard '*' is prepended
|
||||
to the pattern if it does not start with '^' and appended to every
|
||||
pattern that does not end with '$'.
|
||||
|
||||
If no PATTERN arguments are present, then various fuzztest, threadtest
|
||||
and other tests are run as part of the "release" permutation. These are
|
||||
@@ -110,10 +144,12 @@ The "script" command outputs the script used to build a configuration.
|
||||
Add the "-msvc" option for a Windows-compatible script. For a list of
|
||||
available configurations enter "$a0 script help".
|
||||
|
||||
The "errors" commands shows the output of all tests that failed in the
|
||||
The "errors" commands shows the output of tests that failed in the
|
||||
most recent run. Complete output is shown if the -v or --verbose options
|
||||
are used. Otherwise, an attempt is made to minimize the output to show
|
||||
only the parts that contain the error messages.
|
||||
only the parts that contain the error messages. The --summary option just
|
||||
shows the jobs that failed. If PATTERN are provided, the error information
|
||||
is only provided for jobs that match PATTERN.
|
||||
|
||||
Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
|
||||
}]]
|
||||
@@ -277,10 +313,14 @@ set TRG(schema) {
|
||||
priority INTEGER NOT NULL, -- higher priority jobs may run earlier
|
||||
|
||||
/* Fields updated as jobs run */
|
||||
starttime INTEGER,
|
||||
endtime INTEGER,
|
||||
starttime INTEGER, -- Start time (milliseconds since 1970)
|
||||
endtime INTEGER, -- End time
|
||||
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
|
||||
output TEXT
|
||||
ntest INT, -- Number of test cases run
|
||||
nerr INT, -- Number of errors reported
|
||||
svers TEXT, -- Reported SQLite version
|
||||
pltfm TEXT, -- Host platform reported
|
||||
output TEXT -- test output
|
||||
);
|
||||
|
||||
CREATE TABLE config(
|
||||
@@ -352,8 +392,8 @@ if {([llength $argv]==2 || [llength $argv]==1)
|
||||
sqlite3 mydb $TRG(dbname)
|
||||
if {[llength $argv]==2} {
|
||||
set param [lindex $argv 1]
|
||||
if {[string is integer $param]==0 || $param<1 || $param>128} {
|
||||
puts stderr "parameter must be an integer between 1 and 128"
|
||||
if {[string is integer $param]==0 || $param<0 || $param>128} {
|
||||
puts stderr "parameter must be an integer between 0 and 128"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -389,14 +429,36 @@ if {[string compare -nocase script [lindex $argv 0]]==0} {
|
||||
exit
|
||||
}
|
||||
|
||||
# Compute an elapse time string MM:SS or HH:MM:SS based on the
|
||||
# number of milliseconds in the argument.
|
||||
#
|
||||
proc elapsetime {ms} {
|
||||
set s [expr {int(($ms+500.0)*0.001)}]
|
||||
set hr [expr {$s/3600}]
|
||||
set mn [expr {($s/60)%60}]
|
||||
set sc [expr {$s%60}]
|
||||
if {$hr>0} {
|
||||
return [format %02d:%02d:%02d $hr $mn $sc]
|
||||
} else {
|
||||
return [format %02d:%02d $mn $sc]
|
||||
}
|
||||
}
|
||||
|
||||
# Helper routine for show_status
|
||||
#
|
||||
proc display_job {jobdict {tm ""}} {
|
||||
array set job $jobdict
|
||||
set dfname [format %-60s $job(displayname)]
|
||||
if {[string length $job(displayname)]>65} {
|
||||
set dfname [format %.65s... $job(displayname)]
|
||||
} else {
|
||||
set dfname [format %-68s $job(displayname)]
|
||||
}
|
||||
set dtm ""
|
||||
if {$tm!=""} {
|
||||
set dtm [format %-10s "\[[expr {$tm-$job(starttime)}]ms\]"]
|
||||
set dtm [expr {$tm-$job(starttime)}]
|
||||
set dtm [format %8s [elapsetime $dtm]]
|
||||
} else {
|
||||
set dtm [format %8s ""]
|
||||
}
|
||||
puts " $dfname $dtm"
|
||||
}
|
||||
@@ -431,6 +493,11 @@ proc show_status {db cls} {
|
||||
incr S($state) $cnt
|
||||
incr total $cnt
|
||||
}
|
||||
set nt 0
|
||||
set ne 0
|
||||
$db eval {
|
||||
SELECT sum(ntest) AS nt, sum(nerr) AS ne FROM jobs HAVING nt>0
|
||||
} break
|
||||
set fin [expr $S(done)+$S(failed)]
|
||||
if {$cmdline!=""} {set cmdline " $cmdline"}
|
||||
|
||||
@@ -439,22 +506,25 @@ proc show_status {db cls} {
|
||||
# overwrite.
|
||||
puts -nonewline "\033\[H"
|
||||
flush stdout
|
||||
set clreol "\033\[K"
|
||||
} else {
|
||||
set clreol ""
|
||||
}
|
||||
set f ""
|
||||
if {$S(failed)>0} {
|
||||
set f "$S(failed) FAILED, "
|
||||
}
|
||||
puts "Command line: \[testrunner.tcl$cmdline\]$clreol"
|
||||
puts "Jobs: $nJob "
|
||||
puts "Summary: ${tm}ms, ($fin/$total) finished,\
|
||||
${f}$S(running) running "
|
||||
puts [format %-79.79s "Command: \[testrunner.tcl$cmdline\]"]
|
||||
puts [format %-79.79s "Summary: [elapsetime $tm], $fin/$total jobs,\
|
||||
$ne errors, $nt tests"]
|
||||
|
||||
set srcdir [file dirname [file dirname $TRG(info_script)]]
|
||||
set line "Running: $S(running) (max: $nJob)"
|
||||
if {$S(running)>0 && $fin>100 && $fin>0.05*$total} {
|
||||
# Only estimate the time remaining after completing at least 100
|
||||
# jobs amounting to 10% of the total. Never estimate less than
|
||||
# 2% of the total time used so far.
|
||||
set tmleft [expr {($tm/$fin)*($total-$fin)}]
|
||||
if {$tmleft<0.02*$tm} {
|
||||
set tmleft [expr {$tm*0.02}]
|
||||
}
|
||||
append line " est time left [elapsetime $tmleft]"
|
||||
}
|
||||
puts [format %-79.79s $line]
|
||||
if {$S(running)>0} {
|
||||
puts "Running: "
|
||||
$db eval {
|
||||
SELECT * FROM jobs WHERE state='running' ORDER BY starttime
|
||||
} job {
|
||||
@@ -462,15 +532,30 @@ proc show_status {db cls} {
|
||||
}
|
||||
}
|
||||
if {$S(failed)>0} {
|
||||
puts "Failures: "
|
||||
# $toshow is the number of failures to report. In $cls mode,
|
||||
# status tries to limit the number of failure reported so that
|
||||
# the status display does not overflow a 24-line terminal. It will
|
||||
# always show at least the most recent 4 failures, even if an overflow
|
||||
# is needed. No limit is imposed for a status within $cls.
|
||||
#
|
||||
if {$cls && $S(failed)>18-$S(running)} {
|
||||
set toshow [expr {18-$S(running)}]
|
||||
if {$toshow<4} {set toshow 4}
|
||||
set shown " (must recent $toshow shown)"
|
||||
} else {
|
||||
set toshow $S(failed)
|
||||
set shown ""
|
||||
}
|
||||
puts [format %-79s "Failed: $S(failed) $shown"]
|
||||
$db eval {
|
||||
SELECT * FROM jobs WHERE state='failed' ORDER BY starttime
|
||||
SELECT * FROM jobs WHERE state='failed'
|
||||
ORDER BY endtime DESC LIMIT $toshow
|
||||
} job {
|
||||
display_job [array get job]
|
||||
}
|
||||
set nOmit [$db one {SELECT count(*) FROM jobs WHERE state='omit'}]
|
||||
if {$nOmit} {
|
||||
puts "$nOmit jobs omitted due to failures$clreol"
|
||||
puts [format %-79s " ... $nOmit jobs omitted due to failures"]
|
||||
}
|
||||
}
|
||||
if {$cls} {
|
||||
@@ -528,44 +613,80 @@ if {[llength $argv]>=1
|
||||
exit
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check if this is the "joblist" command:
|
||||
#
|
||||
if {[llength $argv]>=1
|
||||
&& [string compare -nocase "joblist" [lindex $argv 0]]==0
|
||||
} {
|
||||
set pattern {}
|
||||
for {set ii 1} {$ii<[llength $argv]} {incr ii} {
|
||||
set a0 [lindex $argv $ii]
|
||||
if {$pattern==""} {
|
||||
set pattern [string trim $a0 *]
|
||||
} else {
|
||||
puts "unknown option: \"$a0\""
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
set SQL {SELECT displaytype, displayname, state FROM jobs}
|
||||
if {$pattern!=""} {
|
||||
regsub -all {[^a-zA-Z0-9*.-/]} $pattern ? pattern
|
||||
append SQL " WHERE displayname GLOB '*$pattern*'"
|
||||
}
|
||||
append SQL " ORDER BY starttime"
|
||||
|
||||
if {![file readable $TRG(dbname)]} {
|
||||
puts "Database missing: $TRG(dbname)"
|
||||
exit
|
||||
}
|
||||
sqlite3 mydb $TRG(dbname)
|
||||
mydb timeout 2000
|
||||
|
||||
mydb eval $SQL {
|
||||
set label UNKNOWN
|
||||
switch -- $state {
|
||||
ready {set label READY}
|
||||
done {set label DONE}
|
||||
failed {set label FAILED}
|
||||
omit {set label OMIT}
|
||||
running {set label RUNNING}
|
||||
}
|
||||
puts [format {%-7s %-5s %s} $label $displaytype $displayname]
|
||||
}
|
||||
mydb close
|
||||
exit
|
||||
}
|
||||
|
||||
# Scan the output of all jobs looking for the summary lines that
|
||||
# report the number of test cases and the number of errors.
|
||||
# Aggregate these numbers and return them.
|
||||
#
|
||||
proc aggregate_test_counts {db} {
|
||||
set ncase 0
|
||||
set nerr 0
|
||||
$db eval {SELECT output FROM jobs WHERE displaytype IN ('tcl','fuzz')} {
|
||||
set n 0
|
||||
set m 0
|
||||
if {[regexp {(\d+) errors out of (\d+) tests} $output all n m]
|
||||
&& [string is integer -strict $n]
|
||||
&& [string is integer -strict $m]} {
|
||||
incr ncase $m
|
||||
incr nerr $n
|
||||
} elseif {[regexp {sessionfuzz.*: *(\d+) cases, (\d+) crash} $output \
|
||||
all m n]
|
||||
&& [string is integer -strict $m]
|
||||
&& [string is integer -strict $n]} {
|
||||
incr ncase $m
|
||||
incr nerr $n
|
||||
}
|
||||
}
|
||||
return [list $nerr $ncase]
|
||||
set ne 0
|
||||
set nt 0
|
||||
$db eval {SELECT sum(nerr) AS ne, sum(ntest) as nt FROM jobs} break
|
||||
return [list $ne $nt]
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check if this is the "errors" command:
|
||||
#
|
||||
if {[llength $argv]>=1 && [llength $argv]<=2
|
||||
if {[llength $argv]>=1
|
||||
&& ([string compare -nocase errors [lindex $argv 0]]==0 ||
|
||||
[string match err* [lindex $argv 0]]==1)
|
||||
} {
|
||||
set verbose 0
|
||||
set pattern {}
|
||||
set summary 0
|
||||
for {set ii 1} {$ii<[llength $argv]} {incr ii} {
|
||||
set a0 [lindex $argv $ii]
|
||||
if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} {
|
||||
set verbose 1
|
||||
} elseif {$a0=="-s" || $a0=="--summary" || $a0=="-summary"} {
|
||||
set summary 1
|
||||
} elseif {$pattern==""} {
|
||||
set pattern *[string trim $a0 *]*
|
||||
} else {
|
||||
puts "unknown option: \"$a0\"". Use --help for more info."
|
||||
exit 1
|
||||
@@ -573,9 +694,22 @@ if {[llength $argv]>=1 && [llength $argv]<=2
|
||||
}
|
||||
set cnt 0
|
||||
sqlite3 mydb $TRG(dbname)
|
||||
mydb timeout 2000
|
||||
mydb eval {SELECT displaytype, displayname, output
|
||||
FROM jobs WHERE state='failed'} {
|
||||
mydb timeout 5000
|
||||
if {$summary} {
|
||||
set sql "SELECT displayname FROM jobs WHERE state='failed'"
|
||||
} else {
|
||||
set sql "SELECT displaytype, displayname, output FROM jobs \
|
||||
WHERE state='failed'"
|
||||
}
|
||||
if {$pattern!=""} {
|
||||
regsub -all {[^a-zA-Z0-9*/ ?]} $pattern . pattern
|
||||
append sql " AND displayname GLOB '$pattern'"
|
||||
}
|
||||
mydb eval $sql {
|
||||
if {$summary} {
|
||||
puts "FAILED: $displayname"
|
||||
continue
|
||||
}
|
||||
puts "**** $displayname ****"
|
||||
if {$verbose || $displaytype!="tcl"} {
|
||||
puts $output
|
||||
@@ -588,9 +722,13 @@ if {[llength $argv]>=1 && [llength $argv]<=2
|
||||
}
|
||||
incr cnt
|
||||
}
|
||||
set summary [aggregate_test_counts mydb]
|
||||
mydb close
|
||||
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
|
||||
if {$pattern==""} {
|
||||
set summary [aggregate_test_counts mydb]
|
||||
mydb close
|
||||
puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
|
||||
} else {
|
||||
mydb close
|
||||
}
|
||||
exit
|
||||
}
|
||||
|
||||
@@ -842,7 +980,18 @@ proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
|
||||
if {[llength $patternlist]>0} {
|
||||
set bMatch 0
|
||||
foreach p $patternlist {
|
||||
if {[string match $p [file tail $f]]} {
|
||||
set p [string trim $p *]
|
||||
if {[string index $p 0]=="^"} {
|
||||
set p [string range $p 1 end]
|
||||
} else {
|
||||
set p "*$p"
|
||||
}
|
||||
if {[string index $p end]=="\$"} {
|
||||
set p [string range $p 0 end-1]
|
||||
} else {
|
||||
set p "$p*"
|
||||
}
|
||||
if {[string match $p "$config [file tail $f]"]} {
|
||||
set bMatch 1
|
||||
break
|
||||
}
|
||||
@@ -1045,6 +1194,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
}
|
||||
}
|
||||
|
||||
devtest -
|
||||
mdevtest {
|
||||
set config_set {
|
||||
All-O0
|
||||
@@ -1068,7 +1218,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
if {[regexp "\\y$b\\y" $TRG(omitconfig)]} continue
|
||||
set bld [add_build_job $b $TRG(testfixture)]
|
||||
foreach c [trd_configs $TRG(platform) $b] {
|
||||
add_tcl_jobs $bld $c $patternlist
|
||||
add_tcl_jobs $bld $c $patternlist SHELL
|
||||
}
|
||||
|
||||
if {$patternlist==""} {
|
||||
@@ -1080,6 +1230,15 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[trdb one "SELECT EXISTS(SELECT 1
|
||||
FROM jobs WHERE depid='SHELL')"]} {
|
||||
set sbld [add_shell_build_job $b [lindex $bld 1] [lindex $bld 0]]
|
||||
set sbldid [lindex $sbld 0]
|
||||
trdb eval {
|
||||
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,15 +1279,29 @@ proc make_new_testset {} {
|
||||
}
|
||||
|
||||
proc mark_job_as_finished {jobid output state endtm} {
|
||||
set ntest 1
|
||||
set nerr 0
|
||||
if {$endtm>0} {
|
||||
set re {\y(\d+) errors out of (\d+) tests( on [^\n]+\n)?}
|
||||
if {[regexp $re $output all a b pltfm]} {
|
||||
set nerr $a
|
||||
set ntest $b
|
||||
}
|
||||
regexp {\ySQLite \d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [0-9a-fA-F]+} \
|
||||
$output svers
|
||||
}
|
||||
r_write_db {
|
||||
if {$state=="failed"} {
|
||||
set childstate omit
|
||||
if {$nerr<=0} {set nerr 1}
|
||||
} else {
|
||||
set childstate ready
|
||||
}
|
||||
if {[info exists pltfm]} {set pltfm [string trim $pltfm]}
|
||||
trdb eval {
|
||||
UPDATE jobs
|
||||
SET output=$output, state=$state, endtime=$endtm
|
||||
SET output=$output, state=$state, endtime=$endtm,
|
||||
ntest=$ntest, nerr=$nerr, svers=$svers, pltfm=$pltfm
|
||||
WHERE jobid=$jobid;
|
||||
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
|
||||
}
|
||||
@@ -1371,6 +1544,26 @@ proc run_testset {} {
|
||||
|
||||
puts "\nTest database is $TRG(dbname)"
|
||||
puts "Test log is $TRG(logname)"
|
||||
trdb eval {
|
||||
SELECT sum(ntest) AS totaltest,
|
||||
sum(nerr) AS totalerr
|
||||
FROM jobs
|
||||
} break
|
||||
trdb eval {
|
||||
SELECT max(endtime)-min(starttime) AS totaltime
|
||||
FROM jobs WHERE endtime>0
|
||||
} break;
|
||||
set et [elapsetime $totaltime]
|
||||
set pltfm {}
|
||||
trdb eval {
|
||||
SELECT pltfm, count(*) FROM jobs WHERE pltfm IS NOT NULL
|
||||
ORDER BY 2 DESC LIMIT 1
|
||||
} break
|
||||
puts "$totalerr errors out of $totaltest tests in $et $pltfm"
|
||||
trdb eval {
|
||||
SELECT DISTINCT substr(svers,1,79) as v1 FROM jobs WHERE svers IS NOT NULL
|
||||
} {puts $v1}
|
||||
|
||||
}
|
||||
|
||||
# Handle the --buildonly option, if it was specified.
|
||||
@@ -1401,7 +1594,14 @@ proc explain_layer {indent depid} {
|
||||
puts "${indent}$displayname in $dirname"
|
||||
explain_layer "${indent} " $jobid
|
||||
} elseif {$showtests} {
|
||||
puts "${indent}[lindex $displayname end]"
|
||||
set tail [lindex $displayname end]
|
||||
set e1 [lindex $displayname 1]
|
||||
if {[string match config=* $e1]} {
|
||||
set cfg [string range $e1 7 end]
|
||||
puts "${indent}($cfg) $tail"
|
||||
} else {
|
||||
puts "${indent}$tail"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1416,7 +1616,7 @@ if {$TRG(explain)} {
|
||||
explain_tests
|
||||
} else {
|
||||
if {$TRG(nJob)>1} {
|
||||
puts "splitting work across $TRG(nJob) jobs"
|
||||
puts "splitting work across $TRG(nJob) cores"
|
||||
}
|
||||
puts "built testset in [expr $tm/1000]ms.."
|
||||
handle_buildonly
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace eval trd {
|
||||
set tcltest(linux.Have-Not) veryquick
|
||||
set tcltest(linux.Secure-Delete) veryquick
|
||||
set tcltest(linux.Unlock-Notify) veryquick
|
||||
set tcltest(linux.User-Auth) veryquick
|
||||
set tcltest(linux.Update-Delete-Limit) veryquick
|
||||
set tcltest(linux.Extra-Robustness) veryquick
|
||||
set tcltest(linux.Device-Two) veryquick
|
||||
@@ -89,6 +88,7 @@ namespace eval trd {
|
||||
--disable-amalgamation --disable-shared
|
||||
--enable-session
|
||||
-DSQLITE_ENABLE_RBU
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS
|
||||
}
|
||||
|
||||
# These two are used by [testrunner.tcl mdevtest] (All-O0) and
|
||||
@@ -96,6 +96,7 @@ namespace eval trd {
|
||||
#
|
||||
set build(All-Debug) {
|
||||
--enable-debug --enable-all
|
||||
-DSQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
}
|
||||
set build(All-O0) {
|
||||
-O0 --enable-all
|
||||
@@ -116,6 +117,7 @@ namespace eval trd {
|
||||
}
|
||||
set build(Stdcall) {
|
||||
-DUSE_STDCALL=1
|
||||
-DSQLITE_USE_ONLY_WIN32=1
|
||||
-O2
|
||||
}
|
||||
|
||||
@@ -139,10 +141,6 @@ namespace eval trd {
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
}
|
||||
set build(User-Auth) {
|
||||
-O2
|
||||
-DSQLITE_USER_AUTHENTICATION=1
|
||||
}
|
||||
set build(Secure-Delete) {
|
||||
-O2
|
||||
-DSQLITE_SECURE_DELETE=1
|
||||
|
||||
@@ -127,6 +127,17 @@ foreach tn {1a 1b 1c 1d 1e 1f} {
|
||||
db3 close
|
||||
}
|
||||
|
||||
# These over-length file and directory names are difficult to delete.
|
||||
# The "file delete -force" might not work, depending on the TCL build
|
||||
# being used. So first try to delete using the windows rmdir command.
|
||||
#
|
||||
set fd [open cleanup.bat w]
|
||||
puts $fd "rmdir /q /s $longPath(1)"
|
||||
close $fd
|
||||
if {[catch {exec cleanup.bat} msg]} {
|
||||
puts "Command \[cleanup.bat\] returns $msg"
|
||||
}
|
||||
|
||||
file delete -force $fileName
|
||||
file delete -force $longPath(3)
|
||||
file delete -force $longPath(2)
|
||||
|
||||
@@ -73,6 +73,38 @@ do_catchsql_test 2.2 {
|
||||
WINDOW w1 AS (PARTITION BY x OVER w1);
|
||||
} {1 {near "OVER": syntax error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE t2(c1 INT, c2 REAL);
|
||||
INSERT INTO t2 VALUES
|
||||
(447,0.0), (448,0.0), (449,0.0), (452,0.0), (453,0.0), (454,0.0), (455,0.0),
|
||||
(456,0.0), (459,0.0), (460,0.0), (462,0.0), (463,0.0), (466,0.0), (467,0.0),
|
||||
(468,0.0), (469,0.0), (470,0.0), (473,0.0), (474,0.0), (475,0.0), (476,0.0),
|
||||
(477,0.0), (480,0.0), (481,0.0), (482,0.0), (483,0.0), (484,0.0), (487,0.0),
|
||||
(488,0.0), (489,0.0), (490,0.0), (491,0.0), (494,0.0), (495,0.0), (496,0.0),
|
||||
(497,0.0), (498,0.0), (501,0.0), (502,0.0), (503,0.0), (504,0.0), (505,0.0),
|
||||
(508,0.0), (509,0.0), (510,0.0), (511,0.0), (512,0.0), (515,0.0), (516,0.0),
|
||||
(517,0.0), (518,0.0), (519,0.0), (522,0.0), (523,0.0), (524,0.0), (525,0.0),
|
||||
(526,0.0), (529,0.0), (530,0.0), (531,0.0), (532,0.0), (533,0.0), (536,0.0),
|
||||
(537,1.0), (538,0.0), (539,0.0), (540,0.0), (543,0.0), (544,0.0);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
select c1, max(c2) over (order by c1 range 366.0 preceding) from t2;
|
||||
} {
|
||||
447 0.0 448 0.0 449 0.0 452 0.0 453 0.0 454 0.0 455 0.0 456 0.0 459 0.0
|
||||
460 0.0 462 0.0 463 0.0 466 0.0 467 0.0 468 0.0 469 0.0 470 0.0 473 0.0
|
||||
474 0.0 475 0.0 476 0.0 477 0.0 480 0.0 481 0.0 482 0.0 483 0.0 484 0.0
|
||||
487 0.0 488 0.0 489 0.0 490 0.0 491 0.0 494 0.0 495 0.0 496 0.0 497 0.0
|
||||
498 0.0 501 0.0 502 0.0 503 0.0 504 0.0 505 0.0 508 0.0 509 0.0 510 0.0
|
||||
511 0.0 512 0.0 515 0.0 516 0.0 517 0.0 518 0.0 519 0.0 522 0.0 523 0.0
|
||||
524 0.0 525 0.0 526 0.0 529 0.0 530 0.0 531 0.0 532 0.0 533 0.0 536 0.0
|
||||
537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+1
-1
@@ -17,5 +17,5 @@ gcc -o sqlite3 -g -Os -I. \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DHAVE_READLINE \
|
||||
../sqlite/src/shell.c \
|
||||
../sqlite/src/test_vfstrace.c \
|
||||
../sqlite/ext/misc/vfstrace.c \
|
||||
sqlite3.c -ldl -lreadline -lncurses
|
||||
|
||||
@@ -159,6 +159,7 @@ set boolean_defnil_options {
|
||||
SQLITE_ENABLE_MULTIPLEX
|
||||
SQLITE_ENABLE_NORMALIZE
|
||||
SQLITE_ENABLE_NULL_TRIM
|
||||
SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
@@ -448,6 +449,7 @@ if {[catch {set cfd [open $destfile w]}]!=0} {
|
||||
puts stderr "File '$destfile' unwritable."
|
||||
exit 1;
|
||||
}
|
||||
fconfigure $cfd -translation binary
|
||||
|
||||
puts $cfd $::headWarning;
|
||||
puts $cfd $::headCode;
|
||||
|
||||
@@ -164,6 +164,11 @@ struct Keyword {
|
||||
#else
|
||||
# define RETURNING 0x00400000
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
|
||||
# define ORDERSET 0
|
||||
#else
|
||||
# define ORDERSET 0x00800000
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -316,6 +321,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "WHERE", "TK_WHERE", ALWAYS, 10 },
|
||||
{ "WINDOW", "TK_WINDOW", WINDOWFUNC, 3 },
|
||||
{ "WITH", "TK_WITH", CTE, 4 },
|
||||
{ "WITHIN", "TK_WITHIN", ORDERSET, 1 },
|
||||
{ "WITHOUT", "TK_WITHOUT", ALWAYS, 1 },
|
||||
};
|
||||
|
||||
|
||||
+201
-351
@@ -1,370 +1,220 @@
|
||||
# Documentation for this script. This may be output to stderr
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Documentation for this script. This may be output to
|
||||
# if the script is invoked incorrectly.
|
||||
#
|
||||
set ::USAGE_MESSAGE {
|
||||
This Tcl script is used to test the various compile time options
|
||||
available for omitting code (the SQLITE_OMIT_xxx options). It
|
||||
should be invoked as follows:
|
||||
available for building SQLite, especially options taht omit
|
||||
features (the SQLITE_OMIT_xxx options). It should be invoked as follows:
|
||||
|
||||
<script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run?
|
||||
./configure CFLAGS=-O0
|
||||
tclsh test/omittest.tcl
|
||||
|
||||
The default value for ::MAKEFILE is "../Makefile.linux.gcc".
|
||||
|
||||
If -skip_run option is given then only the compile part is attempted.
|
||||
|
||||
This script builds the testfixture program and runs the SQLite test suite
|
||||
once with each SQLITE_OMIT_ option defined and then once with all options
|
||||
defined together. Each run is performed in a seperate directory created
|
||||
as a sub-directory of the current directory by the script. The output
|
||||
of the build is saved in <sub-directory>/build.log. The output of the
|
||||
test-suite is saved in <sub-directory>/test.log.
|
||||
|
||||
Almost any SQLite makefile (except those generated by configure - see below)
|
||||
should work. The following properties are required:
|
||||
|
||||
* The makefile should support the "testfixture" target.
|
||||
* The makefile should support the "test" target.
|
||||
* The makefile should support the variable "OPTS" as a way to pass
|
||||
options from the make command line to lemon and the C compiler.
|
||||
|
||||
More precisely, the following two invocations must be supported:
|
||||
|
||||
$::MAKEBIN -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1"
|
||||
$::MAKEBIN -f $::MAKEFILE test
|
||||
|
||||
Makefiles generated by the sqlite configure program cannot be used as
|
||||
they do not respect the OPTS variable.
|
||||
}
|
||||
|
||||
|
||||
# Build a testfixture executable and run quick.test using it. The first
|
||||
# parameter is the name of the directory to create and use to run the
|
||||
# test in. The second parameter is a list of OMIT symbols to define
|
||||
# when doing so. For example:
|
||||
# List of all options to be tested.
|
||||
#
|
||||
# run_quick_test /tmp/testdir {SQLITE_OMIT_TRIGGER SQLITE_OMIT_VIEW}
|
||||
#
|
||||
#
|
||||
proc run_quick_test {dir omit_symbol_list} {
|
||||
# Compile the value of the OPTS Makefile variable.
|
||||
set opts ""
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
append opts "OPTS += -DSQLITE_OS_WIN=1\n"
|
||||
set target "testfixture.exe"
|
||||
} else {
|
||||
append opts "OPTS += -DSQLITE_OS_UNIX=1\n"
|
||||
}
|
||||
foreach sym $omit_symbol_list {
|
||||
append opts "OPTS += -D${sym}=1\n"
|
||||
}
|
||||
set CompileOptionsToTest {
|
||||
SQLITE_OMIT_ALTERTABLE
|
||||
SQLITE_OMIT_ANALYZE
|
||||
SQLITE_OMIT_ATTACH
|
||||
SQLITE_OMIT_AUTHORIZATION
|
||||
SQLITE_OMIT_AUTOINCREMENT
|
||||
SQLITE_OMIT_AUTOINIT
|
||||
SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
SQLITE_OMIT_AUTORESET
|
||||
SQLITE_OMIT_AUTOVACUUM
|
||||
SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS
|
||||
SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
SQLITE_OMIT_BLOB_LITERAL
|
||||
SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA
|
||||
SQLITE_OMIT_CAST
|
||||
SQLITE_OMIT_CHECK
|
||||
SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
SQLITE_OMIT_COMPLETE
|
||||
SQLITE_OMIT_COMPOUND_SELECT
|
||||
SQLITE_OMIT_CONFLICT_CLAUSE
|
||||
SQLITE_OMIT_CTE
|
||||
SQLITE_OMIT_DATETIME_FUNCS
|
||||
SQLITE_OMIT_DECLTYPE
|
||||
SQLITE_OMIT_DEPRECATED
|
||||
SQLITE_OMIT_DESERIALIZE
|
||||
SQLITE_OMIT_DISKIO
|
||||
SQLITE_OMIT_EXPLAIN
|
||||
SQLITE_OMIT_FLAG_PRAGMAS
|
||||
SQLITE_OMIT_FLOATING_POINT
|
||||
SQLITE_OMIT_FOREIGN_KEY
|
||||
SQLITE_OMIT_GENERATED_COLUMNS
|
||||
SQLITE_OMIT_GET_TABLE
|
||||
SQLITE_OMIT_HEX_INTEGER
|
||||
SQLITE_OMIT_INCRBLOB
|
||||
SQLITE_OMIT_INTEGRITY_CHECK
|
||||
SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
SQLITE_OMIT_JSON
|
||||
SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
SQLITE_OMIT_LOAD_EXTENSION
|
||||
SQLITE_OMIT_LOCALTIME
|
||||
SQLITE_OMIT_LOOKASIDE
|
||||
SQLITE_OMIT_MEMORYDB
|
||||
SQLITE_OMIT_OR_OPTIMIZATION
|
||||
SQLITE_OMIT_PAGER_PRAGMAS
|
||||
SQLITE_OMIT_PARSER_TRACE
|
||||
SQLITE_OMIT_POPEN
|
||||
SQLITE_OMIT_PRAGMA
|
||||
SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
SQLITE_OMIT_QUICKBALANCE
|
||||
SQLITE_OMIT_RANDOMNESS
|
||||
SQLITE_OMIT_REINDEX
|
||||
SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
SQLITE_OMIT_SHARED_CACHE
|
||||
SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
SQLITE_OMIT_SUBQUERY
|
||||
SQLITE_OMIT_TCL_VARIABLE
|
||||
SQLITE_OMIT_TEMPDB
|
||||
SQLITE_OMIT_TEST_CONTROL
|
||||
SQLITE_OMIT_TRACE
|
||||
SQLITE_OMIT_TRIGGER
|
||||
SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
||||
SQLITE_OMIT_UPSERT
|
||||
SQLITE_OMIT_UTF
|
||||
SQLITE_OMIT_VACUUM
|
||||
SQLITE_OMIT_VIEW
|
||||
SQLITE_OMIT_VIRTUALTABLE
|
||||
SQLITE_OMIT_WAL
|
||||
SQLITE_OMIT_WINDOWFUNC
|
||||
SQLITE_OMIT_WSD
|
||||
SQLITE_OMIT_XFER_OPT
|
||||
SQLITE_ALLOW_ROWID_IN_VIEW
|
||||
SQLITE_DISABLE_DIRSYNC
|
||||
SQLITE_DISABLE_FTS
|
||||
SQLITE_DISABLE_INTRINSIC
|
||||
SQLITE_DISABLE_LFS
|
||||
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
||||
SQLITE_ENABLE_API_ARMOR
|
||||
SQLITE_ENABLE_ATOMIC_WRITE
|
||||
SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
SQLITE_ENABLE_BYTECODE_VTAB
|
||||
SQLITE_ENABLE_CEROD
|
||||
SQLITE_ENABLE_COLUMN_METADATA
|
||||
SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
SQLITE_ENABLE_COMMENTS
|
||||
SQLITE_ENABLE_CORRUPT_PGNO
|
||||
SQLITE_ENABLE_COSTMULT
|
||||
SQLITE_ENABLE_CURSOR_HINTS
|
||||
SQLITE_ENABLE_DBPAGE_VTAB
|
||||
SQLITE_ENABLE_DBSTAT_VTAB
|
||||
SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SQLITE_ENABLE_FTS
|
||||
SQLITE_ENABLE_GEOPOLY
|
||||
SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
SQLITE_ENABLE_ICU
|
||||
SQLITE_ENABLE_ICU_COLLATIONS
|
||||
SQLITE_ENABLE_INTERNAL_FUNCTIONS
|
||||
SQLITE_ENABLE_IOTRACE
|
||||
SQLITE_ENABLE_LOAD_EXTENSION
|
||||
SQLITE_ENABLE_LOCKING_STYLE
|
||||
SQLITE_ENABLE_MATH_FUNCTIONS
|
||||
SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
SQLITE_ENABLE_MEMSYS
|
||||
SQLITE_ENABLE_MODULE_COMMENTS
|
||||
SQLITE_ENABLE_MULTIPLEX
|
||||
SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
SQLITE_ENABLE_NORMALIZE
|
||||
SQLITE_ENABLE_NULL_TRIM
|
||||
SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
SQLITE_ENABLE_QPSG
|
||||
SQLITE_ENABLE_RBU
|
||||
SQLITE_ENABLE_RTREE
|
||||
SQLITE_ENABLE_SELECTTRACE
|
||||
SQLITE_ENABLE_SESSION
|
||||
SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
SQLITE_ENABLE_SNAPSHOT
|
||||
SQLITE_ENABLE_SORTER_MMAP
|
||||
SQLITE_ENABLE_SORTER_REFERENCE
|
||||
SQLITE_ENABLE_SORTER_REFERENCES
|
||||
SQLITE_ENABLE_SQLLOG
|
||||
SQLITE_ENABLE_STAT
|
||||
SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
SQLITE_ENABLE_STMTVTAB
|
||||
SQLITE_ENABLE_TREETRACE
|
||||
SQLITE_ENABLE_UNKNOWN_FUNCTION
|
||||
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
SQLITE_ENABLE_URI_00_ERROR
|
||||
SQLITE_ENABLE_VFSTRACE
|
||||
SQLITE_ENABLE_WHERETRACE
|
||||
SQLITE_ENABLE_ZIPVFS
|
||||
}
|
||||
|
||||
# Create the directory and do the build. If an error occurs return
|
||||
# early without attempting to run the test suite.
|
||||
file mkdir $dir
|
||||
puts -nonewline "Building $dir..."
|
||||
flush stdout
|
||||
catch {
|
||||
file copy -force ./config.h $dir
|
||||
file copy -force ./libtool $dir
|
||||
}
|
||||
set fd [open $::MAKEFILE]
|
||||
set mkfile [read $fd]
|
||||
close $fd
|
||||
regsub {\ninclude} $mkfile "\n$opts\ninclude" mkfile
|
||||
set fd [open $dir/makefile w]
|
||||
puts $fd $mkfile
|
||||
close $fd
|
||||
|
||||
set rc [catch {
|
||||
exec $::MAKEBIN -C $dir -f makefile clean $::TARGET >& $dir/build.log
|
||||
}]
|
||||
if {$rc} {
|
||||
puts "No good. See $dir/build.log."
|
||||
return
|
||||
} else {
|
||||
puts "Ok"
|
||||
}
|
||||
|
||||
# Create an empty file "$dir/sqlite3". This is to trick the makefile out
|
||||
# of trying to build the sqlite shell. The sqlite shell won't build
|
||||
# with some of the OMIT options (i.e OMIT_COMPLETE).
|
||||
set sqlite3_dummy $dir/sqlite3
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
append sqlite3_dummy ".exe"
|
||||
}
|
||||
if {![file exists $sqlite3_dummy]} {
|
||||
set wr [open $sqlite3_dummy w]
|
||||
puts $wr "dummy"
|
||||
close $wr
|
||||
# Parse command-line options.
|
||||
#
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
set arg [lindex $argv $i]
|
||||
switch -- $arg {
|
||||
-start -
|
||||
--start {
|
||||
incr i
|
||||
set startat [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$::SKIP_RUN} {
|
||||
# puts "Skip testing $dir."
|
||||
} else {
|
||||
# Run the test suite.
|
||||
puts -nonewline "Testing $dir..."
|
||||
flush stdout
|
||||
set rc [catch {
|
||||
exec $::MAKEBIN -C $dir -f makefile test >& $dir/test.log
|
||||
}]
|
||||
if {$rc} {
|
||||
puts "No good. See $dir/test.log."
|
||||
# Additional options required for some settings.
|
||||
#
|
||||
set More(SQLITE_OMIT_DISKIO) {-DSQLITE_OMIT_WAL}
|
||||
|
||||
# Compile-time options for Mac only
|
||||
#
|
||||
set MacOnly(SQLITE_ENABLE_LOCKING_STYLE) 1
|
||||
|
||||
# Compile-time options that might fail, depending on what libraries
|
||||
# are installed. Failures on these tests issue a warning, but testing
|
||||
# continues.
|
||||
#
|
||||
set FailIsOk(SQLITE_ENABLE_ICU) 1
|
||||
set FailIsOk(SQLITE_ENABLE_ICU_COLLATIONS) 1
|
||||
|
||||
file mkdir omittest
|
||||
foreach sym $CompileOptionsToTest {
|
||||
if {[info exists startat]} {
|
||||
if {$startat==$sym} {
|
||||
unset startat
|
||||
} else {
|
||||
puts "Ok"
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# This proc processes the command line options passed to this script.
|
||||
# Currently the only option supported is "-makefile", default
|
||||
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
|
||||
# option.
|
||||
#
|
||||
proc process_options {argv} {
|
||||
set ::MAKEBIN make ;# Default value
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
set ::MAKEFILE ./Makefile ;# Default value on Windows
|
||||
if {[info exists MacOnly($sym)] && $tcl_platform(os)!="Darwin"} {
|
||||
continue
|
||||
}
|
||||
set logfile "omittest/$sym.log"
|
||||
if {[info exists More($sym)]} {
|
||||
append opts "OPT_FEATURE_FLAGS=-D$sym $More($sym)"
|
||||
} else {
|
||||
set ::MAKEFILE ./Makefile.linux-gcc ;# Default value
|
||||
set opts OPT_FEATURE_FLAGS=-D$sym
|
||||
}
|
||||
set ::SKIP_RUN 1 ;# Default to attempt test
|
||||
set ::TARGET testfixture ;# Default thing to build
|
||||
|
||||
for {set i 0} {$i < [llength $argv]} {incr i} {
|
||||
switch -regexp -- [lindex $argv $i] {
|
||||
-{1,2}makefile {
|
||||
incr i
|
||||
set ::MAKEFILE [lindex $argv $i]
|
||||
}
|
||||
|
||||
-{1,2}nmake {
|
||||
set ::MAKEBIN nmake
|
||||
set ::MAKEFILE ./Makefile.msc
|
||||
}
|
||||
|
||||
-{1,2}target {
|
||||
incr i
|
||||
set ::TARGET [lindex $argv $i]
|
||||
}
|
||||
|
||||
-{1,2}skip_run {
|
||||
set ::SKIP_RUN 1
|
||||
}
|
||||
-{1,2}run {
|
||||
set ::SKIP_RUN 0
|
||||
}
|
||||
|
||||
-{1,2}help {
|
||||
puts $::USAGE_MESSAGE
|
||||
exit
|
||||
}
|
||||
|
||||
-.* {
|
||||
puts stderr "Unknown option: [lindex $argv i]"
|
||||
puts stderr $::USAGE_MESSAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
default {
|
||||
if {[info exists ::SYMBOL]} {
|
||||
puts stderr [string trim $::USAGE_MESSAGE]
|
||||
exit -1
|
||||
}
|
||||
set ::SYMBOL [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
set ::MAKEFILE [file normalize $::MAKEFILE]
|
||||
}
|
||||
}
|
||||
|
||||
# Main routine.
|
||||
#
|
||||
|
||||
proc main {argv} {
|
||||
# List of SQLITE_OMIT_XXX symbols supported by SQLite.
|
||||
set ::OMIT_SYMBOLS [list \
|
||||
SQLITE_OMIT_ALTERTABLE \
|
||||
SQLITE_OMIT_ANALYZE \
|
||||
SQLITE_OMIT_ATTACH \
|
||||
SQLITE_OMIT_AUTHORIZATION \
|
||||
SQLITE_OMIT_AUTOINCREMENT \
|
||||
SQLITE_OMIT_AUTOINIT \
|
||||
SQLITE_OMIT_AUTOMATIC_INDEX \
|
||||
SQLITE_OMIT_AUTORESET \
|
||||
SQLITE_OMIT_AUTOVACUUM \
|
||||
SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS \
|
||||
SQLITE_OMIT_BETWEEN_OPTIMIZATION \
|
||||
SQLITE_OMIT_BLOB_LITERAL \
|
||||
SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA \
|
||||
SQLITE_OMIT_CAST \
|
||||
SQLITE_OMIT_CHECK \
|
||||
SQLITE_OMIT_COMPILEOPTION_DIAGS \
|
||||
SQLITE_OMIT_COMPLETE \
|
||||
SQLITE_OMIT_COMPOUND_SELECT \
|
||||
SQLITE_OMIT_CONFLICT_CLAUSE \
|
||||
SQLITE_OMIT_CTE \
|
||||
SQLITE_OMIT_DATETIME_FUNCS \
|
||||
SQLITE_OMIT_DECLTYPE \
|
||||
SQLITE_OMIT_DEPRECATED \
|
||||
SQLITE_OMIT_DESERIALIZE \
|
||||
SQLITE_OMIT_DISKIO \
|
||||
SQLITE_OMIT_EXPLAIN \
|
||||
SQLITE_OMIT_FLAG_PRAGMAS \
|
||||
SQLITE_OMIT_FLOATING_POINT \
|
||||
SQLITE_OMIT_FOREIGN_KEY \
|
||||
SQLITE_OMIT_GENERATED_COLUMNS \
|
||||
SQLITE_OMIT_GET_TABLE \
|
||||
SQLITE_OMIT_HEX_INTEGER \
|
||||
SQLITE_OMIT_INCRBLOB \
|
||||
SQLITE_OMIT_INTEGRITY_CHECK \
|
||||
SQLITE_OMIT_INTROSPECTION_PRAGMAS \
|
||||
SQLITE_OMIT_JSON \
|
||||
SQLITE_OMIT_LIKE_OPTIMIZATION \
|
||||
SQLITE_OMIT_LOAD_EXTENSION \
|
||||
SQLITE_OMIT_LOCALTIME \
|
||||
SQLITE_OMIT_LOOKASIDE \
|
||||
SQLITE_OMIT_MEMORYDB \
|
||||
SQLITE_OMIT_OR_OPTIMIZATION \
|
||||
SQLITE_OMIT_PAGER_PRAGMAS \
|
||||
SQLITE_OMIT_PARSER_TRACE \
|
||||
SQLITE_OMIT_POPEN \
|
||||
SQLITE_OMIT_PRAGMA \
|
||||
SQLITE_OMIT_PROGRESS_CALLBACK \
|
||||
SQLITE_OMIT_QUICKBALANCE \
|
||||
SQLITE_OMIT_RANDOMNESS \
|
||||
SQLITE_OMIT_REINDEX \
|
||||
SQLITE_OMIT_SCHEMA_PRAGMAS \
|
||||
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS \
|
||||
SQLITE_OMIT_SHARED_CACHE \
|
||||
SQLITE_OMIT_SHUTDOWN_DIRECTORIES \
|
||||
SQLITE_OMIT_SUBQUERY \
|
||||
SQLITE_OMIT_TCL_VARIABLE \
|
||||
SQLITE_OMIT_TEMPDB \
|
||||
SQLITE_OMIT_TEST_CONTROL \
|
||||
SQLITE_OMIT_TRACE \
|
||||
SQLITE_OMIT_TRIGGER \
|
||||
SQLITE_OMIT_TRUNCATE_OPTIMIZATION \
|
||||
SQLITE_OMIT_TWOSIZE_LOOKASIDE \
|
||||
SQLITE_OMIT_UPSERT \
|
||||
SQLITE_OMIT_UTF \
|
||||
SQLITE_OMIT_VACUUM \
|
||||
SQLITE_OMIT_VIEW \
|
||||
SQLITE_OMIT_VIRTUALTABLE \
|
||||
SQLITE_OMIT_WAL \
|
||||
SQLITE_OMIT_WINDOWFUNC \
|
||||
SQLITE_OMIT_WSD \
|
||||
SQLITE_OMIT_XFER_OPT \
|
||||
]
|
||||
|
||||
set ::ENABLE_SYMBOLS [list \
|
||||
SQLITE_ALLOW_ROWID_IN_VIEW \
|
||||
SQLITE_DISABLE_DIRSYNC \
|
||||
SQLITE_DISABLE_FTS \
|
||||
SQLITE_DISABLE_INTRINSIC \
|
||||
SQLITE_DISABLE_LFS \
|
||||
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS \
|
||||
SQLITE_DISABLE_SKIPAHEAD_DISTINCT \
|
||||
SQLITE_ENABLE_API_ARMOR \
|
||||
SQLITE_ENABLE_ATOMIC_WRITE \
|
||||
SQLITE_ENABLE_BATCH_ATOMIC_WRITE \
|
||||
SQLITE_ENABLE_BYTECODE_VTAB \
|
||||
SQLITE_ENABLE_CEROD \
|
||||
SQLITE_ENABLE_COLUMN_METADATA \
|
||||
SQLITE_ENABLE_COLUMN_USED_MASK \
|
||||
SQLITE_ENABLE_COMMENTS \
|
||||
SQLITE_ENABLE_CORRUPT_PGNO \
|
||||
SQLITE_ENABLE_COSTMULT \
|
||||
SQLITE_ENABLE_CURSOR_HINTS \
|
||||
SQLITE_ENABLE_DBPAGE_VTAB \
|
||||
SQLITE_ENABLE_DBSTAT_VTAB \
|
||||
SQLITE_ENABLE_EXPENSIVE_ASSERT \
|
||||
SQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||
SQLITE_ENABLE_FTS \
|
||||
SQLITE_ENABLE_GEOPOLY \
|
||||
SQLITE_ENABLE_HIDDEN_COLUMNS \
|
||||
SQLITE_ENABLE_ICU \
|
||||
SQLITE_ENABLE_ICU_COLLATIONS \
|
||||
SQLITE_ENABLE_INTERNAL_FUNCTIONS \
|
||||
SQLITE_ENABLE_IOTRACE \
|
||||
SQLITE_ENABLE_LOAD_EXTENSION \
|
||||
SQLITE_ENABLE_LOCKING_STYLE \
|
||||
SQLITE_ENABLE_MATH_FUNCTIONS \
|
||||
SQLITE_ENABLE_MEMORY_MANAGEMENT \
|
||||
SQLITE_ENABLE_MEMSYS \
|
||||
SQLITE_ENABLE_MODULE_COMMENTS \
|
||||
SQLITE_ENABLE_MULTIPLEX \
|
||||
SQLITE_ENABLE_MULTITHREADED_CHECKS \
|
||||
SQLITE_ENABLE_NORMALIZE \
|
||||
SQLITE_ENABLE_NULL_TRIM \
|
||||
SQLITE_ENABLE_OFFSET_SQL_FUNC \
|
||||
SQLITE_ENABLE_OVERSIZE_CELL_CHECK \
|
||||
SQLITE_ENABLE_PREUPDATE_HOOK \
|
||||
SQLITE_ENABLE_QPSG \
|
||||
SQLITE_ENABLE_RBU \
|
||||
SQLITE_ENABLE_RTREE \
|
||||
SQLITE_ENABLE_SELECTTRACE \
|
||||
SQLITE_ENABLE_SESSION \
|
||||
SQLITE_ENABLE_SETLK_TIMEOUT \
|
||||
SQLITE_ENABLE_SNAPSHOT \
|
||||
SQLITE_ENABLE_SORTER_MMAP\
|
||||
SQLITE_ENABLE_SORTER_REFERENCE \
|
||||
SQLITE_ENABLE_SORTER_REFERENCES \
|
||||
SQLITE_ENABLE_SQLLOG\
|
||||
SQLITE_ENABLE_STAT \
|
||||
SQLITE_ENABLE_STMT_SCANSTATUS \
|
||||
SQLITE_ENABLE_STMTVTAB \
|
||||
SQLITE_ENABLE_TREETRACE \
|
||||
SQLITE_ENABLE_UNKNOWN_FUNCTION \
|
||||
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
|
||||
SQLITE_ENABLE_UNLOCK_NOTIFY \
|
||||
SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
|
||||
SQLITE_ENABLE_URI_00_ERROR \
|
||||
SQLITE_ENABLE_VFSTRACE \
|
||||
SQLITE_ENABLE_WHERETRACE \
|
||||
SQLITE_ENABLE_ZIPVFS \
|
||||
]
|
||||
|
||||
# Process any command line options.
|
||||
process_options $argv
|
||||
|
||||
if {[info exists ::SYMBOL] } {
|
||||
set sym $::SYMBOL
|
||||
|
||||
if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
|
||||
puts stderr "No such symbol: $sym"
|
||||
exit -1
|
||||
}
|
||||
|
||||
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
|
||||
run_quick_test $dirname $sym
|
||||
} else {
|
||||
# First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT
|
||||
# and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
|
||||
# and the latter is currently incompatible with the test suite (this should
|
||||
# be fixed, but it will be a lot of work).
|
||||
set allsyms [list]
|
||||
foreach s $::OMIT_SYMBOLS {
|
||||
if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
|
||||
lappend allsyms $s
|
||||
}
|
||||
}
|
||||
run_quick_test test_OMIT_EVERYTHING $allsyms
|
||||
|
||||
# Now try one quick.test with each of the OMIT symbols defined. Included
|
||||
# are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
|
||||
# know they will fail. It's good to be reminded of this from time to time.
|
||||
foreach sym $::OMIT_SYMBOLS {
|
||||
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
|
||||
run_quick_test $dirname $sym
|
||||
}
|
||||
|
||||
# Try the ENABLE/DISABLE symbols one at a time.
|
||||
# We don't do them all at once since some are conflicting.
|
||||
foreach sym $::ENABLE_SYMBOLS {
|
||||
set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]"
|
||||
run_quick_test $dirname $sym
|
||||
puts "make tidy sqlite3.lo $opts"
|
||||
if {[catch {exec make tidy sqlite3.lo $opts >& $logfile}]} {
|
||||
puts "BUILD FAILED: see $logfile for details"
|
||||
if {[info exists FailIsOk($sym)]} {
|
||||
set Failure($sym) 1
|
||||
} else {
|
||||
puts "Note: After fixes, continue the test using:\n"
|
||||
puts " [info nameofexe] $argv0 --start $sym\n"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main $argv
|
||||
if {[llength [array names Failure]]>0} {
|
||||
puts "BUILD FAILED on the following:"
|
||||
foreach sym [array names Failure] {
|
||||
puts " * $sym"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
** the entire block.
|
||||
**
|
||||
** For blocks of more than 16 bytes, the signature is a hex dump of the
|
||||
** first 8 bytes followed by a 64-bit has of the entire block.
|
||||
** first 8 bytes followed by a 64-bit hash of the entire block.
|
||||
*/
|
||||
static void vlogSignature(unsigned char *p, int n, char *zCksum){
|
||||
unsigned int s0 = 0, s1 = 0;
|
||||
|
||||
+14
-3
@@ -1084,17 +1084,28 @@ static void ptrmap_coverage_report(const char *zDbName){
|
||||
printf("%5llu: PTRMAP page covering %llu..%llu\n", pgno,
|
||||
pgno+1, pgno+perPage);
|
||||
a = fileRead((pgno-1)*g.pagesize, usable);
|
||||
for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
|
||||
const char *zType = "???";
|
||||
for(i=0; i+5<=usable; i+=5){
|
||||
const char *zType;
|
||||
u32 iFrom = decodeInt32(&a[i+1]);
|
||||
const char *zExtra = pgno+1+i/5>g.mxPage ? " (off end of DB)" : "";
|
||||
switch( a[i] ){
|
||||
case 1: zType = "b-tree root page"; break;
|
||||
case 2: zType = "freelist page"; break;
|
||||
case 3: zType = "first page of overflow"; break;
|
||||
case 4: zType = "later page of overflow"; break;
|
||||
case 5: zType = "b-tree non-root page"; break;
|
||||
default: {
|
||||
if( zExtra[0]==0 ){
|
||||
printf("%5llu: invalid (0x%02x), parent=%u\n",
|
||||
pgno+1+i/5, a[i], iFrom);
|
||||
}
|
||||
zType = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( zType ){
|
||||
printf("%5llu: %s, parent=%u%s\n", pgno+1+i/5, zType, iFrom, zExtra);
|
||||
}
|
||||
printf("%5llu: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
|
||||
}
|
||||
sqlite3_free(a);
|
||||
}
|
||||
|
||||
+16
-4
@@ -74,6 +74,16 @@ Options:
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Exit with given code, but first close db if open.
|
||||
#
|
||||
proc exit_clean {exit_code} {
|
||||
if {0 < [llength [info commands db]]} {
|
||||
db close
|
||||
}
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
set file_to_analyze {}
|
||||
set flags(-pageinfo) 0
|
||||
set flags(-stats) 0
|
||||
@@ -157,7 +167,7 @@ if {![db exists {SELECT 1 FROM pragma_compile_options
|
||||
lacks required capabilities. Recompile using the\
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB compile-time option to fix\
|
||||
this problem."
|
||||
exit 1
|
||||
exit_clean 1
|
||||
}
|
||||
|
||||
db eval {SELECT count(*) FROM sqlite_schema}
|
||||
@@ -168,7 +178,7 @@ if {$flags(-pageinfo)} {
|
||||
db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {
|
||||
puts "$pageno $name $path"
|
||||
}
|
||||
exit 0
|
||||
exit_clean 0
|
||||
}
|
||||
if {$flags(-stats)} {
|
||||
db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
|
||||
@@ -198,7 +208,7 @@ if {$flags(-stats)} {
|
||||
puts "INSERT INTO stats VALUES($x);"
|
||||
}
|
||||
puts "COMMIT;"
|
||||
exit 0
|
||||
exit_clean 0
|
||||
}
|
||||
|
||||
|
||||
@@ -901,5 +911,7 @@ puts "COMMIT;"
|
||||
} err]} {
|
||||
puts "ERROR: $err"
|
||||
puts $errorInfo
|
||||
exit 1
|
||||
exit_clean 1
|
||||
}
|
||||
|
||||
exit_clean 0
|
||||
|
||||
+69
-81
@@ -14,7 +14,7 @@
|
||||
** between two SQLite databases.
|
||||
**
|
||||
** To compile, simply link against SQLite. (Windows builds must also link
|
||||
** against ext/consio/console_io.c.)
|
||||
** against ext/misc/sqlite3_stdio.c.)
|
||||
**
|
||||
** See the showHelp() routine below for a brief description of how to
|
||||
** run the utility.
|
||||
@@ -26,19 +26,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/* Output function substitutions that cause UTF8 characters to be rendered
|
||||
** correctly on Windows:
|
||||
**
|
||||
** fprintf() -> Wfprintf()
|
||||
**
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
# include "console_io.h"
|
||||
# define Wfprintf fPrintfUtf8
|
||||
#else
|
||||
# define Wfprintf fprintf
|
||||
#endif
|
||||
#include "sqlite3_stdio.h"
|
||||
|
||||
/*
|
||||
** All global variables are gathered into the "g" singleton.
|
||||
@@ -76,9 +64,9 @@ static void cmdlineError(const char *zFormat, ...){
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_str_vappendf(pOut, zFormat, ap);
|
||||
va_end(ap);
|
||||
Wfprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
sqlite3_fprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
strFree(pOut);
|
||||
Wfprintf(stderr, "\"%s --help\" for more help\n", g.zArgv0);
|
||||
sqlite3_fprintf(stderr, "\"%s --help\" for more help\n", g.zArgv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -92,7 +80,7 @@ static void runtimeError(const char *zFormat, ...){
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_str_vappendf(pOut, zFormat, ap);
|
||||
va_end(ap);
|
||||
Wfprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
sqlite3_fprintf(stderr, "%s: %s\n", g.zArgv0, sqlite3_str_value(pOut));
|
||||
strFree(pOut);
|
||||
exit(1);
|
||||
}
|
||||
@@ -349,11 +337,11 @@ static void printQuoted(FILE *out, sqlite3_value *X){
|
||||
char zBuf[50];
|
||||
r1 = sqlite3_value_double(X);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
|
||||
fprintf(out, "%s", zBuf);
|
||||
sqlite3_fprintf(out, "%s", zBuf);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
fprintf(out, "%lld", sqlite3_value_int64(X));
|
||||
sqlite3_fprintf(out, "%lld", sqlite3_value_int64(X));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
@@ -361,14 +349,14 @@ static void printQuoted(FILE *out, sqlite3_value *X){
|
||||
int nBlob = sqlite3_value_bytes(X);
|
||||
if( zBlob ){
|
||||
int i;
|
||||
fprintf(out, "x'");
|
||||
sqlite3_fprintf(out, "x'");
|
||||
for(i=0; i<nBlob; i++){
|
||||
fprintf(out, "%02x", zBlob[i]);
|
||||
sqlite3_fprintf(out, "%02x", zBlob[i]);
|
||||
}
|
||||
fprintf(out, "'");
|
||||
sqlite3_fprintf(out, "'");
|
||||
}else{
|
||||
/* Could be an OOM, could be a zero-byte blob */
|
||||
fprintf(out, "X''");
|
||||
sqlite3_fprintf(out, "X''");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -376,38 +364,38 @@ static void printQuoted(FILE *out, sqlite3_value *X){
|
||||
const unsigned char *zArg = sqlite3_value_text(X);
|
||||
|
||||
if( zArg==0 ){
|
||||
fprintf(out, "NULL");
|
||||
sqlite3_fprintf(out, "NULL");
|
||||
}else{
|
||||
int inctl = 0;
|
||||
int i, j;
|
||||
fprintf(out, "'");
|
||||
sqlite3_fprintf(out, "'");
|
||||
for(i=j=0; zArg[i]; i++){
|
||||
char c = zArg[i];
|
||||
int ctl = iscntrl((unsigned char)c);
|
||||
if( ctl>inctl ){
|
||||
inctl = ctl;
|
||||
fprintf(out, "%.*s'||X'%02x", i-j, &zArg[j], c);
|
||||
sqlite3_fprintf(out, "%.*s'||X'%02x", i-j, &zArg[j], c);
|
||||
j = i+1;
|
||||
}else if( ctl ){
|
||||
fprintf(out, "%02x", c);
|
||||
sqlite3_fprintf(out, "%02x", c);
|
||||
j = i+1;
|
||||
}else{
|
||||
if( inctl ){
|
||||
inctl = 0;
|
||||
fprintf(out, "'\n||'");
|
||||
sqlite3_fprintf(out, "'\n||'");
|
||||
}
|
||||
if( c=='\'' ){
|
||||
fprintf(out, "%.*s'", i-j+1, &zArg[j]);
|
||||
sqlite3_fprintf(out, "%.*s'", i-j+1, &zArg[j]);
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(out, "%s'", &zArg[j]);
|
||||
sqlite3_fprintf(out, "%s'", &zArg[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_NULL: {
|
||||
fprintf(out, "NULL");
|
||||
sqlite3_fprintf(out, "NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -428,7 +416,7 @@ static void dump_table(const char *zTab, FILE *out){
|
||||
|
||||
pStmt = db_prepare("SELECT sql FROM aux.sqlite_schema WHERE name=%Q", zTab);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
sqlite3_fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
if( !g.bSchemaOnly ){
|
||||
@@ -463,14 +451,14 @@ static void dump_table(const char *zTab, FILE *out){
|
||||
}
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
Wfprintf(out, "%s",sqlite3_str_value(pIns));
|
||||
sqlite3_fprintf(out, "%s",sqlite3_str_value(pIns));
|
||||
zSep = "(";
|
||||
for(i=0; i<nCol; i++){
|
||||
Wfprintf(out, "%s",zSep);
|
||||
sqlite3_fprintf(out, "%s",zSep);
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
zSep = ",";
|
||||
}
|
||||
Wfprintf(out, ");\n");
|
||||
sqlite3_fprintf(out, ");\n");
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
strFree(pIns);
|
||||
@@ -479,7 +467,7 @@ static void dump_table(const char *zTab, FILE *out){
|
||||
" WHERE type='index' AND tbl_name=%Q AND sql IS NOT NULL",
|
||||
zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
Wfprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
sqlite3_fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_free(zId);
|
||||
@@ -514,14 +502,14 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
*/
|
||||
az = columnNames("aux",zTab, &nPk, 0);
|
||||
if( az==0 ){
|
||||
Wfprintf(stdout, "Rowid not accessible for %s\n", zId);
|
||||
sqlite3_fprintf(stdout, "Rowid not accessible for %s\n", zId);
|
||||
}else{
|
||||
Wfprintf(stdout, "%s:", zId);
|
||||
sqlite3_fprintf(stdout, "%s:", zId);
|
||||
for(i=0; az[i]; i++){
|
||||
Wfprintf(stdout, " %s", az[i]);
|
||||
if( i+1==nPk ) Wfprintf(stdout, " *");
|
||||
sqlite3_fprintf(stdout, " %s", az[i]);
|
||||
if( i+1==nPk ) sqlite3_fprintf(stdout, " *");
|
||||
}
|
||||
Wfprintf(stdout, "\n");
|
||||
sqlite3_fprintf(stdout, "\n");
|
||||
}
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
@@ -530,9 +518,9 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from second database. */
|
||||
if( g.bSchemaCompare )
|
||||
Wfprintf(out, "-- 2nd DB has no %s table\n", zTab);
|
||||
sqlite3_fprintf(out, "-- 2nd DB has no %s table\n", zTab);
|
||||
else
|
||||
Wfprintf(out, "DROP TABLE %s;\n", zId);
|
||||
sqlite3_fprintf(out, "DROP TABLE %s;\n", zId);
|
||||
}
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
@@ -540,7 +528,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from source */
|
||||
if( g.bSchemaCompare ){
|
||||
Wfprintf(out, "-- 1st DB has no %s table\n", zTab);
|
||||
sqlite3_fprintf(out, "-- 1st DB has no %s table\n", zTab);
|
||||
}else{
|
||||
dump_table(zTab, out);
|
||||
}
|
||||
@@ -560,7 +548,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
|| az[n]
|
||||
){
|
||||
/* Schema mismatch */
|
||||
Wfprintf(out, "%sDROP TABLE %s; -- due to schema mismatch\n", zLead, zId);
|
||||
sqlite3_fprintf(out, "%sDROP TABLE %s; -- due to schema mismatch\n", zLead, zId);
|
||||
dump_table(zTab, out);
|
||||
goto end_diff_one_table;
|
||||
}
|
||||
@@ -568,7 +556,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
/* Build the comparison query */
|
||||
for(n2=n; az2[n2]; n2++){
|
||||
char *zNTab = safeId(az2[n2]);
|
||||
Wfprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, zNTab);
|
||||
sqlite3_fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, zNTab);
|
||||
sqlite3_free(zNTab);
|
||||
}
|
||||
nQ = nPk2+1+2*(n2-nPk2);
|
||||
@@ -669,7 +657,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
zTab, zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
char *z = safeId((const char*)sqlite3_column_text(pStmt,0));
|
||||
fprintf(out, "DROP INDEX %s;\n", z);
|
||||
sqlite3_fprintf(out, "DROP INDEX %s;\n", z);
|
||||
sqlite3_free(z);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
@@ -681,39 +669,39 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
int iType = sqlite3_column_int(pStmt, nPk);
|
||||
if( iType==1 || iType==2 ){
|
||||
if( iType==1 ){ /* Change the content of a row */
|
||||
fprintf(out, "%sUPDATE %s", zLead, zId);
|
||||
sqlite3_fprintf(out, "%sUPDATE %s", zLead, zId);
|
||||
zSep = " SET";
|
||||
for(i=nPk+1; i<nQ; i+=2){
|
||||
if( sqlite3_column_int(pStmt,i)==0 ) continue;
|
||||
fprintf(out, "%s %s=", zSep, az2[(i+nPk-1)/2]);
|
||||
sqlite3_fprintf(out, "%s %s=", zSep, az2[(i+nPk-1)/2]);
|
||||
zSep = ",";
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i+1));
|
||||
}
|
||||
}else{ /* Delete a row */
|
||||
fprintf(out, "%sDELETE FROM %s", zLead, zId);
|
||||
sqlite3_fprintf(out, "%sDELETE FROM %s", zLead, zId);
|
||||
}
|
||||
zSep = " WHERE";
|
||||
for(i=0; i<nPk; i++){
|
||||
fprintf(out, "%s %s=", zSep, az2[i]);
|
||||
sqlite3_fprintf(out, "%s %s=", zSep, az2[i]);
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
zSep = " AND";
|
||||
}
|
||||
fprintf(out, ";\n");
|
||||
sqlite3_fprintf(out, ";\n");
|
||||
}else{ /* Insert a row */
|
||||
fprintf(out, "%sINSERT INTO %s(%s", zLead, zId, az2[0]);
|
||||
for(i=1; az2[i]; i++) fprintf(out, ",%s", az2[i]);
|
||||
fprintf(out, ") VALUES");
|
||||
sqlite3_fprintf(out, "%sINSERT INTO %s(%s", zLead, zId, az2[0]);
|
||||
for(i=1; az2[i]; i++) sqlite3_fprintf(out, ",%s", az2[i]);
|
||||
sqlite3_fprintf(out, ") VALUES");
|
||||
zSep = "(";
|
||||
for(i=0; i<nPk2; i++){
|
||||
fprintf(out, "%s", zSep);
|
||||
sqlite3_fprintf(out, "%s", zSep);
|
||||
zSep = ",";
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
}
|
||||
for(i=nPk2+2; i<nQ; i+=2){
|
||||
fprintf(out, ",");
|
||||
sqlite3_fprintf(out, ",");
|
||||
printQuoted(out, sqlite3_column_value(pStmt,i));
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
sqlite3_fprintf(out, ");\n");
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
@@ -729,7 +717,7 @@ static void diff_one_table(const char *zTab, FILE *out){
|
||||
" AND sql IS NOT NULL)",
|
||||
zTab, zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
sqlite3_fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
@@ -1283,17 +1271,17 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
** statement first. And reset pCt so that it will not be
|
||||
** printed again. */
|
||||
if( sqlite3_str_length(pCt) ){
|
||||
fprintf(out, "%s\n", sqlite3_str_value(pCt));
|
||||
sqlite3_fprintf(out, "%s\n", sqlite3_str_value(pCt));
|
||||
sqlite3_str_reset(pCt);
|
||||
}
|
||||
|
||||
/* Output the first part of the INSERT statement */
|
||||
fprintf(out, "%s", sqlite3_str_value(pInsert));
|
||||
sqlite3_fprintf(out, "%s", sqlite3_str_value(pInsert));
|
||||
nRow++;
|
||||
|
||||
if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){
|
||||
for(i=0; i<=nCol; i++){
|
||||
if( i>0 ) fprintf(out, ", ");
|
||||
if( i>0 ) sqlite3_fprintf(out, ", ");
|
||||
printQuoted(out, sqlite3_column_value(pStmt, i));
|
||||
}
|
||||
}else{
|
||||
@@ -1320,9 +1308,9 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
nDelta = rbuDeltaCreate(aSrc, nSrc, aFinal, nFinal, aDelta);
|
||||
if( nDelta<nFinal ){
|
||||
int j;
|
||||
fprintf(out, "x'");
|
||||
for(j=0; j<nDelta; j++) fprintf(out, "%02x", (u8)aDelta[j]);
|
||||
fprintf(out, "'");
|
||||
sqlite3_fprintf(out, "x'");
|
||||
for(j=0; j<nDelta; j++) sqlite3_fprintf(out, "%02x", (u8)aDelta[j]);
|
||||
sqlite3_fprintf(out, "'");
|
||||
zOtaControl[i-bOtaRowid] = 'f';
|
||||
bDone = 1;
|
||||
}
|
||||
@@ -1332,14 +1320,14 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
if( bDone==0 ){
|
||||
printQuoted(out, sqlite3_column_value(pStmt, i));
|
||||
}
|
||||
fprintf(out, ", ");
|
||||
sqlite3_fprintf(out, ", ");
|
||||
}
|
||||
fprintf(out, "'%s'", zOtaControl);
|
||||
sqlite3_fprintf(out, "'%s'", zOtaControl);
|
||||
sqlite3_free(zOtaControl);
|
||||
}
|
||||
|
||||
/* And the closing bracket of the insert statement */
|
||||
fprintf(out, ");\n");
|
||||
sqlite3_fprintf(out, ");\n");
|
||||
}
|
||||
|
||||
sqlite3_finalize(pStmt);
|
||||
@@ -1347,7 +1335,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_str *pCnt = sqlite3_str_new(0);
|
||||
sqlite3_str_appendf(pCnt,
|
||||
"INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow);
|
||||
fprintf(out, "%s\n", sqlite3_str_value(pCnt));
|
||||
sqlite3_fprintf(out, "%s\n", sqlite3_str_value(pCnt));
|
||||
strFree(pCnt);
|
||||
}
|
||||
|
||||
@@ -1386,14 +1374,14 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
if( sqlite3_table_column_metadata(g.db,"aux",zTab,0,0,0,0,0,0) ){
|
||||
if( !sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from second database. */
|
||||
Wfprintf(out, "%s: missing from second database\n", zTab);
|
||||
sqlite3_fprintf(out, "%s: missing from second database\n", zTab);
|
||||
}
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
if( sqlite3_table_column_metadata(g.db,"main",zTab,0,0,0,0,0,0) ){
|
||||
/* Table missing from source */
|
||||
Wfprintf(out, "%s: missing from first database\n", zTab);
|
||||
sqlite3_fprintf(out, "%s: missing from first database\n", zTab);
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
@@ -1410,7 +1398,7 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
|| az[n]
|
||||
){
|
||||
/* Schema mismatch */
|
||||
Wfprintf(out, "%s: incompatible schema\n", zTab);
|
||||
sqlite3_fprintf(out, "%s: incompatible schema\n", zTab);
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
@@ -1455,7 +1443,7 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_str_appendf(pSql, ")\n ORDER BY 1;\n");
|
||||
|
||||
if( (g.fDebug & DEBUG_DIFF_SQL)!=0 ){
|
||||
Wfprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
sqlite3_fprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
goto end_summarize_one_table;
|
||||
}
|
||||
|
||||
@@ -1480,7 +1468,7 @@ static void summarize_one_table(const char *zTab, FILE *out){
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
Wfprintf(out,
|
||||
sqlite3_fprintf(out,
|
||||
"%s: %lld changes, %lld inserts, %lld deletes, %lld unchanged\n",
|
||||
zTab, nUpdate, nInsert, nDelete, nUnchanged);
|
||||
|
||||
@@ -1661,7 +1649,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_str_appendf(pSql, ";\n");
|
||||
|
||||
if( g.fDebug & DEBUG_DIFF_SQL ){
|
||||
Wfprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
sqlite3_fprintf(stdout, "SQL for %s:\n%s\n", zId, sqlite3_str_value(pSql));
|
||||
goto end_changeset_one_table;
|
||||
}
|
||||
|
||||
@@ -1891,8 +1879,8 @@ const char *all_tables_sql(){
|
||||
** Print sketchy documentation for this utility program
|
||||
*/
|
||||
static void showHelp(void){
|
||||
Wfprintf(stdout, "Usage: %s [options] DB1 DB2\n", g.zArgv0);
|
||||
Wfprintf(stdout,
|
||||
sqlite3_fprintf(stdout, "Usage: %s [options] DB1 DB2\n", g.zArgv0);
|
||||
sqlite3_fprintf(stdout,
|
||||
"Output SQL text that would transform DB1 into DB2.\n"
|
||||
"Options:\n"
|
||||
" --changeset FILE Write a CHANGESET into FILE\n"
|
||||
@@ -1935,7 +1923,7 @@ int main(int argc, char **argv){
|
||||
if( z[0]=='-' ) z++;
|
||||
if( strcmp(z,"changeset")==0 ){
|
||||
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
|
||||
out = fopen(argv[++i], "wb");
|
||||
out = sqlite3_fopen(argv[++i], "wb");
|
||||
if( out==0 ) cmdlineError("cannot open: %s", argv[i]);
|
||||
xDiff = changeset_one_table;
|
||||
neverUseTransaction = 1;
|
||||
@@ -2036,9 +2024,9 @@ int main(int argc, char **argv){
|
||||
}
|
||||
|
||||
if( neverUseTransaction ) useTransaction = 0;
|
||||
if( useTransaction ) Wfprintf(out, "BEGIN TRANSACTION;\n");
|
||||
if( useTransaction ) sqlite3_fprintf(out, "BEGIN TRANSACTION;\n");
|
||||
if( xDiff==rbudiff_one_table ){
|
||||
Wfprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
|
||||
sqlite3_fprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
|
||||
"(tbl TEXT PRIMARY KEY COLLATE NOCASE, cnt INTEGER) "
|
||||
"WITHOUT ROWID;\n"
|
||||
);
|
||||
@@ -2053,7 +2041,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
if( useTransaction ) Wfprintf(stdout,"COMMIT;\n");
|
||||
if( useTransaction ) sqlite3_fprintf(stdout,"COMMIT;\n");
|
||||
|
||||
/* TBD: Handle trigger differences */
|
||||
/* TBD: Handle view differences */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,8 +20,8 @@ INCLUDE sqlite3.c
|
||||
INCLUDE $ROOT/src/tclsqlite.c
|
||||
|
||||
#if defined(_WIN32)
|
||||
INCLUDE $ROOT/ext/consio/console_io.h
|
||||
INCLUDE $ROOT/ext/consio/console_io.c
|
||||
INCLUDE $ROOT/ext/misc/sqlite3_stdio.h
|
||||
INCLUDE $ROOT/ext/misc/sqlite3_stdio.c
|
||||
|
||||
/* Substitute "puts" command. Only these forms recognized:
|
||||
**
|
||||
@@ -56,8 +56,8 @@ static int subst_puts(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
fPutsUtf8(zOut, pOut);
|
||||
if( addNewLine ) fPutsUtf8("\n", pOut);
|
||||
sqlite3_fputs(zOut, pOut);
|
||||
if( addNewLine ) sqlite3_fputs("\n", pOut);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
Reference in New Issue
Block a user