Compare commits
186 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fba24d3528 | |||
| 74672acd94 | |||
| 2c72c55dca | |||
| 706fdeebb8 | |||
| c8c95f5149 | |||
| 51bbf0c7b8 | |||
| 1e2834dd45 | |||
| c51dccbd8b | |||
| 46a62afbab | |||
| 44b8c37017 | |||
| c5c3cbc026 | |||
| 3b3f230d95 | |||
| 92e71573ce | |||
| 010f9f8704 | |||
| dceffee1ba | |||
| 512ad53f3a | |||
| f9d1141a3b | |||
| e8b2c92240 | |||
| 7151010919 | |||
| 1f2faa647f | |||
| c9c1b65698 | |||
| dac22f6566 | |||
| ed94e0e677 | |||
| cacef23082 | |||
| d5838eaa42 | |||
| 54fd01c4ab | |||
| dcf757c2ea | |||
| 33669ef289 | |||
| 54e35b543d | |||
| 5ec9ed7fe9 | |||
| 6a8336987a | |||
| d4c735d491 | |||
| 51fb37db61 | |||
| fabae7a134 | |||
| 3c58039e9e | |||
| add19478c1 | |||
| 58b4a8f6e7 | |||
| 43eafb7b76 | |||
| 08f1ba0767 | |||
| c707b2eb6d | |||
| 0992764c7a | |||
| bcd6d5d393 | |||
| c94e4a7b2f | |||
| 74194f14ec | |||
| 2b041fb97a | |||
| 2c77d51dfe | |||
| d0720eee5e | |||
| 2fb055366d | |||
| b7ceffdadf | |||
| 66b3ed318b | |||
| 878db7b099 | |||
| 7119a6c16b | |||
| 95f35b64da | |||
| 62d96919f6 | |||
| 2a9254cf2c | |||
| 9e59c06fb1 | |||
| 777c35dbe8 | |||
| 853520ddbf | |||
| 38b4158aba | |||
| 8f1f9ef09f | |||
| 8cd30e3f5b | |||
| f4382b2415 | |||
| 613c2ee21f | |||
| 18e2ace468 | |||
| 697c3fb25b | |||
| 63558eae54 | |||
| 6ba175f0c8 | |||
| a55901a27c | |||
| 0be2dd9a1b | |||
| 29057f3d18 | |||
| 57b32ef924 | |||
| d2917d9f69 | |||
| 88c43ce1f6 | |||
| 3c90b86372 | |||
| 4e34558f1b | |||
| 118ac6a7ad | |||
| 7d24e6b080 | |||
| 405ae974ee | |||
| 415acd09d7 | |||
| 6ed21e8fd7 | |||
| 69cce89425 | |||
| 1d9db01065 | |||
| 253695caf3 | |||
| d69b4249ff | |||
| 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 | |||
| 0218424e5a | |||
| 8550e4a9f8 | |||
| 99f50dd219 | |||
| 6e8b3d3caa | |||
| 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 | |||
| de30fb5fc2 | |||
| fd486258a0 | |||
| 940cdc94f3 | |||
| 23a16c8387 | |||
| e6e49bfef2 | |||
| 06638117bb | |||
| 22cd1eec5a | |||
| 7c6f2880aa | |||
| 70989b6f59 | |||
| ef7c692baf | |||
| da52f11250 | |||
| 7a29505e57 | |||
| 8ade1d2f97 | |||
| 57a0af406e | |||
| d35a69a8da | |||
| e7840ce681 | |||
| 520d1a8486 | |||
| cc65612e35 |
+34
-8
@@ -661,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
|
||||
@@ -689,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)
|
||||
@@ -1168,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 \
|
||||
@@ -1186,9 +1203,13 @@ SHELL_DEP = \
|
||||
$(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 \
|
||||
@@ -1566,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)
|
||||
@@ -1626,8 +1652,8 @@ tidy:
|
||||
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)
|
||||
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)
|
||||
|
||||
+26
-7
@@ -938,7 +938,7 @@ TCLSUFFIX =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLDIR
|
||||
TCLDIR = $(TOP)\compat\tcl
|
||||
TCLDIR = C:\Tcl
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLINCDIR
|
||||
@@ -1861,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)
|
||||
|
||||
@@ -1894,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)
|
||||
|
||||
@@ -2299,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 \
|
||||
@@ -2317,9 +2332,13 @@ SHELL_DEP = \
|
||||
$(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 \
|
||||
@@ -2605,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)
|
||||
@@ -2760,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 devtest ;# 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,12 @@ 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,
|
||||
@@ -143,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
|
||||
@@ -157,15 +165,21 @@ 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 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 tclextension-install
|
||||
nmake /f Makefile.msc sqlite3_analyzer.exe
|
||||
|
||||
There are many other makefile targets. See comments in Makefile.msc for
|
||||
details.
|
||||
@@ -372,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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -655,6 +655,10 @@ cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
|
||||
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;
|
||||
@@ -665,7 +669,10 @@ cfGets(char *cBuf, int n, FILE *pf){
|
||||
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( 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+12
-13
@@ -224,6 +224,7 @@ struct Fts5Config {
|
||||
int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
|
||||
int eContent; /* An FTS5_CONTENT value */
|
||||
int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */
|
||||
int bContentlessUnindexed; /* "contentless_unindexed=" option (dflt=0) */
|
||||
char *zContent; /* content table */
|
||||
char *zContentRowid; /* "content_rowid=" option value */
|
||||
int bColumnsize; /* "columnsize=" option value (dflt==1) */
|
||||
@@ -262,9 +263,10 @@ struct Fts5Config {
|
||||
#define FTS5_CURRENT_VERSION 4
|
||||
#define FTS5_CURRENT_VERSION_SECUREDELETE 5
|
||||
|
||||
#define FTS5_CONTENT_NORMAL 0
|
||||
#define FTS5_CONTENT_NONE 1
|
||||
#define FTS5_CONTENT_EXTERNAL 2
|
||||
#define FTS5_CONTENT_NORMAL 0
|
||||
#define FTS5_CONTENT_NONE 1
|
||||
#define FTS5_CONTENT_EXTERNAL 2
|
||||
#define FTS5_CONTENT_UNINDEXED 3
|
||||
|
||||
#define FTS5_DETAIL_FULL 0
|
||||
#define FTS5_DETAIL_NONE 1
|
||||
@@ -636,16 +638,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.
|
||||
@@ -727,7 +726,7 @@ int sqlite3Fts5DropAll(Fts5Config*);
|
||||
int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
|
||||
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int);
|
||||
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
|
||||
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, int, sqlite3_value**, i64*);
|
||||
int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
|
||||
|
||||
int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
|
||||
|
||||
+50
-5
@@ -241,6 +241,7 @@ static int fts5ConfigParseSpecial(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nCmd = (int)strlen(zCmd);
|
||||
|
||||
if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
|
||||
const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
|
||||
const char *p;
|
||||
@@ -360,6 +361,16 @@ static int fts5ConfigParseSpecial(
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("contentless_unindexed", zCmd, nCmd)==0 ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
|
||||
*pzErr = sqlite3_mprintf("malformed contentless_delete=... directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pConfig->bContentlessUnindexed = (zArg[0]=='1');
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){
|
||||
if( pConfig->zContentRowid ){
|
||||
*pzErr = sqlite3_mprintf("multiple content_rowid=... directives");
|
||||
@@ -477,7 +488,8 @@ static int fts5ConfigParseColumn(
|
||||
Fts5Config *p,
|
||||
char *zCol,
|
||||
char *zArg,
|
||||
char **pzErr
|
||||
char **pzErr,
|
||||
int *pbUnindexed
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME)
|
||||
@@ -488,6 +500,7 @@ static int fts5ConfigParseColumn(
|
||||
}else if( zArg ){
|
||||
if( 0==sqlite3_stricmp(zArg, "unindexed") ){
|
||||
p->abUnindexed[p->nCol] = 1;
|
||||
*pbUnindexed = 1;
|
||||
}else{
|
||||
*pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -508,11 +521,26 @@ static int fts5ConfigMakeExprlist(Fts5Config *p){
|
||||
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid);
|
||||
if( p->eContent!=FTS5_CONTENT_NONE ){
|
||||
assert( p->eContent==FTS5_CONTENT_EXTERNAL
|
||||
|| p->eContent==FTS5_CONTENT_NORMAL
|
||||
|| p->eContent==FTS5_CONTENT_UNINDEXED
|
||||
);
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( p->eContent==FTS5_CONTENT_EXTERNAL ){
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
|
||||
}else{
|
||||
}else if( p->eContent==FTS5_CONTENT_NORMAL || p->abUnindexed[i] ){
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
|
||||
}else{
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,6 +574,7 @@ int sqlite3Fts5ConfigParse(
|
||||
Fts5Config *pRet; /* New object to return */
|
||||
int i;
|
||||
sqlite3_int64 nByte;
|
||||
int bUnindexed = 0; /* True if there are one or more UNINDEXED */
|
||||
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
@@ -605,7 +634,7 @@ int sqlite3Fts5ConfigParse(
|
||||
pzErr
|
||||
);
|
||||
}else{
|
||||
rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
|
||||
rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr, &bUnindexed);
|
||||
zOne = 0;
|
||||
}
|
||||
}
|
||||
@@ -637,14 +666,30 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* We only allow contentless_unindexed=1 if the table is actually a
|
||||
** contentless one.
|
||||
*/
|
||||
if( rc==SQLITE_OK
|
||||
&& pRet->bContentlessUnindexed
|
||||
&& pRet->eContent!=FTS5_CONTENT_NONE
|
||||
){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
"contentless_unindexed=1 requires a contentless table"
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
const char *zTail = 0;
|
||||
assert( pRet->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pRet->eContent==FTS5_CONTENT_NONE
|
||||
assert( pRet->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pRet->eContent==FTS5_CONTENT_NONE
|
||||
);
|
||||
if( pRet->eContent==FTS5_CONTENT_NORMAL ){
|
||||
zTail = "content";
|
||||
}else if( bUnindexed && pRet->bContentlessUnindexed ){
|
||||
pRet->eContent = FTS5_CONTENT_UNINDEXED;
|
||||
zTail = "content";
|
||||
}else if( pRet->bColumnsize ){
|
||||
zTail = "docsize";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -4889,6 +4889,11 @@ static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){
|
||||
nBest = nPercent;
|
||||
}
|
||||
}
|
||||
|
||||
/* If pLvl is already the input level to an ongoing merge, look no
|
||||
** further for a merge candidate. The caller should be allowed to
|
||||
** continue merging from pLvl first. */
|
||||
if( pLvl->nMerge ) break;
|
||||
}
|
||||
}
|
||||
return iRet;
|
||||
@@ -8813,7 +8818,7 @@ static int fts5structConnectMethod(
|
||||
|
||||
/*
|
||||
** We must have a single struct=? constraint that will be passed through
|
||||
** into the xFilter method. If there is no valid stmt=? constraint,
|
||||
** into the xFilter method. If there is no valid struct=? constraint,
|
||||
** then return an SQLITE_CONSTRAINT error.
|
||||
*/
|
||||
static int fts5structBestIndexMethod(
|
||||
|
||||
+295
-295
@@ -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.
|
||||
@@ -329,10 +332,16 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return true if pTab is a contentless table.
|
||||
** Return true if pTab is a contentless table. If parameter bIncludeUnindexed
|
||||
** is true, this includes contentless tables that store UNINDEXED columns
|
||||
** only.
|
||||
*/
|
||||
static int fts5IsContentless(Fts5FullTable *pTab){
|
||||
return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
|
||||
static int fts5IsContentless(Fts5FullTable *pTab, int bIncludeUnindexed){
|
||||
int eContent = pTab->p.pConfig->eContent;
|
||||
return (
|
||||
eContent==FTS5_CONTENT_NONE
|
||||
|| (bIncludeUnindexed && eContent==FTS5_CONTENT_UNINDEXED)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1256,7 +1265,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
|
||||
@@ -1267,127 +1276,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1396,8 +1352,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
|
||||
@@ -1409,24 +1365,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;
|
||||
@@ -1778,7 +1732,7 @@ static int fts5SpecialInsert(
|
||||
}
|
||||
bLoadConfig = 1;
|
||||
}else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NONE ){
|
||||
if( fts5IsContentless(pTab, 1) ){
|
||||
fts5SetVtabError(pTab,
|
||||
"'rebuild' may not be used with a contentless fts5 table"
|
||||
);
|
||||
@@ -1847,7 +1801,7 @@ static void fts5StorageInsert(
|
||||
){
|
||||
int rc = *pRc;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
|
||||
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, 0, apVal, piRowid);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
|
||||
@@ -1855,6 +1809,67 @@ static void fts5StorageInsert(
|
||||
*pRc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** This function is called when the user attempts an UPDATE on a contentless
|
||||
** table. Parameter bRowidModified is true if the UPDATE statement modifies
|
||||
** the rowid value. Parameter apVal[] contains the new values for each user
|
||||
** defined column of the fts5 table. pConfig is the configuration object of the
|
||||
** table being updated (guaranteed to be contentless). The contentless_delete=1
|
||||
** and contentless_unindexed=1 options may or may not be set.
|
||||
**
|
||||
** This function returns SQLITE_OK if the UPDATE can go ahead, or an SQLite
|
||||
** error code if it cannot. In this case an error message is also loaded into
|
||||
** pConfig. Output parameter (*pbContent) is set to true if the caller should
|
||||
** update the %_content table only - not the FTS index or any other shadow
|
||||
** table. This occurs when an UPDATE modifies only UNINDEXED columns of the
|
||||
** table.
|
||||
**
|
||||
** An UPDATE may proceed if:
|
||||
**
|
||||
** * The only columns modified are UNINDEXED columns, or
|
||||
**
|
||||
** * The contentless_delete=1 option was specified and all of the indexed
|
||||
** columns (not a subset) have been modified.
|
||||
*/
|
||||
static int fts5ContentlessUpdate(
|
||||
Fts5Config *pConfig,
|
||||
sqlite3_value **apVal,
|
||||
int bRowidModified,
|
||||
int *pbContent
|
||||
){
|
||||
int ii;
|
||||
int bSeenIndex = 0; /* Have seen modified indexed column */
|
||||
int bSeenIndexNC = 0; /* Have seen unmodified indexed column */
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
for(ii=0; ii<pConfig->nCol; ii++){
|
||||
if( pConfig->abUnindexed[ii]==0 ){
|
||||
if( sqlite3_value_nochange(apVal[ii]) ){
|
||||
bSeenIndexNC++;
|
||||
}else{
|
||||
bSeenIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( bSeenIndex==0 && bRowidModified==0 ){
|
||||
*pbContent = 1;
|
||||
}else{
|
||||
if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3Fts5ConfigErrmsg(pConfig,
|
||||
(pConfig->bContentlessDelete ?
|
||||
"%s a subset of columns on fts5 contentless-delete table: %s" :
|
||||
"%s contentless fts5 table: %s")
|
||||
, "cannot UPDATE", pConfig->zName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is the implementation of the xUpdate callback used by
|
||||
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
|
||||
@@ -1941,44 +1956,34 @@ static int fts5UpdateMethod(
|
||||
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
|
||||
assert( nArg!=1 || eType0==SQLITE_INTEGER );
|
||||
|
||||
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
|
||||
** This is not suported. Except - they are both supported if the CREATE
|
||||
** VIRTUAL TABLE statement contained "contentless_delete=1". */
|
||||
if( eType0==SQLITE_INTEGER
|
||||
&& pConfig->eContent==FTS5_CONTENT_NONE
|
||||
&& pConfig->bContentlessDelete==0
|
||||
){
|
||||
pTab->p.base.zErrMsg = sqlite3_mprintf(
|
||||
"cannot %s contentless fts5 table: %s",
|
||||
(nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* DELETE */
|
||||
else if( nArg==1 ){
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
if( nArg==1 ){
|
||||
/* It is only possible to DELETE from a contentless table if the
|
||||
** contentless_delete=1 flag is set. */
|
||||
if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){
|
||||
fts5SetVtabError(pTab,
|
||||
"cannot DELETE from contentless fts5 table: %s", pConfig->zName
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* INSERT or UPDATE */
|
||||
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;
|
||||
}
|
||||
@@ -1998,35 +2003,55 @@ static int fts5UpdateMethod(
|
||||
|
||||
/* UPDATE */
|
||||
else{
|
||||
Fts5Storage *pStorage = pTab->pStorage;
|
||||
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
|
||||
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
|
||||
int bContent = 0; /* Content only update */
|
||||
|
||||
/* If this is a contentless table (including contentless_unindexed=1
|
||||
** tables), check if the UPDATE may proceed. */
|
||||
if( fts5IsContentless(pTab, 1) ){
|
||||
rc = fts5ContentlessUpdate(pConfig, &apVal[2], iOld!=iNew, &bContent);
|
||||
if( rc!=SQLITE_OK ) goto update_out;
|
||||
}
|
||||
|
||||
if( eType1!=SQLITE_INTEGER ){
|
||||
rc = SQLITE_MISMATCH;
|
||||
}else if( iOld!=iNew ){
|
||||
assert( bContent==0 );
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1);
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iNew, 0, 0);
|
||||
}
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageFindDeleteRow(pTab->pStorage, iOld);
|
||||
rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage,apVal,pRowid);
|
||||
rc = sqlite3Fts5StorageContentInsert(pStorage, 0, apVal, pRowid);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1);
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
|
||||
rc = sqlite3Fts5StorageIndexInsert(pStorage, apVal, *pRowid);
|
||||
}
|
||||
}
|
||||
}else if( bContent ){
|
||||
/* This occurs when an UPDATE on a contentless table affects *only*
|
||||
** UNINDEXED columns. This is a no-op for contentless_unindexed=0
|
||||
** tables, or a write to the %_content table only for =1 tables. */
|
||||
assert( fts5IsContentless(pTab, 1) );
|
||||
rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid);
|
||||
}
|
||||
}else{
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0, 1);
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
bUpdateOrDelete = 1;
|
||||
sqlite3Fts5StorageReleaseDeleteRow(pTab->pStorage);
|
||||
sqlite3Fts5StorageReleaseDeleteRow(pStorage);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2139,11 +2164,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;
|
||||
}
|
||||
@@ -2171,6 +2196,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,
|
||||
@@ -2184,16 +2252,14 @@ static int fts5ApiColumnText(
|
||||
assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
|
||||
if( iCol<0 || iCol>=pTab->pConfig->nCol ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) ){
|
||||
}else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){
|
||||
*pz = 0;
|
||||
*pn = 0;
|
||||
}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;
|
||||
@@ -2219,7 +2285,7 @@ static int fts5CsrPoslist(
|
||||
if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else if( pConfig->eDetail!=FTS5_DETAIL_FULL
|
||||
&& pConfig->eContent==FTS5_CONTENT_NONE
|
||||
&& fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
|
||||
){
|
||||
*pa = 0;
|
||||
*pn = 0;
|
||||
@@ -2235,17 +2301,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);
|
||||
|
||||
@@ -2417,7 +2481,7 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
|
||||
if( pConfig->bColumnsize ){
|
||||
i64 iRowid = fts5CursorRowid(pCsr);
|
||||
rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
|
||||
}else if( pConfig->zContent==0 ){
|
||||
}else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
|
||||
int i;
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
@@ -2431,17 +2495,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2708,42 +2769,19 @@ static int fts5ApiColumnLocale(
|
||||
rc = SQLITE_RANGE;
|
||||
}else if(
|
||||
pConfig->abUnindexed[iCol]==0
|
||||
&& pConfig->eContent!=FTS5_CONTENT_NONE
|
||||
&& 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
|
||||
&& pConfig->bLocale
|
||||
){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2964,57 +3002,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.
|
||||
@@ -3057,22 +3044,27 @@ static int fts5ColumnMethod(
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* A column created by the user containing values. */
|
||||
int bNochange = sqlite3_vtab_nochange(pCtx);
|
||||
|
||||
if( fts5IsContentless(pTab) ){
|
||||
if( bNochange && pConfig->bContentlessDelete ){
|
||||
fts5ResultError(pCtx, "cannot UPDATE a subset of "
|
||||
"columns on fts5 contentless-delete table: %s", pConfig->zName
|
||||
);
|
||||
}
|
||||
}else if( bNochange==0 || pConfig->eContent!=FTS5_CONTENT_NORMAL ){
|
||||
if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){
|
||||
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -3634,13 +3626,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);
|
||||
@@ -3648,8 +3639,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;
|
||||
@@ -3657,7 +3648,6 @@ static void fts5LocaleFunc(
|
||||
assert( &pCsr[nText]==&pBlob[nBlob] );
|
||||
|
||||
sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
|
||||
sqlite3_result_subtype(pCtx, FTS5_LOCALE_SUBTYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3759,6 +3749,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);
|
||||
|
||||
+211
-82
@@ -143,20 +143,35 @@ static int fts5StorageGetStmt(
|
||||
|
||||
case FTS5_STMT_INSERT_CONTENT:
|
||||
case FTS5_STMT_REPLACE_CONTENT: {
|
||||
int nCol = pC->nCol + 1;
|
||||
char *zBind;
|
||||
char *zBind = 0;
|
||||
int i;
|
||||
|
||||
zBind = sqlite3_malloc64(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
zBind[i*2 + 1] = ',';
|
||||
assert( pC->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pC->eContent==FTS5_CONTENT_UNINDEXED
|
||||
);
|
||||
|
||||
/* Add bindings for the "c*" columns - those that store the actual
|
||||
** table content. If eContent==NORMAL, then there is one binding
|
||||
** for each column. Or, if eContent==UNINDEXED, then there are only
|
||||
** bindings for the UNINDEXED columns. */
|
||||
for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){
|
||||
if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){
|
||||
zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1);
|
||||
}
|
||||
zBind[i*2-1] = '\0';
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
|
||||
sqlite3_free(zBind);
|
||||
}
|
||||
|
||||
/* Add bindings for any "l*" columns. Only non-UNINDEXED columns
|
||||
** require these. */
|
||||
if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){
|
||||
for(i=0; rc==SQLITE_OK && i<pC->nCol; i++){
|
||||
if( pC->abUnindexed[i]==0 ){
|
||||
zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind);
|
||||
sqlite3_free(zBind);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -342,9 +357,11 @@ int sqlite3Fts5StorageOpen(
|
||||
p->pIndex = pIndex;
|
||||
|
||||
if( bCreate ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
|
||||
){
|
||||
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{
|
||||
@@ -353,8 +370,20 @@ int sqlite3Fts5StorageOpen(
|
||||
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
|
||||
iOff = (int)strlen(zDefn);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pConfig->abUnindexed[i]
|
||||
){
|
||||
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);
|
||||
}
|
||||
@@ -507,7 +536,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 +547,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 +568,7 @@ static int fts5StorageDeleteFromIndex(
|
||||
if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
if( bReset ) sqlite3Fts5ClearLocale(pConfig);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -574,7 +613,9 @@ static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( p->pConfig->bContentlessDelete );
|
||||
assert( p->pConfig->eContent==FTS5_CONTENT_NONE );
|
||||
assert( p->pConfig->eContent==FTS5_CONTENT_NONE
|
||||
|| p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
|
||||
);
|
||||
|
||||
/* Look up the origin of the document in the %_docsize table. Store
|
||||
** this in stack variable iOrigin. */
|
||||
@@ -698,6 +739,12 @@ int sqlite3Fts5StorageDelete(
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p->pConfig->bContentlessDelete ){
|
||||
rc = fts5StorageContentlessDelete(p, iDel);
|
||||
if( rc==SQLITE_OK
|
||||
&& bSaveRow
|
||||
&& p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
|
||||
){
|
||||
rc = sqlite3Fts5StorageFindDeleteRow(p, iDel);
|
||||
}
|
||||
}else{
|
||||
rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow);
|
||||
}
|
||||
@@ -714,7 +761,9 @@ int sqlite3Fts5StorageDelete(
|
||||
}
|
||||
|
||||
/* Delete the %_content record */
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
|
||||
){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
|
||||
}
|
||||
@@ -746,8 +795,13 @@ int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
|
||||
);
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DELETE FROM %Q.'%q_docsize';",
|
||||
pConfig->zDb, pConfig->zName
|
||||
"DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName
|
||||
);
|
||||
}
|
||||
|
||||
@@ -788,20 +842,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);
|
||||
@@ -868,6 +937,7 @@ static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
|
||||
*/
|
||||
int sqlite3Fts5StorageContentInsert(
|
||||
Fts5Storage *p,
|
||||
int bReplace, /* True to use REPLACE instead of INSERT */
|
||||
sqlite3_value **apVal,
|
||||
i64 *piRowid
|
||||
){
|
||||
@@ -875,7 +945,9 @@ int sqlite3Fts5StorageContentInsert(
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* Insert the new row into the %_content table. */
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL
|
||||
&& pConfig->eContent!=FTS5_CONTENT_UNINDEXED
|
||||
){
|
||||
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
|
||||
*piRowid = sqlite3_value_int64(apVal[1]);
|
||||
}else{
|
||||
@@ -884,33 +956,52 @@ int sqlite3Fts5StorageContentInsert(
|
||||
}else{
|
||||
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
|
||||
int i; /* Counter variable */
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
sqlite3_value *pVal = apVal[i];
|
||||
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);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = sqlite3_bind_value(pInsert, i, pVal);
|
||||
assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT );
|
||||
assert( bReplace==0 || bReplace==1 );
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0);
|
||||
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];
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){
|
||||
sqlite3_value *pVal = apVal[i];
|
||||
|
||||
if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
|
||||
/* This is an UPDATE statement, and user-defined column (i-2) was not
|
||||
** modified. Retrieve the value from Fts5Storage.pSavedRow. */
|
||||
pVal = sqlite3_column_value(p->pSavedRow, i-1);
|
||||
if( pConfig->bLocale && bUnindexed==0 ){
|
||||
sqlite3_bind_value(pInsert, pConfig->nCol + i,
|
||||
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 + i;
|
||||
sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = sqlite3_bind_value(pInsert, i, pVal);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
@@ -945,23 +1036,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 +1231,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);
|
||||
|
||||
@@ -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 {}}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
@@ -35,8 +35,8 @@ do_execsql_test 1.01 {
|
||||
}
|
||||
|
||||
# explain_i "UPDATE t1 SET a='a' WHERE t1.rowid=1"
|
||||
breakpoint
|
||||
explain_i "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1 AND b IS NULL"
|
||||
#breakpoint
|
||||
#explain_i "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1 AND b IS NULL"
|
||||
|
||||
#breakpoint
|
||||
#explain_i "UPDATE t1 SET a='a' WHERE b IS NULL AND rowid=?"
|
||||
@@ -56,4 +56,56 @@ foreach {tn up err} {
|
||||
do_catchsql_test 1.$tn $up $res($err)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
proc random {n} { expr {abs(int(rand()*$n))} }
|
||||
proc select_one {list} {
|
||||
set n [llength $list]
|
||||
lindex $list [random $n]
|
||||
}
|
||||
proc vocab {} {
|
||||
list abc def ghi jkl mno pqr stu vwx yza
|
||||
}
|
||||
proc term {} {
|
||||
select_one [vocab]
|
||||
}
|
||||
proc document {} {
|
||||
set nTerm [expr [random 3] + 7]
|
||||
set doc ""
|
||||
for {set ii 0} {$ii < $nTerm} {incr ii} {
|
||||
lappend doc [term]
|
||||
}
|
||||
set doc
|
||||
}
|
||||
db func document document
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, contentless_delete=1, content='');
|
||||
INSERT INTO ft(ft, rank) VALUES('pgsz', 64);
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
for {set ii 1} {$ii < 12} {incr ii} {
|
||||
db transaction {
|
||||
for {set jj 0} {$jj < 10} {incr jj} {
|
||||
set doc [document]
|
||||
execsql { INSERT INTO ft VALUES($doc); }
|
||||
}
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 2.2 {
|
||||
foreach r [db eval {SELECT rowid FROM ft}] {
|
||||
execsql { DELETE FROM ft WHERE rowid=$r }
|
||||
}
|
||||
} {}
|
||||
|
||||
set doc [document]
|
||||
do_execsql_test 2.3 {
|
||||
INSERT INTO ft VALUES($doc)
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -113,5 +113,58 @@ do_execsql_test 3.4 {
|
||||
INSERT INTO tx(tx) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(a, b UNINDEXED,
|
||||
content='', contentless_unindexed=1
|
||||
);
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(a, b UNINDEXED,
|
||||
content='', contentless_unindexed=1, contentless_delete=1
|
||||
);
|
||||
|
||||
INSERT INTO ft1(rowid, a, b) VALUES(1, 'one', 'i');
|
||||
INSERT INTO ft1(rowid, a, b) VALUES(2, 'two', 'ii');
|
||||
INSERT INTO ft1(rowid, a, b) VALUES(3, 'three', 'iii');
|
||||
INSERT INTO ft2(rowid, a, b) VALUES(1, 'one', 'i');
|
||||
INSERT INTO ft2(rowid, a, b) VALUES(2, 'two', 'ii');
|
||||
INSERT INTO ft2(rowid, a, b) VALUES(3, 'three', 'iii');
|
||||
}
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
DELETE FROM ft1 WHERE rowid=2
|
||||
} {1 {cannot DELETE from contentless fts5 table: ft1}}
|
||||
do_catchsql_test 4.2 {
|
||||
DELETE FROM ft2 WHERE rowid=2
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 4.3 {
|
||||
INSERT INTO ft1(ft1, rowid, a) VALUES('delete', 2, 'two');
|
||||
} {0 {}}
|
||||
do_catchsql_test 4.2 {
|
||||
INSERT INTO ft2(ft2, rowid, a) VALUES('delete', 2, 'two');
|
||||
} {1 {'delete' may not be used with a contentless_delete=1 table}}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
SELECT rowid, * FROM ft1;
|
||||
} {
|
||||
1 {} i
|
||||
3 {} iii
|
||||
}
|
||||
do_execsql_test 4.4 {
|
||||
SELECT rowid, * FROM ft2;
|
||||
} {
|
||||
1 {} i
|
||||
3 {} iii
|
||||
}
|
||||
|
||||
do_execsql_test 4.5 {
|
||||
SELECT * FROM ft1_content
|
||||
} {1 i 3 iii}
|
||||
|
||||
do_execsql_test 4.6 {
|
||||
SELECT * FROM ft2_content
|
||||
} {1 i 3 iii}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -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,18 @@ 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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
# 2024 Sep 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The tests in this file focus on "unindexed" columns in contentless
|
||||
# tables.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5unindexed2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(
|
||||
a, b UNINDEXED, content=, contentless_unindexed=1
|
||||
);
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
INSERT INTO t1 VALUES('abc def', 'ghi jkl');
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT rowid, a, b FROM t1
|
||||
} {1 {} {ghi jkl}}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
INSERT INTO t1(rowid, a, b) VALUES(11, 'hello world', 'one two three');
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
INSERT INTO t1(t1, rowid, a, b) VALUES('delete', 1, 'abc def', 'ghi jkl');
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT rowid, a, b FROM t1
|
||||
} {
|
||||
11 {} {one two three}
|
||||
}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 1.8 {
|
||||
INSERT INTO t1(rowid, a, b) VALUES(12, 'abc def', 'ghi jkl');
|
||||
}
|
||||
|
||||
do_execsql_test 1.9 {
|
||||
SELECT rowid, a, b FROM t1('def')
|
||||
} {12 {} {ghi jkl}}
|
||||
|
||||
do_execsql_test 1.10 {
|
||||
SELECT rowid, a, b FROM t1('def OR hello') ORDER BY rank
|
||||
} {11 {} {one two three} 12 {} {ghi jkl}}
|
||||
|
||||
do_execsql_test 1.11 {
|
||||
SELECT rowid, a, b FROM t1 WHERE rowid=11
|
||||
} {11 {} {one two three}}
|
||||
|
||||
do_execsql_test 1.12 {
|
||||
SELECT rowid, a, b FROM t1
|
||||
} {11 {} {one two three} 12 {} {ghi jkl}}
|
||||
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 1.12.2 {
|
||||
SELECT rowid, fts5_test_columntext(t1) FROM t1('def OR hello')
|
||||
} {11 {{} {one two three}} 12 {{} {ghi jkl}}}
|
||||
|
||||
do_execsql_test 1.13 {
|
||||
INSERT INTO t1(t1) VALUES('delete-all');
|
||||
}
|
||||
|
||||
do_execsql_test 1.14 {
|
||||
SELECT rowid, a, b FROM t1
|
||||
}
|
||||
|
||||
do_execsql_test 1.15 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5(
|
||||
x, y UNINDEXED, z, columnsize=0, content='', contentless_unindexed=1
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO t4(rowid, x, y, z) VALUES(1, 'a a', 'b b b', 'c');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(
|
||||
a UNINDEXED, b, c UNINDEXED, d, content=, contentless_delete=1,
|
||||
contentless_unindexed=1
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
INSERT INTO x1(rowid, a, b, c, d) VALUES(131, 'aaa', 'bbb', 'ccc', 'ddd');
|
||||
}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM x1
|
||||
} {aaa {} ccc {}}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
INSERT INTO x1(rowid, a, b, c, d) VALUES(1000, 'AAA', 'BBB', 'CCC', 'DDD');
|
||||
}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT rowid, * FROM x1
|
||||
} {
|
||||
131 aaa {} ccc {}
|
||||
1000 AAA {} CCC {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.5 {
|
||||
DELETE FROM x1 WHERE rowid=131;
|
||||
SELECT rowid, * FROM x1
|
||||
} {
|
||||
1000 AAA {} CCC {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.6 {
|
||||
INSERT INTO x1(rowid, a, b, c, d) VALUES(112, 'aaa', 'bbb', 'ccc', 'ddd');
|
||||
SELECT rowid, * FROM x1
|
||||
} {
|
||||
112 aaa {} ccc {}
|
||||
1000 AAA {} CCC {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.7 {
|
||||
UPDATE x1 SET b='hello', d='world', rowid=1120 WHERE rowid=112
|
||||
}
|
||||
|
||||
do_execsql_test 3.8 {
|
||||
SELECT rowid, * FROM x1
|
||||
} {
|
||||
1000 AAA {} CCC {}
|
||||
1120 aaa {} ccc {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.9 {
|
||||
SELECT rowid, * FROM x1('hello');
|
||||
} {
|
||||
1120 aaa {} ccc {}
|
||||
}
|
||||
|
||||
do_execsql_test 3.9 {
|
||||
SELECT rowid, * FROM x1('bbb');
|
||||
} {
|
||||
1000 AAA {} CCC {}
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 3.10 {
|
||||
SELECT rowid, fts5_test_columntext(x1) FROM x1('b*')
|
||||
} {1000 {AAA {} CCC {}}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that if contentless_unindexed=1 is not specified, the values
|
||||
# of UNINDEXED columns are not stored in the database.
|
||||
#
|
||||
# Also check that contentless_unindexed=1 is not allowed unless the table
|
||||
# is actually contentless.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, c UNINDEXED, content='');
|
||||
INSERT INTO ft VALUES('one', 'two', 'three');
|
||||
SELECT rowid, * FROM ft;
|
||||
} {1 {} {} {}}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
SELECT name FROM sqlite_schema ORDER BY 1
|
||||
} {
|
||||
ft ft_config ft_data ft_docsize ft_idx
|
||||
}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(
|
||||
a, b, c UNINDEXED, contentless_unindexed=1
|
||||
);
|
||||
} {1 {contentless_unindexed=1 requires a contentless table}}
|
||||
|
||||
do_catchsql_test 4.3 {
|
||||
DELETE FROM ft WHERE rowid=1
|
||||
} {1 {cannot DELETE from contentless fts5 table: ft}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the usual restrictions on contentless tables apply to
|
||||
# contentless_unindexed=1 tables.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
a, b UNINDEXED, c, content='', contentless_unindexed=1
|
||||
);
|
||||
INSERT INTO ft VALUES('one', 'two', 'three');
|
||||
INSERT INTO ft VALUES('four', 'five', 'six');
|
||||
INSERT INTO ft VALUES('seven', 'eight', 'nine');
|
||||
SELECT rowid, * FROM ft;
|
||||
} {
|
||||
1 {} two {}
|
||||
2 {} five {}
|
||||
3 {} eight {}
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
do_catchsql_test 5.2 {
|
||||
DELETE FROM ft WHERE rowid=2
|
||||
} {1 {cannot DELETE from contentless fts5 table: ft}}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
SELECT rowid, * FROM ft('six')
|
||||
} {
|
||||
2 {} five {}
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
UPDATE ft SET a='x', b='y', c='z' WHERE rowid=3
|
||||
} {1 {cannot UPDATE contentless fts5 table: ft}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 5.5 {
|
||||
SELECT fts5_test_columntext(ft) FROM ft WHERE rowid=3
|
||||
} {
|
||||
{{} eight {}}
|
||||
}
|
||||
do_execsql_test 5.6 {
|
||||
SELECT fts5_test_columntext(ft) FROM ft('three');
|
||||
} {
|
||||
{{} two {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that it is possible to UPDATE a contentless_unindexed=1 table
|
||||
# if the only columns being modified are UNINDEXED.
|
||||
#
|
||||
# If the contentless_unindexed=1 table is also contentless_delete=1, then
|
||||
# it is also possible to update indexed columns - but only if *all* indexed
|
||||
# columns are updated.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(a, b UNINDEXED, c UNINDEXED, d,
|
||||
contentless_unindexed=1, content=''
|
||||
);
|
||||
|
||||
INSERT INTO ft1(rowid, a, b, c, d) VALUES
|
||||
(100, 'x y', 'b1', 'c1', 'a b'),
|
||||
(200, 'c d', 'b2', 'c2', 'a b'),
|
||||
(300, 'e f', 'b3', 'c3', 'a b');
|
||||
}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
UPDATE ft1 SET b='b1.1', c='c1.1' WHERE rowid=100;
|
||||
}
|
||||
do_execsql_test 6.2 {
|
||||
UPDATE ft1 SET b='b2.1' WHERE rowid=200;
|
||||
}
|
||||
do_execsql_test 6.3 {
|
||||
UPDATE ft1 SET c='c3.1' WHERE rowid=300;
|
||||
}
|
||||
|
||||
do_execsql_test 6.4 {
|
||||
SELECT rowid, a, b, c, d FROM ft1
|
||||
} {
|
||||
100 {} b1.1 c1.1 {}
|
||||
200 {} b2.1 c2 {}
|
||||
300 {} b3 c3.1 {}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
# 2024 Sep 27
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5update2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the various types of UPDATE statement are handled correctly
|
||||
# by different table types.
|
||||
#
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach {tn cu} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
reset_db
|
||||
do_execsql_test 1.$tn.1 "
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(a, b UNINDEXED, c UNINDEXED, d,
|
||||
content='',
|
||||
contentless_unindexed=$cu,
|
||||
detail=%DETAIL%
|
||||
);
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(a, b UNINDEXED, c UNINDEXED, d,
|
||||
content='',
|
||||
contentless_unindexed=$cu, contentless_delete=1,
|
||||
detail=%DETAIL%
|
||||
);
|
||||
"
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
INSERT INTO ft1(rowid, a, b, c, d) VALUES(1, 'a1', 'b1', 'c1', 'd1');
|
||||
INSERT INTO ft1(rowid, a, b, c, d) VALUES(2, 'a2', 'b2', 'c2', 'd2');
|
||||
INSERT INTO ft1(rowid, a, b, c, d) VALUES(3, 'a3', 'b3', 'c3', 'd3');
|
||||
|
||||
INSERT INTO ft2(rowid, a, b, c, d) VALUES(1, 'a1', 'b1', 'c1', 'd1');
|
||||
INSERT INTO ft2(rowid, a, b, c, d) VALUES(2, 'a2', 'b2', 'c2', 'd2');
|
||||
INSERT INTO ft2(rowid, a, b, c, d) VALUES(3, 'a3', 'b3', 'c3', 'd3');
|
||||
}
|
||||
|
||||
# It should be possible to update a subset of the UNINDEXED columns of
|
||||
# a contentless table. Regardless of whether or not contentless_unindexed=1
|
||||
# or contentless_delete=1 is set.
|
||||
do_execsql_test 1.$tn.3 {
|
||||
UPDATE ft1 SET b=b||'.1';
|
||||
UPDATE ft2 SET b=b||'.1';
|
||||
}
|
||||
do_execsql_test 1.$tn.4 {
|
||||
UPDATE ft1 SET b=b||'.2', c=c||'.2';
|
||||
UPDATE ft2 SET b=b||'.2', c=c||'.2';
|
||||
}
|
||||
|
||||
set res(0) {
|
||||
1 {} {} {} {}
|
||||
2 {} {} {} {}
|
||||
3 {} {} {} {}
|
||||
}
|
||||
set res(1) {
|
||||
1 {} b1.1.2 c1.2 {}
|
||||
2 {} b2.1.2 c2.2 {}
|
||||
3 {} b3.1.2 c3.2 {}
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.5 {
|
||||
SELECT rowid, * FROM ft2
|
||||
} $res($cu)
|
||||
|
||||
do_execsql_test 1.6.1 { SELECT rowid FROM ft1('a2') } {2}
|
||||
do_execsql_test 1.6.2 { SELECT rowid FROM ft2('a2') } {2}
|
||||
|
||||
# It should be possible to update all indexed columns (but no other subset)
|
||||
# if the contentless_delete=1 option is set, as it is for "ft2".
|
||||
do_execsql_test 1.$tn.7 {
|
||||
UPDATE ft2 SET a='a22', d='d22' WHERE rowid=2;
|
||||
}
|
||||
do_execsql_test 1.$tn.8 { SELECT rowid FROM ft2('a22 AND d22') } {2}
|
||||
|
||||
do_execsql_test 1.$tn.9 {
|
||||
UPDATE ft2 SET a='a33', d='d33', b='b3' WHERE rowid=3;
|
||||
}
|
||||
|
||||
set res(1) {
|
||||
1 {} b1.1.2 c1.2 {}
|
||||
2 {} b2.1.2 c2.2 {}
|
||||
3 {} b3 c3.2 {}
|
||||
}
|
||||
do_execsql_test 1.$tn.10 {
|
||||
SELECT rowid, * FROM ft2
|
||||
} $res($cu)
|
||||
|
||||
do_catchsql_test 1.$tn.11 {
|
||||
UPDATE ft2 SET a='a11' WHERE rowid=1
|
||||
} {1 {cannot UPDATE a subset of columns on fts5 contentless-delete table: ft2}}
|
||||
do_catchsql_test 1.$tn.12 {
|
||||
UPDATE ft2 SET d='d11' WHERE rowid=1
|
||||
} {1 {cannot UPDATE a subset of columns on fts5 contentless-delete table: ft2}}
|
||||
|
||||
# It is not possible to update the values of indexed columns if
|
||||
# contentless_delete=1 is not set.
|
||||
do_catchsql_test 1.$tn.13 {
|
||||
UPDATE ft1 SET a='a11' WHERE rowid=1
|
||||
} {1 {cannot UPDATE contentless fts5 table: ft1}}
|
||||
do_catchsql_test 1.$tn.14 {
|
||||
UPDATE ft1 SET d='d11' WHERE rowid=1
|
||||
} {1 {cannot UPDATE contentless fts5 table: ft1}}
|
||||
|
||||
# It should be possible to update the rowid if contentless_delete=1 is
|
||||
# set and all indexed columns are updated.
|
||||
do_execsql_test 1.$tn.15 {
|
||||
UPDATE ft2 SET a='aXone', d='dXone', rowid=11 WHERE rowid=1
|
||||
}
|
||||
|
||||
set res(0) {
|
||||
2 {} {} {} {}
|
||||
3 {} {} {} {}
|
||||
11 {} {} {} {}
|
||||
}
|
||||
set res(1) {
|
||||
2 {} b2.1.2 c2.2 {}
|
||||
3 {} b3 c3.2 {}
|
||||
11 {} b1.1.2 c1.2 {}
|
||||
}
|
||||
do_execsql_test 1.$tn.16 {
|
||||
SELECT rowid, * FROM ft2
|
||||
} $res($cu)
|
||||
|
||||
# Should not be possible to update the rowid of a contentless_delete=1
|
||||
# table if no indexed columns are updated.
|
||||
do_catchsql_test 1.$tn.17 {
|
||||
UPDATE ft2 SET rowid=12 WHERE rowid=11
|
||||
} {1 {cannot UPDATE a subset of columns on fts5 contentless-delete table: ft2}}
|
||||
do_catchsql_test 1.$tn.18 {
|
||||
UPDATE ft1 SET rowid=12 WHERE rowid=1
|
||||
} {1 {cannot UPDATE contentless fts5 table: ft1}}
|
||||
|
||||
do_execsql_test 1.$tn.19 {
|
||||
UPDATE ft2 SET a='aXtwo', d='dXtwo', c='newval', rowid=12 WHERE rowid=2
|
||||
} {}
|
||||
|
||||
set res(0) {
|
||||
3 {} {} {} {}
|
||||
11 {} {} {} {}
|
||||
12 {} {} {} {}
|
||||
}
|
||||
set res(1) {
|
||||
3 {} b3 c3.2 {}
|
||||
11 {} b1.1.2 c1.2 {}
|
||||
12 {} b2.1.2 newval {}
|
||||
}
|
||||
do_execsql_test 1.$tn.20 {
|
||||
SELECT rowid, * FROM ft2
|
||||
} $res($cu)
|
||||
|
||||
do_execsql_test 1.$tn.21 {
|
||||
SELECT rowid, * FROM ft2('aXtwo AND dXtwo')
|
||||
} [lrange $res($cu) 10 end]
|
||||
|
||||
}} ;# end of [foreach_detail_mode] loop
|
||||
|
||||
finish_test
|
||||
+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 ){
|
||||
|
||||
+9
-26
@@ -113,7 +113,9 @@
|
||||
** often small. The developers might revisit that decision later,
|
||||
** should the need arise.
|
||||
*/
|
||||
#ifdef SQLITE_STATIC_PERCENTILE
|
||||
#if defined(SQLITE3_H)
|
||||
/* no-op */
|
||||
#elif defined(SQLITE_STATIC_PERCENTILE)
|
||||
# include "sqlite3.h"
|
||||
#else
|
||||
# include "sqlite3ext.h"
|
||||
@@ -171,19 +173,6 @@ static int percentSameValue(double a, double b){
|
||||
return a>=-0.001 && a<=0.001;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Verify that the elements of the Percentile p are in fact sorted.
|
||||
** Used for testing and debugging only.
|
||||
*/
|
||||
static void percentAssertSorted(Percentile *p){
|
||||
int i;
|
||||
for(i=p->nUsed-2; i>=0 && p->a[i]<=p->a[i+1]; i--){}
|
||||
assert( i<0 );
|
||||
}
|
||||
#else
|
||||
# define percentAssertSorted(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Search p (which must have p->bSorted) looking for an entry with
|
||||
** value y. Return the index of that entry.
|
||||
@@ -229,7 +218,7 @@ static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
|
||||
va_start(ap, zFormat);
|
||||
zMsg1 = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
zMsg2 = sqlite3_mprintf(zMsg1, pFunc->zName);
|
||||
zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0;
|
||||
sqlite3_result_error(pCtx, zMsg2, -1);
|
||||
sqlite3_free(zMsg1);
|
||||
sqlite3_free(zMsg2);
|
||||
@@ -317,9 +306,8 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
p->a[p->nUsed++] = y;
|
||||
}else if( p->bKeepSorted ){
|
||||
int i;
|
||||
percentAssertSorted(p);
|
||||
i = percentBinarySearch(p, y, 0);
|
||||
if( i<p->nUsed ){
|
||||
if( i<(int)p->nUsed ){
|
||||
memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
|
||||
}
|
||||
p->a[i] = y;
|
||||
@@ -428,8 +416,6 @@ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}else{
|
||||
percentAssertSorted(p);
|
||||
}
|
||||
p->bKeepSorted = 1;
|
||||
|
||||
@@ -437,11 +423,10 @@ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
|
||||
i = percentBinarySearch(p, y, 1);
|
||||
if( i>=0 ){
|
||||
p->nUsed--;
|
||||
if( i<p->nUsed ){
|
||||
if( i<(int)p->nUsed ){
|
||||
memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
|
||||
}
|
||||
}
|
||||
percentAssertSorted(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -462,8 +447,6 @@ static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}else{
|
||||
percentAssertSorted(p);
|
||||
}
|
||||
ix = p->rPct*(p->nUsed-1);
|
||||
i1 = (unsigned)ix;
|
||||
@@ -491,7 +474,7 @@ 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(
|
||||
@@ -500,8 +483,8 @@ int sqlite3_percentile_init(
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
#ifdef SQLITE_STATIC_PERCENTILE
|
||||
unsigned int i;
|
||||
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
|
||||
+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,
|
||||
|
||||
+4
-4
@@ -351,7 +351,7 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
|
||||
** Negative values indicate an error:
|
||||
** -1 One of the inputs is NULL
|
||||
** -2 Non-ASCII characters on input
|
||||
** -3 Unable to allocate memory
|
||||
** -3 Unable to allocate memory
|
||||
**
|
||||
** If pnMatch is not NULL, then *pnMatch is set to the number of bytes
|
||||
** of zB that matched the pattern in zA. If zA does not end with a '*',
|
||||
@@ -360,8 +360,8 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
|
||||
** of zB that was deemed to match zA.
|
||||
*/
|
||||
static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
int nA, nB; /* Number of characters in zA[] and zB[] */
|
||||
int xA, xB; /* Loop counters for zA[] and zB[] */
|
||||
unsigned int nA, nB; /* Number of characters in zA[] and zB[] */
|
||||
unsigned int xA, xB; /* Loop counters for zA[] and zB[] */
|
||||
char cA = 0, cB; /* Current character of zA and zB */
|
||||
char cAprev, cBprev; /* Previous character of zA and zB */
|
||||
char cAnext, cBnext; /* Next character in zA and zB */
|
||||
@@ -3021,7 +3021,7 @@ static sqlite3_module spellfix1Module = {
|
||||
*/
|
||||
static int spellfix1Register(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
unsigned int i;
|
||||
rc = sqlite3_create_function(db, "spellfix1_translit", 1,
|
||||
SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
|
||||
transliterateSqlFunc, 0, 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;
|
||||
|
||||
+272
-312
@@ -15,8 +15,9 @@
|
||||
# by the target name. Rebuild is necessary for all components to get
|
||||
# the desired optimization level.
|
||||
#
|
||||
# quick, q = do just a minimal build (sqlite3.js/wasm, tester1) for
|
||||
# faster development-mode turnaround.
|
||||
# quick, q = do just build the essentials for testing
|
||||
# (sqlite3.js/wasm, tester1) for faster development-mode
|
||||
# turnaround.
|
||||
#
|
||||
# dist = create end user deliverables. Add dist.build=oX to build
|
||||
# with a specific optimization level, where oX is one of the
|
||||
@@ -35,25 +36,21 @@
|
||||
# - wasm-strip for release builds: https://github.com/WebAssembly/wabt
|
||||
# - InfoZip for 'dist' zip file
|
||||
########################################################################
|
||||
#
|
||||
# Significant TODOs for this build include, but are not necessarily
|
||||
# limited to:
|
||||
#
|
||||
# 1) Consolidate the code generation for sqlite3*.*js into a script
|
||||
# which generates the makefile code, rather than using $(call) and
|
||||
# $(eval), or at least centralize the setup of the numerous vars
|
||||
# related to each build variant $(JS_BUILD_MODES). (Update: an
|
||||
# external script was attempted but generating properly-escaped
|
||||
# makefile code from within a shell script is even less legible
|
||||
# than the $(eval) indirection going on in this file.)
|
||||
#
|
||||
default: all
|
||||
#default: quick
|
||||
SHELL := $(shell which bash 2>/dev/null)
|
||||
SHELL := $(firstword $(wildcard /usr/local/bin/bash /usr/bin/bash /bin/bash))
|
||||
ifeq (,$(SHELL))
|
||||
$(error Cannot find the bash shell)
|
||||
endif
|
||||
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
CLEAN_FILES :=
|
||||
DISTCLEAN_FILES := ./--dummy--
|
||||
release: oz
|
||||
DISTCLEAN_FILES :=
|
||||
MAKING_CLEAN := $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
|
||||
.PHONY: clean distclean
|
||||
clean:
|
||||
-rm -f $(CLEAN_FILES)
|
||||
distclean: clean
|
||||
-rm -f $(DISTCLEAN_FILES)
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
|
||||
@@ -86,46 +83,6 @@ JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
|
||||
#
|
||||
JS_BUILD_MODES := vanilla esm bunder-friendly node
|
||||
|
||||
########################################################################
|
||||
# Emscripten SDK home dir and related binaries...
|
||||
EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/emsdk $(HOME)/src/emsdk))
|
||||
emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell which emcc))
|
||||
ifeq (,$(emcc.bin))
|
||||
$(error Cannot find emcc.)
|
||||
endif
|
||||
emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
|
||||
| sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
ifeq (,$(emcc.version))
|
||||
$(warning Cannot determine emcc version. This might unduly impact build flags.)
|
||||
else
|
||||
$(info using emcc version [$(emcc.version)])
|
||||
endif
|
||||
|
||||
wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
|
||||
ifeq (,$(filter clean,$(MAKECMDGOALS)))
|
||||
ifeq (,$(wasm-strip))
|
||||
$(info WARNING: *******************************************************************)
|
||||
$(info WARNING: builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,)
|
||||
$(info WARNING: breaking _All The Things_. The workaround for that is to build)
|
||||
$(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
|
||||
$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
|
||||
$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
|
||||
$(info WARNING: If this build uses any optimization level higher than -O1 then)
|
||||
$(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.)
|
||||
$(info WARNING: wasm-strip is part of the wabt package:)
|
||||
$(info WARNING: https://github.com/WebAssembly/wabt)
|
||||
$(info WARNING: on Ubuntu-like systems it can be installed with:)
|
||||
$(info WARNING: sudo apt install wabt)
|
||||
$(info WARNING: *******************************************************************)
|
||||
endif
|
||||
endif # 'make clean' check
|
||||
|
||||
ifeq (,$(wasm-strip))
|
||||
maybe-wasm-strip = echo "not wasm-stripping"
|
||||
else
|
||||
maybe-wasm-strip = $(wasm-strip)
|
||||
endif
|
||||
|
||||
########################################################################
|
||||
# dir.top = the top dir of the canonical build tree, where
|
||||
# sqlite3.[ch] live.
|
||||
@@ -141,41 +98,19 @@ dir.common := common
|
||||
dir.fiddle := fiddle
|
||||
dir.fiddle-debug := fiddle-debug
|
||||
dir.tool := $(dir.top)/tool
|
||||
CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
|
||||
$(dir.fiddle-debug)/*
|
||||
|
||||
########################################################################
|
||||
# dir.dout = output dir for deliverables.
|
||||
#
|
||||
# MAINTENANCE REMINDER: the output .js and .wasm files of certain emcc
|
||||
# buildables must be in _this_ dir, rather than a subdir, or else
|
||||
# parts of the generated code get confused and cannot load
|
||||
# property. Specifically, when X.js loads X.wasm, whether or not X.js
|
||||
# uses the correct path for X.wasm depends on how it's loaded: an HTML
|
||||
# script tag will resolve it intuitively, whereas a Worker's call to
|
||||
# importScripts() will not. That's a fundamental incompatibility with
|
||||
# how URL resolution in JS happens between those two contexts. See:
|
||||
#
|
||||
# https://zzz.buzz/2017/03/14/relative-uris-in-web-development/
|
||||
#
|
||||
# We unfortunately have no way, from Worker-initiated code, to
|
||||
# automatically resolve the path from X.js to X.wasm.
|
||||
#
|
||||
# We have an "only slightly unsightly" solution for our main builds
|
||||
# but it does not work for the WASMFS builds, so those builds have to
|
||||
# be built to _this_ directory and can only run when the client app is
|
||||
# loaded from the same directory.
|
||||
# dir.dout = output dir for deliverables
|
||||
dir.dout := $(dir.wasm)/jswasm
|
||||
# dir.tmp = output dir for intermediary build files, as opposed to
|
||||
# end-user deliverables.
|
||||
dir.tmp := $(dir.wasm)/bld
|
||||
CLEAN_FILES += $(dir.tmp)/* $(dir.dout)/*
|
||||
ifeq (,$(wildcard $(dir.dout)))
|
||||
dir._tmp := $(shell mkdir -p $(dir.dout))
|
||||
endif
|
||||
ifeq (,$(wildcard $(dir.tmp)))
|
||||
dir._tmp := $(shell mkdir -p $(dir.tmp))
|
||||
endif
|
||||
dir.wasmfs := $(dir.dout)
|
||||
|
||||
MKDIR.bld := $(dir.tmp)
|
||||
$(MKDIR.bld):
|
||||
-mkdir -p $@ $(dir.dout)
|
||||
|
||||
CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
|
||||
$(dir.fiddle-debug)/* $(dir.dout)/* $(dir.tmp)/*
|
||||
|
||||
########################################################################
|
||||
# Set up sqlite3.c and sqlite3.h...
|
||||
@@ -197,48 +132,14 @@ endif
|
||||
sqlite3.canonical.c := $(dir.top)/sqlite3.c
|
||||
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
|
||||
sqlite3.h := $(dir.top)/sqlite3.h
|
||||
ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c) 2>/dev/null))
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c)))
|
||||
SQLITE_C_IS_SEE := 0
|
||||
else
|
||||
SQLITE_C_IS_SEE := 1
|
||||
$(info This is an SEE build.)
|
||||
$(info This is an SEE build)
|
||||
endif
|
||||
# Most SQLITE_OPT flags are set in sqlite3-wasm.c but we need them
|
||||
# made explicit here for building speedtest1.c.
|
||||
SQLITE_OPT = \
|
||||
-DSQLITE_ENABLE_FTS5 \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
||||
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
|
||||
-DSQLITE_ENABLE_STMTVTAB \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_OMIT_SHARED_CACHE \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=2 \
|
||||
-DSQLITE_OS_KV_OPTIONAL=1 \
|
||||
'-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
|
||||
-DSQLITE_USE_URI=1 \
|
||||
-DSQLITE_WASM_ENABLE_C_TESTS \
|
||||
-DSQLITE_C=$(sqlite3.c)
|
||||
#SQLITE_OPT += -DSQLITE_DEBUG
|
||||
# Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file()
|
||||
# (and thus sqlite3_js_vfs_create_file()). Those functions are
|
||||
# deprecated and alternatives are in place, but this crash behavior
|
||||
# can be used to find errant uses of sqlite3_js_vfs_create_file()
|
||||
# in client code.
|
||||
|
||||
########################################################################
|
||||
# minimal=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
|
||||
# goal being to create a WASM file with only the core APIs.
|
||||
minimal ?= 0
|
||||
ifeq (1,$(minimal))
|
||||
SQLITE_OPT += -DSQLITE_WASM_MINIMAL
|
||||
endif
|
||||
|
||||
########################################################################@
|
||||
@@ -250,21 +151,179 @@ $(sqlite3.h):
|
||||
$(MAKE) -C $(dir.top) sqlite3.c
|
||||
$(sqlite3.c): $(sqlite3.h)
|
||||
|
||||
.PHONY: clean distclean
|
||||
clean:
|
||||
-rm -f $(CLEAN_FILES)
|
||||
distclean: clean
|
||||
-rm -f $(DISTCLEAN_FILES)
|
||||
########################################################################
|
||||
# Special-case builds for which we require certain pre-conditions
|
||||
# which, if not met, may cause warnings or fatal errors in the build.
|
||||
# This also affects the default optimization level flags. Note that
|
||||
# the fiddle targets are in this list because they are used for
|
||||
# generating sqlite.org/fiddle.
|
||||
OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug
|
||||
|
||||
ifeq (release,$(filter release,$(MAKECMDGOALS)))
|
||||
ifeq (,$(wasm-strip))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available. \
|
||||
See notes in the warning above)
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(info ==============================================================)
|
||||
$(info == Development build. Make one of (dist, snapshot) for a)
|
||||
$(info == smaller release build.)
|
||||
$(info ==============================================================)
|
||||
endif
|
||||
else
|
||||
$(info Development build. Use '$(MAKE) release' for a smaller release build.)
|
||||
endif
|
||||
|
||||
########################################################################
|
||||
# Find emcc (Emscripten compiler)...
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
emcc.bin := echo
|
||||
emcc.version := unknown
|
||||
else
|
||||
emcc.bin := $(shell which emcc 2>/dev/null)
|
||||
ifeq (,$(emcc.bin))
|
||||
ifneq (,$(EMSDK_HOME))
|
||||
emcc.bin := $(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc)
|
||||
endif
|
||||
ifeq (,$(emcc.bin))
|
||||
$(error Cannot find emcc in path.)
|
||||
endif
|
||||
endif
|
||||
emcc.version := $(shell $(emcc.bin) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
$(info using emcc version [$(emcc.version)])
|
||||
endif
|
||||
#########################################################################
|
||||
# Find wasm-strip, which we need for release builds (see below for
|
||||
# why) but not strictly for non-release builds.
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
wasm-strip-bin := irrelevant
|
||||
else
|
||||
wasm-strip.bin ?= $(shell which wasm-strip 2>/dev/null)
|
||||
ifeq (,$(wasm-strip.bin))
|
||||
$(info WARNING: *******************************************************************)
|
||||
$(info WARNING: Builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,)
|
||||
$(info WARNING: breaking _All The Things_. The workaround for that is to build)
|
||||
$(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
|
||||
$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
|
||||
$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
|
||||
$(info WARNING: If this build uses any optimization level higher than -O1 then)
|
||||
$(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.)
|
||||
$(info WARNING: wasm-strip is part of the wabt package:)
|
||||
$(info WARNING: https://github.com/WebAssembly/wabt)
|
||||
$(info WARNING: on Ubuntu-like systems it can be installed with:)
|
||||
$(info WARNING: sudo apt install wabt)
|
||||
$(info WARNING: *******************************************************************)
|
||||
ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available.)
|
||||
endif
|
||||
wasm-strip.bin := echo "not wasm-stripping"
|
||||
endif
|
||||
endif
|
||||
maybe-wasm-strip := $(wasm-strip.bin)
|
||||
|
||||
########################################################################
|
||||
# barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
|
||||
# goal being to create a WASM file with only the core APIs.
|
||||
ifeq (1,$(barebones))
|
||||
wasm-bare-bones := 1
|
||||
$(info ==============================================================)
|
||||
$(info == This is a bare-bones build. It trades away features for)
|
||||
$(info == a smaller .wasm file.)
|
||||
$(info ==============================================================)
|
||||
else
|
||||
wasm-bare-bones := 0
|
||||
endif
|
||||
undefine barebones
|
||||
|
||||
# Common options for building sqlite3-wasm.c and speedtest1.c.
|
||||
# Explicit ENABLEs...
|
||||
SQLITE_OPT.common := \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=2 \
|
||||
-DSQLITE_ENABLE_MATH_FUNCTIONS \
|
||||
-DSQLITE_OS_KV_OPTIONAL=1 \
|
||||
'-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
|
||||
-DSQLITE_USE_URI=1 \
|
||||
-DSQLITE_C=$(sqlite3.c) \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_SHARED_CACHE
|
||||
# ^^^ These particular OMITs are hard-coded in sqlite3-wasm.c and
|
||||
# removing them from this list will serve only to break the speedtest1
|
||||
# builds.
|
||||
|
||||
# Currently always needed but TODO is paring tester1.c-pp.js down
|
||||
# to be able to run without this:
|
||||
SQLITE_OPT.common += -DSQLITE_WASM_ENABLE_C_TESTS
|
||||
|
||||
# Extra flags for full-featured builds...
|
||||
SQLITE_OPT.full-featured := \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_FTS5 \
|
||||
-DSQLITE_ENABLE_MATH_FUNCTIONS \
|
||||
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
|
||||
-DSQLITE_ENABLE_PREUPDATE_HOOK \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_SESSION \
|
||||
-DSQLITE_ENABLE_STMTVTAB \
|
||||
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
|
||||
ifeq (0,$(wasm-bare-bones))
|
||||
# The so-called canonical build is full-featured:
|
||||
SQLITE_OPT := \
|
||||
$(SQLITE_OPT.common) \
|
||||
$(SQLITE_OPT.full-featured)
|
||||
else
|
||||
# The so-called bare-bones build is exactly that:
|
||||
SQLITE_OPT := \
|
||||
$(SQLITE_OPT.common) \
|
||||
-DSQLITE_WASM_BARE_BONES
|
||||
# SQLITE_WASM_BARE_BONES tells sqlite3-wasm.c to explicitly omit
|
||||
# a bunch of stuff, in the interest of keeping the wasm file size
|
||||
# down. As of this writing it equates to:
|
||||
#
|
||||
# -USQLITE_ENABLE_DBPAGE_VTAB
|
||||
# -USQLITE_ENABLE_DBSTAT_VTAB
|
||||
# -USQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
# -USQLITE_ENABLE_FTS5
|
||||
# -USQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# -USQLITE_ENABLE_PREUPDATE_HOOK
|
||||
# -USQLITE_ENABLE_RTREE
|
||||
# -USQLITE_ENABLE_SESSION
|
||||
# -USQLITE_ENABLE_STMTVTAB
|
||||
# -DSQLITE_OMIT_AUTHORIZATION
|
||||
# -DSQLITE_OMIT_GET_TABLE
|
||||
# -DSQLITE_OMIT_INCRBLOB
|
||||
# -DSQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
# -DSQLITE_OMIT_JSON
|
||||
# -DSQLITE_OMIT_PROGRESS_CALLBACK
|
||||
# -DSQLITE_OMIT_WAL
|
||||
#
|
||||
# There are others we want here but which require explicit OMIT when
|
||||
# creating their amalgamation, and that step is TODO:
|
||||
#
|
||||
# -DSQLITE_OMIT_EXPLAIN
|
||||
# -DSQLITE_OMIT_TRIGGER
|
||||
# -DSQLITE_OMIT_VIRTUALTABLE
|
||||
# -DSQLITE_OMIT_WINDOWFUNC
|
||||
endif
|
||||
|
||||
#SQLITE_OPT += -DSQLITE_DEBUG
|
||||
# Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file()
|
||||
# (and thus sqlite3_js_vfs_create_file()). Those functions are
|
||||
# deprecated and alternatives are in place, but this crash behavior
|
||||
# can be used to find errant uses of sqlite3_js_vfs_create_file()
|
||||
# in client code.
|
||||
|
||||
########################################################################
|
||||
# The following flags are hard-coded into sqlite3-wasm.c and cannot be
|
||||
# modified via the build process:
|
||||
#
|
||||
# SQLITE_ENABLE_API_ARMOR
|
||||
# SQLITE_OMIT_LOAD_EXTENSION
|
||||
# SQLITE_OMIT_DEPRECATED
|
||||
# SQLITE_OMIT_UTF16
|
||||
# SQLITE_OMIT_SHARED_CACHE
|
||||
########################################################################
|
||||
|
||||
|
||||
########################################################################
|
||||
# Adding custom C code via sqlite3_wasm_extra_init.c:
|
||||
#
|
||||
@@ -321,6 +380,18 @@ $(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
|
||||
########################################################################
|
||||
# bin.mkwb is used for generating some of the makefile code for the
|
||||
# various wasm builds. It used to be generated in this makefile via a
|
||||
# difficult-to-read/maintain block of $(eval)'d code. Attempts were
|
||||
# made to generate it from tcl and bash (shell) but having to escape
|
||||
# the $ references in those languages made it just as illegible as the
|
||||
# native makefile code. Somewhat surprisingly, moving that code generation
|
||||
# to C makes it slightly less illegible than the previous 3 options.
|
||||
bin.mkwb := ./mkwasmbuilds
|
||||
$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.mkwb)
|
||||
|
||||
########################################################################
|
||||
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
|
||||
@@ -360,6 +431,7 @@ $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
|
||||
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
DISTCLEAN_FILES += $(bin.c-pp)
|
||||
C-PP.FILTER.global ?=
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
C-PP.FILTER.global += -Denable-see
|
||||
@@ -371,7 +443,7 @@ define C-PP.FILTER
|
||||
# $3 = optional c-pp -D... flags
|
||||
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
|
||||
CLEAN_FILES += $(2)
|
||||
#CLEAN_FILES += $(2)
|
||||
endef
|
||||
# /end C-PP.FILTER
|
||||
########################################################################
|
||||
@@ -386,7 +458,17 @@ emcc.WASM_BIGINT ?= 1
|
||||
# emcc_opt = optimization-related flags. These are primarily used by
|
||||
# the various oX targets. build times for -O levels higher than 0 are
|
||||
# painful at dev-time.
|
||||
emcc_opt ?= -O0
|
||||
#
|
||||
# When running any of the $(OPTIMIZED_TARGETS) explicitly, e.g. for a
|
||||
# release distribution, use a higher optimization level. Experience
|
||||
# has shown -Oz to produce the smallest deliverables with only a
|
||||
# roughly 10% performance hit in the resulting WASM file compared to
|
||||
# -O2 (which consistently creates the fastest-running deliverables).
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
emcc_opt ?= -O0
|
||||
else
|
||||
emcc_opt ?= -Oz
|
||||
endif
|
||||
|
||||
# When passing emcc_opt from the CLI, += and re-assignment have no
|
||||
# effect, so emcc_opt+=-g3 doesn't work. So...
|
||||
@@ -421,24 +503,16 @@ emcc_opt_full := $(emcc_opt) -g3
|
||||
########################################################################
|
||||
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
|
||||
# -sEXPORTED_FUNCTION flag.
|
||||
EXPORTED_FUNCTIONS.api.core := $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core)
|
||||
EXPORTED_FUNCTIONS.api.core := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core
|
||||
EXPORTED_FUNCTIONS.api.in := $(EXPORTED_FUNCTIONS.api.core)
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
EXPORTED_FUNCTIONS.api.in += $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-see)
|
||||
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-see
|
||||
endif
|
||||
ifeq (0,$(minimal))
|
||||
EXPORTED_FUNCTIONS.api.in += \
|
||||
$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-auth) \
|
||||
$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-preupdate) \
|
||||
$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-session) \
|
||||
$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-vtab)
|
||||
else
|
||||
$(info ========================================)
|
||||
$(info This is a minimal-mode build)
|
||||
$(info ========================================)
|
||||
ifeq (0,$(wasm-bare-bones))
|
||||
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
|
||||
endif
|
||||
EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api
|
||||
$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
|
||||
$(EXPORTED_FUNCTIONS.api): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
|
||||
cat $(EXPORTED_FUNCTIONS.api.in) > $@
|
||||
|
||||
########################################################################
|
||||
@@ -470,8 +544,10 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.c-pp.js
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.c-pp.js
|
||||
# sqlite3-vfs-helper = helper APIs for VFSes:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.c-pp.js
|
||||
# sqlite3-vtab-helper = helper APIs for VTABLEs:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
|
||||
ifeq (0,$(wasm-bare-bones))
|
||||
# sqlite3-vtab-helper = helper APIs for VTABLEs:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
|
||||
endif
|
||||
# sqlite3-vfs-opfs = the first OPFS VFS:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
|
||||
# sqlite3-vfs-opfs-sahpool = the second OPFS VFS:
|
||||
@@ -520,7 +596,7 @@ $(SOAP.js.bld): $(SOAP.js)
|
||||
# preprocessed. It contains all of $(sqlite3-api.jses) but none of the
|
||||
# Emscripten-specific headers and footers.
|
||||
sqlite3-api.js.in := $(dir.tmp)/sqlite3-api.c-pp.js
|
||||
$(sqlite3-api.js.in): $(sqlite3-api.jses) $(MAKEFILE)
|
||||
$(sqlite3-api.js.in): $(MKDIR.bld) $(sqlite3-api.jses) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@for i in $(sqlite3-api.jses); do \
|
||||
echo "/* BEGIN FILE: $$i */"; \
|
||||
@@ -687,7 +763,7 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
|
||||
########################################################################
|
||||
# $(sqlite3-api-build-version.js) injects the build version info into
|
||||
# the bundle in JSON form.
|
||||
$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
|
||||
$(sqlite3-api-build-version.js): $(MKDIR.bld) $(bin.version-info) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@{ \
|
||||
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
|
||||
@@ -703,7 +779,7 @@ $(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
|
||||
#
|
||||
# Maintenance reminder: there are awk binaries out there which do not
|
||||
# support -e SCRIPT.
|
||||
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
|
||||
$(sqlite3-license-version.js): $(MKDIR.bld) $(sqlite3.h) $(sqlite3-license-version-header.js) \
|
||||
$(MAKEFILE)
|
||||
@echo "Making $@..."; { \
|
||||
cat $(sqlite3-license-version-header.js); \
|
||||
@@ -731,7 +807,7 @@ post-jses.js := \
|
||||
$(dir.api)/post-js-header.js \
|
||||
$(sqlite3-api.js.in) \
|
||||
$(dir.api)/post-js-footer.js
|
||||
$(post-js.js.in): $(post-jses.js) $(MAKEFILE)
|
||||
$(post-js.js.in): $(MKDIR.bld) $(post-jses.js) $(MAKEFILE)
|
||||
@echo "Making $@..."
|
||||
@for i in $(post-jses.js); do \
|
||||
echo "/* BEGIN FILE: $$i */"; \
|
||||
@@ -740,55 +816,6 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE)
|
||||
done > $@
|
||||
|
||||
|
||||
########################################################################
|
||||
# call-make-pre-post is a $(call)able which creates rules for
|
||||
# pre-js.$(1)-$(2).js. $1 = the base name of the JS file on whose
|
||||
# behalf this pre-js is for (one of: $(JS_BUILD_NAMES)). $2 is
|
||||
# the build mode: one of $(JS_BUILD_MODES). This sets up
|
||||
# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and
|
||||
# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get
|
||||
# filtered using $(C-PP.FILTER). Any flags necessary for such
|
||||
# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing
|
||||
# this.
|
||||
#
|
||||
# Maintenance note: a shell script was written to generate these rules
|
||||
# with the hope that it would make them more legible and maintainable,
|
||||
# but embedding makefile code in another language makes it even less
|
||||
# legible than having the level of $(eval) indirection which we have
|
||||
# here.
|
||||
define call-make-pre-post
|
||||
pre-post-$(1)-$(2).flags ?=
|
||||
pre-js.js.$(1)-$(2).intermediary := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
|
||||
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
#$$(error $$(pre-js.js.$(1)-$(2).intermediary) $$(pre-js.js.$(1)-$(2)))
|
||||
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2).intermediary),$$(c-pp.D.$(1)-$(2))))
|
||||
post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js
|
||||
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
|
||||
extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js
|
||||
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
|
||||
pre-post-common.flags.$(1)-$(2) := \
|
||||
$$(pre-post-common.flags) \
|
||||
--post-js=$$(post-js.js.$(1)-$(2)) \
|
||||
--extern-post-js=$$(extern-post-js.js.$(1)-$(2))
|
||||
pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \
|
||||
$$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2))
|
||||
$$(pre-js.js.$(1)-$(2)): $$(pre-js.js.$(1)-$(2).intermediary) $$(MAKEFILE)
|
||||
cp $$(pre-js.js.$(1)-$(2).intermediary) $$@
|
||||
@if [ sqlite3-wasmfs = $(1) ]; then \
|
||||
echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
|
||||
elif [ sqlite3 != $(1) ]; then \
|
||||
echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
|
||||
fi >> $$@
|
||||
pre-post-$(1)-$(2).deps := \
|
||||
$$(pre-post-jses.$(1)-$(2).deps) \
|
||||
$$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
pre-post-$(1)-$(2).flags += \
|
||||
$$(pre-post-common.flags.$(1)-$(2)) \
|
||||
--pre-js=$$(dir.tmp)/pre-js.$(1)-$(2).js
|
||||
endef
|
||||
# /post-js and pre-js
|
||||
########################################################################
|
||||
|
||||
# Undocumented Emscripten feature: if the target file extension is
|
||||
# "mjs", it defaults to ES6 module builds:
|
||||
# https://github.com/emscripten-core/emscripten/issues/14383
|
||||
@@ -802,11 +829,13 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
# difference, so we build all binaries against sqlite3-wasm.c instead
|
||||
# of building a shared copy of sqlite3-wasm.o to link against.
|
||||
########################################################################
|
||||
# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and
|
||||
# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code
|
||||
# duplication. $1 is 1 if the build mode needs this workaround (esm,
|
||||
# bundler-friendly, node) and 0 if not (vanilla). $2 must be empty for
|
||||
# all builds except sqlite3-wasmfs.mjs, in which case it must be 1.
|
||||
|
||||
########################################################################
|
||||
# SQLITE3.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the
|
||||
# wasmfs build. $1 is 1 if the build mode needs this workaround
|
||||
# (modes: esm, bundler-friendly, node) and 0 if not (vanilla). $2 must
|
||||
# be 0 for all builds except sqlite3-wasmfs.mjs, in which case it must
|
||||
# be 1.
|
||||
#
|
||||
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
|
||||
# adds:
|
||||
@@ -825,11 +854,11 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
# use awk instead of sed for this.
|
||||
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
|
||||
if [ x1 = x$(1) ]; then \
|
||||
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.RECIPE."; \
|
||||
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.ESM-EXPORT-DEFAULT."; \
|
||||
{\
|
||||
awk '/^export default/ && !f{f=1; next} 1' $@ > $@.tmp && mv $@.tmp $@; \
|
||||
} || exit $$?; \
|
||||
if [ x != x$(2) ]; then \
|
||||
if [ x1 = x$(2) ]; then \
|
||||
if ! grep -q '^export default' $@; then \
|
||||
echo "Cannot find export default." 1>&2; \
|
||||
exit 1; \
|
||||
@@ -838,78 +867,6 @@ if [ x1 = x$(1) ]; then \
|
||||
fi
|
||||
endef
|
||||
|
||||
########################################################################
|
||||
# extern-post-js* and extern-pre-js* are files for use with
|
||||
# Emscripten's --extern-pre-js and --extern-post-js flags.
|
||||
extern-pre-js.js := $(dir.api)/extern-pre-js.js
|
||||
extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js
|
||||
# Emscripten flags for --[extern-][pre|post]-js=... for the
|
||||
# various builds.
|
||||
pre-post-common.flags := \
|
||||
--extern-pre-js=$(sqlite3-license-version.js)
|
||||
# pre-post-jses.deps.* = a list of dependencies for the
|
||||
# --[extern-][pre/post]-js files.
|
||||
pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
|
||||
|
||||
########################################################################
|
||||
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
|
||||
# for one of the build modes.
|
||||
#
|
||||
# $1 = one of: $(JS_BUILD_NAMES)
|
||||
# $2 = build mode name: one of $(JS_BUILD_MODES)
|
||||
# $3 = 1 for ESM build mode, else 0
|
||||
# $4 = resulting sqlite-api JS/MJS file
|
||||
# $5 = resulting JS/MJS file
|
||||
# $6 = -D... flags for $(bin.c-pp)
|
||||
# $7 = optional extra flags for emcc
|
||||
#
|
||||
# Maintenance reminder: be careful not to introduce spaces around args
|
||||
# ($1, $2), otherwise string concatenation will malfunction.
|
||||
#
|
||||
# Before calling this, emcc.environment.$(2) must be set to a value
|
||||
# for emcc's -sENVIRONMENT flag.
|
||||
#
|
||||
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
|
||||
# CFLAGS to a given build mode.
|
||||
#
|
||||
# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to
|
||||
# append emcc-specific flags to a given build mode.
|
||||
define SETUP_LIB_BUILD_MODE
|
||||
$(info Setting up build [$(1)-$(2)]: $(5))
|
||||
c-pp.D.$(1)-$(2) := $(6)
|
||||
$$(eval $$(call call-make-pre-post,$(1),$(2)))
|
||||
emcc.flags.$(1).$(2) ?=
|
||||
emcc.flags.$(1).$(2) += $(7)
|
||||
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(4), $(6)))
|
||||
$(5): $(4) $$(MAKEFILE) $$(sqlite3-wasm.cfiles) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-$(1)-$(2).deps)
|
||||
@echo "Building $$@ ..."
|
||||
$$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \
|
||||
$$(emcc.jsflags) \
|
||||
-sENVIRONMENT=$$(emcc.environment.$(2)) \
|
||||
$$(pre-post-$(1)-$(2).flags) \
|
||||
$$(emcc.flags.$(1)) $$(emcc.flags.$(1).$(2)) \
|
||||
$$(cflags.common) $$(SQLITE_OPT) \
|
||||
$$(cflags.$(1)) $$(cflags.$(1).$(2)) \
|
||||
$$(cflags.wasm_extra_init) $$(sqlite3-wasm.cfiles)
|
||||
@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(3))
|
||||
@dotwasm=$$(basename $$@).wasm; \
|
||||
chmod -x $$$$dotwasm; \
|
||||
$(maybe-wasm-strip) $$$$dotwasm; \
|
||||
case $(2) in \
|
||||
bundler-friendly|node) \
|
||||
echo "Patching $$@ for $(1).wasm..."; \
|
||||
rm -f $$$$dotwasm; \
|
||||
dotwasm=; \
|
||||
sed -i -e 's/$(1)-$(2).wasm/$(1).wasm/g' $$@ || exit $$$$?; \
|
||||
;; \
|
||||
esac; \
|
||||
ls -la $$$$dotwasm $$@
|
||||
all: $(5)
|
||||
#quick: $(5)
|
||||
CLEAN_FILES += $(4) $(5)
|
||||
endef
|
||||
# ^^^ /SETUP_LIB_BUILD_MODE
|
||||
########################################################################
|
||||
sqlite3-api.js := $(dir.dout)/sqlite3-api.js
|
||||
sqlite3.js := $(dir.dout)/sqlite3.js
|
||||
sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs
|
||||
@@ -918,17 +875,18 @@ sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
|
||||
sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
|
||||
sqlite3-api-node.mjs := $(dir.dout)/sqlite3-api-node.mjs
|
||||
sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
|
||||
#$(info $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\
|
||||
$(sqlite3-api.js), $(sqlite3.js)))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\
|
||||
$(sqlite3-api.mjs), $(sqlite3.mjs), -Dtarget=es6-module))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\
|
||||
$(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
|
||||
$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly))
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\
|
||||
$(sqlite3-api-node.mjs),$(sqlite3-node.mjs),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node))
|
||||
sqlite3-api-wasmfs.mjs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
|
||||
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
.wasmbuilds.make: $(bin.mkwb)
|
||||
@rm -f $@
|
||||
$(bin.mkwb) > $@
|
||||
@chmod -w $@
|
||||
-include .wasmbuilds.make
|
||||
endif
|
||||
DISTCLEAN_FILES += .wasmbuilds.make
|
||||
|
||||
# The various -D... values used by *.c-pp.js include:
|
||||
#
|
||||
# -Dtarget=es6-module: for all ESM module builds
|
||||
@@ -962,7 +920,7 @@ $(sqlite3.wasm): $(sqlite3.js)
|
||||
$(sqlite3.mjs): $(sqlite3.js)
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
|
||||
$(sqlite3-node.mjs): $(sqlite3.mjs)
|
||||
CLEAN_FILES += $(sqlite3.wasm)
|
||||
#CLEAN_FILES += $(sqlite3.wasm)
|
||||
|
||||
########################################################################
|
||||
# We need separate copies of certain supplementary JS files for the
|
||||
@@ -1078,15 +1036,13 @@ speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1
|
||||
# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
|
||||
# which runs speedtest1 multiple times.
|
||||
|
||||
$(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api.core)
|
||||
$(EXPORTED_FUNCTIONS.speedtest1): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.core)
|
||||
@echo "Making $@ ..."
|
||||
@{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.core); } > $@
|
||||
speedtest1.js := $(dir.dout)/speedtest1.js
|
||||
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
|
||||
emcc.flags.speedtest1-vanilla := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
|
||||
|
||||
speedtest1.cfiles := $(speedtest1.c) $(sqlite3-wasm.c)
|
||||
$(eval $(call call-make-pre-post,speedtest1,vanilla))
|
||||
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
$(pre-post-speedtest1-vanilla.deps) \
|
||||
$(EXPORTED_FUNCTIONS.speedtest1)
|
||||
@@ -1096,7 +1052,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
$(emcc.speedtest1.common) \
|
||||
$(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
|
||||
$(SQLITE_OPT) \
|
||||
-USQLITE_WASM_MINIMAL \
|
||||
-USQLITE_WASM_BARE_BONES \
|
||||
-USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
|
||||
$(speedtest1.exit-runtime0) \
|
||||
-o $@ $(speedtest1.cfiles) -lm
|
||||
@@ -1106,7 +1062,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
|
||||
speedtest1: $(speedtest1.js)
|
||||
all: speedtest1
|
||||
CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
|
||||
#CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
|
||||
# end speedtest1.js
|
||||
########################################################################
|
||||
|
||||
@@ -1143,24 +1099,29 @@ quick: $(sqlite3.js)
|
||||
# painful.
|
||||
|
||||
.PHONY: o0 o1 o2 o3 os oz
|
||||
o-xtra :=
|
||||
#o-xtra ?= -flto
|
||||
emcc-opt-extra :=
|
||||
#ifeq (1,$(wasm-bare-bones))
|
||||
#emcc-opt-extra += -flto
|
||||
# ^^^^ -flto can have a considerably performance boost at -O0 but
|
||||
# doubles the build time and seems to have negligible, if any, effect
|
||||
# on higher optimization levels.
|
||||
#
|
||||
# -flto does ont shrink the size of bare-bones builds by any measurable
|
||||
# amount.
|
||||
#endif
|
||||
o0: clean
|
||||
$(MAKE) -e "emcc_opt=-O0"
|
||||
o1: clean
|
||||
$(MAKE) -e "emcc_opt=-O1 $(o-xtra)"
|
||||
$(MAKE) -e "emcc_opt=-O1 $(emcc-opt-extra)"
|
||||
o2: clean
|
||||
$(MAKE) -j2 -e "emcc_opt=-O2 $(o-xtra)"
|
||||
$(MAKE) -j2 -e "emcc_opt=-O2 $(emcc-opt-extra)"
|
||||
o3: clean
|
||||
$(MAKE) -e "emcc_opt=-O3 $(o-xtra)"
|
||||
$(MAKE) -e "emcc_opt=-O3 $(emcc-opt-extra)"
|
||||
os: clean
|
||||
@echo "WARNING: -Os can result in a build with mysteriously missing pieces!"
|
||||
$(MAKE) -e "emcc_opt=-Os $(o-xtra)"
|
||||
$(MAKE) -e "emcc_opt=-Os $(emcc-opt-extra)"
|
||||
oz: clean
|
||||
$(MAKE) -j2 -e "emcc_opt=-Oz $(o-xtra)"
|
||||
$(MAKE) -j2 -e "emcc_opt=-Oz $(emcc-opt-extra)"
|
||||
|
||||
########################################################################
|
||||
# Sub-makes...
|
||||
@@ -1174,7 +1135,7 @@ wasmfs.enable ?= 1
|
||||
else
|
||||
# Unconditionally enable wasmfs for [dist]clean so that the wasmfs
|
||||
# sub-make can clean up.
|
||||
wasmfs.enable ?= $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
|
||||
wasmfs.enable ?= $(MAKING_CLEAN)
|
||||
endif
|
||||
ifeq (1,$(wasmfs.enable))
|
||||
# wasmfs build disabled 2022-10-19 per /chat discussion.
|
||||
@@ -1253,4 +1214,3 @@ endif
|
||||
# Run local web server for the test/demo pages.
|
||||
httpd:
|
||||
althttpd -max-age 1 -enable-sab 1 -page index.html
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
_sqlite3_set_authorizer
|
||||
@@ -41,7 +41,6 @@ _sqlite3_create_collation
|
||||
_sqlite3_create_collation_v2
|
||||
_sqlite3_create_function
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_create_window_function
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_handle
|
||||
@@ -49,7 +48,6 @@ _sqlite3_db_name
|
||||
_sqlite3_db_readonly
|
||||
_sqlite3_db_status
|
||||
_sqlite3_deserialize
|
||||
_sqlite3_drop_modules
|
||||
_sqlite3_errcode
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
@@ -81,7 +79,6 @@ _sqlite3_open_v2
|
||||
_sqlite3_overload_function
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_progress_handler
|
||||
_sqlite3_randomness
|
||||
_sqlite3_realloc
|
||||
_sqlite3_realloc64
|
||||
|
||||
+21
@@ -1,3 +1,12 @@
|
||||
_sqlite3_create_window_function
|
||||
_sqlite3_progress_handler
|
||||
_sqlite3_set_authorizer
|
||||
_sqlite3_preupdate_blobwrite
|
||||
_sqlite3_preupdate_count
|
||||
_sqlite3_preupdate_depth
|
||||
_sqlite3_preupdate_hook
|
||||
_sqlite3_preupdate_new
|
||||
_sqlite3_preupdate_old
|
||||
_sqlite3changegroup_add
|
||||
_sqlite3changegroup_add_strm
|
||||
_sqlite3changegroup_delete
|
||||
@@ -40,3 +49,15 @@ _sqlite3session_object_config
|
||||
_sqlite3session_patchset
|
||||
_sqlite3session_patchset_strm
|
||||
_sqlite3session_table_filter
|
||||
_sqlite3_create_module
|
||||
_sqlite3_create_module_v2
|
||||
_sqlite3_declare_vtab
|
||||
_sqlite3_drop_modules
|
||||
_sqlite3_vtab_collation
|
||||
_sqlite3_vtab_distinct
|
||||
_sqlite3_vtab_in
|
||||
_sqlite3_vtab_in_first
|
||||
_sqlite3_vtab_in_next
|
||||
_sqlite3_vtab_nochange
|
||||
_sqlite3_vtab_on_conflict
|
||||
_sqlite3_vtab_rhs_value
|
||||
@@ -1,6 +0,0 @@
|
||||
_sqlite3_preupdate_blobwrite
|
||||
_sqlite3_preupdate_count
|
||||
_sqlite3_preupdate_depth
|
||||
_sqlite3_preupdate_hook
|
||||
_sqlite3_preupdate_new
|
||||
_sqlite3_preupdate_old
|
||||
@@ -1,11 +0,0 @@
|
||||
_sqlite3_create_module
|
||||
_sqlite3_create_module_v2
|
||||
_sqlite3_declare_vtab
|
||||
_sqlite3_vtab_collation
|
||||
_sqlite3_vtab_distinct
|
||||
_sqlite3_vtab_in
|
||||
_sqlite3_vtab_in_first
|
||||
_sqlite3_vtab_in_next
|
||||
_sqlite3_vtab_nochange
|
||||
_sqlite3_vtab_on_conflict
|
||||
_sqlite3_vtab_rhs_value
|
||||
@@ -48,7 +48,7 @@ Module['locateFile'] = function(path, prefix) {
|
||||
}else{
|
||||
theFile = prefix + path;
|
||||
}
|
||||
sqlite3InitModuleState.debugModule(
|
||||
this.debugModule(
|
||||
"locateFile(",arguments[0], ',', arguments[1],")",
|
||||
'sqlite3InitModuleState.scriptDir =',this.scriptDir,
|
||||
'up.entries() =',Array.from(up.entries()),
|
||||
@@ -59,6 +59,7 @@ Module['locateFile'] = function(path, prefix) {
|
||||
}.bind(sqlite3InitModuleState);
|
||||
//#endif ifnot target=es6-bundler-friendly
|
||||
|
||||
//#if custom-Module.instantiateModule
|
||||
/**
|
||||
Bug warning: a custom Module.instantiateWasm() does not work
|
||||
in WASMFS builds:
|
||||
@@ -67,7 +68,15 @@ Module['locateFile'] = function(path, prefix) {
|
||||
|
||||
In such builds we must disable this.
|
||||
*/
|
||||
const xNameOfInstantiateWasm = false
|
||||
const xNameOfInstantiateWasm =
|
||||
//#if wasmfs
|
||||
false
|
||||
//#else
|
||||
true /* This works, but it does not have the testing coverage in the
|
||||
wild which Emscripten's default impl does, so we'll save
|
||||
this option until we really need a custom
|
||||
Module.instantiateWasm() */
|
||||
//#endif
|
||||
? 'instantiateWasm'
|
||||
: 'emscripten-bug-17951';
|
||||
Module[xNameOfInstantiateWasm] = function callee(imports,onSuccess){
|
||||
@@ -80,6 +89,7 @@ Module[xNameOfInstantiateWasm] = function callee(imports,onSuccess){
|
||||
sqlite3InitModuleState.debugModule(
|
||||
"instantiateWasm() uri =", uri
|
||||
);
|
||||
//console.warn("Custom instantiateModule",uri);
|
||||
const wfetch = ()=>fetch(uri, {credentials: 'same-origin'});
|
||||
const loadWasm = WebAssembly.instantiateStreaming
|
||||
? async ()=>{
|
||||
@@ -105,6 +115,7 @@ Module[xNameOfInstantiateWasm] = function callee(imports,onSuccess){
|
||||
scripts.
|
||||
*/
|
||||
Module[xNameOfInstantiateWasm].uri = 'sqlite3.wasm';
|
||||
//#endif custom-Module.instantiateModule
|
||||
/* END FILE: api/pre-js.js, noting that the build process may add a
|
||||
line after this one to change the above .uri to a build-specific
|
||||
one. */
|
||||
|
||||
@@ -136,20 +136,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_compileoption_used", "int", "string"],
|
||||
["sqlite3_complete", "int", "string:flexible"],
|
||||
["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],
|
||||
|
||||
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
|
||||
use hand-written bindings to simplify passing of the callback
|
||||
function. */
|
||||
/* sqlite3_create_function(), sqlite3_create_function_v2(), and
|
||||
sqlite3_create_window_function() use hand-written bindings to
|
||||
simplify handling of their function-type arguments. */
|
||||
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
|
||||
use hand-written bindings to simplify passing of the callback
|
||||
function.
|
||||
["sqlite3_create_collation", "int",
|
||||
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
||||
"*", "*"],
|
||||
["sqlite3_create_collation_v2", "int",
|
||||
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
||||
"*", "*", "*"],
|
||||
*/
|
||||
["sqlite3_data_count", "int", "sqlite3_stmt*"],
|
||||
["sqlite3_db_filename", "string", "sqlite3*", "string"],
|
||||
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
|
||||
@@ -211,14 +203,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
for those, depending on how their SQL argument is provided. */
|
||||
/* sqlite3_randomness() uses a hand-written wrapper to extend
|
||||
the range of supported argument types. */
|
||||
["sqlite3_progress_handler", undefined, [
|
||||
"sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
|
||||
name: 'xProgressHandler',
|
||||
signature: 'i(p)',
|
||||
bindScope: 'context',
|
||||
contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
|
||||
}), "*"
|
||||
]],
|
||||
["sqlite3_realloc", "*","*","int"],
|
||||
["sqlite3_reset", "int", "sqlite3_stmt*"],
|
||||
/* sqlite3_reset_auto_extension() has a hand-written binding. */
|
||||
@@ -303,6 +287,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
|
||||
]/*wasm.bindingSignatures*/;
|
||||
|
||||
if( !!wasm.exports.sqlite3_progress_handler ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_progress_handler", undefined, [
|
||||
"sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
|
||||
name: 'xProgressHandler',
|
||||
signature: 'i(p)',
|
||||
bindScope: 'context',
|
||||
contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
|
||||
}), "*"
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
if( !!wasm.exports.sqlite3_stmt_explain ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"],
|
||||
@@ -336,7 +333,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}/* sqlite3_set_authorizer() */
|
||||
|
||||
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
||||
/* ^^^ "the problem" is that this is an option feature and the
|
||||
/* ^^^ "the problem" is that this is an optional feature and the
|
||||
build-time function-export list does not currently take
|
||||
optional features into account. */
|
||||
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||
@@ -385,7 +382,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
of this, the canonical builds of sqlite3.wasm/js guarantee that
|
||||
sqlite3.wasm.alloc() and friends use those allocators. Custom builds
|
||||
may not guarantee that, however. */,
|
||||
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
|
||||
["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
|
||||
["sqlite3_malloc64", "*","i64"],
|
||||
["sqlite3_msize", "i64", "*"],
|
||||
@@ -422,6 +418,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_create_module_v2", "int",
|
||||
["sqlite3*","string","sqlite3_module*","*","*"]],
|
||||
["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
|
||||
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
|
||||
["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
|
||||
["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
|
||||
["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
|
||||
@@ -950,7 +947,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
/** Code duplication reducer for functions which take an encoding
|
||||
argument and require SQLITE_UTF8. Sets the db error code to
|
||||
SQLITE_FORMAT and returns that code. */
|
||||
SQLITE_FORMAT, installs a descriptive error message,
|
||||
and returns SQLITE_FORMAT. */
|
||||
const __errEncoding = (pDb)=>{
|
||||
return util.sqlite3__wasm_db_error(
|
||||
pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
|
||||
@@ -1000,11 +998,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
this._addUDF(pDb, name, arity, m.udf);
|
||||
};
|
||||
|
||||
__dbCleanupMap.addWindowFunc = function(pDb, name, arity){
|
||||
const m = __dbCleanupMap(pDb, 1);
|
||||
if(!m.wudf) m.wudf = new Map;
|
||||
this._addUDF(pDb, name, arity, m.wudf);
|
||||
};
|
||||
if( wasm.exports.sqlite3_create_window_function ){
|
||||
__dbCleanupMap.addWindowFunc = function(pDb, name, arity){
|
||||
const m = __dbCleanupMap(pDb, 1);
|
||||
if(!m.wudf) m.wudf = new Map;
|
||||
this._addUDF(pDb, name, arity, m.wudf);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
Intended to be called _only_ from sqlite3_close_v2(),
|
||||
@@ -1273,17 +1273,20 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
]
|
||||
);
|
||||
|
||||
const __sqlite3CreateWindowFunction = wasm.xWrap(
|
||||
"sqlite3_create_window_function", "int", [
|
||||
"sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
|
||||
"int"/*eTextRep*/, "*"/*pApp*/,
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
|
||||
]
|
||||
);
|
||||
const __sqlite3CreateWindowFunction =
|
||||
wasm.exports.sqlite3_create_window_function
|
||||
? wasm.xWrap(
|
||||
"sqlite3_create_window_function", "int", [
|
||||
"sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
|
||||
"int"/*eTextRep*/, "*"/*pApp*/,
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
|
||||
new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
|
||||
]
|
||||
)
|
||||
: undefined;
|
||||
|
||||
/* Documented in the api object's initializer. */
|
||||
capi.sqlite3_create_function_v2 = function f(
|
||||
@@ -1328,61 +1331,71 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
};
|
||||
|
||||
/* Documented in the api object's initializer. */
|
||||
capi.sqlite3_create_window_function = function f(
|
||||
pDb, funcName, nArg, eTextRep, pApp,
|
||||
xStep, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
|
||||
xFinal, //void (*xFinal)(sqlite3_context*)
|
||||
xValue, //void (*xValue)(sqlite3_context*)
|
||||
xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
|
||||
xDestroy //void (*xDestroy)(void*)
|
||||
){
|
||||
if( f.length!==arguments.length ){
|
||||
return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
|
||||
}else if( 0 === (eTextRep & 0xf) ){
|
||||
eTextRep |= capi.SQLITE_UTF8;
|
||||
}else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
|
||||
return __errEncoding(pDb);
|
||||
}
|
||||
try{
|
||||
const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
|
||||
pApp, xStep, xFinal, xValue,
|
||||
xInverse, xDestroy);
|
||||
if(0===rc && (xStep instanceof Function
|
||||
|| xFinal instanceof Function
|
||||
|| xValue instanceof Function
|
||||
|| xInverse instanceof Function
|
||||
|| xDestroy instanceof Function)){
|
||||
__dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
|
||||
if( __sqlite3CreateWindowFunction ){
|
||||
capi.sqlite3_create_window_function = function f(
|
||||
pDb, funcName, nArg, eTextRep, pApp,
|
||||
xStep, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
|
||||
xFinal, //void (*xFinal)(sqlite3_context*)
|
||||
xValue, //void (*xValue)(sqlite3_context*)
|
||||
xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
|
||||
xDestroy //void (*xDestroy)(void*)
|
||||
){
|
||||
if( f.length!==arguments.length ){
|
||||
return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
|
||||
}else if( 0 === (eTextRep & 0xf) ){
|
||||
eTextRep |= capi.SQLITE_UTF8;
|
||||
}else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
|
||||
return __errEncoding(pDb);
|
||||
}
|
||||
return rc;
|
||||
}catch(e){
|
||||
console.error("sqlite3_create_window_function() setup threw:",e);
|
||||
return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
|
||||
}
|
||||
};
|
||||
try{
|
||||
const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
|
||||
pApp, xStep, xFinal, xValue,
|
||||
xInverse, xDestroy);
|
||||
if(0===rc && (xStep instanceof Function
|
||||
|| xFinal instanceof Function
|
||||
|| xValue instanceof Function
|
||||
|| xInverse instanceof Function
|
||||
|| xDestroy instanceof Function)){
|
||||
__dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
|
||||
}
|
||||
return rc;
|
||||
}catch(e){
|
||||
console.error("sqlite3_create_window_function() setup threw:",e);
|
||||
return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
|
||||
}
|
||||
};
|
||||
}else{
|
||||
delete capi.sqlite3_create_window_function;
|
||||
}
|
||||
/**
|
||||
A _deprecated_ alias for capi.sqlite3_result_js() which
|
||||
predates the addition of that function in the public API.
|
||||
*/
|
||||
capi.sqlite3_create_function_v2.udfSetResult =
|
||||
capi.sqlite3_create_function.udfSetResult =
|
||||
capi.sqlite3_create_function.udfSetResult = capi.sqlite3_result_js;
|
||||
if(capi.sqlite3_create_window_function){
|
||||
capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js;
|
||||
}
|
||||
|
||||
/**
|
||||
A _deprecated_ alias for capi.sqlite3_values_to_js() which
|
||||
predates the addition of that function in the public API.
|
||||
*/
|
||||
capi.sqlite3_create_function_v2.udfConvertArgs =
|
||||
capi.sqlite3_create_function.udfConvertArgs =
|
||||
capi.sqlite3_create_function.udfConvertArgs = capi.sqlite3_values_to_js;
|
||||
if(capi.sqlite3_create_window_function){
|
||||
capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js;
|
||||
}
|
||||
|
||||
/**
|
||||
A _deprecated_ alias for capi.sqlite3_result_error_js() which
|
||||
predates the addition of that function in the public API.
|
||||
*/
|
||||
capi.sqlite3_create_function_v2.udfSetError =
|
||||
capi.sqlite3_create_function.udfSetError =
|
||||
capi.sqlite3_create_function.udfSetError = capi.sqlite3_result_error_js;
|
||||
if(capi.sqlite3_create_window_function){
|
||||
capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js;
|
||||
}
|
||||
|
||||
}/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
|
||||
|
||||
|
||||
+78
-100
@@ -14,16 +14,17 @@
|
||||
*/
|
||||
#define SQLITE_WASM
|
||||
#ifdef SQLITE_WASM_ENABLE_C_TESTS
|
||||
# undef SQLITE_WASM_ENABLE_C_TESTS
|
||||
# define SQLITE_WASM_ENABLE_C_TESTS 1
|
||||
/*
|
||||
** Code blocked off by SQLITE_WASM_TESTS is intended solely for use in
|
||||
** unit/regression testing. They may be safely omitted from
|
||||
** Code blocked off by SQLITE_WASM_ENABLE_C_TESTS is intended solely
|
||||
** for use in unit/regression testing. They may be safely omitted from
|
||||
** client-side builds. The main unit test script, tester1.js, will
|
||||
** skip related tests if it doesn't find the corresponding functions
|
||||
** in the WASM exports.
|
||||
*/
|
||||
# define SQLITE_WASM_TESTS 1
|
||||
#else
|
||||
# define SQLITE_WASM_TESTS 0
|
||||
# define SQLITE_WASM_ENABLE_C_TESTS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -92,60 +93,18 @@
|
||||
#undef SQLITE_ENABLE_API_ARMOR
|
||||
#define SQLITE_ENABLE_API_ARMOR 1
|
||||
|
||||
#ifndef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
# define SQLITE_ENABLE_BYTECODE_VTAB 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_DBPAGE_VTAB
|
||||
# define SQLITE_ENABLE_DBPAGE_VTAB 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_DBSTAT_VTAB
|
||||
# define SQLITE_ENABLE_DBSTAT_VTAB 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_FTS5
|
||||
# define SQLITE_ENABLE_FTS5 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
|
||||
# define SQLITE_ENABLE_MATH_FUNCTIONS 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
# define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_RTREE
|
||||
# define SQLITE_ENABLE_RTREE 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_SESSION
|
||||
# define SQLITE_ENABLE_SESSION 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_STMTVTAB
|
||||
# define SQLITE_ENABLE_STMTVTAB 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
# define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_O... */
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
# define SQLITE_OMIT_DEPRECATED 1
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
# define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
# define SQLITE_OMIT_SHARED_CACHE 1
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
# define SQLITE_OMIT_UTF16 1
|
||||
#endif
|
||||
#ifndef SQLITE_OS_KV_OPTIONAL
|
||||
# define SQLITE_OS_KV_OPTIONAL 1
|
||||
#endif
|
||||
#undef SQLITE_OMIT_DEPRECATED
|
||||
#define SQLITE_OMIT_DEPRECATED 1
|
||||
#undef SQLITE_OMIT_LOAD_EXTENSION
|
||||
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
#undef SQLITE_OMIT_SHARED_CACHE
|
||||
#define SQLITE_OMIT_SHARED_CACHE 1
|
||||
#undef SQLITE_OMIT_UTF16
|
||||
#define SQLITE_OMIT_UTF16 1
|
||||
#undef SQLITE_OS_KV_OPTIONAL
|
||||
#define SQLITE_OS_KV_OPTIONAL 1
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_S... */
|
||||
@@ -173,45 +132,64 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If SQLITE_WASM_MINIMAL is defined, undefine most of the ENABLE
|
||||
** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE
|
||||
** macros.
|
||||
*/
|
||||
#ifdef SQLITE_WASM_MINIMAL
|
||||
# undef SQLITE_ENABLE_DBPAGE_VTAB
|
||||
# undef SQLITE_ENABLE_DBSTAT_VTAB
|
||||
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
# undef SQLITE_ENABLE_FTS5
|
||||
# undef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# undef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
# undef SQLITE_ENABLE_RTREE
|
||||
# undef SQLITE_ENABLE_SESSION
|
||||
# undef SQLITE_ENABLE_STMTVTAB
|
||||
# undef SQLITE_OMIT_AUTHORIZATION
|
||||
#ifdef SQLITE_WASM_BARE_BONES
|
||||
# undef SQLITE_ENABLE_DBPAGE_VTAB
|
||||
# undef SQLITE_ENABLE_DBSTAT_VTAB
|
||||
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
# undef SQLITE_ENABLE_FTS5
|
||||
# undef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# undef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
# undef SQLITE_ENABLE_RTREE
|
||||
# undef SQLITE_ENABLE_SESSION
|
||||
# undef SQLITE_ENABLE_STMTVTAB
|
||||
# undef SQLITE_OMIT_AUTHORIZATION
|
||||
# define SQLITE_OMIT_AUTHORIZATION
|
||||
/*Reminder re. custom sqlite3.c:
|
||||
# undef SQLITE_OMIT_GET_TABLE
|
||||
# define SQLITE_OMIT_GET_TABLE
|
||||
# undef SQLITE_OMIT_INCRBLOB
|
||||
# define SQLITE_OMIT_INCRBLOB
|
||||
# undef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
# define SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
# undef SQLITE_OMIT_JSON
|
||||
# define SQLITE_OMIT_JSON
|
||||
# undef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
# define SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
# undef SQLITE_OMIT_WAL
|
||||
# define SQLITE_OMIT_WAL
|
||||
/*
|
||||
The following OMITs do not work with the standard amalgamation, so
|
||||
require a custom build:
|
||||
|
||||
fossil clean -x
|
||||
./configure
|
||||
OPTS='-DSQLITE_OMIT_VIRTUALTABLE -DSQLITE_OMIT_EXPLAIN -DSQLITE_OMIT_TRIGGER' make -e sqlite3
|
||||
*/
|
||||
/*Requires a custom sqlite3.c
|
||||
# undef SQLITE_OMIT_TRIGGER
|
||||
# define SQLITE_OMIT_TRIGGER
|
||||
*/
|
||||
/*TODO (requires build tweaks)
|
||||
# undef SQLITE_OMIT_WINDOWFUNC
|
||||
# define SQLITE_OMIT_WINDOWFUNC
|
||||
*/
|
||||
/*Requires a custom sqlite3.c
|
||||
OPTS='...' make -e sqlite3
|
||||
|
||||
where ... has a -D... for each of the following OMIT flags:
|
||||
|
||||
# undef SQLITE_OMIT_EXPLAIN
|
||||
# define SQLITE_OMIT_EXPLAIN
|
||||
*/
|
||||
/*Requires a custom sqlite3.c
|
||||
|
||||
# undef SQLITE_OMIT_TRIGGER
|
||||
# define SQLITE_OMIT_TRIGGER
|
||||
|
||||
# undef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
# undef SQLITE_OMIT_WINDOWFUNC
|
||||
# define SQLITE_OMIT_WINDOWFUNC
|
||||
|
||||
As of this writing (2024-07-25), such a build fails in various ways
|
||||
for as-yet-unknown reasons.
|
||||
*/
|
||||
# undef SQLITE_OMIT_JSON
|
||||
# define SQLITE_OMIT_JSON
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_BARE_BONES)
|
||||
# define SQLITE_WASM_HAS_VTAB 1
|
||||
#else
|
||||
# define SQLITE_WASM_HAS_VTAB 0
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
@@ -264,10 +242,6 @@
|
||||
#undef INC__STRINGIFY
|
||||
#undef SQLITE_C
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
# include <emscripten/console.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** An EXPERIMENT in implementing a stack-based allocator analog to
|
||||
@@ -412,7 +386,7 @@ int sqlite3__wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
|
||||
return err_code;
|
||||
}
|
||||
|
||||
#if SQLITE_WASM_TESTS
|
||||
#if SQLITE_WASM_ENABLE_C_TESTS
|
||||
struct WasmTestStruct {
|
||||
int v4;
|
||||
void * ppV;
|
||||
@@ -432,7 +406,7 @@ void sqlite3__wasm_test_struct(WasmTestStruct * s){
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* SQLITE_WASM_TESTS */
|
||||
#endif /* SQLITE_WASM_ENABLE_C_TESTS */
|
||||
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
@@ -967,7 +941,7 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(vtab) {
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_MINIMAL)
|
||||
#if SQLITE_WASM_HAS_VTAB
|
||||
DefInt(SQLITE_INDEX_SCAN_UNIQUE);
|
||||
DefInt(SQLITE_INDEX_CONSTRAINT_EQ);
|
||||
DefInt(SQLITE_INDEX_CONSTRAINT_GT);
|
||||
@@ -995,7 +969,7 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
DefInt(SQLITE_FAIL);
|
||||
//DefInt(SQLITE_ABORT); // Also an error code
|
||||
DefInt(SQLITE_REPLACE);
|
||||
#endif /*!SQLITE_OMIT_VIRTUALTABLE*/
|
||||
#endif /*SQLITE_WASM_HAS_VTAB*/
|
||||
} _DefGroup;
|
||||
|
||||
#undef DefGroup
|
||||
@@ -1110,6 +1084,7 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
#undef CurrentStruct
|
||||
|
||||
|
||||
#if SQLITE_WASM_HAS_VTAB
|
||||
#define CurrentStruct sqlite3_vtab
|
||||
StructBinder {
|
||||
M(pModule, "p");
|
||||
@@ -1155,7 +1130,6 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
} _StructBinder;
|
||||
#undef CurrentStruct
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_MINIMAL)
|
||||
/**
|
||||
** Workaround: in order to map the various inner structs from
|
||||
** sqlite3_index_info, we have to uplift those into constructs we
|
||||
@@ -1232,9 +1206,9 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
} _StructBinder;
|
||||
#undef CurrentStruct
|
||||
|
||||
#endif /*!SQLITE_OMIT_VIRTUALTABLE*/
|
||||
#endif /*SQLITE_WASM_HAS_VTAB*/
|
||||
|
||||
#if SQLITE_WASM_TESTS
|
||||
#if SQLITE_WASM_ENABLE_C_TESTS
|
||||
#define CurrentStruct WasmTestStruct
|
||||
StructBinder {
|
||||
M(v4, "i");
|
||||
@@ -1244,7 +1218,7 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
M(xFunc, "v(p)");
|
||||
} _StructBinder;
|
||||
#undef CurrentStruct
|
||||
#endif
|
||||
#endif /*SQLITE_WASM_ENABLE_C_TESTS*/
|
||||
|
||||
} out( "]"/*structs*/);
|
||||
|
||||
@@ -1603,7 +1577,7 @@ sqlite3_kvvfs_methods * sqlite3__wasm_kvvfs_methods(void){
|
||||
return &sqlite3KvvfsMethods;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_MINIMAL)
|
||||
#if SQLITE_WASM_HAS_VTAB
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
** for use by the sqlite project's own JS/WASM bindings.
|
||||
@@ -1626,7 +1600,7 @@ int sqlite3__wasm_vtab_config(sqlite3 *pDb, int op, int arg){
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
}
|
||||
#endif /*!SQLITE_OMIT_VIRTUALTABLE*/
|
||||
#endif /*SQLITE_WASM_HAS_VTAB*/
|
||||
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
@@ -1750,6 +1724,7 @@ char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
|
||||
}
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
|
||||
#include <emscripten/console.h>
|
||||
#include <emscripten/wasmfs.h>
|
||||
|
||||
/*
|
||||
@@ -1801,7 +1776,7 @@ int sqlite3__wasm_init_wasmfs(const char *zUnused){
|
||||
}
|
||||
#endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */
|
||||
|
||||
#if SQLITE_WASM_TESTS
|
||||
#if SQLITE_WASM_ENABLE_C_TESTS
|
||||
|
||||
SQLITE_WASM_EXPORT
|
||||
int sqlite3__wasm_test_intptr(int * p){
|
||||
@@ -1967,6 +1942,9 @@ int sqlite3__wasm_SQLTester_strglob(const char *zGlob, const char *z){
|
||||
return !sqlite3__wasm_SQLTester_strnotglob(zGlob, z);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_WASM_TESTS */
|
||||
#endif /* SQLITE_WASM_ENABLE_C_TESTS */
|
||||
|
||||
#undef SQLITE_WASM_EXPORT
|
||||
#undef SQLITE_WASM_HAS_VTAB
|
||||
#undef SQLITE_WASM_BARE_BONES
|
||||
#undef SQLITE_WASM_ENABLE_C_TESTS
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
** 2022-11-12:
|
||||
**
|
||||
** In place of a legal notice, here is a blessing:
|
||||
** 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.
|
||||
@@ -1507,7 +1508,7 @@ int main(int argc, char const * const * argv){
|
||||
}
|
||||
ISFLAG("debug"){
|
||||
++g.doDebug;
|
||||
}else if(!zInfile){
|
||||
}else if(!zInfile && '-'!=argv[i][0]){
|
||||
goto do_infile;
|
||||
}else{
|
||||
fatal("Unhandled flag: %s", argv[i]);
|
||||
|
||||
+26
-53
@@ -7,21 +7,23 @@ MAKEFILE.fiddle := $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
########################################################################
|
||||
# shell.c and its build flags...
|
||||
make-np-0 := make -C $(dir.top) -n -p
|
||||
make-np-1 := sed -e 's/(TOP)/(dir.top)/g'
|
||||
# Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
|
||||
# them as vars here...
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_DEP ' | $(make-np-1)))
|
||||
# ^^^ can't do that in 1 invocation b/c newlines get stripped
|
||||
ifeq (,$(SHELL_OPT))
|
||||
$(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
|
||||
endif
|
||||
ifeq (,$(SHELL_DEP))
|
||||
$(error Could not parse SHELL_DEP from $(dir.top)/Makefile.)
|
||||
endif
|
||||
$(dir.top)/shell.c: $(SHELL_DEP) $(dir.top)/tool/mkshellc.tcl $(sqlite3.c)
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
make-np-0 := make -C $(dir.top) -n -p
|
||||
make-np-1 := sed -e 's/(TOP)/(dir.top)/g'
|
||||
# Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
|
||||
# them as vars here...
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_DEP ' | $(make-np-1)))
|
||||
# ^^^ can't do that in 1 invocation b/c newlines get stripped
|
||||
ifeq (,$(SHELL_OPT))
|
||||
$(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
|
||||
endif
|
||||
ifeq (,$(SHELL_DEP))
|
||||
$(error Could not parse SHELL_DEP from $(dir.top)/Makefile.)
|
||||
endif
|
||||
$(dir.top)/shell.c: $(SHELL_DEP) $(dir.tool)/mkshellc.tcl $(sqlite3.c)
|
||||
$(MAKE) -C $(dir.top) shell.c
|
||||
endif
|
||||
# /shell.c
|
||||
########################################################################
|
||||
|
||||
@@ -41,10 +43,11 @@ fiddle.emcc-flags = \
|
||||
$(emcc.exportedRuntimeMethods) \
|
||||
-sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
|
||||
-sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \
|
||||
$(SQLITE_OPT) $(SHELL_OPT) \
|
||||
-USQLITE_WASM_MINIMAL \
|
||||
$(SQLITE_OPT.full-featured) \
|
||||
$(SQLITE_OPT.common) \
|
||||
$(SHELL_OPT) \
|
||||
-USQLITE_WASM_BARE_BONES \
|
||||
-DSQLITE_SHELL_FIDDLE
|
||||
# -D_POSIX_C_SOURCE is needed for strdup() with emcc
|
||||
|
||||
# Flags specifically for debug builds of fiddle. Performance suffers
|
||||
# greatly in debug builds.
|
||||
@@ -55,52 +58,22 @@ fiddle.emcc-flags.debug := $(fiddle.emcc-flags) \
|
||||
|
||||
fiddle.EXPORTED_FUNCTIONS.in := \
|
||||
EXPORTED_FUNCTIONS.fiddle.in \
|
||||
$(EXPORTED_FUNCTIONS.api)
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
|
||||
|
||||
$(EXPORTED_FUNCTIONS.fiddle): $(fiddle.EXPORTED_FUNCTIONS.in) $(MAKEFILE.fiddle)
|
||||
$(EXPORTED_FUNCTIONS.fiddle): $(MKDIR.bld) $(fiddle.EXPORTED_FUNCTIONS.in) \
|
||||
$(MAKEFILE.fiddle)
|
||||
sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
|
||||
|
||||
fiddle.cses := $(dir.top)/shell.c $(sqlite3-wasm.c)
|
||||
$(eval $(call call-make-pre-post,fiddle-module,vanilla))
|
||||
|
||||
########################################################################
|
||||
# emit rules for one of the two fiddle builds. $1 must be
|
||||
# either $(dir.fiddle) or $(dir.fiddle-debug). $2 must be empty
|
||||
# in the former case and .debug in the latter.
|
||||
define make-fiddle-rules
|
||||
fiddle-module.js$(2) := $(1)/fiddle-module.js
|
||||
fiddle-module.wasm$(2) := $$(subst .js,.wasm,$$(fiddle-module.js$(2)))
|
||||
$$(fiddle-module.js$(2)): $$(MAKEFILE) $$(MAKEFILE.fiddle) \
|
||||
$$(EXPORTED_FUNCTIONS.fiddle) \
|
||||
$$(fiddle.cses) $$(pre-post-fiddle-module-vanilla.deps) $$(SOAP.js)
|
||||
@test -d "$$(dir $$@)" || mkdir -p "$$(dir $$@)"
|
||||
$$(emcc.bin) -o $$@ $$(fiddle.emcc-flags$(2)) \
|
||||
$$(pre-post-fiddle-module-vanilla.flags) \
|
||||
$$(fiddle.cses)
|
||||
$$(maybe-wasm-strip) $$(fiddle-module.wasm$(2))
|
||||
@cp -p $$(SOAP.js) $$(dir $$@)
|
||||
@if [[ x.debug = x$(2) ]]; then \
|
||||
cp -p $$(dir.fiddle)/index.html \
|
||||
$$(dir.fiddle)/fiddle.js \
|
||||
$$(dir.fiddle)/fiddle-worker.js \
|
||||
$$(dir $$@)/.; \
|
||||
fi
|
||||
@for i in $(1)/*.*js $(1)/*.html $(1)/*.wasm; do \
|
||||
test -f $$$${i} || continue; \
|
||||
gzip < $$$${i} > $$$${i}.gz; \
|
||||
done
|
||||
fiddle$(2): $$(fiddle-module.js$(2)) $(1)/fiddle.js.gz
|
||||
endef
|
||||
|
||||
$(eval $(call make-fiddle-rules,$(dir.fiddle)))
|
||||
$(eval $(call make-fiddle-rules,$(dir.fiddle-debug),.debug))
|
||||
fiddle: $(fiddle-module.js) $(fiddle-module.js.debug)
|
||||
fiddle.debug: $(fiddle-module.js.debug)
|
||||
|
||||
clean: clean-fiddle
|
||||
clean-fiddle:
|
||||
rm -f $(fiddle-module.js) \
|
||||
$(fiddle-module.wasm) \
|
||||
rm -f $(dir.fiddle)/fiddle-module.js \
|
||||
$(dir.fiddle)/*.wasm \
|
||||
$(dir.fiddle)/sqlite3-opfs-*.js \
|
||||
$(dir.fiddle)/*.gz \
|
||||
EXPORTED_FUNCTIONS.fiddle
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
two lines and ensure that these files are on the web server. -->
|
||||
<!--script src="jqterm/jqterm-bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="jqterm/jquery.terminal.min.css"/-->
|
||||
<link rel="stylesheet" href="emscripten.css"/>
|
||||
<style>
|
||||
/* The following styles are for app-level use. */
|
||||
:root {
|
||||
|
||||
+3
-3
@@ -125,10 +125,10 @@
|
||||
the WASMFS build is available on this server (it is not by
|
||||
default) and that this server emits the COOP/COEP headers.
|
||||
<ul>
|
||||
<li><a href='scratchpad-wasmfs.html'>scratchpad-wasmfs</a>:
|
||||
<!--li><a href='scratchpad-wasmfs.html'>scratchpad-wasmfs</a>:
|
||||
experimenting with WASMFS/OPFS-based persistence.
|
||||
</li>
|
||||
<li><a href='speedtest1-wasmfs.html?flags=--size,15'>speedtest1-wasmfs</a>:
|
||||
</li-->
|
||||
<li><a href='speedtest1-wasmfs.html?flags=--size,10'>speedtest1-wasmfs</a>:
|
||||
a variant of speedtest1 built solely for the wasmfs/opfs
|
||||
feature.
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
** 2024-09-23
|
||||
**
|
||||
** 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 app's single purpose is to emit parts of the Makefile code for
|
||||
** building sqlite3's WASM build. The main motivation is to generate
|
||||
** code which "can" be created via GNU Make's eval command but is
|
||||
** highly illegible when constructed that way. Attempts to write this
|
||||
** app in Bash and TCL have suffered from the problem that both
|
||||
** require escaping $ symbols, making the resulting script code as
|
||||
** illegible as the eval spaghetti we want to get away from. Writing
|
||||
** it in C is, somewhat surprisingly, _slightly_ less illegible than
|
||||
** writing it in bash, tcl, or native Make code.
|
||||
**
|
||||
** The emitted makefile code is not standalone - it depends on
|
||||
** variables and $(call)able functions from the main makefile.
|
||||
**
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
#define DEBUG 1
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define pf printf
|
||||
#define ps puts
|
||||
/* Very common printf() args combo. */
|
||||
#define zNM zName, zMode
|
||||
|
||||
/*
|
||||
** Valid names for the zName arguments.
|
||||
*/
|
||||
#define JS_BUILD_NAMES sqlite3 sqlite3-wasmfs
|
||||
/*
|
||||
** Valid names for the zMode arguments of the "sqlite3" build. For the
|
||||
** "sqlite3-wasmfs" build, only "esm" (ES6 Module) is legal.
|
||||
*/
|
||||
#define JS_BUILD_MODES vanilla esm bundler-friendly node
|
||||
static const char * zBanner =
|
||||
"\n########################################################################\n";
|
||||
|
||||
/*
|
||||
** Emits common vars needed by the rest of the emitted code (but not
|
||||
** needed by makefile code outside of these generated pieces).
|
||||
*/
|
||||
static void mk_prologue(void){
|
||||
pf("%s", zBanner);
|
||||
ps("# extern-post-js* and extern-pre-js* are files for use with");
|
||||
ps("# Emscripten's --extern-pre-js and --extern-post-js flags.");
|
||||
ps("extern-pre-js.js := $(dir.api)/extern-pre-js.js");
|
||||
ps("extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js");
|
||||
ps("# Emscripten flags for --[extern-][pre|post]-js=... for the");
|
||||
ps("# various builds.");
|
||||
ps("pre-post-common.flags := --extern-pre-js=$(sqlite3-license-version.js)");
|
||||
ps("# pre-post-jses.deps.* = a list of dependencies for the");
|
||||
ps("# --[extern-][pre/post]-js files.");
|
||||
ps("pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)");
|
||||
}
|
||||
|
||||
/*
|
||||
** Emits makefile code for setting up values for the --pre-js=FILE,
|
||||
** --post-js=FILE, and --extern-post-js=FILE emcc flags, as well as
|
||||
** populating those files.
|
||||
*/
|
||||
static void mk_pre_post(const char *zName /* build name */,
|
||||
const char *zMode /* build mode */,
|
||||
const char *zCmppD /* optional -D flags for c-pp for the
|
||||
** --pre/--post-js files. */){
|
||||
pf("%s# Begin --pre/--post flags for %s-%s\n", zBanner, zName, zMode);
|
||||
pf("c-pp.D.%s-%s := %s\n", zNM, zCmppD ? zCmppD : "");
|
||||
pf("pre-post-%s-%s.flags ?=\n", zNM);
|
||||
|
||||
/* --pre-js=... */
|
||||
pf("pre-js.js.%s-%s := $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
zNM, zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(MAKEFILE)\n", zNM);
|
||||
#if 1
|
||||
pf("$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s),"
|
||||
"$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
#else
|
||||
/* This part is needed if/when we re-enable the custom
|
||||
** Module.instantiateModule() impl in api/pre-js.c-pp.js. */
|
||||
pf("pre-js.js.%s-%s.intermediary := $(dir.tmp)/pre-js.%s-%s.intermediary.js\n",
|
||||
zNM, zNM);
|
||||
pf("$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s.intermediary),"
|
||||
"$(c-pp.D.%s-%s) -Dcustom-Module.instantiateModule))\n", zNM, zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(pre-js.js.%s-%s.intermediary)\n", zNM, zNM);
|
||||
pf("\tcp $(pre-js.js.%s-%s.intermediary) $@\n", zNM);
|
||||
|
||||
/* Amend $(pre-js.js.zName-zMode) for all targets except the plain
|
||||
** "sqlite3" build... */
|
||||
if( 0!=strcmp("sqlite3-wasmfs", zName)
|
||||
&& 0!=strcmp("sqlite3", zName) ){
|
||||
pf("\t@echo 'Module[xNameOfInstantiateWasm].uri = "
|
||||
"\"%s.wasm\";' >> $@\n", zName);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --post-js=... */
|
||||
pf("post-js.js.%s-%s := $(dir.tmp)/post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("$(eval $(call C-PP.FILTER,$(post-js.js.in),"
|
||||
"$(post-js.js.%s-%s),$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
|
||||
/* --extern-post-js=... */
|
||||
pf("extern-post-js.js.%s-%s := $(dir.tmp)/extern-post-js.%s-%s.js\n", zNM, zNM);
|
||||
pf("$(eval $(call C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.%s-%s),"
|
||||
"$(c-pp.D.%s-%s)))\n", zNM, zNM);
|
||||
|
||||
/* Combine flags for use with emcc... */
|
||||
pf("pre-post-common.flags.%s-%s := "
|
||||
"$(pre-post-common.flags) "
|
||||
"--post-js=$(post-js.js.%s-%s) "
|
||||
"--extern-post-js=$(extern-post-js.js.%s-%s)\n", zNM, zNM, zNM);
|
||||
|
||||
pf("pre-post-%s-%s.flags += $(pre-post-common.flags.%s-%s) "
|
||||
"--pre-js=$(pre-js.js.%s-%s)\n", zNM, zNM, zNM);
|
||||
|
||||
/* Set up deps... */
|
||||
pf("pre-post-jses.%s-%s.deps := $(pre-post-jses.deps.common) "
|
||||
"$(post-js.js.%s-%s) $(extern-post-js.js.%s-%s)\n",
|
||||
zNM, zNM, zNM);
|
||||
pf("pre-post-%s-%s.deps := $(pre-post-jses.%s-%s.deps) $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
zNM, zNM, zNM);
|
||||
pf("# End --pre/--post flags for %s-%s%s", zName, zMode, zBanner);
|
||||
}
|
||||
|
||||
/*
|
||||
** Emits rules for the fiddle builds.
|
||||
**
|
||||
*/
|
||||
static void mk_fiddle(){
|
||||
int i = 0;
|
||||
|
||||
mk_pre_post("fiddle-module","vanilla", 0);
|
||||
for( ; i < 2; ++i ){
|
||||
const char *zTail = i ? ".debug" : "";
|
||||
const char *zDir = i ? "$(dir.fiddle-debug)" : "$(dir.fiddle)";
|
||||
|
||||
pf("%s# Begin fiddle%s\n", zBanner, zTail);
|
||||
pf("fiddle-module.js%s := %s/fiddle-module.js\n", zTail, zDir);
|
||||
pf("fiddle-module.wasm%s := "
|
||||
"$(subst .js,.wasm,$(fiddle-module.js%s))\n", zTail, zTail);
|
||||
pf("$(fiddle-module.js%s):%s $(MAKEFILE) $(MAKEFILE.fiddle) "
|
||||
"$(EXPORTED_FUNCTIONS.fiddle) "
|
||||
"$(fiddle.cses) $(pre-post-fiddle-module-vanilla.deps) "
|
||||
"$(SOAP.js)\n",
|
||||
zTail, (i ? " $(fiddle-module.js)" : ""));
|
||||
if( 1==i ){/*fiddle.debug*/
|
||||
pf(" @test -d \"$(dir $@)\" || mkdir -p \"$(dir $@)\"\n");
|
||||
}
|
||||
pf(" $(emcc.bin) -o $@ $(fiddle.emcc-flags%s) "
|
||||
"$(pre-post-fiddle-module-vanilla.flags) $(fiddle.cses)\n",
|
||||
zTail);
|
||||
pf(" $(maybe-wasm-strip) $(fiddle-module.wasm%s)\n", zTail);
|
||||
pf(" @cp -p $(SOAP.js) $(dir $@)\n");
|
||||
if( 1==i ){/*fiddle.debug*/
|
||||
pf(" cp -p $(dir.fiddle)/index.html "
|
||||
"$(dir.fiddle)/fiddle.js "
|
||||
"$(dir.fiddle)/fiddle-worker.js "
|
||||
"$(dir $@)\n");
|
||||
}
|
||||
pf(" @for i in %s/*.*js %s/*.html %s/*.wasm; do \\\n"
|
||||
" test -f $${i} || continue; \\\n"
|
||||
" gzip < $${i} > $${i}.gz; \\\n"
|
||||
" done\n", zDir, zDir, zDir);
|
||||
if( 0==i ){
|
||||
ps("fiddle: $(fiddle-module.js)");
|
||||
}else{
|
||||
ps("fiddle-debug: $(fiddle-module-debug.js)");
|
||||
}
|
||||
pf("# End fiddle%s%s", zTail, zBanner);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Emits makefile code for one build of the library, primarily defined
|
||||
** by the combination of zName and zMode, each of which must be values
|
||||
** from JS_BUILD_NAMES resp. JS_BUILD_MODES.
|
||||
*/
|
||||
static void mk_lib_mode(const char *zName /* build name */,
|
||||
const char *zMode /* build mode */,
|
||||
int bIsEsm /* true only for ESM build */,
|
||||
const char *zApiJsOut /* name of generated sqlite3-api.js/.mjs */,
|
||||
const char *zJsOut /* name of generated sqlite3.js/.mjs */,
|
||||
const char *zCmppD /* extra -D flags for c-pp */,
|
||||
const char *zEmcc /* extra flags for emcc */){
|
||||
assert( zName );
|
||||
assert( zMode );
|
||||
assert( zApiJsOut );
|
||||
assert( zJsOut );
|
||||
if( !zCmppD ) zCmppD = "";
|
||||
if( !zEmcc ) zEmcc = "";
|
||||
|
||||
pf("%s# Begin build [%s-%s]\n", zBanner, zNM);
|
||||
pf("ifneq (1,$(MAKING_CLEAN))\n");
|
||||
pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut);
|
||||
mk_pre_post(zNM, zCmppD);
|
||||
pf("\nemcc.flags.%s.%s ?=\n", zNM);
|
||||
if( zEmcc[0] ){
|
||||
pf("emcc.flags.%s.%s += %s\n", zNM, zEmcc);
|
||||
}
|
||||
pf("$(eval $(call C-PP.FILTER, $(sqlite3-api.js.in), %s, %s))\n",
|
||||
zApiJsOut, zCmppD);
|
||||
|
||||
/* target zJsOut */
|
||||
pf("%s: %s $(MAKEFILE) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) "
|
||||
"$(pre-post-%s-%s.deps)\n",
|
||||
zJsOut, zApiJsOut, zNM);
|
||||
pf("\t@echo \"Building $@ ...\"\n");
|
||||
pf("\t$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n");
|
||||
pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode);
|
||||
pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM);
|
||||
pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM);
|
||||
pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n"
|
||||
"\t\t$(cflags.%s) $(cflags.%s.%s) \\\n"
|
||||
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM);
|
||||
if( bIsEsm ){
|
||||
/* TODO? Replace this CALL with the corresponding makefile code.
|
||||
** OTOH, we also use this $(call) in the speedtest1-wasmfs build,
|
||||
** which is not part of the rules emitted by this program. */
|
||||
pf("\t@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,%d)\n",
|
||||
0==strcmp("sqlite3-wasmfs", zName) ? 1 : 0);
|
||||
}
|
||||
pf("\t@dotwasm=$(basename $@).wasm; \\\n"
|
||||
"\tchmod -x $$dotwasm; \\\n"
|
||||
"\t$(maybe-wasm-strip) $$dotwasm; \\\n");
|
||||
/*
|
||||
** The above $(emcc.bin) call will write zJsOut and will create a
|
||||
** like-named .wasm file. That .wasm file name gets hard-coded into
|
||||
** zJsOut so we need to, for some cases, patch zJsOut to use the
|
||||
** name sqlite3.wasm instead. Note that the resulting .wasm file is
|
||||
** identical for all builds for which zEmcc is empty.
|
||||
*/
|
||||
if( 0==strcmp("bundler-friendly", zMode)
|
||||
|| 0==strcmp("node", zMode) ) {
|
||||
pf("\techo 'Patching $@ for %s.wasm...' \\\n", zName);
|
||||
pf("\trm -f $$dotwasm; dotwasm=; \\\n"
|
||||
"\tsed -i -e 's/%s-%s.wasm/%s.wasm/g' $@ || exit $$?; \\\n",
|
||||
zNM, zName);
|
||||
}
|
||||
pf("\tls -la $$dotwasm $@\n");
|
||||
if( 0!=strcmp("sqlite3-wasmfs", zName) ){
|
||||
/* The sqlite3-wasmfs build is optional and needs to be invoked
|
||||
** conditionally using info we don't have here. */
|
||||
pf("all: %s\n", zJsOut);
|
||||
}
|
||||
ps("endif\n# ^^^ !$(MAKING_CLEAN)");
|
||||
pf("# End build [%s-%s]%s", zNM, zBanner);
|
||||
}
|
||||
|
||||
int main(void){
|
||||
int rc = 0;
|
||||
pf("# What follows was GENERATED by %s. Edit at your own risk.\n", __FILE__);
|
||||
mk_prologue();
|
||||
mk_lib_mode("sqlite3", "vanilla", 0,
|
||||
"$(sqlite3-api.js)", "$(sqlite3.js)", 0, 0);
|
||||
mk_lib_mode("sqlite3", "esm", 1,
|
||||
"$(sqlite3-api.mjs)", "$(sqlite3.mjs)",
|
||||
"-Dtarget=es6-module", 0);
|
||||
mk_lib_mode("sqlite3", "bundler-friendly", 1,
|
||||
"$(sqlite3-api-bundler-friendly.mjs)", "$(sqlite3-bundler-friendly.mjs)",
|
||||
"$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly", 0);
|
||||
mk_lib_mode("sqlite3" , "node", 1,
|
||||
"$(sqlite3-api-node.mjs)", "$(sqlite3-node.mjs)",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node", 0);
|
||||
mk_lib_mode("sqlite3-wasmfs", "esm" ,1,
|
||||
"$(sqlite3-api-wasmfs.mjs)", "$(sqlite3-wasmfs.mjs)",
|
||||
"$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs",
|
||||
"-sEXPORT_ES6 -sUSE_ES6_IMPORT_META");
|
||||
|
||||
mk_fiddle();
|
||||
mk_pre_post("speedtest1","vanilla", 0);
|
||||
mk_pre_post("speedtest1-wasmfs","esm", "$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs");
|
||||
return rc;
|
||||
}
|
||||
@@ -10,14 +10,14 @@ wMsg('log',"speedtest1-wasmfs starting...");
|
||||
*/
|
||||
const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
|
||||
if(undefined !== f._) return f._;
|
||||
if( !self.FileSystemHandle
|
||||
|| !self.FileSystemDirectoryHandle
|
||||
|| !self.FileSystemFileHandle){
|
||||
if( !globalThis.FileSystemHandle
|
||||
|| !globalThis.FileSystemDirectoryHandle
|
||||
|| !globalThis.FileSystemFileHandle){
|
||||
return f._ = "";
|
||||
}
|
||||
try{
|
||||
if(0===wasmUtil.xCallWrapped(
|
||||
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
|
||||
'sqlite3__wasm_init_wasmfs', 'i32', ['string'], dirName
|
||||
)){
|
||||
return f._ = dirName;
|
||||
}else{
|
||||
@@ -36,7 +36,7 @@ const logErr = (...args)=>wMsg('logErr',...args);
|
||||
const runTests = function(sqlite3){
|
||||
console.log("Module inited.",sqlite3);
|
||||
const wasm = sqlite3.wasm;
|
||||
const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
|
||||
const __unlink = wasm.xWrap("sqlite3__wasm_vfs_unlink", "int", ["*","string"]);
|
||||
const unlink = (fn)=>__unlink(0,fn);
|
||||
const pDir = wasmfsDir(wasm);
|
||||
if(pDir) log("Persistent storage:",pDir);
|
||||
@@ -46,7 +46,7 @@ const runTests = function(sqlite3){
|
||||
}
|
||||
const scope = wasm.scopedAllocPush();
|
||||
const dbFile = pDir+"/speedtest1.db";
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
const urlParams = new URL(globalThis.location.href).searchParams;
|
||||
const argv = ["speedtest1"];
|
||||
if(urlParams.has('flags')){
|
||||
argv.push(...(urlParams.get('flags').split(',')));
|
||||
|
||||
+254
-244
@@ -848,171 +848,176 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}/*WhWasmUtil*/)
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t('sqlite3.StructBinder (jaccwabyt🐇)', function(sqlite3){
|
||||
const S = sqlite3, W = S.wasm;
|
||||
const MyStructDef = {
|
||||
sizeof: 16,
|
||||
members: {
|
||||
p4: {offset: 0, sizeof: 4, signature: "i"},
|
||||
pP: {offset: 4, sizeof: 4, signature: "P"},
|
||||
ro: {offset: 8, sizeof: 4, signature: "i", readOnly: true},
|
||||
cstr: {offset: 12, sizeof: 4, signature: "s"}
|
||||
}
|
||||
};
|
||||
if(W.bigIntEnabled){
|
||||
const m = MyStructDef;
|
||||
m.members.p8 = {offset: m.sizeof, sizeof: 8, signature: "j"};
|
||||
m.sizeof += m.members.p8.sizeof;
|
||||
}
|
||||
const StructType = S.StructBinder.StructType;
|
||||
const K = S.StructBinder('my_struct',MyStructDef);
|
||||
T.mustThrowMatching(()=>K(), /via 'new'/).
|
||||
mustThrowMatching(()=>new K('hi'), /^Invalid pointer/);
|
||||
const k1 = new K(), k2 = new K();
|
||||
try {
|
||||
T.assert(k1.constructor === K).
|
||||
assert(K.isA(k1)).
|
||||
assert(k1 instanceof K).
|
||||
assert(K.prototype.lookupMember('p4').key === '$p4').
|
||||
assert(K.prototype.lookupMember('$p4').name === 'p4').
|
||||
mustThrowMatching(()=>K.prototype.lookupMember('nope'), /not a mapped/).
|
||||
assert(undefined === K.prototype.lookupMember('nope',false)).
|
||||
assert(k1 instanceof StructType).
|
||||
assert(StructType.isA(k1)).
|
||||
mustThrowMatching(()=>k1.$ro = 1, /read-only/);
|
||||
Object.keys(MyStructDef.members).forEach(function(key){
|
||||
key = K.memberKey(key);
|
||||
T.assert(0 == k1[key],
|
||||
"Expecting allocation to zero the memory "+
|
||||
"for "+key+" but got: "+k1[key]+
|
||||
" from "+k1.memoryDump());
|
||||
});
|
||||
T.assert('number' === typeof k1.pointer).
|
||||
mustThrowMatching(()=>k1.pointer = 1, /pointer/);
|
||||
k1.$p4 = 1; k1.$pP = 2;
|
||||
T.assert(1 === k1.$p4).assert(2 === k1.$pP);
|
||||
if(MyStructDef.members.$p8){
|
||||
k1.$p8 = 1/*must not throw despite not being a BigInt*/;
|
||||
k1.$p8 = BigInt(Number.MAX_SAFE_INTEGER * 2);
|
||||
T.assert(BigInt(2 * Number.MAX_SAFE_INTEGER) === k1.$p8);
|
||||
}
|
||||
T.assert(!k1.ondispose);
|
||||
k1.setMemberCString('cstr', "A C-string.");
|
||||
T.assert(Array.isArray(k1.ondispose)).
|
||||
assert(k1.ondispose[0] === k1.$cstr).
|
||||
assert('number' === typeof k1.$cstr).
|
||||
assert('A C-string.' === k1.memberToJsString('cstr'));
|
||||
k1.$pP = k2;
|
||||
T.assert(k1.$pP === k2.pointer);
|
||||
k1.$pP = null/*null is special-cased to 0.*/;
|
||||
T.assert(0===k1.$pP);
|
||||
let ptr = k1.pointer;
|
||||
k1.dispose();
|
||||
T.assert(undefined === k1.pointer).
|
||||
mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
|
||||
}finally{
|
||||
k1.dispose();
|
||||
k2.dispose();
|
||||
}
|
||||
|
||||
if(!W.bigIntEnabled){
|
||||
log("Skipping WasmTestStruct tests: BigInt not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
const WTStructDesc =
|
||||
W.ctype.structs.filter((e)=>'WasmTestStruct'===e.name)[0];
|
||||
const autoResolvePtr = true /* EXPERIMENTAL */;
|
||||
if(autoResolvePtr){
|
||||
WTStructDesc.members.ppV.signature = 'P';
|
||||
}
|
||||
const WTStruct = S.StructBinder(WTStructDesc);
|
||||
//log(WTStruct.structName, WTStruct.structInfo);
|
||||
const wts = new WTStruct();
|
||||
//log("WTStruct.prototype keys:",Object.keys(WTStruct.prototype));
|
||||
try{
|
||||
T.assert(wts.constructor === WTStruct).
|
||||
assert(WTStruct.memberKeys().indexOf('$ppV')>=0).
|
||||
assert(wts.memberKeys().indexOf('$v8')>=0).
|
||||
assert(!K.isA(wts)).
|
||||
assert(WTStruct.isA(wts)).
|
||||
assert(wts instanceof WTStruct).
|
||||
assert(wts instanceof StructType).
|
||||
assert(StructType.isA(wts)).
|
||||
assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
|
||||
assert(0===wts.$ppV).assert(0===wts.$xFunc);
|
||||
const testFunc =
|
||||
W.xGet('sqlite3__wasm_test_struct'/*name gets mangled in -O3 builds!*/);
|
||||
let counter = 0;
|
||||
//log("wts.pointer =",wts.pointer);
|
||||
const wtsFunc = function(arg){
|
||||
/*log("This from a JS function called from C, "+
|
||||
"which itself was called from JS. arg =",arg);*/
|
||||
++counter;
|
||||
if(3===counter){
|
||||
tossQuietly("Testing exception propagation.");
|
||||
.t({
|
||||
name: 'sqlite3.StructBinder (jaccwabyt🐇)',
|
||||
predicate: (sqlite3)=>!!sqlite3.wasm.exports.sqlite3__wasm_test_struct
|
||||
|| "Built without SQLITE_WASM_ENABLE_C_TESTS",
|
||||
test: function(sqlite3){
|
||||
const S = sqlite3, W = S.wasm;
|
||||
const MyStructDef = {
|
||||
sizeof: 16,
|
||||
members: {
|
||||
p4: {offset: 0, sizeof: 4, signature: "i"},
|
||||
pP: {offset: 4, sizeof: 4, signature: "P"},
|
||||
ro: {offset: 8, sizeof: 4, signature: "i", readOnly: true},
|
||||
cstr: {offset: 12, sizeof: 4, signature: "s"}
|
||||
}
|
||||
};
|
||||
if(W.bigIntEnabled){
|
||||
const m = MyStructDef;
|
||||
m.members.p8 = {offset: m.sizeof, sizeof: 8, signature: "j"};
|
||||
m.sizeof += m.members.p8.sizeof;
|
||||
}
|
||||
const StructType = S.StructBinder.StructType;
|
||||
const K = S.StructBinder('my_struct',MyStructDef);
|
||||
T.mustThrowMatching(()=>K(), /via 'new'/).
|
||||
mustThrowMatching(()=>new K('hi'), /^Invalid pointer/);
|
||||
const k1 = new K(), k2 = new K();
|
||||
try {
|
||||
T.assert(k1.constructor === K).
|
||||
assert(K.isA(k1)).
|
||||
assert(k1 instanceof K).
|
||||
assert(K.prototype.lookupMember('p4').key === '$p4').
|
||||
assert(K.prototype.lookupMember('$p4').name === 'p4').
|
||||
mustThrowMatching(()=>K.prototype.lookupMember('nope'), /not a mapped/).
|
||||
assert(undefined === K.prototype.lookupMember('nope',false)).
|
||||
assert(k1 instanceof StructType).
|
||||
assert(StructType.isA(k1)).
|
||||
mustThrowMatching(()=>k1.$ro = 1, /read-only/);
|
||||
Object.keys(MyStructDef.members).forEach(function(key){
|
||||
key = K.memberKey(key);
|
||||
T.assert(0 == k1[key],
|
||||
"Expecting allocation to zero the memory "+
|
||||
"for "+key+" but got: "+k1[key]+
|
||||
" from "+k1.memoryDump());
|
||||
});
|
||||
T.assert('number' === typeof k1.pointer).
|
||||
mustThrowMatching(()=>k1.pointer = 1, /pointer/);
|
||||
k1.$p4 = 1; k1.$pP = 2;
|
||||
T.assert(1 === k1.$p4).assert(2 === k1.$pP);
|
||||
if(MyStructDef.members.$p8){
|
||||
k1.$p8 = 1/*must not throw despite not being a BigInt*/;
|
||||
k1.$p8 = BigInt(Number.MAX_SAFE_INTEGER * 2);
|
||||
T.assert(BigInt(2 * Number.MAX_SAFE_INTEGER) === k1.$p8);
|
||||
}
|
||||
T.assert(!k1.ondispose);
|
||||
k1.setMemberCString('cstr', "A C-string.");
|
||||
T.assert(Array.isArray(k1.ondispose)).
|
||||
assert(k1.ondispose[0] === k1.$cstr).
|
||||
assert('number' === typeof k1.$cstr).
|
||||
assert('A C-string.' === k1.memberToJsString('cstr'));
|
||||
k1.$pP = k2;
|
||||
T.assert(k1.$pP === k2.pointer);
|
||||
k1.$pP = null/*null is special-cased to 0.*/;
|
||||
T.assert(0===k1.$pP);
|
||||
let ptr = k1.pointer;
|
||||
k1.dispose();
|
||||
T.assert(undefined === k1.pointer).
|
||||
mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
|
||||
}finally{
|
||||
k1.dispose();
|
||||
k2.dispose();
|
||||
}
|
||||
wts.$v4 = 10; wts.$v8 = 20;
|
||||
wts.$xFunc = W.installFunction(wtsFunc, wts.memberSignature('xFunc'))
|
||||
T.assert(0===counter).assert(10 === wts.$v4).assert(20n === wts.$v8)
|
||||
.assert(0 === wts.$ppV).assert('number' === typeof wts.$xFunc)
|
||||
.assert(0 === wts.$cstr)
|
||||
.assert(wts.memberIsString('$cstr'))
|
||||
.assert(!wts.memberIsString('$v4'))
|
||||
.assert(null === wts.memberToJsString('$cstr'))
|
||||
.assert(W.functionEntry(wts.$xFunc) instanceof Function);
|
||||
/* It might seem silly to assert that the values match
|
||||
what we just set, but recall that all of those property
|
||||
reads and writes are, via property interceptors,
|
||||
actually marshaling their data to/from a raw memory
|
||||
buffer, so merely reading them back is actually part of
|
||||
testing the struct-wrapping API. */
|
||||
|
||||
testFunc(wts.pointer);
|
||||
//log("wts.pointer, wts.$ppV",wts.pointer, wts.$ppV);
|
||||
T.assert(1===counter).assert(20 === wts.$v4).assert(40n === wts.$v8)
|
||||
.assert(wts.$ppV === wts.pointer)
|
||||
.assert('string' === typeof wts.memberToJsString('cstr'))
|
||||
.assert(wts.memberToJsString('cstr') === wts.memberToJsString('$cstr'))
|
||||
.mustThrowMatching(()=>wts.memberToJsString('xFunc'),
|
||||
/Invalid member type signature for C-string/)
|
||||
;
|
||||
testFunc(wts.pointer);
|
||||
T.assert(2===counter).assert(40 === wts.$v4).assert(80n === wts.$v8)
|
||||
.assert(wts.$ppV === wts.pointer);
|
||||
/** The 3rd call to wtsFunc throw from JS, which is called
|
||||
from C, which is called from JS. Let's ensure that
|
||||
that exception propagates back here... */
|
||||
T.mustThrowMatching(()=>testFunc(wts.pointer),/^Testing/);
|
||||
W.uninstallFunction(wts.$xFunc);
|
||||
wts.$xFunc = 0;
|
||||
wts.$ppV = 0;
|
||||
T.assert(!wts.$ppV);
|
||||
//WTStruct.debugFlags(0x03);
|
||||
wts.$ppV = wts;
|
||||
T.assert(wts.pointer === wts.$ppV)
|
||||
wts.setMemberCString('cstr', "A C-string.");
|
||||
T.assert(Array.isArray(wts.ondispose)).
|
||||
assert(wts.ondispose[0] === wts.$cstr).
|
||||
assert('A C-string.' === wts.memberToJsString('cstr'));
|
||||
const ptr = wts.pointer;
|
||||
wts.dispose();
|
||||
T.assert(ptr).assert(undefined === wts.pointer);
|
||||
}finally{
|
||||
wts.dispose();
|
||||
}
|
||||
if(!W.bigIntEnabled){
|
||||
log("Skipping WasmTestStruct tests: BigInt not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(1){ // ondispose of other struct instances
|
||||
const s1 = new WTStruct, s2 = new WTStruct, s3 = new WTStruct;
|
||||
T.assert(s1.lookupMember instanceof Function)
|
||||
.assert(s1.addOnDispose instanceof Function);
|
||||
s1.addOnDispose(s2,"testing variadic args");
|
||||
T.assert(2===s1.ondispose.length);
|
||||
s2.addOnDispose(s3);
|
||||
s1.dispose();
|
||||
T.assert(!s2.pointer,"Expecting s2 to be ondispose'd by s1.");
|
||||
T.assert(!s3.pointer,"Expecting s3 to be ondispose'd by s2.");
|
||||
const WTStructDesc =
|
||||
W.ctype.structs.filter((e)=>'WasmTestStruct'===e.name)[0];
|
||||
const autoResolvePtr = true /* EXPERIMENTAL */;
|
||||
if(autoResolvePtr){
|
||||
WTStructDesc.members.ppV.signature = 'P';
|
||||
}
|
||||
const WTStruct = S.StructBinder(WTStructDesc);
|
||||
//log(WTStruct.structName, WTStruct.structInfo);
|
||||
const wts = new WTStruct();
|
||||
//log("WTStruct.prototype keys:",Object.keys(WTStruct.prototype));
|
||||
try{
|
||||
T.assert(wts.constructor === WTStruct).
|
||||
assert(WTStruct.memberKeys().indexOf('$ppV')>=0).
|
||||
assert(wts.memberKeys().indexOf('$v8')>=0).
|
||||
assert(!K.isA(wts)).
|
||||
assert(WTStruct.isA(wts)).
|
||||
assert(wts instanceof WTStruct).
|
||||
assert(wts instanceof StructType).
|
||||
assert(StructType.isA(wts)).
|
||||
assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
|
||||
assert(0===wts.$ppV).assert(0===wts.$xFunc);
|
||||
const testFunc =
|
||||
W.xGet('sqlite3__wasm_test_struct'/*name gets mangled in -O3 builds!*/);
|
||||
let counter = 0;
|
||||
//log("wts.pointer =",wts.pointer);
|
||||
const wtsFunc = function(arg){
|
||||
/*log("This from a JS function called from C, "+
|
||||
"which itself was called from JS. arg =",arg);*/
|
||||
++counter;
|
||||
if(3===counter){
|
||||
tossQuietly("Testing exception propagation.");
|
||||
}
|
||||
}
|
||||
wts.$v4 = 10; wts.$v8 = 20;
|
||||
wts.$xFunc = W.installFunction(wtsFunc, wts.memberSignature('xFunc'))
|
||||
T.assert(0===counter).assert(10 === wts.$v4).assert(20n === wts.$v8)
|
||||
.assert(0 === wts.$ppV).assert('number' === typeof wts.$xFunc)
|
||||
.assert(0 === wts.$cstr)
|
||||
.assert(wts.memberIsString('$cstr'))
|
||||
.assert(!wts.memberIsString('$v4'))
|
||||
.assert(null === wts.memberToJsString('$cstr'))
|
||||
.assert(W.functionEntry(wts.$xFunc) instanceof Function);
|
||||
/* It might seem silly to assert that the values match
|
||||
what we just set, but recall that all of those property
|
||||
reads and writes are, via property interceptors,
|
||||
actually marshaling their data to/from a raw memory
|
||||
buffer, so merely reading them back is actually part of
|
||||
testing the struct-wrapping API. */
|
||||
|
||||
testFunc(wts.pointer);
|
||||
//log("wts.pointer, wts.$ppV",wts.pointer, wts.$ppV);
|
||||
T.assert(1===counter).assert(20 === wts.$v4).assert(40n === wts.$v8)
|
||||
.assert(wts.$ppV === wts.pointer)
|
||||
.assert('string' === typeof wts.memberToJsString('cstr'))
|
||||
.assert(wts.memberToJsString('cstr') === wts.memberToJsString('$cstr'))
|
||||
.mustThrowMatching(()=>wts.memberToJsString('xFunc'),
|
||||
/Invalid member type signature for C-string/)
|
||||
;
|
||||
testFunc(wts.pointer);
|
||||
T.assert(2===counter).assert(40 === wts.$v4).assert(80n === wts.$v8)
|
||||
.assert(wts.$ppV === wts.pointer);
|
||||
/** The 3rd call to wtsFunc throw from JS, which is called
|
||||
from C, which is called from JS. Let's ensure that
|
||||
that exception propagates back here... */
|
||||
T.mustThrowMatching(()=>testFunc(wts.pointer),/^Testing/);
|
||||
W.uninstallFunction(wts.$xFunc);
|
||||
wts.$xFunc = 0;
|
||||
wts.$ppV = 0;
|
||||
T.assert(!wts.$ppV);
|
||||
//WTStruct.debugFlags(0x03);
|
||||
wts.$ppV = wts;
|
||||
T.assert(wts.pointer === wts.$ppV)
|
||||
wts.setMemberCString('cstr', "A C-string.");
|
||||
T.assert(Array.isArray(wts.ondispose)).
|
||||
assert(wts.ondispose[0] === wts.$cstr).
|
||||
assert('A C-string.' === wts.memberToJsString('cstr'));
|
||||
const ptr = wts.pointer;
|
||||
wts.dispose();
|
||||
T.assert(ptr).assert(undefined === wts.pointer);
|
||||
}finally{
|
||||
wts.dispose();
|
||||
}
|
||||
|
||||
if(1){ // ondispose of other struct instances
|
||||
const s1 = new WTStruct, s2 = new WTStruct, s3 = new WTStruct;
|
||||
T.assert(s1.lookupMember instanceof Function)
|
||||
.assert(s1.addOnDispose instanceof Function);
|
||||
s1.addOnDispose(s2,"testing variadic args");
|
||||
T.assert(2===s1.ondispose.length);
|
||||
s2.addOnDispose(s3);
|
||||
s1.dispose();
|
||||
T.assert(!s2.pointer,"Expecting s2 to be ondispose'd by s1.");
|
||||
T.assert(!s3.pointer,"Expecting s3 to be ondispose'd by s2.");
|
||||
}
|
||||
}
|
||||
}/*StructBinder*/)
|
||||
|
||||
@@ -1126,75 +1131,83 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('sqlite3.oo1')
|
||||
.t('Create db', function(sqlite3){
|
||||
const dbFile = '/tester1.db';
|
||||
sqlite3.util.sqlite3__wasm_vfs_unlink(0, dbFile);
|
||||
const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
|
||||
db.onclose = {
|
||||
disposeAfter: [],
|
||||
disposeBefore: [
|
||||
(db)=>{
|
||||
//console.debug("db.onclose.before dropping modules");
|
||||
//sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
|
||||
}
|
||||
],
|
||||
before: function(db){
|
||||
while(this.disposeBefore.length){
|
||||
const v = this.disposeBefore.shift();
|
||||
console.debug("db.onclose.before cleaning up:",v);
|
||||
if(wasm.isPtr(v)) wasm.dealloc(v);
|
||||
else if(v instanceof sqlite3.StructBinder.StructType){
|
||||
v.dispose();
|
||||
}else if(v instanceof Function){
|
||||
try{ v(db) } catch(e){
|
||||
console.warn("beforeDispose() callback threw:",e);
|
||||
.t({
|
||||
name:'Create db',
|
||||
//predicate: (sqlite3)=>
|
||||
test: function(sqlite3){
|
||||
const dbFile = '/tester1.db';
|
||||
sqlite3.util.sqlite3__wasm_vfs_unlink(0, dbFile);
|
||||
const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
|
||||
db.onclose = {
|
||||
disposeAfter: [],
|
||||
disposeBefore: [
|
||||
(db)=>{
|
||||
//console.debug("db.onclose.before dropping modules");
|
||||
//sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
|
||||
}
|
||||
],
|
||||
before: function(db){
|
||||
while(this.disposeBefore.length){
|
||||
const v = this.disposeBefore.shift();
|
||||
console.debug("db.onclose.before cleaning up:",v);
|
||||
if(wasm.isPtr(v)) wasm.dealloc(v);
|
||||
else if(v instanceof sqlite3.StructBinder.StructType){
|
||||
v.dispose();
|
||||
}else if(v instanceof Function){
|
||||
try{ v(db) } catch(e){
|
||||
console.warn("beforeDispose() callback threw:",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
after: function(){
|
||||
while(this.disposeAfter.length){
|
||||
const v = this.disposeAfter.shift();
|
||||
console.debug("db.onclose.after cleaning up:",v);
|
||||
if(wasm.isPtr(v)) wasm.dealloc(v);
|
||||
else if(v instanceof sqlite3.StructBinder.StructType){
|
||||
v.dispose();
|
||||
}else if(v instanceof Function){
|
||||
try{v()} catch(e){/*ignored*/}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
after: function(){
|
||||
while(this.disposeAfter.length){
|
||||
const v = this.disposeAfter.shift();
|
||||
console.debug("db.onclose.after cleaning up:",v);
|
||||
if(wasm.isPtr(v)) wasm.dealloc(v);
|
||||
else if(v instanceof sqlite3.StructBinder.StructType){
|
||||
v.dispose();
|
||||
}else if(v instanceof Function){
|
||||
try{v()} catch(e){/*ignored*/}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
T.assert(wasm.isPtr(db.pointer))
|
||||
.mustThrowMatching(()=>db.pointer=1, /read-only/)
|
||||
.assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
|
||||
.assert('main'===db.dbName(0))
|
||||
.assert('string' === typeof db.dbVfsName())
|
||||
.assert(db.pointer === wasm.xWrap.testConvertArg('sqlite3*',db));
|
||||
// Custom db error message handling via sqlite3_prepare_v2/v3()
|
||||
let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
|
||||
T.assert(capi.SQLITE_MISUSE === rc)
|
||||
.assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"))
|
||||
.assert(dbFile === db.dbFilename())
|
||||
.assert(!db.dbFilename('nope'));
|
||||
//Sanity check DB.checkRc()...
|
||||
let ex;
|
||||
try{db.checkRc(rc)}
|
||||
catch(e){ex = e}
|
||||
T.assert(ex instanceof sqlite3.SQLite3Error)
|
||||
.assert(capi.SQLITE_MISUSE===ex.resultCode)
|
||||
.assert(0===ex.message.indexOf("SQLITE_MISUSE: sqlite3 result code"))
|
||||
.assert(ex.message.indexOf("Invalid SQL")>0);
|
||||
T.assert(db === db.checkRc(0))
|
||||
.assert(db === sqlite3.oo1.DB.checkRc(db,0))
|
||||
.assert(null === sqlite3.oo1.DB.checkRc(null,0));
|
||||
this.progressHandlerCount = 0;
|
||||
if( wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK') ){
|
||||
T.assert( !capi.sqlite3_progress_handler );
|
||||
}else{
|
||||
T.assert( !!capi.sqlite3_progress_handler );
|
||||
capi.sqlite3_progress_handler(db, 5, (p)=>{
|
||||
++this.progressHandlerCount;
|
||||
return 0;
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
T.assert(wasm.isPtr(db.pointer))
|
||||
.mustThrowMatching(()=>db.pointer=1, /read-only/)
|
||||
.assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
|
||||
.assert('main'===db.dbName(0))
|
||||
.assert('string' === typeof db.dbVfsName())
|
||||
.assert(db.pointer === wasm.xWrap.testConvertArg('sqlite3*',db));
|
||||
// Custom db error message handling via sqlite3_prepare_v2/v3()
|
||||
let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
|
||||
T.assert(capi.SQLITE_MISUSE === rc)
|
||||
.assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"))
|
||||
.assert(dbFile === db.dbFilename())
|
||||
.assert(!db.dbFilename('nope'));
|
||||
//Sanity check DB.checkRc()...
|
||||
let ex;
|
||||
try{db.checkRc(rc)}
|
||||
catch(e){ex = e}
|
||||
T.assert(ex instanceof sqlite3.SQLite3Error)
|
||||
.assert(capi.SQLITE_MISUSE===ex.resultCode)
|
||||
.assert(0===ex.message.indexOf("SQLITE_MISUSE: sqlite3 result code"))
|
||||
.assert(ex.message.indexOf("Invalid SQL")>0);
|
||||
T.assert(db === db.checkRc(0))
|
||||
.assert(db === sqlite3.oo1.DB.checkRc(db,0))
|
||||
.assert(null === sqlite3.oo1.DB.checkRc(null,0));
|
||||
|
||||
this.progressHandlerCount = 0;
|
||||
capi.sqlite3_progress_handler(db, 5, (p)=>{
|
||||
++this.progressHandlerCount;
|
||||
return 0;
|
||||
}, 0);
|
||||
}
|
||||
})
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
|
||||
@@ -1236,7 +1249,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
new TextEncoder('utf-8').encode("select 3 as a")
|
||||
);
|
||||
//debug("statement =",st);
|
||||
this.progressHandlerCount = 0;
|
||||
T.assert( !this.progressHandlerCount );
|
||||
let rc;
|
||||
try {
|
||||
T.assert(wasm.isPtr(st.pointer))
|
||||
@@ -1278,7 +1291,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
st, capi.SQLITE_STMTSTATUS_RUN, 0
|
||||
) > 0);
|
||||
|
||||
T.assert(this.progressHandlerCount > 0,
|
||||
T.assert(this.progressHandlerCount>0
|
||||
|| wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'),
|
||||
"Expecting progress callback.").
|
||||
assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
|
||||
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
|
||||
@@ -1363,7 +1377,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
.assert(2 === list.length)
|
||||
.assert('string'===typeof list[1])
|
||||
.assert(3===db.changes())
|
||||
.assert(this.progressHandlerCount > 0,
|
||||
.assert(this.progressHandlerCount > 0
|
||||
|| wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'),
|
||||
"Expecting progress callback.")
|
||||
if(wasm.bigIntEnabled){
|
||||
T.assert(3n===db.changes(false,true));
|
||||
@@ -1904,7 +1919,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
name: 'Window UDFs',
|
||||
//predicate: ()=>false,
|
||||
predicate: (sqlite3)=>!!sqlite3.wasm.exports.sqlite3_create_window_function
|
||||
/*!sqlite3.wasm.compileOptionUsed('OMIT_WINDOWFUNC')*/
|
||||
|| "Missing window functions",
|
||||
test: function(){
|
||||
/* Example window function, table, and results taken from:
|
||||
https://sqlite.org/windowfunctions.html#udfwinfunc */
|
||||
@@ -2153,7 +2170,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
name: 'virtual table #1: eponymous w/ manual exception handling',
|
||||
predicate: ()=>!!capi.sqlite3_create_module || "Missing vtab support",
|
||||
predicate: (sqlite3)=>!!sqlite3.capi.sqlite3_vtab || "Missing vtab support",
|
||||
test: function(sqlite3){
|
||||
const VT = sqlite3.vtab;
|
||||
const tmplCols = Object.assign(Object.create(null),{
|
||||
@@ -2350,7 +2367,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
name: 'virtual table #2: non-eponymous w/ automated exception wrapping',
|
||||
predicate: ()=>!!capi.sqlite3_create_module || "Missing vtab support",
|
||||
predicate: (sqlite3)=>!!sqlite3.capi.sqlite3_vtab || "Missing vtab support",
|
||||
test: function(sqlite3){
|
||||
const VT = sqlite3.vtab;
|
||||
const tmplCols = Object.assign(Object.create(null),{
|
||||
@@ -3132,7 +3149,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
]);
|
||||
T.assert(2 === u1.getFileCount() /* one is the journal file */)
|
||||
.assert(3 === db.selectValue('select count(*) from t'))
|
||||
.assert('wal'===db.selectValue('pragma journal_mode'));
|
||||
.assert(
|
||||
'wal'===db.selectValue('pragma journal_mode')
|
||||
|| wasm.compileOptionUsed('OMIT_WAL')
|
||||
);
|
||||
db.close();
|
||||
T.assert(1 === u1.getFileCount());
|
||||
db = new u2.OpfsSAHPoolDb(dbName);
|
||||
@@ -3300,17 +3320,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
T.g('Bug Reports')
|
||||
.t({
|
||||
name: 'Delete via bound parameter in subquery',
|
||||
predicate: function(sqlite3){
|
||||
const d = new sqlite3.oo1.DB();
|
||||
try{
|
||||
d.exec("create virtual table f using fts5(x)");
|
||||
return true;
|
||||
}catch(e){
|
||||
return "FTS5 is not available";
|
||||
}finally{
|
||||
d.close();
|
||||
}
|
||||
},
|
||||
predicate: ()=>wasm.compileOptionUsed('ENABLE_FTS5') || "Missing FTS5",
|
||||
test: function(sqlite3){
|
||||
// Testing https://sqlite.org/forum/forumpost/40ce55bdf5
|
||||
// with the exception that that post uses "external content"
|
||||
|
||||
+20
-24
@@ -6,19 +6,20 @@
|
||||
# GNUMakefile.
|
||||
########################################################################
|
||||
MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST))
|
||||
$(warning The WASMFS build is currently incomplete.)
|
||||
# ensure that the following message starts on line 10 or higher for proper
|
||||
# $(warning) alignment!
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
$(warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
|
||||
$(warning !! The WASMFS build is not well-supported. WASMFS is a proverbial)
|
||||
$(warning !! moving target, sometimes changing in incompatible ways between)
|
||||
$(warning !! Emscripten versions. This build is provided for adventurous folks)
|
||||
$(warning !! and is not a supported deliverable of the SQLite project.)
|
||||
$(warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
|
||||
endif
|
||||
|
||||
#dir.wasmfs := $(dir.wasm)
|
||||
dir.wasmfs := $(dir.dout)
|
||||
sqlite3-wasmfs.js := $(dir.wasmfs)/sqlite3-wasmfs.js
|
||||
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
sqlite3-wasmfs.wasm := $(dir.wasmfs)/sqlite3-wasmfs.wasm
|
||||
|
||||
CLEAN_FILES += $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.wasm) \
|
||||
$(subst .js,.worker.js,$(sqlite3-wasmfs.js)) \
|
||||
$(sqlite3-wasmfs.mjs) \
|
||||
$(subst .mjs,.worker.mjs,$(sqlite3-wasmfs.mjs))
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o.
|
||||
cflags.sqlite3-wasmfs :=
|
||||
@@ -30,12 +31,15 @@ cflags.sqlite3-wasmfs += -DSQLITE_ENABLE_WASMFS
|
||||
# emcc flags specific to building the final .js/.wasm file...
|
||||
emcc.flags.sqlite3-wasmfs :=
|
||||
emcc.flags.sqlite3-wasmfs += \
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory,allocateUTF8OnStack,stringToUTF8OnStack
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory
|
||||
# wasmMemory ==> for -sIMPORTED_MEMORY
|
||||
# *OnStack ==> wasmfs internals (leaky abstraction)
|
||||
# Some version of emcc between 3.1.60-ish(?) and 3.1.62 deprecated the
|
||||
# use of (allocateUTF8OnStack,stringToUTF8OnStack). Earlier emcc
|
||||
# versions will fail to build without those in the
|
||||
# EXPORTED_RUNTIME_METHODS list.
|
||||
emcc.flags.sqlite3-wasmfs += -sUSE_CLOSURE_COMPILER=0
|
||||
emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations
|
||||
# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
|
||||
# ^^^^^ emcc likes to warn when we have "limited optimizations" via the -g3 flag.
|
||||
emcc.flags.sqlite3-wasmfs += -sMEMORY64=0
|
||||
emcc.flags.sqlite3-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
|
||||
# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
|
||||
@@ -51,12 +55,7 @@ emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH=0
|
||||
# And, indeed, it runs slowly if memory is permitted to grow.
|
||||
#emcc.flags.sqlite3-wasmfs.vanilla :=
|
||||
#emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
|
||||
sqlite3-api.mjs.wasmfs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
|
||||
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3-wasmfs,esm,1,\
|
||||
$(sqlite3-api.mjs.wasmfs), $(sqlite3-wasmfs.mjs),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs,\
|
||||
-sEXPORT_ES6 -sUSE_ES6_IMPORT_META\
|
||||
))
|
||||
all: $(sqlite3-wasmfs.mjs)
|
||||
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
|
||||
########################################################################
|
||||
# Build quirk: we cannot build BOTH .js and .mjs with our current
|
||||
@@ -67,8 +66,8 @@ $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
|
||||
# build both modes they would need to have distinct base names or
|
||||
# output directories. "The problem" with giving them distinct base
|
||||
# names is that it means that the corresponding .wasm file is also
|
||||
# built/saved multiple times.
|
||||
#
|
||||
# built/saved multiple times. It is likely that anyone wanting to use
|
||||
# WASMFS will want an ES6 module, so that's what we build here.
|
||||
wasmfs.build.ext := mjs
|
||||
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(SOAP.js.bld)
|
||||
ifeq (js,$(wasmfs.build.ext))
|
||||
@@ -78,7 +77,6 @@ else
|
||||
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.mjs)
|
||||
wasmfs: $(sqlite3-wasmfs.mjs)
|
||||
endif
|
||||
#all: wasmfs
|
||||
|
||||
########################################################################
|
||||
# speedtest1 for wasmfs.
|
||||
@@ -103,13 +101,11 @@ $(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \
|
||||
$(emcc.flags.sqlite3-wasmfs) \
|
||||
$(emcc.flags.speedtest1-wasmfs) \
|
||||
-o $@ $(speedtest1.cfiles) -lm
|
||||
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1)
|
||||
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,1)
|
||||
$(maybe-wasm-strip) $(speedtest1-wasmfs.wasm)
|
||||
chmod -x $(speedtest1-wasmfs.wasm)
|
||||
ls -la $@ $(speedtest1-wasmfs.wasm)
|
||||
|
||||
wasmfs: $(speedtest1-wasmfs.mjs)
|
||||
CLEAN_FILES += $(speedtest1-wasmfs.mjs) $(speedtest1-wasmfs.wasm) \
|
||||
$(subst .js,.worker.js,$(speedtest1-wasmfs.mjs))
|
||||
# end speedtest1.js
|
||||
########################################################################
|
||||
|
||||
@@ -560,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)
|
||||
|
||||
@@ -750,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 \
|
||||
@@ -768,9 +779,13 @@ SHELL_DEP = \
|
||||
$(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 \
|
||||
@@ -1144,7 +1159,7 @@ clean:
|
||||
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)
|
||||
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)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Improved\serror\smessages\son\spercentile\sfunctions.\s\sMore\stests\scases\sfor\npercentile\sand\sfor\sordered-set\saggregates.
|
||||
D 2024-09-02T11:17:04.726
|
||||
C Origin\sshould\snot\ssend\scontent\sfor\sthe\slock-byte\spage\sto\sthe\sreplica,\sin\nsqlite3-rsync.\n[forum:/forumpost/d14b55e5fa19c25f|Forum\spost\sd14b55e5fa19c25f].
|
||||
D 2024-10-06T21:26:56.282
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in af5fbc3453b745daa68c7aa5dfdb945c09cb724971db3b783d6b5e1a62279e28
|
||||
F Makefile.in 6a826facc78c3c8ad38bf00ed588f6aa3665ccd7a9749b891d20582fc290c77e
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 2c905f4c795a628d7fd892294e8fdec6d5f719fa5b252cb839fed147e64435a0
|
||||
F README.md 5b678e264236788390d11991f2c0052bd73f19790173883fc56d638bcb849154
|
||||
F Makefile.msc 9c6d80d9d103fa42e931f4c464884a5e577fae8563acc7589bff4e43fbe8f864
|
||||
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
|
||||
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -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 6e02dea912a49f55785b0027fe77960aafee6c236307c23f82ec86a69f1a2001 x
|
||||
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
|
||||
@@ -93,15 +93,15 @@ F ext/fts3/unicode/mkunicode.tcl 63db9624ccf70d4887836c320eda93ab552f21008f3be7e
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
|
||||
F ext/fts5/fts5.h efaaac0df3d3bc740383044c144b582f47921aafa21d7b10eb98f42c24c740b0
|
||||
F ext/fts5/fts5Int.h 26a71a09cefa4ef6b4516b204ed48da3e1380970a19b3482eea7c5d805655360
|
||||
F ext/fts5/fts5Int.h bf0d3efa144f36e00f9b5206626aec2f436f58186a0835092394f2202e9828e3
|
||||
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 a6633d88596758941c625b526075b85d3d9fd1089d8d9eab5db6e8a71fd347ad
|
||||
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 1fddb53f495425d9314c74b30c5848a9dd254be0e5f445bfe38292d5ab21c288
|
||||
F ext/fts5/fts5_storage.c 9a9b880be12901f1962ae2a5a7e1b74348b3099a1e728764e419f75d98e3e612
|
||||
F ext/fts5/fts5_index.c 368a968570ce12ba40223e284a588d9f93ee23a0133727f0df1fcd64086b1fb6
|
||||
F ext/fts5/fts5_main.c 50eb059e51d730e8e0c77df4e568b018079e112a755c094488b0d5b1aa06afbb
|
||||
F ext/fts5/fts5_storage.c 337b05e4c66fc822d031e264d65bde807ec2fab08665ca2cc8aaf9c5fa06792c
|
||||
F ext/fts5/fts5_tcl.c 4db9258a7882c5eac0da4433042132aaf15b87dd1e1636c7a6ca203abd2c8bfe
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
@@ -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
|
||||
@@ -145,7 +145,7 @@ F ext/fts5/test/fts5contentless.test 606f063b29ba0f46d4b79aa36cdd1ef4dab5de53eae
|
||||
F ext/fts5/test/fts5contentless2.test 70ffe6c611d8f278240da56734df8a77948f04e2739b358439e9bdcf56ced35f
|
||||
F ext/fts5/test/fts5contentless3.test 75eaae5ad6b284ee447788943974d323228f27cc35a1681da997135cff95bc6a
|
||||
F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b05ea89964c863833b6eff8
|
||||
F ext/fts5/test/fts5contentless5.test 40cdcb4fe751672450829c5a96bd32c25fc2f6076279dd2ce5c58ac9a390132a
|
||||
F ext/fts5/test/fts5contentless5.test 38cd0392c730dc7090c550321ce3c24ba4c392bc97308b51a4180e9959dca7b5
|
||||
F ext/fts5/test/fts5corrupt.test 6485f721b88ba355ca5d701e7ee87a4efa3ea578d8e6adb26f51ef956c8328bd
|
||||
F ext/fts5/test/fts5corrupt2.test 335911e3f68b9625d850325f9e29a128db3f4276a8c9d4e32134580da8f924c4
|
||||
F ext/fts5/test/fts5corrupt3.test 4fc3bf129f1616bea00884a23fd9d7b0e46d01791d2b57fe8d68ac36e8d3ff7c
|
||||
@@ -154,7 +154,7 @@ F ext/fts5/test/fts5corrupt5.test 11b47126f5772cc37b67e3e8b2ed05895c4d07c05338bc
|
||||
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/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
|
||||
F ext/fts5/test/fts5dlidx.test a7c42b0a74dc7c8aa1a46d586e0aadda4b6cc42c24450f8d3774b21166e93159
|
||||
@@ -178,17 +178,18 @@ 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 ae4b83ac953200bd7b66d53038f7d6a4fc29cd64831b8e1795538babcea7c638
|
||||
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
|
||||
@@ -205,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
|
||||
@@ -245,7 +246,9 @@ F ext/fts5/test/fts5unicode2.test 3bbd30152f9f760bf13886e5b1e5ec23ff62f56758ddda
|
||||
F ext/fts5/test/fts5unicode3.test f4891a3dac3b49c3d7c0fdb29566e9eb0ecff35263370c89f9661b1952b20818
|
||||
F ext/fts5/test/fts5unicode4.test 728c8f0caafb05567f524ad313d9f8b780fa45987b8a8df04eff87923c74b4d0
|
||||
F ext/fts5/test/fts5unindexed.test 168838d2c385e131120bbf5b516d2432a5fabc4caa2259c932e1d49ae209a4ae
|
||||
F ext/fts5/test/fts5unindexed2.test 516236eceaac05ace322290a0d3705b4c4ffe4760d8eb9d014d9d27d56dfcc02
|
||||
F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
|
||||
F ext/fts5/test/fts5update2.test c5baa76799ac605ebb8e5e21035db2014b396cef25c903eb96ba39b1d6f9f046
|
||||
F ext/fts5/test/fts5version.test c22d163c17e60a99f022cbc52de5a48bb7f84deaa00fe15e9bc4c3aa1996204e
|
||||
F ext/fts5/test/fts5vocab.test 2a2bdb60d0998fa3124d541b6d30b019504918dc43a6584645b63a24be72f992
|
||||
F ext/fts5/test/fts5vocab2.test bbba149c254375d00055930c1a501c9a51e80b0d20bf7b98f3e9fa3b03786373
|
||||
@@ -398,7 +401,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
|
||||
@@ -410,7 +413,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 4e333fc78d2a7b9cf362e29f30fa3f486cdab9e69fbc9aa0f680399683aa22f7
|
||||
F ext/misc/percentile.c 42eb041edab407e512aaa087f99ed9287fe0b3224f7a6d194456c00fc1454312
|
||||
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
|
||||
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
@@ -419,11 +422,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/spellfix.c bcc42ef3fd29429bc01a83e751332b8d4690e65d45008449bdffe7656371487f
|
||||
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
|
||||
@@ -434,10 +439,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
|
||||
@@ -483,7 +489,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
|
||||
@@ -573,7 +579,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
|
||||
@@ -581,10 +587,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
|
||||
@@ -592,14 +598,14 @@ 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
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile d4f6586d9a36ee2869a8c7f77227a8b7f42b6c4623f3be594beafb1554ab20d9
|
||||
F ext/wasm/GNUmakefile bfd63f0462ac7e5b814a267e9101b8284d61731574ec673dae3178643cdb89ef
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -607,21 +613,18 @@ F ext/wasm/SQLTester/SQLTester.mjs ce765c0ad7d57f93553d12ef4dca574deb00300134a26
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs c72b7fe2072d05992f7a3d8c6a1d34e95712513ceabe40849784e24e41c84638
|
||||
F ext/wasm/SQLTester/index.html 3f8a016df0776be76605abf20e815ecaafbe055abac0e1fe5ea080e7846b760d
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-auth 7ac80cc3b6a6d52e041bb295e85555ce797be78c15ef2008a64ae58815014080
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 400213eb52a7e5ad5f448053d375cacf4dac2cf45d134f3edfe485ae4a49a183
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-preupdate d1d62a2212099f2c0782d730beb8cb84a7a52d99c15ead2cb9b1411fff5fd6b1
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 2bcbbfe3b95c043ed6037e2708a2ee078d212dd1612c364f93588d8dc97300fe
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-session 213b6c04267cb9bd760172db011eb1650732805fb3d01f9395478a8ceec18eb0
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-vtab fd57af1f4502a052be27d8402df74be1dc60fcb6a687d372972abd90e424120a
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
F ext/wasm/api/README.md 34fe11466f9c1d81b10a0469e1114e5f1c5a6365c73d80a1a6ca639a1a358b73
|
||||
F ext/wasm/api/extern-post-js.c-pp.js c4154a7f90c2d7e51fd6738273908152036c3457fdc0b6523f1be3ef51105aac
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
|
||||
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
|
||||
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
|
||||
F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 54b32b5321105a72d6f3d3e8b77f28f162d0367b08c63184263d3f85f3d7dbed
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js fb6dbfe692cc23000a65a4cd95a1a47ed5eb592dc9d8b55363b3c2952a787244
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 6f1257e04885632ed9f44d43aba200b86e0bc16709ffdba29abbbeb1bc8e8b76
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 5cc22a3c0d52828cb32aad8691488719f47d27567e63e8bc8b832d74371c352d
|
||||
@@ -631,14 +634,14 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js e529a99b7d5a088284821e2902b20d3404b561126969876997d5a73a656c9199
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e99e3d99f736937914527070f00ab13e9391d3f1cef884ab99a64cbcbee8d675
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
||||
F ext/wasm/api/sqlite3-wasm.c 09a938fc570f282e602acd111147c7b74b5332da72540c512a79b916ab57882a
|
||||
F ext/wasm/api/sqlite3-wasm.c 83f5e9f998e9fa4261eb84e9f092210e3ffe03895119f5ded0429eb34ab9d2be
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46f303ba8ddd1b2f0a391798837beddfa72e8c897038c8047eda49ce7d5ed46b
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
F ext/wasm/batch-runner.js 05ec254f5dbfe605146d9640b3db17d6ef8c3fbef6aa8396051ca72bb5884e3f
|
||||
F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25b4
|
||||
F ext/wasm/c-pp.c 6d131069644964223305582a80973477fa8b06b57306781690d7874ebd3a4f84
|
||||
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
|
||||
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
||||
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
|
||||
@@ -654,19 +657,20 @@ F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2
|
||||
F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
|
||||
F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5248ce
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make 2406b02473878a99fb6a2eaff0923277017adc45eb041b2afb2d7707bf7b375c
|
||||
F ext/wasm/fiddle.make ec2353f0eddade864f67b993376a0949e27b72465c24b1970940e48b70bc2df1
|
||||
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
|
||||
F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
|
||||
F ext/wasm/fiddle/index.html 739e0b75bc592679665d25e2f7649d2b8b2db678f3b41a772a8720b609b8482d
|
||||
F ext/wasm/fiddle/index.html c79b1741cbeba78f88af0a84cf5ec7de87a909a6a8d10a369b1f4824c66c2088
|
||||
F ext/wasm/index-dist.html 564b5ec5669676482c5a25dea9e721d8eafed426ecb155f93d29aeff8507511f
|
||||
F ext/wasm/index.html 4337f495416756802669f69f9f9f3df9f87ee4c1918e6718719b4b5718e4713a
|
||||
F ext/wasm/index.html e4bbffdb3d40eff12b3f9c7abedef91787e2935620b7f8d40f2c774b80ad8fa9
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
|
||||
F ext/wasm/mkwasmbuilds.c e3580b26bc393e4e4beb25f6349b999878782f3319b740469f64c2e772632e03
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
|
||||
F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
|
||||
F ext/wasm/speedtest1-wasmfs.mjs c77c7231338ed5c0e1ce16aa29106df8e5b5cf11a48319c49433490a8d3ded30
|
||||
F ext/wasm/speedtest1-worker.html 864b65ed78ce24847a348c180e7f267621a02ca027068a1863ec1c90187c1852
|
||||
F ext/wasm/speedtest1-worker.js 95e549e13a4d35863a9a7fc66122b5f546c0130d3be7b06dfcc556eb66d24bde
|
||||
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
|
||||
@@ -677,15 +681,15 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js a88b9c669715adc1c5e76750ca8c0994ae33d04572e3bf295b6f4f5870f3bdf3
|
||||
F ext/wasm/tester1.c-pp.js bb8c41a56ca0eabb945ca2e8f06324a7b63ad91630959d714b071bee88322019
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
|
||||
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966f1bc16a
|
||||
F ext/wasm/wasmfs.make bc8bb227f35d5bd3863a7bd2233437c37472a0d81585979f058f9b9b503bef35
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 5a2e7d4a852c058373efc78407816de41595d06975148c766092b3cf0fea4298
|
||||
F main.mk 0a55ebec3508ca1bdb593d86f3aa19d7fa42a2ddd3220703e6dc0a65f1338a43
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -712,23 +716,23 @@ F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d49
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
|
||||
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbpage.c db1be8adaf1f839ad733c08baeac5c22aa912f7b535865c0c061382602081360
|
||||
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 df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
|
||||
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
|
||||
F src/func.c ed6baeeb414ef18ce729793587dae8bd30f11e6aacec8675bd33727e0bcb3765
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
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 e7b53893f9fb3ad76baa8513f85c167b34d5c8e25ce64608db440f5637d0fe9e
|
||||
F src/main.c d55d27db5a3b7bb12e1b723e350efd833586f22baa4b15ca2c0b4bde9a44ae29
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -738,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
|
||||
@@ -749,7 +753,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 6e3e4fc75904ff85184091dbab996e6e35c1799e771788961cc3b4fcbe8f852c
|
||||
F src/os_unix.c 779e83666ecd535f6725497ba6da069c1d15138ff6a4ee123edad1ae0cdfbe83
|
||||
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
|
||||
@@ -760,23 +764,23 @@ 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 40de636c1d90fb8a9ca7f49dc8f50d930f1b60736e73aca5eb37c4c7d0e47f9d
|
||||
F src/sqlite.h.in 77f55bd1978a04a14db211732f0a609077cf60ba4ccf9baf39988f508945419c
|
||||
F src/shell.c.in 981efe98f98a983c1d0193d18528eb2d765207c0c82b67b610be60f17995a43e
|
||||
F src/sqlite.h.in 1def838497ad53c81486649ce79821925d1ac20a9843af317a344d507efe116e
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 889cd632f4386bbd8619b166abb7d25f1c8ce6514e90cb7f22f63bd530fc6107
|
||||
F src/sqliteInt.h 989dca8b25ca11f5c52e5a457cc500042c43b0b3e5fea9a12d9020d0350722cd
|
||||
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 8bf8b74145b768f42386787f93f6d6dad7bc400a4ee2d50e4ad5a06a20a97ef1
|
||||
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
|
||||
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
|
||||
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
|
||||
@@ -790,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 345b8e383f71cecc36d0fa05f2f06639c254b188f98101c3c97749df43037086
|
||||
F src/test_config.c e8d041a84151cbaee4dd82eb32e4153abe06856bcfab4771968a8cf930a86332
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -822,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
|
||||
@@ -833,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/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
|
||||
F src/utf.c 7bc550af6f3ddd5f5dc82d092c41f728acb760c92e0b47f391963b01ae52569b
|
||||
F src/util.c 4d57ae861d0e234019be9596818228d7715e44e6efaccb612cf4498bedc2e023
|
||||
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/vdbeInt.h af7d7e8291edd0b19f2cd698e60e4d4031078f9a2f2328ac8f0b7efb134f8a1d
|
||||
F src/vdbeapi.c 53c7e26a2c0821a892b20eee2cde4656e31998212f3d515576c780dfaa45fd17
|
||||
F src/vdbeaux.c f06f011e4fac948941ea821ac365a9f1c163ef473e63756d6e499a37c6bda9ef
|
||||
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
|
||||
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
|
||||
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 a0d42bfdef935e1389737152394d08e59e7c48697f40a9fc2e0552cb19dc731f
|
||||
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
|
||||
@@ -905,7 +908,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test f2765d7fdc1348ae58b279d096d301a208e46da623213877b2ba580dc2768975
|
||||
F test/atof1.test 7ec56debc04b32e8f9dc87239f4bbb07d84550fb83dd7475b0ead9e83beb35da
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
|
||||
@@ -988,7 +991,7 @@ F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a49
|
||||
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/carray01.test 23ed7074307c4a829ba5ff2970993a9d87db7c5cdbbe1a2cbef672d0df6d6e31
|
||||
F test/cast.test 42f7d79d88ab5e8080e96c650c52fcf72eef3e6476aaaee2c9f6e074396cfdfc
|
||||
F test/cast.test 6d095303492432a973e6dfc0071cb94cac2969ffbe2e6a68432be0c7b3b0a2d3
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/changes.test 4377d202a487f66fc2822c1bf57c46798c8b2caf7446f4f701723b1dbb6b86f6
|
||||
F test/changes2.test 07949edcc732af28cb54276bfb7d99723bccc1e905a423648bf57ac5cb0dc792
|
||||
@@ -1152,7 +1155,7 @@ F test/fkey8.test 51deda7f1a1448bca95875e4a6e1a3a75b4bd7215e924e845bd60de60e4d84
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958fdde5c
|
||||
F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
|
||||
F test/fp-speed-1.c ca95152d579530c967240ead1387dc1208052d310dfa22bc9ebded56d4e6c026
|
||||
F test/fp-speed-1.c b37de94eba034e1703668816225f54510ec60fb0685406608cc707afe6b8234d
|
||||
F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
@@ -1183,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
|
||||
@@ -1250,10 +1253,10 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75
|
||||
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
|
||||
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test b56905748ce0567c01d60005f3e6ad1af19453d224ba4730ee687d048fd09ef9
|
||||
F test/func.test 098d28ecd1284e0625797a981c9dbf7c1664763af2900f96b9716af80e6cbe40
|
||||
F test/func2.test 69f6ae3751b4ec765bdc3b803c0a255aa0f693f28f44805bef03e6b4a3fd242f
|
||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||
F test/func4.test a3f9062487dbd826776f54f4e0e9517fe8c3cf689af92735308965774d51fac5
|
||||
F test/func4.test a02e695f62beb31cb092dccf6873ff97543407fff97a5f3ec4da70b5b337bc84
|
||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||
F test/func6.test 3bc89ec0f2605736d3a118f43d25ef58115a7db4dba8ae939a363917d815c0bb
|
||||
F test/func7.test 7e009275f52c52954c8c028fdb62f8bc16cc47276fcc8753c1d2b22c6e074598
|
||||
@@ -1266,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 20be6c96bd0da2e91d25f089a037c1b3f8142211c97104f20629bf15610019e6
|
||||
F test/fuzzcheck.c 89b71d92b150a532e945e489d6e0721a4b15353c9255e079c198ed2a1958018b
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1278,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
|
||||
@@ -1345,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
|
||||
@@ -1380,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
|
||||
@@ -1625,7 +1628,7 @@ 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/shell1.test b02d628494fa284cdb2b7b2fecdadea96913796afd623f340a79d68f055dcb7e
|
||||
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
|
||||
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
|
||||
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
|
||||
@@ -1646,7 +1649,7 @@ F test/skipscan5.test 0672103fd2c8f96bd114133f356192b35ece45c794fe3677e1d9e5e310
|
||||
F test/skipscan6.test bddbb35dd335e2d21b7791a61e3b2e1f3255dc307ce80aa6fe19cc298e6feb13
|
||||
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
|
||||
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
|
||||
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
|
||||
F test/snapshot3.test 41350216abc6c7da37113ad462259c070786e5ad70bdc8709daaed148b1b3a2c
|
||||
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
|
||||
F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a
|
||||
F test/snapshot_up.test 77dc7853bfb2b4fa249f76e1714cfa1e596826165d9ef22c06ac3a0b7b778d9a
|
||||
@@ -1667,7 +1670,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c 19c9b60908d25502d2831f97efee8b81006c356ab8c08327e25d24a4144f2131
|
||||
F test/speedtest1.c cc503febbb8559d541a67d7a33d3d7bb8a2c8cbbfc89eb336e2e2bd6ad6a63ee
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1713,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 662af46f1f0a41eb197f17583698853dd130ff3d47cf136dd519c3aecd9a9d7d
|
||||
F test/testrunner_data.tcl d64e69aba227492fc459eb0f6a88c3e1b252bd9323847b7e8bcf5e1faa358714
|
||||
F test/tester.tcl 7b44f1a9b9a2de8112695b908afc21dd9a68cd2d44e84b73f1b27b53492c0d59
|
||||
F test/testrunner.tcl 3dd75b45593d2afa2e3bca76121297a9f163bebb98474b13536f326829a71db1 x
|
||||
F test/testrunner_data.tcl c7b3b911e44f7e8c01cc6bc7571e16115cdc2e4db46630bd2acd7a931a46380e
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -2050,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
|
||||
@@ -2101,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
|
||||
@@ -2151,20 +2154,20 @@ F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c611528584
|
||||
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
|
||||
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/speed-check.sh e8d20cc2eb9c85ec1ba562226de144435456dcdff4ee618de49603c6958f6116
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/speed-check.sh e566ab3934d7d78631743a984ad3f67c331c911bb18ff5d0a6c616a2afee7f91
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
@@ -2172,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 7c78ba15afa0b929604adb91c94af8dbdf8cbe87be8a5cba5353af0e320ca65a
|
||||
F tool/sqlite3_analyzer.c.in 348ba349bbdc93c9866439f9f935d7284866a2a4e6898bc906ae1204ade56918
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
|
||||
@@ -2211,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 3b1cdddf8339cc339ec74cd8be2bfa42e62b500048a444eb9e5d9817bc4702ae
|
||||
R a80c34160df19b1603ad0e7833a0d0c3
|
||||
P 37d3b6b17e92b2c760239c3053bbc7fb85091acd688c54a73af7611fe9501312
|
||||
R dbb5b993debce35e50244d3495f9b61e
|
||||
U drh
|
||||
Z baa1dd0d6096edf0ada0dc3da2ddafed
|
||||
Z 45e873ac682d74f4a4a29dbca970bb7d
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e1bca168e70335fa2f9537632fd16e374c566a564fab4974c0b8f61cb63d08ce
|
||||
aa9bd711cc1b0136098388976d22adc0a2fc89f50fe2273ed80ee3e4e50c98b6
|
||||
|
||||
+68
-24
@@ -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 iDbTrunc; /* Database to truncate */
|
||||
Pgno pgnoTrunc; /* Size to truncate to */
|
||||
};
|
||||
|
||||
/* Columns */
|
||||
@@ -59,7 +67,6 @@ struct DbpageTable {
|
||||
#define DBPAGE_COLUMN_SCHEMA 2
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Connect to or create a dbpagevfs virtual table.
|
||||
*/
|
||||
@@ -321,11 +328,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 +343,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 +373,25 @@ 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 && pgno>1 ){
|
||||
/* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and
|
||||
** all subsequent pages to be deleted. */
|
||||
pTab->iDbTrunc = iDb;
|
||||
pgno--;
|
||||
pTab->pgnoTrunc = 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);
|
||||
pTab->pgnoTrunc = 0;
|
||||
}
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
@@ -393,9 +415,31 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
}
|
||||
pTab->pgnoTrunc = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
|
||||
*/
|
||||
static int dbpageSync(sqlite3_vtab *pVtab){
|
||||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
if( pTab->pgnoTrunc>0 ){
|
||||
Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt;
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc);
|
||||
}
|
||||
pTab->pgnoTrunc = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Cancel any pending truncate.
|
||||
*/
|
||||
static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){
|
||||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
pTab->pgnoTrunc = 0;
|
||||
(void)notUsed1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke this routine to register the "dbpage" virtual table module
|
||||
@@ -417,14 +461,14 @@ int sqlite3DbpageRegister(sqlite3 *db){
|
||||
dbpageRowid, /* xRowid - read data */
|
||||
dbpageUpdate, /* xUpdate */
|
||||
dbpageBegin, /* xBegin */
|
||||
0, /* xSync */
|
||||
dbpageSync, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
dbpageRollbackTo, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
0 /* xIntegrity */
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+84
-1
@@ -2535,7 +2535,13 @@ static void signFunc(
|
||||
** Implementation of fpdecode(x,y,z) function.
|
||||
**
|
||||
** x is a real number that is to be decoded. y is the precision.
|
||||
** z is the maximum real precision.
|
||||
** z is the maximum real precision. Return a string that shows the
|
||||
** results of the sqlite3FpDecode() function.
|
||||
**
|
||||
** Used for testing and debugging only, specifically testing and debugging
|
||||
** of the sqlite3FpDecode() function. This SQL function does not appear
|
||||
** in production builds. This function is not an API and is subject to
|
||||
** modification or removal in future versions of SQLite.
|
||||
*/
|
||||
static void fpdecodeFunc(
|
||||
sqlite3_context *context,
|
||||
@@ -2562,6 +2568,82 @@ static void fpdecodeFunc(
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Implementation of parseuri(uri,flags) function.
|
||||
**
|
||||
** Required Arguments:
|
||||
** "uri" The URI to parse.
|
||||
** "flags" Bitmask of flags, as if to sqlite3_open_v2().
|
||||
**
|
||||
** Additional arguments beyond the first two make calls to
|
||||
** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
|
||||
** anything else.
|
||||
**
|
||||
** The result is a string showing the results of calling sqlite3ParseUri().
|
||||
**
|
||||
** Used for testing and debugging only, specifically testing and debugging
|
||||
** of the sqlite3ParseUri() function. This SQL function does not appear
|
||||
** in production builds. This function is not an API and is subject to
|
||||
** modification or removal in future versions of SQLite.
|
||||
*/
|
||||
static void parseuriFunc(
|
||||
sqlite3_context *ctx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_str *pResult;
|
||||
const char *zVfs;
|
||||
const char *zUri;
|
||||
unsigned int flgs;
|
||||
int rc;
|
||||
sqlite3_vfs *pVfs = 0;
|
||||
char *zFile = 0;
|
||||
char *zErr = 0;
|
||||
|
||||
if( argc<2 ) return;
|
||||
pVfs = sqlite3_vfs_find(0);
|
||||
assert( pVfs );
|
||||
zVfs = pVfs->zName;
|
||||
zUri = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zUri==0 ) return;
|
||||
flgs = (unsigned int)sqlite3_value_int(argv[1]);
|
||||
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
|
||||
pResult = sqlite3_str_new(0);
|
||||
if( pResult ){
|
||||
int i;
|
||||
sqlite3_str_appendf(pResult, "rc=%d", rc);
|
||||
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
|
||||
sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
|
||||
sqlite3_str_appendf(pResult, ", err=%Q", zErr);
|
||||
sqlite3_str_appendf(pResult, ", file=%Q", zFile);
|
||||
if( zFile ){
|
||||
const char *z = zFile;
|
||||
z += sqlite3Strlen30(z)+1;
|
||||
while( z[0] ){
|
||||
sqlite3_str_appendf(pResult, ", %Q", z);
|
||||
z += sqlite3Strlen30(z)+1;
|
||||
}
|
||||
for(i=2; i<argc; i++){
|
||||
const char *zArg;
|
||||
if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){
|
||||
int k = sqlite3_value_int(argv[i]);
|
||||
sqlite3_str_appendf(pResult, ", '%d:%q'",k,sqlite3_uri_key(zFile, k));
|
||||
}else if( (zArg = (const char*)sqlite3_value_text(argv[i]))!=0 ){
|
||||
sqlite3_str_appendf(pResult, ", '%q:%q'",
|
||||
zArg, sqlite3_uri_parameter(zFile,zArg));
|
||||
}else{
|
||||
sqlite3_str_appendf(pResult, ", NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
|
||||
}
|
||||
sqlite3_free_filename(zFile);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** All of the FuncDef structures in the aBuiltinFunc[] array above
|
||||
** to the global function hash table. This occurs at start-time (as
|
||||
@@ -2635,6 +2717,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
#ifdef SQLITE_DEBUG
|
||||
FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ),
|
||||
FUNCTION(parseuri, -1, 0, 0, parseuriFunc ),
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
FUNCTION(round, 1, 0, 0, roundFunc ),
|
||||
|
||||
@@ -243,7 +243,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
|
||||
0, /* bSmallMalloc */
|
||||
1, /* bExtraSchemaChecks */
|
||||
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
|
||||
#ifdef SQLITE_DEBUG
|
||||
0, /* bJsonSelfcheck */
|
||||
#endif
|
||||
|
||||
+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++;
|
||||
|
||||
+5
-51
@@ -159,32 +159,6 @@ char *sqlite3_temp_directory = 0;
|
||||
*/
|
||||
char *sqlite3_data_directory = 0;
|
||||
|
||||
/*
|
||||
** Determine whether or not high-precision (long double) floating point
|
||||
** math works correctly on CPU currently running.
|
||||
*/
|
||||
static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){
|
||||
if( sizeof(LONGDOUBLE_TYPE)<=8 ){
|
||||
/* If the size of "long double" is not more than 8, then
|
||||
** high-precision math is not possible. */
|
||||
return 0;
|
||||
}else{
|
||||
/* Just because sizeof(long double)>8 does not mean that the underlying
|
||||
** hardware actually supports high-precision floating point. For example,
|
||||
** clearing the 0x100 bit in the floating-point control word on Intel
|
||||
** processors will make long double work like double, even though long
|
||||
** double takes up more space. The only way to determine if long double
|
||||
** actually works is to run an experiment. */
|
||||
LONGDOUBLE_TYPE a, b, c;
|
||||
rc++;
|
||||
a = 1.0+rc*0.1;
|
||||
b = 1.0e+18+rc*25.0;
|
||||
c = a+b;
|
||||
return b!=c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Initialize SQLite.
|
||||
**
|
||||
@@ -379,13 +353,6 @@ int sqlite3_initialize(void){
|
||||
rc = SQLITE_EXTRA_INIT(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Experimentally determine if high-precision floating point is
|
||||
** available. */
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3482,6 +3449,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 ){
|
||||
@@ -4637,24 +4605,6 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_WSD)
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X);
|
||||
**
|
||||
** X<0 Make no changes to the bUseLongDouble. Just report value.
|
||||
** X==0 Disable bUseLongDouble
|
||||
** X==1 Enable bUseLongDouble
|
||||
** X>=2 Set bUseLongDouble to its default value for this platform
|
||||
*/
|
||||
case SQLITE_TESTCTRL_USELONGDOUBLE: {
|
||||
int b = va_arg(ap, int);
|
||||
if( b>=2 ) b = hasHighPrecisionDouble(b);
|
||||
if( b>=0 ) sqlite3Config.bUseLongDouble = b>0;
|
||||
rc = sqlite3Config.bUseLongDouble!=0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
|
||||
**
|
||||
@@ -4962,7 +4912,11 @@ int sqlite3_snapshot_get(
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
i64 dummy = 0;
|
||||
sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
sqlite3PagerSnapshotOpen(pPager, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
|
||||
}
|
||||
|
||||
+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) */
|
||||
|
||||
+3
-3
@@ -4159,7 +4159,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
|
||||
static void setDeviceCharacteristics(unixFile *pFile){
|
||||
if( pFile->sectorSize == 0 ){
|
||||
struct statvfs fsInfo;
|
||||
|
||||
|
||||
/* Set defaults for non-supported filesystems */
|
||||
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
|
||||
pFile->deviceCharacteristics = 0;
|
||||
@@ -4199,7 +4199,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
|
||||
pFile->sectorSize = fsInfo.f_bsize;
|
||||
pFile->deviceCharacteristics =
|
||||
/* full bitset of atomics from max sector size and smaller */
|
||||
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
|
||||
(((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
|
||||
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
||||
** so it is ordered */
|
||||
0;
|
||||
@@ -4207,7 +4207,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
|
||||
pFile->sectorSize = fsInfo.f_bsize;
|
||||
pFile->deviceCharacteristics =
|
||||
/* full bitset of atomics from max sector size and smaller */
|
||||
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
|
||||
(((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
|
||||
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
||||
** so it is ordered */
|
||||
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 ){
|
||||
|
||||
+1054
-748
File diff suppressed because it is too large
Load Diff
+16
-4
@@ -4222,13 +4222,17 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** and sqlite3_prepare16_v3() use UTF-16.
|
||||
**
|
||||
** ^If the nByte argument is negative, then zSql is read up to the
|
||||
** first zero terminator. ^If nByte is positive, then it is the
|
||||
** number of bytes read from zSql. ^If nByte is zero, then no prepared
|
||||
** first zero terminator. ^If nByte is positive, then it is the maximum
|
||||
** number of bytes read from zSql. When nByte is positive, zSql is read
|
||||
** up to the first zero terminator or until the nByte bytes have been read,
|
||||
** whichever comes first. ^If nByte is zero, then no prepared
|
||||
** statement is generated.
|
||||
** If the caller knows that the supplied string is nul-terminated, then
|
||||
** there is a small performance advantage to passing an nByte parameter that
|
||||
** is the number of bytes in the input string <i>including</i>
|
||||
** the nul-terminator.
|
||||
** Note that nByte measure the length of the input in bytes, not
|
||||
** characters, even for the UTF-16 inferfaces.
|
||||
**
|
||||
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
|
||||
** past the end of the first SQL statement in zSql. These routines only
|
||||
@@ -5599,7 +5603,7 @@ int sqlite3_create_window_function(
|
||||
** This flag instructs SQLite to omit some corner-case optimizations that
|
||||
** might disrupt the operation of the [sqlite3_value_subtype()] function,
|
||||
** causing it to return zero rather than the correct subtype().
|
||||
** SQL functions that invokes [sqlite3_value_subtype()] should have this
|
||||
** All SQL functions that invoke [sqlite3_value_subtype()] should have this
|
||||
** property. If the SQLITE_SUBTYPE property is omitted, then the return
|
||||
** value from [sqlite3_value_subtype()] might sometimes be zero even though
|
||||
** a non-zero subtype was specified by the function argument expression.
|
||||
@@ -8364,7 +8368,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
@@ -10539,6 +10543,14 @@ typedef struct sqlite3_snapshot {
|
||||
** If there is not already a read-transaction open on schema S when
|
||||
** this function is called, one is opened automatically.
|
||||
**
|
||||
** If a read-transaction is opened by this function, then it is guaranteed
|
||||
** that the returned snapshot object may not be invalidated by a database
|
||||
** writer or checkpointer until after the read-transaction is closed. This
|
||||
** is not guaranteed if a read-transaction is already open when this
|
||||
** function is called. In that case, any subsequent write or checkpoint
|
||||
** operation on the database may invalidate the returned snapshot handle,
|
||||
** even while the read-transaction remains open.
|
||||
**
|
||||
** The following must be true for this function to succeed. If any of
|
||||
** the following statements are false when sqlite3_snapshot_get() is
|
||||
** called, SQLITE_ERROR is returned. The final value of *P is undefined
|
||||
|
||||
+2
-15
@@ -638,6 +638,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
|
||||
@@ -660,7 +661,6 @@
|
||||
# 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)
|
||||
# endif
|
||||
@@ -835,9 +835,6 @@
|
||||
# define INT8_TYPE signed char
|
||||
# endif
|
||||
#endif
|
||||
#ifndef LONGDOUBLE_TYPE
|
||||
# define LONGDOUBLE_TYPE long double
|
||||
#endif
|
||||
typedef sqlite_int64 i64; /* 8-byte signed integer */
|
||||
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
|
||||
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
|
||||
@@ -4262,7 +4259,6 @@ struct Sqlite3Config {
|
||||
u8 bUseCis; /* Use covering indices for full-scans */
|
||||
u8 bSmallMalloc; /* Avoid large memory allocations if true */
|
||||
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
|
||||
u8 bUseLongDouble; /* Make use of long double */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 bJsonSelfcheck; /* Double-check JSON parsing */
|
||||
#endif
|
||||
@@ -4637,15 +4633,6 @@ int sqlite3CantopenError(int);
|
||||
# define SQLITE_ENABLE_FTS3 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The ctype.h header is needed for non-ASCII systems. It is also
|
||||
** needed by FTS3 when FTS3 is included in the amalgamation.
|
||||
*/
|
||||
#if !defined(SQLITE_ASCII) || \
|
||||
(defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following macros mimic the standard library functions toupper(),
|
||||
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
|
||||
@@ -5267,7 +5254,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
-36
@@ -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;
|
||||
@@ -7313,37 +7313,6 @@ static int SQLITE_TCLAPI extra_schema_checks(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: use_long_double BOOLEAN|"default"
|
||||
**
|
||||
** If no argument, report the current value of the use-long-double flag.
|
||||
**
|
||||
** If argument is "default", set the use-long-double flag to the default
|
||||
** value for this build, based on the size of LONGDOUBLE_TYPE.
|
||||
**
|
||||
** If argument is a boolean, set the use-long-double flag accordingly.
|
||||
**
|
||||
** Return the new setting.
|
||||
*/
|
||||
static int SQLITE_TCLAPI use_long_double(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int i = -1;
|
||||
if( objc==2 ){
|
||||
if( strcmp(Tcl_GetString(objv[1]),"default")==0 ){
|
||||
i = 2;
|
||||
}else{
|
||||
if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
i = sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, i);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: database_may_be_corrupt
|
||||
**
|
||||
@@ -9150,7 +9119,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "reset_prng_state", reset_prng_state, 0 },
|
||||
{ "prng_seed", prng_seed, 0 },
|
||||
{ "extra_schema_checks", extra_schema_checks, 0},
|
||||
{ "use_long_double", use_long_double, 0},
|
||||
{ "database_never_corrupt", database_never_corrupt, 0},
|
||||
{ "database_may_be_corrupt", database_may_be_corrupt, 0},
|
||||
{ "optimization_control", optimization_control,0},
|
||||
@@ -9299,7 +9267,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
#endif
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
|
||||
int i;
|
||||
extern int sqlite3_sync_count, sqlite3_fullsync_count;
|
||||
extern int sqlite3_opentemp_count;
|
||||
@@ -9400,8 +9367,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
(char*)&sqlite3_data_directory, TCL_LINK_STRING);
|
||||
Tcl_LinkVar(interp, "bitmask_size",
|
||||
(char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
||||
Tcl_LinkVar(interp, "longdouble_size",
|
||||
(char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
||||
Tcl_LinkVar(interp, "sqlite_sync_count",
|
||||
(char*)&sqlite3_sync_count, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite_fullsync_count",
|
||||
|
||||
@@ -512,10 +512,6 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "lookaside", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
Tcl_SetVar2(interp, "sqlite_options", "long_double",
|
||||
sizeof(LONGDOUBLE_TYPE)>sizeof(double) ? "1" : "0",
|
||||
TCL_GLOBAL_ONLY);
|
||||
|
||||
#ifdef SQLITE_OMIT_MEMORYDB
|
||||
Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -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)
|
||||
|
||||
+68
-109
@@ -539,6 +539,8 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
int eValid = 1; /* True exponent is either not used or is well-formed */
|
||||
int nDigit = 0; /* Number of digits processed */
|
||||
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
|
||||
double rr[2];
|
||||
u64 s2;
|
||||
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
*pResult = 0.0; /* Default return value, in case of an error */
|
||||
@@ -650,68 +652,41 @@ do_atof_calc:
|
||||
e++;
|
||||
}
|
||||
|
||||
if( e==0 ){
|
||||
*pResult = s;
|
||||
}else if( sqlite3Config.bUseLongDouble ){
|
||||
LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
|
||||
if( e>0 ){
|
||||
while( e>=100 ){ e-=100; r *= 1.0e+100L; }
|
||||
while( e>=10 ){ e-=10; r *= 1.0e+10L; }
|
||||
while( e>=1 ){ e-=1; r *= 1.0e+01L; }
|
||||
}else{
|
||||
while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
|
||||
while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
|
||||
while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
|
||||
}
|
||||
assert( r>=0.0 );
|
||||
if( r>+1.7976931348623157081452742373e+308L ){
|
||||
#ifdef INFINITY
|
||||
*pResult = +INFINITY;
|
||||
#else
|
||||
*pResult = 1.0e308*10.0;
|
||||
rr[0] = (double)s;
|
||||
s2 = (u64)rr[0];
|
||||
#if defined(_MSC_VER) && _MSC_VER<1700
|
||||
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
|
||||
#endif
|
||||
}else{
|
||||
*pResult = (double)r;
|
||||
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
||||
if( e>0 ){
|
||||
while( e>=100 ){
|
||||
e -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( e>=10 ){
|
||||
e -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( e>=1 ){
|
||||
e -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
}else{
|
||||
double rr[2];
|
||||
u64 s2;
|
||||
rr[0] = (double)s;
|
||||
s2 = (u64)rr[0];
|
||||
#if defined(_MSC_VER) && _MSC_VER<1700
|
||||
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
|
||||
#endif
|
||||
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
||||
if( e>0 ){
|
||||
while( e>=100 ){
|
||||
e -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( e>=10 ){
|
||||
e -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( e>=1 ){
|
||||
e -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
}else{
|
||||
while( e<=-100 ){
|
||||
e += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( e<=-10 ){
|
||||
e += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( e<=-1 ){
|
||||
e += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
while( e<=-100 ){
|
||||
e += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( e<=-10 ){
|
||||
e += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( e<=-1 ){
|
||||
e += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
*pResult = rr[0]+rr[1];
|
||||
if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
|
||||
}
|
||||
*pResult = rr[0]+rr[1];
|
||||
if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
|
||||
if( sign<0 ) *pResult = -*pResult;
|
||||
assert( !sqlite3IsNaN(*pResult) );
|
||||
|
||||
@@ -1032,9 +1007,10 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
int i;
|
||||
u64 v;
|
||||
int e, exp = 0;
|
||||
double rr[2];
|
||||
|
||||
p->isSpecial = 0;
|
||||
p->z = p->zBuf;
|
||||
|
||||
assert( mxRound>0 );
|
||||
|
||||
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
||||
@@ -1062,62 +1038,45 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
|
||||
/* Multiply r by powers of ten until it lands somewhere in between
|
||||
** 1.0e+19 and 1.0e+17.
|
||||
**
|
||||
** Use Dekker-style double-double computation to increase the
|
||||
** precision.
|
||||
**
|
||||
** The error terms on constants like 1.0e+100 computed using the
|
||||
** decimal extension, for example as follows:
|
||||
**
|
||||
** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
|
||||
*/
|
||||
if( sqlite3Config.bUseLongDouble ){
|
||||
LONGDOUBLE_TYPE rr = r;
|
||||
if( rr>=1.0e+19 ){
|
||||
while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
|
||||
while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
|
||||
while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
|
||||
}else{
|
||||
while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
|
||||
while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
|
||||
while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
|
||||
rr[0] = r;
|
||||
rr[1] = 0.0;
|
||||
if( rr[0]>9.223372036854774784e+18 ){
|
||||
while( rr[0]>9.223372036854774784e+118 ){
|
||||
exp += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( rr[0]>9.223372036854774784e+28 ){
|
||||
exp += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( rr[0]>9.223372036854774784e+18 ){
|
||||
exp += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
v = (u64)rr;
|
||||
}else{
|
||||
/* If high-precision floating point is not available using "long double",
|
||||
** then use Dekker-style double-double computation to increase the
|
||||
** precision.
|
||||
**
|
||||
** The error terms on constants like 1.0e+100 computed using the
|
||||
** decimal extension, for example as follows:
|
||||
**
|
||||
** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
|
||||
*/
|
||||
double rr[2];
|
||||
rr[0] = r;
|
||||
rr[1] = 0.0;
|
||||
if( rr[0]>9.223372036854774784e+18 ){
|
||||
while( rr[0]>9.223372036854774784e+118 ){
|
||||
exp += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( rr[0]>9.223372036854774784e+28 ){
|
||||
exp += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( rr[0]>9.223372036854774784e+18 ){
|
||||
exp += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
}else{
|
||||
while( rr[0]<9.223372036854774784e-83 ){
|
||||
exp -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( rr[0]<9.223372036854774784e+07 ){
|
||||
exp -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( rr[0]<9.22337203685477478e+17 ){
|
||||
exp -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
while( rr[0]<9.223372036854774784e-83 ){
|
||||
exp -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( rr[0]<9.223372036854774784e+07 ){
|
||||
exp -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( rr[0]<9.22337203685477478e+17 ){
|
||||
exp -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
|
||||
}
|
||||
|
||||
v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
|
||||
|
||||
/* Extract significant digits. */
|
||||
i = sizeof(p->zBuf)-1;
|
||||
|
||||
@@ -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 );
|
||||
|
||||
+8
-8
@@ -4512,7 +4512,7 @@ SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
|
||||
** We must use separate SQLITE_NOINLINE functions here, since otherwise
|
||||
** optimizer code movement causes gcov to become very confused.
|
||||
*/
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
static int SQLITE_NOINLINE doubleLt(double a, double b){ return a<b; }
|
||||
static int SQLITE_NOINLINE doubleEq(double a, double b){ return a==b; }
|
||||
#endif
|
||||
@@ -4527,13 +4527,6 @@ int sqlite3IntFloatCompare(i64 i, double r){
|
||||
/* SQLite considers NaN to be a NULL. And all integer values are greater
|
||||
** than NULL */
|
||||
return 1;
|
||||
}
|
||||
if( sqlite3Config.bUseLongDouble ){
|
||||
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
|
||||
testcase( x<r );
|
||||
testcase( x>r );
|
||||
testcase( x==r );
|
||||
return (x<r) ? -1 : (x>r);
|
||||
}else{
|
||||
i64 y;
|
||||
if( r<-9223372036854775808.0 ) return +1;
|
||||
@@ -5543,5 +5536,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 */
|
||||
|
||||
+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:
|
||||
**
|
||||
@@ -541,6 +541,7 @@ struct Wal {
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
|
||||
int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
sqlite3 *db;
|
||||
@@ -3097,7 +3098,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
|
||||
SEH_INJECT_FAULT;
|
||||
if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
|
||||
&& ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
|
||||
#endif
|
||||
){
|
||||
/* The WAL has been completely backfilled (or it is empty).
|
||||
@@ -4497,7 +4498,20 @@ void sqlite3WalSnapshotOpen(
|
||||
Wal *pWal,
|
||||
sqlite3_snapshot *pSnapshot
|
||||
){
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
|
||||
/* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In
|
||||
** this case set the bGetSnapshot flag so that if the call to
|
||||
** sqlite3_snapshot_get() is about to read transaction on this wal
|
||||
** file, it does not take read-lock 0 if the wal file has been completely
|
||||
** checkpointed. Taking read-lock 0 would work, but then it would be
|
||||
** possible for a subsequent writer to destroy the snapshot even while
|
||||
** this connection is holding its read-transaction open. This is contrary
|
||||
** to user expectations, so we avoid it by not taking read-lock 0. */
|
||||
pWal->bGetSnapshot = 1;
|
||||
}else{
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
pWal->bGetSnapshot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+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 ){
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set mxpow [expr {[use_long_double]?100:35}]
|
||||
set mxpow 35
|
||||
expr srand(1)
|
||||
for {set i 1} {$i<20000} {incr i} {
|
||||
set pow [expr {int((rand()-0.5)*$mxpow)}]
|
||||
|
||||
+12
-18
@@ -262,11 +262,9 @@ do_test cast-3.12 {
|
||||
do_realnum_test cast-3.13 {
|
||||
execsql {SELECT CAST('9223372036854774800' AS real)}
|
||||
} 9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
do_test cast-3.14 {
|
||||
execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)}
|
||||
} 9223372036854774784
|
||||
}
|
||||
do_test cast-3.14 {
|
||||
execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)}
|
||||
} 9223372036854774784
|
||||
do_test cast-3.15 {
|
||||
execsql {SELECT CAST('-9223372036854774800' AS integer)}
|
||||
} -9223372036854774800
|
||||
@@ -276,11 +274,9 @@ do_test cast-3.16 {
|
||||
do_realnum_test cast-3.17 {
|
||||
execsql {SELECT CAST('-9223372036854774800' AS real)}
|
||||
} -9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
do_test cast-3.18 {
|
||||
execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)}
|
||||
} -9223372036854774784
|
||||
}
|
||||
do_test cast-3.18 {
|
||||
execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)}
|
||||
} -9223372036854774784
|
||||
if {[db eval {PRAGMA encoding}]=="UTF-8"} {
|
||||
do_test cast-3.21 {
|
||||
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS integer)}
|
||||
@@ -291,14 +287,12 @@ if {[db eval {PRAGMA encoding}]=="UTF-8"} {
|
||||
do_realnum_test cast-3.23 {
|
||||
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)}
|
||||
} 9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
do_test cast-3.24 {
|
||||
execsql {
|
||||
SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
|
||||
AS integer)
|
||||
}
|
||||
} 9223372036854774784
|
||||
}
|
||||
do_test cast-3.24 {
|
||||
execsql {
|
||||
SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
|
||||
AS integer)
|
||||
}
|
||||
} 9223372036854774784
|
||||
}
|
||||
do_test cast-3.31 {
|
||||
execsql {SELECT CAST(NULL AS numeric)}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
**
|
||||
** time ./a.out 0 10000000 <-- standard library
|
||||
** time ./a.out 1 10000000 <-- SQLite
|
||||
** time ./a.out 2 10000000 <-- SQLite with long-double disabled
|
||||
*/
|
||||
static double aVal[] = {
|
||||
-1.0163830486285643089e+063,
|
||||
@@ -150,15 +149,6 @@ int main(int argc, char **argv){
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
printf("Doing %d calls to sqlite3_snprintf() without long double\n", cnt);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, 0);
|
||||
for(i=0; i<cnt; i++){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.26g", aVal[i%NN]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 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)
|
||||
|
||||
@@ -261,9 +261,6 @@ ifcapable floatingpoint {
|
||||
catchsql {SELECT round(b,2.0) FROM t1 ORDER BY b}
|
||||
} {0 {-2.0 1.23 2.0}}
|
||||
# Verify some values reported on the mailing list.
|
||||
# Some of these fail on MSVC builds with 64-bit
|
||||
# long doubles, but not on GCC builds with 80-bit
|
||||
# long doubles.
|
||||
for {set i 1} {$i<999} {incr i} {
|
||||
set x1 [expr 40222.5 + $i]
|
||||
set x2 [expr 40223.0 + $i]
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ set highPrecision(3) [expr \
|
||||
{[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}]
|
||||
|
||||
if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} {
|
||||
puts "NOTICE: use_long_double: [use_long_double] \
|
||||
puts "NOTICE:\
|
||||
highPrecision: $highPrecision(1) $highPrecision(2) $highPrecision(3)"
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -1038,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}}
|
||||
|
||||
|
||||
@@ -96,4 +96,43 @@ do_test 1.8 {
|
||||
list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg
|
||||
} {1 SQLITE_ERROR_SNAPSHOT}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
} {wal}
|
||||
|
||||
sqlite3 db2 test.db
|
||||
sqlite3 db3 test.db
|
||||
do_execsql_test -db db2 2.0.1 {
|
||||
SELECT * FROM t1
|
||||
} {1 2 3 4}
|
||||
do_execsql_test -db db3 2.0.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 2 3 4}
|
||||
|
||||
do_execsql_test -db db2 2.2 {
|
||||
PRAGMA wal_checkpoint;
|
||||
} {0 4 4}
|
||||
|
||||
do_test 2.1 {
|
||||
db eval { BEGIN }
|
||||
set snap [sqlite3_snapshot_get db main]
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 2.3 {
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
} {}
|
||||
|
||||
do_test 2.2 {
|
||||
execsql { BEGIN } db3
|
||||
sqlite3_snapshot_open db3 main $snap
|
||||
} {}
|
||||
|
||||
sqlite3_snapshot_free $snap
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -21,7 +21,6 @@ static const char zHelp[] =
|
||||
" --memdb Use an in-memory database\n"
|
||||
" --mmap SZ MMAP the first SZ bytes of the database file\n"
|
||||
" --multithread Set multithreaded mode\n"
|
||||
" --nolongdouble Disable the use of long double\n"
|
||||
" --nomemstat Disable memory statistics\n"
|
||||
" --nomutex Open db with SQLITE_OPEN_NOMUTEX\n"
|
||||
" --nosync Set PRAGMA synchronous=OFF\n"
|
||||
@@ -2352,10 +2351,6 @@ int main(int argc, char **argv){
|
||||
ARGC_VALUE_CHECK(1);
|
||||
mmapSize = integerValue(argv[++i]);
|
||||
#endif
|
||||
}else if( strcmp(z,"nolongdouble")==0 ){
|
||||
#ifdef SQLITE_TESTCTRL_USELONGDOUBLE
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, 0);
|
||||
#endif
|
||||
}else if( strcmp(z,"nomutex")==0 ){
|
||||
openFlags |= SQLITE_OPEN_NOMUTEX;
|
||||
}else if( strcmp(z,"nosync")==0 ){
|
||||
|
||||
+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
+139
-36
@@ -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?
|
||||
@@ -112,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
|
||||
}]]
|
||||
@@ -284,6 +318,8 @@ set TRG(schema) {
|
||||
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
|
||||
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
|
||||
);
|
||||
|
||||
@@ -356,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
|
||||
}
|
||||
|
||||
@@ -577,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
|
||||
@@ -622,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
|
||||
@@ -637,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
|
||||
}
|
||||
|
||||
@@ -1105,6 +1194,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
}
|
||||
}
|
||||
|
||||
devtest -
|
||||
mdevtest {
|
||||
set config_set {
|
||||
All-O0
|
||||
@@ -1192,10 +1282,13 @@ proc mark_job_as_finished {jobid output state endtm} {
|
||||
set ntest 1
|
||||
set nerr 0
|
||||
if {$endtm>0} {
|
||||
if {[regexp {\y(\d+) errors out of (\d+) tests} $output all a b]} {
|
||||
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"} {
|
||||
@@ -1204,10 +1297,11 @@ proc mark_job_as_finished {jobid output state endtm} {
|
||||
} else {
|
||||
set childstate ready
|
||||
}
|
||||
if {[info exists pltfm]} {set pltfm [string trim $pltfm]}
|
||||
trdb eval {
|
||||
UPDATE jobs
|
||||
SET output=$output, state=$state, endtime=$endtm,
|
||||
ntest=$ntest, nerr=$nerr
|
||||
ntest=$ntest, nerr=$nerr, svers=$svers, pltfm=$pltfm
|
||||
WHERE jobid=$jobid;
|
||||
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
|
||||
}
|
||||
@@ -1460,7 +1554,16 @@ proc run_testset {} {
|
||||
FROM jobs WHERE endtime>0
|
||||
} break;
|
||||
set et [elapsetime $totaltime]
|
||||
puts "$totalerr errors out of $totaltest tests in about $et"
|
||||
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.
|
||||
|
||||
@@ -88,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
|
||||
@@ -202,7 +203,6 @@ namespace eval trd {
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
-DSQLITE_MAX_MMAP_SIZE=12884901888
|
||||
-DSQLITE_ENABLE_SORTER_MMAP=1
|
||||
-DLONGDOUBLE_TYPE=double
|
||||
--enable-session
|
||||
}
|
||||
set build(Device-One) {
|
||||
@@ -342,7 +342,6 @@ namespace eval trd {
|
||||
-DSQLITE_ENABLE_FTS4
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DLONGDOUBLE_TYPE=double
|
||||
-DCONFIG_SLOWDOWN_FACTOR=8.0
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+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
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user