diff --git a/Makefile.in b/Makefile.in
index 9bc763911a..01d029f562 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -703,7 +703,7 @@ 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 \
+ $(TOP)/tool/sqlite3_rsync.c \
sqlite3.c
RSYNC_OPT = \
@@ -713,7 +713,7 @@ RSYNC_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
-sqlite3-rsync$(TEXE): $(RSYNC_SRC)
+sqlite3_rsync$(TEXE): $(RSYNC_SRC)
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
@@ -724,13 +724,13 @@ srcck1$(BEXE): $(TOP)/tool/srcck1.c
$(BCC) -o srcck1$(BEXE) $(TOP)/tool/srcck1.c
sourcetest: srcck1$(BEXE) sqlite3.c
- ./srcck1 sqlite3.c
+ ./srcck1$(BEXE) sqlite3.c
-src-verify: $(TOP)/tool/src-verify.c
+src-verify$(BEXE): $(TOP)/tool/src-verify.c
$(BCC) -o src-verify$(BEXE) $(TOP)/tool/src-verify.c
-verify-source: ./src-verify
- ./src-verify $(TOP)
+verify-source: ./src-verify$(BEXE)
+ ./src-verify$(BEXE) $(TOP)
fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
@@ -848,7 +848,7 @@ has_tclconfig:
cp fts5.c fts5.h tsrc
touch .target_source
-sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84
+sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify$(BEXE) has_tclsh84
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC)
cp tsrc/sqlite3ext.h .
cp $(TOP)/ext/session/sqlite3session.h .
@@ -1560,7 +1560,8 @@ snapshot-tarball: sqlite3.c sqlite3rc.h
# Build a ZIP archive containing various command-line tools.
#
-tool-zip: testfixture sqlite3 sqldiff sqlite3_analyzer $(TOP)/tool/mktoolzip.tcl
+tool-zip: testfixture sqlite3 sqldiff sqlite3_analyzer sqlite3_rsync $(TOP)/tool/mktoolzip.tcl
+ strip sqlite3 sqldiff sqlite3_analyzer sqlite3_rsync
./testfixture $(TOP)/tool/mktoolzip.tcl
# The next two rules are used to support the "threadtest" target. Building
@@ -1589,10 +1590,10 @@ lib_install: libsqlite3.la
$(INSTALL) -d $(DESTDIR)$(libdir)
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
-# Use $(tcl_install_$(HAVE_TCL)) to resolve to either tcl_install or
+# Use $(tcl_install_$(HAVE_TCL)) to resolve to either tclextension-install or
# an empty value.
tcl_install_0 =
-tcl_install_1 = tcl_install
+tcl_install_1 = tclextension-install
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc $(tcl_install_$(HAVE_TCL))
$(INSTALL) -d $(DESTDIR)$(bindir)
@@ -1603,27 +1604,18 @@ install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc $(tcl_install_$(HAVE_TC
$(INSTALL) -d $(DESTDIR)$(pkgconfigdir)
$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
-pkgIndex.tcl:
- echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
-
-tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
- $(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
- $(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
- rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
- $(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
-
# Build the SQLite TCL extension in a way that make it compatible
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
# by --with-tclsh=
#
tclextension: tclsqlite3.c
- $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only --cc $(CC) $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
+ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only --cc "$(CC)" $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
# to find it.
#
tclextension-install: tclsqlite3.c
- $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --cc $(CC) $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
+ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --cc "$(CC)" $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
# Install the SQLite TCL extension that is used by $TCLSH_CMD
#
@@ -1655,11 +1647,11 @@ tidy:
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 *.so *.dylib pkgIndex.tcl
- rm -f sqlite3_analyzer$(TEXE) sqlite3-rsync$(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)
- rm -f src-verify has_tclsh*
+ rm -f src-verify$(BEXE) has_tclsh* has_tclconfig
# Removes build products and test logs. Retains ./configure outputs.
#
diff --git a/Makefile.msc b/Makefile.msc
index bf89efe6bb..dfa998f9b5 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -66,6 +66,14 @@ USE_STDCALL = 0
USE_SEH = 1
!ENDIF
+# Use STATICALLY_LINK_TCL=1 to statically link against TCL
+#
+!IFNDEF STATICALLY_LINK_TCL
+STATICALLY_LINK_TCL = 0
+!ELSEIF $(STATICALLY_LINK_TCL)!=0
+CCOPTS = $(CCOPTS) -DSTATIC_BUILD
+!ENDIF
+
# Set this non-0 to have the shell executable link against the core dynamic
# link library.
#
@@ -929,10 +937,9 @@ TCC = $(TCC) /fsanitize=address
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
-!IFNDEF TCLVERSION
-TCLVERSION = 86
+!IF $(STATICALLY_LINK_TCL)!=0
+TCLSUFFIX = s
!ENDIF
-
!IFNDEF TCLSUFFIX
TCLSUFFIX =
!ENDIF
@@ -941,6 +948,19 @@ TCLSUFFIX =
TCLDIR = C:\Tcl
!ENDIF
+!IFNDEF TCLVERSION
+!IF EXISTS("$(TCLDIR)\lib\tcl90$(TCLSUFFIX).lib")
+TCLVERSION = 90
+!ELSEIF EXISTS("$(TCLDIR)\lib\tcl86$(TCLSUFFIX).lib")
+TCLVERSION = 86
+!ELSEIF EXISTS("$(TCLDIR)\lib\tcl86t.lib")
+TCLSUFFIX = t
+TCLVERSION = 86
+!ELSE
+TCLVERSION = 90
+!ENDIF
+!ENDIF
+
!IFNDEF TCLINCDIR
TCLINCDIR = $(TCLDIR)\include
!ENDIF
@@ -953,9 +973,21 @@ TCLLIBDIR = $(TCLDIR)\lib
LIBTCL = tcl$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF
+!IFNDEF TCLLIBS
+!IF $(STATICALLY_LINK_TCL)!=0
+TCLLIBS = /NODEFAULTLIB:libucrt.lib netapi32.lib user32.lib ucrt.lib
+!ELSE
+TCLLIBS =
+!ENDIF
+!ENDIF
+
!IFNDEF LIBTCLSTUB
+!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
+LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
+!ELSE
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
!ENDIF
+!ENDIF
!IFNDEF LIBTCLPATH
LIBTCLPATH = $(TCLDIR)\bin
@@ -1013,10 +1045,18 @@ LIBICU = icuuc.lib icuin.lib
# specific Tcl shell to use.
#
!IFNDEF TCLSH_CMD
-!IF $(USE_TCLSH_IN_PATH)!=0 || !EXIST("$(TCLDIR)\bin\tclsh.exe")
-TCLSH_CMD = tclsh
-!ELSE
+!IF EXISTS("$(TCLDIR)\bin\tclsh$(TCLVERSION).exe")
+TCLSH_CMD = $(TCLDIR)\bin\tclsh$(TCLVERSION).exe
+!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh90.exe")
+TCLSH_CMD = $(TCLDIR)\bin\tclsh90.exe
+!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh86.exe")
+TCLSH_CMD = $(TCLDIR)\bin\tclsh86.exe
+!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh86t.exe")
+TCLSH_CMD = $(TCLDIR)\bin\tclsh86t.exe
+!ELSEIF EXISTS("$(TCLDIR)\bin\tclsh.exe")
TCLSH_CMD = $(TCLDIR)\bin\tclsh.exe
+!ELSE
+TCLSH_CMD = tclsh
!ENDIF
!ENDIF
# <>
@@ -1825,7 +1865,7 @@ tclsqlite3.def: tclsqlite.lo
pkgIndex.tcl: $(TOP)\VERSION
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
- echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] sqlite3] \
+ echo package ifneeded sqlite3 @version@ [list load [file join $$dir $(SQLITE3TCLDLL)] Sqlite3] \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact @version@ %%V > pkgIndex.tcl \
)
@@ -1869,7 +1909,7 @@ 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 \
+ $(TOP)\tool\sqlite3_rsync.c \
$(SQLITE3C)
RSYNC_OPT = \
@@ -1878,7 +1918,7 @@ RSYNC_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
-sqlite3-rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
+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)
@@ -2538,7 +2578,7 @@ extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
-tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl
+tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe sqlite3_rsync.exe $(TOP)\tool\mktoolzip.tcl
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl
coretestprogs: testfixture.exe sqlite3.exe
@@ -2747,6 +2787,16 @@ THREADTEST3_SRC = \
threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+# Display key variables that control which version of TCL is to be used.
+#
+tcl-env:
+ @echo TCLDIR = $(TCLDIR)
+ @echo TCLVERSION = $(TCLVERSION)
+ @echo TCLSUFFIX = $(TCLSUFFIX)
+ @echo LIBTCL = $(LIBTCL)
+ @echo LIBTCLSTUB = $(LIBTCLSTUB)
+ @echo TCLSH_CMD = $(TCLSH_CMD)
+
LSMDIR=$(TOP)\ext\lsm1
!INCLUDE $(LSMDIR)\Makefile.msc
@@ -2780,7 +2830,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 sqlite3-rsync.exe 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
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index f8a65e90cc..efebc9931a 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -66,6 +66,14 @@ USE_STDCALL = 0
USE_SEH = 1
!ENDIF
+# Use STATICALLY_LINK_TCL=1 to statically link against TCL
+#
+!IFNDEF STATICALLY_LINK_TCL
+STATICALLY_LINK_TCL = 0
+!ELSEIF $(STATICALLY_LINK_TCL)!=0
+CCOPTS = $(CCOPTS) -DSTATIC_BUILD
+!ENDIF
+
# Set this non-0 to have the shell executable link against the core dynamic
# link library.
#
diff --git a/autoconf/tea/README b/autoconf/tea/README.txt
similarity index 66%
rename from autoconf/tea/README
rename to autoconf/tea/README.txt
index 99dc8b8f03..ea7eb930f2 100644
--- a/autoconf/tea/README
+++ b/autoconf/tea/README.txt
@@ -3,6 +3,27 @@ Architecture (TEA). For additional information on SQLite see
http://www.sqlite.org/
+-------------------------------------------------------------------
+Update 2024-10-11:
+
+A better way to build the TCL extension for SQLite is to use the
+canonical source code tarball. For Unix:
+
+ ./configure --with-tclsh=$(TCLSH)
+ make tclextension-install
+
+For Windows:
+
+ nmake /f Makefile.msc tclextension-install TCLSH_CMD=$(TCLSH)
+
+In both of the above, replace $(TCLSH) with the full pathname of
+of the tclsh that you want the SQLite extension to work with.
+
+This TEA builder is antiquated. It does not work for TCL9. The
+SQLite devs don't know how to fix it. If you would like to help
+fix it, contact us.
+------------------------------------------------------------------
+
UNIX BUILD
==========
diff --git a/autoconf/tea/pkgIndex.tcl.in b/autoconf/tea/pkgIndex.tcl.in
index f95f7d3893..666812dee7 100644
--- a/autoconf/tea/pkgIndex.tcl.in
+++ b/autoconf/tea/pkgIndex.tcl.in
@@ -3,8 +3,8 @@
#
if {[package vsatisfies [package provide Tcl] 9.0-]} {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
- [list load [file join $dir @PKG_LIB_FILE9@] sqlite3]
+ [list load [file join $dir @PKG_LIB_FILE9@] Sqlite3]
} else {
package ifneeded sqlite3 @PACKAGE_VERSION@ \
- [list load [file join $dir @PKG_LIB_FILE8@] sqlite3]
+ [list load [file join $dir @PKG_LIB_FILE8@] Sqlite3]
}
diff --git a/autoconf/tea/win/makefile.vc b/autoconf/tea/win/makefile.vc
index da56e811fc..dacb7c6b3a 100644
--- a/autoconf/tea/win/makefile.vc
+++ b/autoconf/tea/win/makefile.vc
@@ -407,7 +407,7 @@ install-libraries:
@echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
@type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
package ifneeded $(PROJECT) $(DOTVERSION) \
- [list load [file join $$dir $(PRJLIBNAME)] sqlite3]
+ [list load [file join $$dir $(PRJLIBNAME)] Sqlite3]
<<
install-docs:
diff --git a/configure b/configure
index 22b961e554..0ddfa67aa6 100755
--- a/configure
+++ b/configure
@@ -10335,7 +10335,7 @@ fi
original_use_tcl=${use_tcl}
if test x"${with_tclsh}" == x -a x"${with_tcl}" == x; then
- for ac_prog in tclsh8.6 tclsh tclsh9.0
+ for ac_prog in tclsh9.0 tclsh8.6 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
diff --git a/configure.ac b/configure.ac
index b3a0dd299f..f2ec22aae2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,7 +125,7 @@ AC_ARG_ENABLE(tcl, AS_HELP_STRING([--disable-tcl],[omit building accessory progr
[use_tcl=$enableval],[use_tcl=yes])
original_use_tcl=${use_tcl}
if test x"${with_tclsh}" == x -a x"${with_tcl}" == x; then
- AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh tclsh9.0],none)
+ AC_CHECK_PROGS(TCLSH_CMD, [tclsh9.0 tclsh8.6 tclsh],none)
with_tclsh=${TCLSH_CMD}
fi
if test x"${with_tclsh}" != x -a x"${with_tclsh}" != xnone; then
diff --git a/doc/compile-for-unix.md b/doc/compile-for-unix.md
new file mode 100644
index 0000000000..ff5e2111a7
--- /dev/null
+++ b/doc/compile-for-unix.md
@@ -0,0 +1,58 @@
+# Notes On Compiling SQLite On All Kinds Of Unix
+
+Here are step-by-step instructions on how to build SQLite from
+canonical source on any modern machine that isn't Windows. These
+notes are tested (on 2024-10-11) on Ubuntu and on MacOS, but they
+are general and should work on most any modern unix platform.
+
+ 1. Install a C-compiler. GCC or Clang both work fine. If you are
+ reading this document, you've probably already done that.
+
+ 2. Install TCL9 development libraries. In this note, we'll do a
+ private install in the $HOME/local directory, but you can make
+ adjustments to install TCL9 wherever you like.
+ install the TCL development libraries in the "`c:\Tcl`" directory.
+
+ This document assumes you are working with TCL version 9.0.
+
+ - Get the TCL source archive, perhaps from
+ [https://www.tcl.tk/software/tcltk/download.html](https://www.tcl.tk/software/tcltk/download.html)
+ or [https://sqlite.org/tmp/tcl9.0.0.tar.gz](https://sqlite.org/tmp/tcl9.0.0.tar.gz)
+
- Untar the source archive. CD into the "unix/" subfolder
+ of the source tree.
+
- Run: `mkdir $HOME/local`
+
- Run: `./configure --prefix=$HOME/local`
+
- Run: `make install`
+
+
+ 4. Download the SQLite source tree and unpack it. CD into the
+ toplevel directory of the source tree.
+
+ 5. Run: `./configure --enable-all --with-tclsh=$HOME/local/bin/tclsh9.0`
+
+ You do not need to use --with-tclsh if the tclsh you want to use is the
+ first one on your PATH.
+
+ 6. Run the "`Makefile`" makefile with an appropriate target.
+ Examples:
+
+ - `make sqlite3.c`
+
- `make sqlite3`
+
- `make sqldiff`
+
- `make sqlite3_rsync`
+
- `make tclextension-install`
+
- `make devtest`
+
- `make releasetest`
+
- `make sqlite3_analyzer`
+
+
+ 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 the --enable-debug argument to configure.
diff --git a/doc/compile-for-windows.md b/doc/compile-for-windows.md
index 1627188acd..fe06697c56 100644
--- a/doc/compile-for-windows.md
+++ b/doc/compile-for-windows.md
@@ -1,7 +1,7 @@
# Notes On Compiling SQLite On Windows 11
Here are step-by-step instructions on how to build SQLite from
-canonical source on a new Windows 11 PC, as of 2023-11-01:
+canonical source on a new Windows 11 PC, as of 2024-10-09:
1. Install Microsoft Visual Studio. The free "community edition"
will work fine. Do a standard install for C++ development.
@@ -20,9 +20,11 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
install the TCL development libraries in the "`c:\Tcl`" directory.
Make adjustments
if you want TCL installed somewhere else. SQLite needs both the
- "tclsh.exe" command-line tool as part of the build process, and
- the "tcl86.lib" library in order to run tests. You will need
- TCL version 8.6 or later.
+ "tclsh90.exe" command-line tool as part of the build process, and
+ the "tcl90.lib" and "tclstub.lib" libraries in order to run tests.
+ This document assumes you are working with TCL version 9.0.
+ See versions of this document from prior to 2024-10-10 for
+ instructions on how to build using TCL version 8.6.
- Get the TCL source archive, perhaps from
[https://www.tcl.tk/software/tcltk/download.html](https://www.tcl.tk/software/tcltk/download.html).
@@ -30,13 +32,10 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
of the source tree.
- Run: `nmake /f makefile.vc release`
- Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install`
-
- CD to `c:\Tcl\lib`. In that subfolder make a copy of the
- "`tcl86t.lib`" file to the alternative name "`tcl86.lib`"
- (omitting the second 't'). Leave the copy in the same directory
- as the original.
-
- CD to `c:\Tcl\bin`. Make a copy of the "`tclsh86t.exe`"
- file into "`tclsh.exe`" (without the "86t") in the same directory.
-
- Add `c:\Tcl\bin` to your %PATH%. To do this, go to Settings
+
- Optional: CD to `c:\Tcl\bin` and make a copy of
+ `tclsh90.exe` over into just `tclsh.exe`.
+
- Optional:
+ Add `c:\Tcl\bin` to your %PATH%. To do this, go to Settings
and search for "path". Select "edit environment variables for
your account" and modify your default PATH accordingly.
You will need to close and reopen your command prompts after
@@ -59,6 +58,7 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
- `nmake /f makefile.msc sqlite3.c`
- `nmake /f makefile.msc sqlite3.exe`
- `nmake /f makefile.msc sqldiff.exe`
+
- `nmake /f makefile.msc sqlite3_rsync.exe`
- `nmake /f makefile.msc tclextension-install`
- `nmake /f makefile.msc devtest`
- `nmake /f makefile.msc releasetest`
@@ -127,7 +127,7 @@ nmake /f Makefile.msc sqlite3_analyzer.exe
~~~~
And you will end up with a working executable. However, that executable
-will depend on having the "tcl86.dll" library somewhere on your %PATH%.
+will depend on having the "tcl98.dll" library somewhere on your %PATH%.
Use the following steps to build an executable that has the TCL library
statically linked so that it does not depend on separate DLL:
@@ -137,27 +137,26 @@ statically linked so that it does not depend on separate DLL:
2. Untar the TCL source tarball into a fresh directory. CD into
the "win/" subfolder.
- 3. Run: `nmake /f makefile.vc OPTS=nothreads,static shell`
-
+ 3. Run: `nmake /f makefile.vc OPTS=static shell`
4. CD into the "Release*" subfolder that is created (note the
wildcard - the full name of the directory might vary). There
- you will find the "tcl86s.lib" file. Copy this file into the
- same directory that you put the "tcl86.lib" on your initial
+ you will find the "tcl90s.lib" file. Copy this file into the
+ same directory that you put the "tcl90.lib" on your initial
installation. (In this document, that directory is
"`C:\Tcl32\lib`" for 32-bit builds and
"`C:\Tcl\lib`" for 64-bit builds.)
5. CD into your SQLite source code directory and build the desired
- utility program, but add the following extra arguments to the
+ utility program, but add the following extra argument to the
nmake command line:
- CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib"
+ STATICALLY_LINK_TCL=1
So, for example, to build a statically linked version of
sqlite3_analyzer.exe, you might type:
- nmake /f Makefile.msc CCOPTS="-DSTATIC_BUILD" LIBTCL="tcl86s.lib netapi32.lib user32.lib" sqlite3_analyzer.exe
+ nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe
6. After your executable is built, you can verify that it does not
diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test
index 239450442e..16bd149fa1 100644
--- a/ext/expert/expert1.test
+++ b/ext/expert/expert1.test
@@ -402,6 +402,19 @@ do_setup_rec_test $tn.19.0 {
SCAN t1 USING COVERING INDEX t1_idx_01a7214e
}
+ifcapable fts5 {
+ do_setup_rec_test $tn.20.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ CREATE TABLE t1(x, y);
+ } {
+ SELECT * FROM ft, t1 WHERE a=x
+ } {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+ SCAN ft VIRTUAL TABLE INDEX 0:
+ SEARCH t1 USING INDEX t1_idx_00000078 (x=?)
+ }
+}
+
}
proc do_candidates_test {tn sql res} {
@@ -507,4 +520,65 @@ do_candidates_test 6.1 {
CREATE INDEX x1_idx_00000062 ON x1(b);
}
+#-------------------------------------------------------------------------
+ifcapable fts5 {
+ reset_db
+ do_execsql_test 7.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ CREATE TABLE t1(x, y);
+ }
+
+ do_candidates_test 7.1 {
+ SELECT * FROM ft, t1 WHERE a=x
+ } {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+ }
+
+ register_tcl_module db
+ proc vtab_command {method args} {
+ global G
+
+ switch -- $method {
+ xConnect {
+ return "CREATE TABLE t1(a, b, c);"
+ }
+
+ xBestIndex {
+ return [list]
+ }
+
+ xFilter {
+ return [list sql "SELECT rowid, * FROM t0"]
+ }
+ }
+
+ return {}
+ }
+
+ do_execsql_test 7.2 {
+ CREATE TABLE t0(a, b, c);
+ INSERT INTO t0 VALUES(1, 2, 3), (11, 22, 33);
+ CREATE VIRTUAL TABLE t2 USING tcl(vtab_command);
+ }
+
+ do_execsql_test 7.3 {
+ SELECT * FROM t2
+ } {
+ 1 2 3
+ 11 22 33
+ }
+
+ do_candidates_test 7.4 {
+ SELECT * FROM ft, t1 WHERE a=x
+ } {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+ }
+
+ do_test 7.5 {
+ set expert [sqlite3_expert_new db]
+ list [catch { $expert sql "SELECT * FROM ft, t2 WHERE b=1" } msg] $msg
+ } {1 {no such table: t2}}
+ $expert destroy
+}
+
finish_test
diff --git a/ext/expert/sqlite3expert.c b/ext/expert/sqlite3expert.c
index 3177339584..099a5235dd 100644
--- a/ext/expert/sqlite3expert.c
+++ b/ext/expert/sqlite3expert.c
@@ -1392,6 +1392,66 @@ static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
return rc;
}
+/*
+** This function tests if the schema of the main database of database handle
+** db contains an object named zTab. Assuming no error occurs, output parameter
+** (*pbContains) is set to true if zTab exists, or false if it does not.
+**
+** Or, if an error occurs, an SQLite error code is returned. The final value
+** of (*pbContains) is undefined in this case.
+*/
+static int expertDbContainsObject(
+ sqlite3 *db,
+ const char *zTab,
+ int *pbContains /* OUT: True if object exists */
+){
+ const char *zSql = "SELECT 1 FROM sqlite_schema WHERE name = ?";
+ sqlite3_stmt *pSql = 0;
+ int rc = SQLITE_OK;
+ int ret = 0;
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_text(pSql, 1, zTab, -1, SQLITE_STATIC);
+ if( SQLITE_ROW==sqlite3_step(pSql) ){
+ ret = 1;
+ }
+ rc = sqlite3_finalize(pSql);
+ }
+
+ *pbContains = ret;
+ return rc;
+}
+
+/*
+** Execute SQL command zSql using database handle db. If no error occurs,
+** set (*pzErr) to NULL and return SQLITE_OK.
+**
+** If an error does occur, return an SQLite error code and set (*pzErr) to
+** point to a buffer containing an English language error message. Except,
+** if the error message begins with "no such module:", then ignore the
+** error and return as if the SQL statement had succeeded.
+**
+** This is used to copy as much of the database schema as possible while
+** ignoring any errors related to missing virtual table modules.
+*/
+static int expertSchemaSql(sqlite3 *db, const char *zSql, char **pzErr){
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+
+ rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
+ if( rc!=SQLITE_OK && zErr ){
+ int nErr = STRLEN(zErr);
+ if( nErr>=15 && memcmp(zErr, "no such module:", 15)==0 ){
+ sqlite3_free(zErr);
+ rc = SQLITE_OK;
+ zErr = 0;
+ }
+ }
+
+ *pzErr = zErr;
+ return rc;
+}
static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
int rc = idxRegisterVtab(p);
@@ -1403,22 +1463,29 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
** 2) Create the equivalent virtual table in dbv.
*/
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
- "SELECT type, name, sql, 1 FROM sqlite_schema "
+ "SELECT type, name, sql, 1, sql LIKE 'create virtual%' "
+ "FROM sqlite_schema "
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
" UNION ALL "
- "SELECT type, name, sql, 2 FROM sqlite_schema "
+ "SELECT type, name, sql, 2, 0 FROM sqlite_schema "
"WHERE type = 'trigger'"
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
- "ORDER BY 4, 1"
+ "ORDER BY 4, 5 DESC, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
+ int bVirtual = sqlite3_column_int(pSchema, 4);
+ int bExists = 0;
if( zType==0 || zName==0 ) continue;
- if( zType[0]=='v' || zType[1]=='r' ){
- if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
+ rc = expertDbContainsObject(p->dbv, zName, &bExists);
+ if( rc || bExists ) continue;
+
+ if( zType[0]=='v' || zType[1]=='r' || bVirtual ){
+ /* A view. Or a trigger on a view. */
+ if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
}else{
IdxTable *pTab;
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
@@ -1957,12 +2024,18 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
if( rc==SQLITE_OK ){
sqlite3_stmt *pSql = 0;
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
- "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
- " AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
+ "SELECT sql, name "
+ " FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
+ " ORDER BY rowid"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
- if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
+ const char *zName = (const char*)sqlite3_column_text(pSql, 1);
+ int bExists = 0;
+ rc = expertDbContainsObject(pNew->dbm, zName, &bExists);
+ if( rc==SQLITE_OK && zSql && bExists==0 ){
+ rc = expertSchemaSql(pNew->dbm, zSql, pzErrmsg);
+ }
}
idxFinalize(&rc, pSql);
}
diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h
index b15521f163..51d8081774 100644
--- a/ext/fts5/fts5Int.h
+++ b/ext/fts5/fts5Int.h
@@ -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
@@ -724,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);
diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c
index 1fade5f7a8..a674b44d0b 100644
--- a/ext/fts5/fts5_config.c
+++ b/ext/fts5/fts5_config.c
@@ -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,17 @@ 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; inCol; 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");
}
}
}
@@ -555,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;
@@ -614,7 +634,7 @@ int sqlite3Fts5ConfigParse(
pzErr
);
}else{
- rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
+ rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr, &bUnindexed);
zOne = 0;
}
}
@@ -646,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";
}
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 4363305a56..a51ae19e72 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -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(
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index db413b572a..5713fccdd1 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -332,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)
+ );
}
/*
@@ -1726,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"
);
@@ -1795,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);
@@ -1803,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; iinCol; 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
@@ -1889,25 +1956,20 @@ 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 */
@@ -1941,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);
}
}
@@ -2170,7 +2252,7 @@ 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{
@@ -2203,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;
@@ -2399,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; inCol; i++){
if( pConfig->abUnindexed[i]==0 ){
@@ -2687,7 +2769,7 @@ 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);
@@ -2962,16 +3044,7 @@ 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 ){
diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c
index e8649c703f..31f5fc5dc3 100644
--- a/ext/fts5/fts5_storage.c
+++ b/ext/fts5/fts5_storage.c
@@ -73,30 +73,6 @@ struct Fts5Storage {
#define FTS5_STMT_REPLACE_CONFIG 10
#define FTS5_STMT_SCAN 11
-/*
-** Return a pointer to a buffer obtained from sqlite3_malloc() that contains
-** nBind comma-separated question marks. e.g. if nBind is passed 5, this
-** function returns "?,?,?,?,?".
-**
-** If *pRc is not SQLITE_OK when this function is called, it is a no-op and
-** NULL is returned immediately. Or, if the attempt to malloc a buffer
-** fails, then *pRc is set to SQLITE_NOMEM and NULL is returned. Otherwise,
-** if it is SQLITE_OK when this function is called and the malloc() succeeds,
-** *pRc is left unchanged.
-*/
-static char *fts5BindingsList(int *pRc, int nBind){
- char *zBind = sqlite3Fts5MallocZero(pRc, 1 + nBind*2);
- if( zBind ){
- int ii;
- for(ii=0; iinCol;
- if( pC->bLocale ){
- for(i=0; inCol; i++){
- if( pC->abUnindexed[i]==0 ) nCol++;
+ 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 = fts5BindingsList(&rc, nCol);
- if( zBind ){
- 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 && inCol; 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;
}
@@ -367,7 +357,9 @@ 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 * 20);
if( zDefn==0 ){
@@ -378,8 +370,12 @@ int sqlite3Fts5StorageOpen(
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
iOff = (int)strlen(zDefn);
for(i=0; inCol; 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; inCol; i++){
@@ -617,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. */
@@ -741,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);
}
@@ -757,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);
}
@@ -789,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
);
}
@@ -926,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
){
@@ -933,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{
@@ -942,8 +956,10 @@ int sqlite3Fts5StorageContentInsert(
}else{
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
int i; /* Counter variable */
- int nIndexed = 0; /* Number indexed columns seen */
- rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
+
+ 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 */
@@ -953,38 +969,39 @@ int sqlite3Fts5StorageContentInsert(
** user-defined column. As is column 1 of pSavedRow. */
for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
int bUnindexed = pConfig->abUnindexed[i-2];
- sqlite3_value *pVal = apVal[i];
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){
+ sqlite3_value *pVal = apVal[i];
- nIndexed += !bUnindexed;
- if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
- /* This is an UPDATE statement, and column (i-2) was not modified.
- ** Retrieve the value from Fts5Storage.pSavedRow instead. */
- pVal = sqlite3_column_value(p->pSavedRow, i-1);
- if( pConfig->bLocale && bUnindexed==0 ){
- sqlite3_bind_value(pInsert, pConfig->nCol + 1 + nIndexed,
- sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
- );
- }
- }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
- const char *pText = 0;
- const char *pLoc = 0;
- int nText = 0;
- int nLoc = 0;
- assert( pConfig->bLocale );
-
- rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
- if( rc==SQLITE_OK ){
- sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
- if( bUnindexed==0 ){
- int iLoc = pConfig->nCol + 1 + nIndexed;
- sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
+ 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;
}
- continue;
+ rc = sqlite3_bind_value(pInsert, i, pVal);
}
-
- rc = sqlite3_bind_value(pInsert, i, pVal);
}
if( rc==SQLITE_OK ){
sqlite3_step(pInsert);
diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c
index f92529b840..f9581b080c 100644
--- a/ext/fts5/fts5_tokenize.c
+++ b/ext/fts5/fts5_tokenize.c
@@ -198,7 +198,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIniColumn==SERIES_COLUMN_VALUE ){
- switch( op ){
- case SQLITE_INDEX_CONSTRAINT_EQ:
- case SQLITE_INDEX_CONSTRAINT_IS: {
- idxNum |= 0x0080;
- idxNum &= ~0x3300;
- aIdx[5] = i;
- aIdx[6] = -1;
- bStartSeen = 1;
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_GE: {
- if( idxNum & 0x0080 ) break;
- idxNum |= 0x0100;
- idxNum &= ~0x0200;
- aIdx[5] = i;
- bStartSeen = 1;
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_GT: {
- if( idxNum & 0x0080 ) break;
- idxNum |= 0x0200;
- idxNum &= ~0x0100;
- aIdx[5] = i;
- bStartSeen = 1;
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_LE: {
- if( idxNum & 0x0080 ) break;
- idxNum |= 0x1000;
- idxNum &= ~0x2000;
- aIdx[6] = i;
- break;
- }
- case SQLITE_INDEX_CONSTRAINT_LT: {
- if( idxNum & 0x0080 ) break;
- idxNum |= 0x2000;
- idxNum &= ~0x1000;
- aIdx[6] = i;
- break;
+ if( pConstraint->iColumniColumn==SERIES_COLUMN_VALUE ){
+ switch( op ){
+ case SQLITE_INDEX_CONSTRAINT_EQ:
+ case SQLITE_INDEX_CONSTRAINT_IS: {
+ idxNum |= 0x0080;
+ idxNum &= ~0x3300;
+ aIdx[5] = i;
+ aIdx[6] = -1;
+ bStartSeen = 1;
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_GE: {
+ if( idxNum & 0x0080 ) break;
+ idxNum |= 0x0100;
+ idxNum &= ~0x0200;
+ aIdx[5] = i;
+ bStartSeen = 1;
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_GT: {
+ if( idxNum & 0x0080 ) break;
+ idxNum |= 0x0200;
+ idxNum &= ~0x0100;
+ aIdx[5] = i;
+ bStartSeen = 1;
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_LE: {
+ if( idxNum & 0x0080 ) break;
+ idxNum |= 0x1000;
+ idxNum &= ~0x2000;
+ aIdx[6] = i;
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_LT: {
+ if( idxNum & 0x0080 ) break;
+ idxNum |= 0x2000;
+ idxNum &= ~0x1000;
+ aIdx[6] = i;
+ break;
+ }
}
}
continue;
diff --git a/ext/misc/sqlite3_stdio.c b/ext/misc/sqlite3_stdio.c
index 46f12dff36..5bb26084c2 100644
--- a/ext/misc/sqlite3_stdio.c
+++ b/ext/misc/sqlite3_stdio.c
@@ -31,27 +31,21 @@
#include
/*
-** 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.
+** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT
+** when appropriate on all output. (Sometimes use O_BINARY when
+** rendering ASCII text in cases where NL-to-CRLF expansion would
+** not be correct.)
**
-** 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.
+** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT
+** when appropriate when writing to stdout or stderr. Use O_BINARY
+** or O_TEXT (depending on things like the .mode and the .crlf setting
+** in the CLI, or other context clues in other applications) for all
+** other output channels.
**
-** 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().
+** The default behavior, if neither of the above is defined is to
+** use O_U8TEXT when writing to the Windows console (or anything
+** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
+** for all other output channels.
*/
#if defined(SQLITE_U8TEXT_ONLY)
# define UseWtextForOutput(fd) 1
@@ -67,6 +61,31 @@
# define IsConsole(fd) 1
#endif
+/*
+** Global variables determine if simulated O_BINARY mode is to be
+** used for stdout or other, respectively. Simulated O_BINARY mode
+** means the mode is usually O_BINARY, but switches to O_U8TEXT for
+** unicode characters U+0080 or greater (any character that has a
+** multi-byte representation in UTF-8). This is the only way we
+** have found to render Unicode characters on a Windows console while
+** at the same time avoiding undesirable \n to \r\n translation.
+*/
+static int simBinaryStdout = 0;
+static int simBinaryOther = 0;
+
+
+/*
+** Determine if simulated binary mode should be used for output to fd
+*/
+static int UseBinaryWText(FILE *fd){
+ if( fd==stdout || fd==stderr ){
+ return simBinaryStdout;
+ }else{
+ return simBinaryOther;
+ }
+}
+
+
/*
** Work-alike for the fopen() routine from the standard C library.
*/
@@ -88,6 +107,7 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
}
free(b1);
free(b2);
+ simBinaryOther = 0;
return fp;
}
@@ -143,13 +163,53 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
}
}
+/*
+** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and
+** greater, switch to O_U8TEXT.
+*/
+static void piecemealOutput(wchar_t *b1, int sz, FILE *out){
+ int i;
+ wchar_t c;
+ while( sz>0 ){
+ for(i=0; i=0x80; i++){}
+ if( i>0 ){
+ c = b1[i];
+ b1[i] = 0;
+ fflush(out);
+ _setmode(_fileno(out), _O_U8TEXT);
+ fputws(b1, out);
+ fflush(out);
+ b1 += i;
+ b1[0] = c;
+ sz -= i;
+ }else{
+ fflush(out);
+ _setmode(_fileno(out), _O_TEXT);
+ _setmode(_fileno(out), _O_BINARY);
+ fwrite(&b1[0], 1, 1, out);
+ for(i=1; iaCol[ii].iBind
+ "%z%sescape_crlf(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
);
zSqlSep = "||', '||";
}else{
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile
index 2602e6b792..00f1ee50a7 100644
--- a/ext/wasm/GNUmakefile
+++ b/ext/wasm/GNUmakefile
@@ -251,6 +251,7 @@ SQLITE_OPT.common := \
# 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 \
diff --git a/main.mk b/main.mk
index d83344aa5b..12e4986559 100644
--- a/main.mk
+++ b/main.mk
@@ -571,7 +571,7 @@ dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
$(TOP)/tool/dbhash.c sqlite3.c $(TLIBS) $(THREADLIB)
RSYNC_SRC = \
- $(TOP)/tool/sqlite3-rsync.c \
+ $(TOP)/tool/sqlite3_rsync.c \
sqlite3.c
RSYNC_OPT = \
@@ -580,7 +580,7 @@ RSYNC_OPT = \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
-sqlite3-rsync$(EXE): $(RSYNC_SRC)
+sqlite3_rsync$(EXE): $(RSYNC_SRC)
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
@@ -1161,7 +1161,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) sqlite3-rsync$(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)
diff --git a/manifest b/manifest
index 88c2dbdff0..e56ed1e48c 100644
--- a/manifest
+++ b/manifest
@@ -1,11 +1,11 @@
C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch.
-D 2024-09-30T15:17:32.851
+D 2024-10-16T15:14:56.854
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 72e579661a39685fa461a09729d404833dfd7f630d9b2c4edbb6d4524095884a
+F Makefile.in 9ec61bc8ed526837e6889ac84002185a8c1521d2e21b8d847987af7152b24d04
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
-F Makefile.msc dd823b4caef98141218c3d508710d0794f602f2ec4551f32574c89d01e9a10db
+F Makefile.msc 317dad4e4f2cb1543d4b9c37679fc743d064486f6a31d950cf6b330ff768d20c
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -17,29 +17,30 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc 2aced6442addab13ed115696eba28d9ed29caa3dd604a31392c2c7a5da301492
+F autoconf/Makefile.msc 0a1fdef1f2c618815cf7c82c817a7369c1e07b3cfed490803db16fb43326d506
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
F autoconf/tea/Makefile.in 106a96f2f745d41a0f6193f1de98d7355830b65d45032c18cd7c90295ec24196
-F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
+F autoconf/tea/README.txt 94fa2472d3ee4139ab24b364d99a70445d0a25531dac3ce03af2055d581f76b4 w autoconf/tea/README
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
F autoconf/tea/configure.ac 0deb5d6c49c8119f75f436488219fc043127d72057af5dfba2c9ce096a5734bc
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
-F autoconf/tea/pkgIndex.tcl.in b9eb6dd37f64e08e637d576b3c83259814b9cddd78bec4af2e5abfc6c5c750ce
+F autoconf/tea/pkgIndex.tcl.in 55aec3c6d7e9a1de9b8d2fdc9c27fd055da3ac3a51b572195e2ae7300bcfd3a2
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 c6e5f2fc7178f40d087403daa044ef3b86a8e30793f3b121bdcbdf152c6a776a
-F autoconf/tea/win/makefile.vc 2c478a9a962e48b2bf9062734e04d7c63c556e217095419173f9d7938d7d78f7
+F autoconf/tea/win/makefile.vc 9b33af4214a5c8360549b96380f55ece1a2df76a51ab4c726296e5c43d8a2227
F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea00342d1a1a7eaa19cb
F autoconf/tea/win/rules.vc 7b3bb2ef32ade0f3f14d951231811678722725e3bca240dd9727ae0dfe10f6a5
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure 49523f0a070b583cea040d26eff53a65fb0893eca4663b1343a4d5a9a964da53 x
-F configure.ac a100ebf7a07f5dedd319ef547dd467d1676ed059b85a7877aa9c44ac309f7000
+F configure 135e050689ea244477582e6d77cc7867dfcfe6e0f82e3eab3e47655a67035f8f x
+F configure.ac aca8ebf47b7644c473e11e599ea986eeb23860a8732a8812039ad961ef52a713
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
-F doc/compile-for-windows.md 4d4bfafda42a7a33f166d23aed4db1bb4ea1e5751595a5cced2bad349fd14652
+F doc/compile-for-unix.md 90f17554cc3d19b2dae8142b5aeda1a8890692d5f2e091ed4a6f9b46b8f10f62
+F doc/compile-for-windows.md a9ab9f6c49763d63d177a386a9e53ee670101f80e8bcb73cafca438156229076
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
@@ -58,8 +59,8 @@ F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c7
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test b10f9e20f64102a015c0fcf54cb7b7680266b397e91d93cdad45f57857cdfba6
-F ext/expert/sqlite3expert.c df417a6d91873a74d35daa9259171647c23c6601415e938e8a71702703f3d677
+F ext/expert/expert1.test 1fa0201d8610883c32214b1d83e3a6cc582694ac1067be8319b280235145a555
+F ext/expert/sqlite3expert.c b7cbbd7cc109c66ebdf6091467d790abb9d7c25ae3b822bb76388509641d37de
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
@@ -94,19 +95,19 @@ 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 93aba03ca417f403b07b2ab6f50aa0e0c1b8b031917a9026b81520e7047a168e
+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 da21548ddbc1a457cb42545f527065221ede8ada6a734891b8c34317a7a9506b
+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 571483823193f09439356741669aa8c81da838ae6f5e1bfa7517f7ee2fb3addd
-F ext/fts5/fts5_main.c 4503498d3453e29a3cd89dacaba029011e89cb8c481a6241611d106e7a369bd4
-F ext/fts5/fts5_storage.c 3332497823c3d171cf56379f2bd8c971ce15a19aadacff961106462022c92470
+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
-F ext/fts5/fts5_tokenize.c ae9c4fa93174ef06ffc138bd4280a1c37f7e13624d3d2706aad4b80573f23c41
+F ext/fts5/fts5_tokenize.c 033e2e43b8e852c0ef6cecc611266d61e2346e52ec7dcfb76a428fe56a07efa9
F ext/fts5/fts5_unicode2.c 6f9b0fb79a8facaed76628ffd4eb9c16d7f2b84b52872784f617cf3422a9b043
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c e4830b00809e5da53bc10f93adc59e321407b0f801c7f4167c0e47f5552267e0
@@ -146,7 +147,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
@@ -155,7 +156,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
@@ -247,7 +248,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
@@ -420,13 +423,13 @@ F ext/misc/regexp.c 4bdd0045912f81c84908bd535ec5ad3b1c8540b4287c70ab840709636240
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c a6089b5e8e3002bd1e5d9877cee6aead0b9a6426e406c09a399817db9e9ae823
+F ext/misc/series.c 596afbfbbc81ccf4ea6da11f016f7eed630ed195b5e9d548117e19f06d63f641
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
F ext/misc/shathree.c 1821d90a0040c9accdbe3e3527d378d30569475d758aa70f6848924c0b430e8c
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c bcc42ef3fd29429bc01a83e751332b8d4690e65d45008449bdffe7656371487f
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
-F ext/misc/sqlite3_stdio.c f110e6f2dc97c67e89f941f82af7dbd221193fa44d1e3ef38a691454a2cbccda
+F ext/misc/sqlite3_stdio.c 73192f75e1e89722fbdf209056a562ca2a35df3c9e998f9270331e03cb621e7a
F ext/misc/sqlite3_stdio.h f05eaf5e0258f0573910324a789a9586fc360a57678c57a6d63cfaa2245b6176
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
@@ -438,7 +441,7 @@ 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 w src/test_vfstrace.c
+F ext/misc/vfstrace.c ac76a4ac4d907774fd423cc2b61410c756f9d0782e27cf6032e058594accaaca
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
@@ -507,7 +510,7 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
-F ext/recover/sqlite3recover.c 2dcf6b56c5e0e2b43fc4c6115b689ab194c374ced7f7f8380ad9a24d8ef24ac9
+F ext/recover/sqlite3recover.c e822ecbb05a04a5c85d1309765fcd6cf392d100d02d2227cd7720c9d6921a17a
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 072260d7452a3b81aba995b2b3269e7ec2aa7f06725544ba4c25b1b0a1dbc61a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -604,7 +607,7 @@ 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 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
-F ext/wasm/GNUmakefile 6b94c3125c40932e71bbe46e582d24ed4c829b9fa2ff34dd842b0ed8a948ac6a
+F ext/wasm/GNUmakefile bfd63f0462ac7e5b814a267e9101b8284d61731574ec673dae3178643cdb89ef
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -613,7 +616,7 @@ F ext/wasm/SQLTester/SQLTester.run.mjs c72b7fe2072d05992f7a3d8c6a1d34e95712513ce
F ext/wasm/SQLTester/index.html 3f8a016df0776be76605abf20e815ecaafbe055abac0e1fe5ea080e7846b760d
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33
-F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13 w ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-session
+F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 34fe11466f9c1d81b10a0469e1114e5f1c5a6365c73d80a1a6ca639a1a358b73
@@ -688,7 +691,7 @@ F ext/wasm/wasmfs.make bc8bb227f35d5bd3863a7bd2233437c37472a0d81585979f058f9b9b5
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk 2e0e2eb583809dd8480a30ab270903964efd774688320c7a509b25f61cb56f2a
+F main.mk 53f6a5a53d495dba2897bc7c5f267464c72053135281e2fffa367da310001c39
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -715,14 +718,14 @@ F src/callback.c fbd4e8247f1a7f37aec721bde0e312e79cc3bfa41f55a59930bc876ca6baf45
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
-F src/dbpage.c 12e49515d67d4a59625d71f9aa42499556cfdc2e4f1ea49086e674a7f47f46e5
+F src/dbpage.c db1be8adaf1f839ad733c08baeac5c22aa912f7b535865c0c061382602081360
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
+F src/expr.c a9d9f5fdfbdd3b2c94d7af1b11f181464b8a641736cf32cb92fa3c5e7ecb30df
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
-F src/func.c df400a1d3f4625997d4dd8a81951c303e066277c29b861d37e03cd152d7858dd
-F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
+F src/func.c 1d093b93b8f097665721e59a1c404d7db4dc591e1a777a7a1022dfbda21e108b
+F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
@@ -731,7 +734,7 @@ F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70
F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
-F src/main.c 22660c327f6cbef3ded329388b97808a9a8f2112c4803eb6748c8c5683e5d148
+F src/main.c a87eca9472a7f6aa8899e4fdf2b1aa68ea2075b33fd8aa55b0f23192dfa6e14f
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -752,7 +755,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 779e83666ecd535f6725497ba6da069c1d15138ff6a4ee123edad1ae0cdfbe83
+F src/os_unix.c 14d0f80e4779f5f76bcc71e7af97e3efe318fa3d0b22335623c59fab7d39302b
F src/os_win.c 3c5614e5ea39e2ea33659d2d652fabd82ec3b5a39e342ca587eb6e5806e6d047
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
@@ -761,25 +764,25 @@ F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
-F src/pragma.c cce8c7b08860023c01fab1c7806d56262745738ec1337bbe031a0ffbb87aff5e
+F src/pragma.c 71993e99ce76cb51ffbb2ec531bcb3cca4a1437abab5b0f4e6c1e7f1d48535d9
F src/pragma.h 50f6d3b408ed56bde4f4e4aead8c0b2022030b692e8de237c1b7a0b5ce87a0c8
F src/prepare.c 2b6fdbfb4b859aa1b40777019e2f9759dc62c5283cd73f853a06c97acd722804
F src/printf.c 6a87534ebfb9e5346011191b1f3a7ebc457f5938c7e4feeea478ecf53f6a41b2
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c 9750a281f7ba073b4e6da2be1a6c4071f5d841a7746c5fb3f70d6d793b6675ea
+F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
-F src/shell.c.in d52bf5223669b7e655ea89464c2aa65c1fa87977831b8a4cad26a2dac175d5fd
-F src/sqlite.h.in e728e4471ebdad5703ca1a013db9c6466c56fe868357cd47a850b2f2f28318b2
+F src/shell.c.in 081736dcf4377c08737bc7bbc321fbd41e2eb9545fa2fcd3be46d87c744f1597
+F src/sqlite.h.in e9eebfd8857322f628fdbb0e76b2ec9be861bdb1f9d5cc10390d552218054770
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h bdf6b0db285827428761acbe0c4159d9d0329eafaba6324affa077f01a2c0906
+F src/sqliteInt.h c3282f35b5beed82f2ac47963ec73dc71c92955489093fdc69381698a9d72402
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c 5028a0afee355aa492f26f0b6a3ec23145caa9261a93164d96cd0b9bf1b2318f
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c f3c74b7612c6f583c94af48531caa1a7fecc53202bf4e0b202d39e54dc9322bc
+F src/tclsqlite.c b69c543cb2a940a4a45d8038988e2e4b05fe55ace6cb7fcb6f758e9a194978ed
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
-F src/test1.c 8d7cd219c004cd2ced60659ebf045025cc5c16ce19d12459589dacd4310f7f07
+F src/test1.c 8bf8b74145b768f42386787f93f6d6dad7bc400a4ee2d50e4ad5a06a20a97ef1
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
@@ -793,7 +796,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 54b4f17e0b4b49a04cd45394c172379d9471066ae56dd7441343146a650a751c
+F src/test_config.c 828e696c55314e35510a801d21f3890c5b368163757edc2a066db61adeefcdd2
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -836,14 +839,14 @@ F src/treeview.c 88aa39b754f5ef7214385c1bbbdd2f3dc20efafeed0cf590e8d1199b9c6e44a
F src/trigger.c cfe7abf63ad096388253f4cd7bd1f1c022e952137da68f4500922a4c4dab2ec8
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
-F src/utf.c 7bc550af6f3ddd5f5dc82d092c41f728acb760c92e0b47f391963b01ae52569b
-F src/util.c 5d1a0134cf4240648d1c6bb5cc8efaca0ea2b5d5c840985aec7e947271f04375
+F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
+F src/util.c 4d57ae861d0e234019be9596818228d7715e44e6efaccb612cf4498bedc2e023
F src/vacuum.c 38577d6f45e10a984720b5219be09ca8649a0e600c2e5c11993900446caca609
F src/vdbe.c d30cf58519ee7557a385c6f3e5b85d8b5366322c53d9e0c4402100fd357c8e6b
F src/vdbe.h ea7ab8f088ae87a71a733f7ac4c5edd9c34dd58dfa6aafbdd3ab81b2d4c9d496
F src/vdbeInt.h af7d7e8291edd0b19f2cd698e60e4d4031078f9a2f2328ac8f0b7efb134f8a1d
F src/vdbeapi.c 53c7e26a2c0821a892b20eee2cde4656e31998212f3d515576c780dfaa45fd17
-F src/vdbeaux.c b4bc5037ee92492710b5e36101e626a795d54821c83dad9093c525e62c0d2026
+F src/vdbeaux.c b05aa2c43ad0f82eae945618c1bb538467f52f5acdc55d2b0a29fc261ae840f7
F src/vdbeblob.c 9e61cd32f3b52bb82d8997f87ecfb0506af1d846f04bfe02d2ac1ab1929692d6
F src/vdbemem.c df568ef0187e4be2788c35174f6d9b8566ab9475f9aff2d73907ed05aa5684b2
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
@@ -851,13 +854,13 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c dae9ef7d94bd06116c020bc3fb2f9a8e8f8243515aaa72d392fe8e6fc14517c2
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c ef68130ba330ee18c1cb22da36a881c82e3a3b109badbdc6a9b9acaf788a6688
+F src/wal.c a0d42bfdef935e1389737152394d08e59e7c48697f40a9fc2e0552cb19dc731f
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c 3f5dcc72b9090465cca092d1981f2b2d432e3e070ef978581af85e3fa43b6aaf
+F src/where.c 6123e8a0333ae0021c5df82579f231143678660e604078dc577e0dbd487cced7
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
-F src/whereexpr.c 44f41ae554c7572e1de1485b3169b233ee04d464b2ee5881687ede3bf07cacfa
+F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f
F src/window.c 499d48f315a09242dc68f2fac635ed27dcf6bbb0d9ab9084857898c64489e975
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -908,7 +911,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
@@ -991,7 +994,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
@@ -1042,7 +1045,7 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test ac13504593d89d69690d45479547616ed12644d42b5cb7eeb2e759a76fc23dcb
F test/corruptL.test 652fc8ac0763a6fd3eb28b951d481924167b2d9936083bcc68253b2274a0c8fe
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
-F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4
+F test/corruptN.test 40bc47aee4af9aadff902be43f14d69dc17b3731448dad6c7cc722da913f1455
F test/cost.test cc434a026b1e9d0d98137a147e24e5daf1b1ad09e9ff7da63b34c83ddd136d92
F test/count.test cd4bd531066e8d77ef8fe1e3fc8253d042072e117ccab214b290cf83f1602249
F test/countofview.test 4088e461a10ee33e69803c177a69aa1d7bba81a9ffc2df66d76465a22ca7fdfc
@@ -1155,7 +1158,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
@@ -1253,10 +1256,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
@@ -1324,6 +1327,7 @@ F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
F test/indexexpr1.test 24fa85a12da384dd1d56f7b24e593c51a8a54b4c5e2e8bbb9e5fdf1099427faf
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
+F test/indexexpr3.test 9d893bf440937ebcc1e59c7c9c1505c40c918346a3ddde76a69078f3c733c45d
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
@@ -1390,7 +1394,7 @@ F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 70110eff607ab137ccc851edb2bc7e14a6d4f246b5d2d25f82a60b69d87a9ff2
-F test/like.test 242ee7f5d08a031144c0daf63bbd7e7710c847ccf387a83347e0b61b3aa69526
+F test/like.test b3ea2ba3558199aa8f25a42ddeb54772e234fab50868c9f066047acdbda8fc58
F test/like2.test d3be15fefee3e02fc88942a9b98f26c5339bbdef7783c90023c092c4955fe3d3
F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
@@ -1404,7 +1408,7 @@ F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37b8
-F test/lock5.test 24693e40a805f71d80836f720d1f2034684a39b64f1e1990989002c7968c11ee
+F test/lock5.test 583cae05992af0f66607286917f7d5f8aed3b6053c52df5994efb98f2a8fdbaf
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
@@ -1635,7 +1639,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 b02d628494fa284cdb2b7b2fecdadea96913796afd623f340a79d68f055dcb7e
+F test/shell1.test 5d84e415adf7cc4edd5913c4f23c761104ff135b9c190fcf7b430a4cbca6cb65
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
@@ -1656,7 +1660,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
@@ -1677,7 +1681,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
@@ -1725,7 +1729,7 @@ F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 14284e98554d0a27c3982dcf4b7c4b88cf025ae8e238dd7e2683071c51c371fd
F test/testrunner.tcl 0f371d50e606c43c09046fda1416ecdf69089bd125cb478800f040c70086bbe8 x
-F test/testrunner_data.tcl 47a8b2430f0f6a31f56fe6c5fe5c736b3619df4081acaa816fd877f96a68d46a
+F test/testrunner_data.tcl bc9b18eabafd08e11bcea4c2565af648ef0d86ade4ee3fe2a8a538e6bf65d352
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1734,7 +1738,7 @@ F test/thread005.test 50d10b5684399676174bd96c94ad4250b1a2c8b6
F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4
F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread3.test a12656a56cdf67acb6a2ff7638826c6d6a645f79909d86df521045ad31cf547d
-F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
+F test/thread_common.tcl b3b19a769fe30ef5537cdfa60acd49b78f771301627720d1add2d3bac77d9039
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c 25cb92accb4fa6d53e708d6006ed2db7a7533ef7b838ef1306455c6fe57e978a
@@ -2156,7 +2160,7 @@ F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6
F tool/mksqlite3c.tcl c6acfdf4e4ef93478ff3ce3cd593e17abb03f446036ce710c3156bcfa18665e0
F tool/mksqlite3h.tcl d391cff7cad0a372ee1406faee9ccc7dad9cb80a0c95cae0f73d10dd26e06762
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
-F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617f8423
+F tool/mktoolzip.tcl 1b3383c6cd1ca3e1bfdf157d1383f29d6264b9600c381e682789c83617dc1014
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
@@ -2175,7 +2179,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3d
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
-F tool/speed-check.sh e8d20cc2eb9c85ec1ba562226de144435456dcdff4ee618de49603c6958f6116
+F tool/speed-check.sh e566ab3934d7d78631743a984ad3f67c331c911bb18ff5d0a6c616a2afee7f91
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -2184,11 +2188,11 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 2a0987d183027c795ced13d6749061c1d2f38e24eddb428f56fa64c3a8f51e4b
-F tool/sqlite3-rsync.c 187b262035c1159b047dbfa1959c168b87b5a153b63465e8c8bd1b54fabf4460
F tool/sqlite3_analyzer.c.in 348ba349bbdc93c9866439f9f935d7284866a2a4e6898bc906ae1204ade56918
+F tool/sqlite3_rsync.c 2a2b79a0463d400696aa9429be5c0ddec6b1f7ceefa5fed7acfdc859a435221f w tool/sqlite3-rsync.c
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
-F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
+F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05bbb4
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/srctree-check.tcl c15f860a3c97d5f7b4c14b60392d9466af29dd006c4ef18127f502641e2977a8
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
@@ -2223,8 +2227,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 f9ce1ababbd62c579658c737059f6992bdb32909e7a06282fe6a359d10ad1272 76b6331e6a705a420a64820a18214f07cf4c1d5151e7158d6fff09964e63f352
-R 5d2d8012beab3e60a854582edf47f1eb
+P 1ba833743dd7aa0cf50a646c5ad44a5349853efba52bd300ce0c72a17dac9ff2 309e6d6f07d4169fbd6ea1d8b3d4809186ad9b7a2e69bbd33eedb9a55e831d68
+R 62de298c9a2928c56916e4819a7f3426
U drh
-Z bc738bb96e4a1c1da7fbee1e6b6b6694
+Z 832d628431ea921e43f087c2d857ebc3
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index c72bd1def0..631de17360 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-1ba833743dd7aa0cf50a646c5ad44a5349853efba52bd300ce0c72a17dac9ff2
+93f0febab4b1da711c2238aaff00b4eff276831b516990040e2957a6b91decdc
diff --git a/src/dbpage.c b/src/dbpage.c
index 42b24f9b8d..a0ee9246dc 100644
--- a/src/dbpage.c
+++ b/src/dbpage.c
@@ -57,8 +57,8 @@ struct DbpageCursor {
struct DbpageTable {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database */
- int nTrunc; /* Entries in aTrunc[] */
- Pgno *aTrunc; /* Truncation size for each database */
+ int iDbTrunc; /* Database to truncate */
+ Pgno pgnoTrunc; /* Size to truncate to */
};
/* Columns */
@@ -107,8 +107,6 @@ static int dbpageConnect(
** Disconnect from or destroy a dbpagevfs virtual table.
*/
static int dbpageDisconnect(sqlite3_vtab *pVtab){
- DbpageTable *pTab = (DbpageTable *)pVtab;
- sqlite3_free(pTab->aTrunc);
sqlite3_free(pVtab);
return SQLITE_OK;
}
@@ -375,19 +373,12 @@ static int dbpageUpdate(
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
|| sqlite3_value_bytes(argv[3])!=szPage
){
- if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){
- if( iDb>=pTab->nTrunc ){
- testcase( pTab->aTrunc!=0 );
- pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno));
- if( pTab->aTrunc ){
- int j;
- for(j=pTab->nTrunc; jaTrunc[j] = 0;
- pTab->nTrunc = iDb+1;
- }else{
- return SQLITE_NOMEM;
- }
- }
- pTab->aTrunc[iDb] = pgno;
+ 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;
@@ -400,6 +391,7 @@ static int dbpageUpdate(
if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
unsigned char *aPage = sqlite3PagerGetData(pDbPage);
memcpy(aPage, pData, szPage);
+ pTab->pgnoTrunc = 0;
}
}
sqlite3PagerUnref(pDbPage);
@@ -423,29 +415,31 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
Btree *pBt = db->aDb[i].pBt;
if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
}
- if( pTab->nTrunc>0 ){
- memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc);
- }
+ pTab->pgnoTrunc = 0;
return SQLITE_OK;
}
/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
*/
static int dbpageSync(sqlite3_vtab *pVtab){
- int iDb;
DbpageTable *pTab = (DbpageTable *)pVtab;
-
- for(iDb=0; iDbnTrunc; iDb++){
- if( pTab->aTrunc[iDb]>0 ){
- Btree *pBt = pTab->db->aDb[iDb].pBt;
- Pager *pPager = sqlite3BtreePager(pBt);
- sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]);
- pTab->aTrunc[iDb] = 0;
- }
+ 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
@@ -474,7 +468,7 @@ int sqlite3DbpageRegister(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0, /* xRollbackTo */
+ dbpageRollbackTo, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
diff --git a/src/expr.c b/src/expr.c
index 1b18828dd6..cc915987dd 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -4554,6 +4554,59 @@ static int exprCodeInlineFunction(
return target;
}
+/*
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
+**
+** Only a function call is able to return a subtype. So if the node
+** is not a function call, return WRC_Prune immediately.
+**
+** A function call is able to return a subtype if it has the
+** SQLITE_RESULT_SUBTYPE property.
+**
+** Assume that every function is able to pass-through a subtype from
+** one of its argument (using sqlite3_result_value()). Most functions
+** are not this way, but we don't have a mechanism to distinguish those
+** that are from those that are not, so assume they all work this way.
+** That means that if one of its arguments is another function and that
+** other function is able to return a subtype, then this function is
+** able to return a subtype.
+*/
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+ int n;
+ FuncDef *pDef;
+ sqlite3 *db;
+ if( pExpr->op!=TK_FUNCTION ){
+ return WRC_Prune;
+ }
+ assert( ExprUseXList(pExpr) );
+ db = pWalker->pParse->db;
+ n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+ pWalker->eCode = 1;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return TRUE if expression pExpr is able to return a subtype.
+**
+** A TRUE return does not guarantee that a subtype will be returned.
+** It only indicates that a subtype return is possible. False positives
+** are acceptable as they only disable an optimization. False negatives,
+** on the other hand, can lead to incorrect answers.
+*/
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = exprNodeCanReturnSubtype;
+ sqlite3WalkExpr(&w, pExpr);
+ return w.eCode;
+}
+
+
/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
@@ -4586,6 +4639,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
+
+ /* Functions that might set a subtype should not be replaced by the
+ ** value taken from an expression index if they are themselves an
+ ** argument to another scalar function or aggregate.
+ ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+ if( ExprHasProperty(pExpr, EP_SubtArg)
+ && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+ ){
+ continue;
+ }
+
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
diff --git a/src/func.c b/src/func.c
index a634a7fbea..2de16b8aa9 100644
--- a/src/func.c
+++ b/src/func.c
@@ -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; i8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
0, /* bJsonSelfcheck */
#endif
diff --git a/src/main.c b/src/main.c
index 7f5e01116d..99a3d469df 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}
@@ -4666,24 +4633,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)
**
@@ -4991,7 +4940,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);
}
diff --git a/src/os_unix.c b/src/os_unix.c
index 92ad9d8607..f71fa8e029 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -2464,54 +2464,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
+ assert( pFile->eFileLock<=SHARED_LOCK );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
+ /* The flock VFS only ever takes exclusive locks (see function flockLock).
+ ** Therefore, if this connection is holding any lock at all, no other
+ ** connection may be holding a RESERVED lock. So set *pResOut to 0
+ ** in this case.
+ **
+ ** Or, this connection may be holding no lock. In that case, set *pResOut to
+ ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+ ** db in order to roll the hot journal back. If there is another connection
+ ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+ ** the user. With other VFS, we try to avoid this, in order to allow a reader
+ ** to proceed while a writer is preparing its transaction. But that won't
+ ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+ ** not a problem in this case. */
+ *pResOut = 0;
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
-
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
+ return SQLITE_OK;
}
/*
diff --git a/src/pragma.c b/src/pragma.c
index 6033459771..8d59728f3c 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1767,6 +1767,7 @@ void sqlite3Pragma(
/* Make sure sufficient number of registers have been allocated */
sqlite3TouchRegister(pParse, 8+cnt);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
diff --git a/src/resolve.c b/src/resolve.c
index 8e8da66910..d6a5144af8 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -1183,6 +1183,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}
#endif
+
+ /* If the function may call sqlite3_value_subtype(), then set the
+ ** EP_SubtArg flag on all of its argument expressions. This prevents
+ ** where.c from replacing the expression with a value read from an
+ ** index on the same expression, which will not have the correct
+ ** subtype. Also set the flag if the function expression itself is
+ ** an EP_SubtArg expression. In this case subtypes are required as
+ ** the function may return a value with a subtype back to its
+ ** caller using sqlite3_result_value(). */
+ if( (pDef->funcFlags & SQLITE_SUBTYPE)
+ || ExprHasProperty(pExpr, EP_SubtArg)
+ ){
+ int ii;
+ for(ii=0; iia[ii].pExpr, EP_SubtArg);
+ }
+ }
+
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
diff --git a/src/shell.c.in b/src/shell.c.in
index c5fd80b6f5..6feb26fed0 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -631,7 +631,7 @@ static const struct {
unsigned char w; /* Width of the character in columns */
int iFirst; /* First character in a span having this width */
} aUWidth[] = {
- /* {0, 0x00000}, {1, 0x00020}, {0, 0x0007f}, {1, 0x000a0}, */
+ /* {1, 0x00000}, */
{0, 0x00300}, {1, 0x00370}, {0, 0x00483}, {1, 0x00487}, {0, 0x00488},
{1, 0x0048a}, {0, 0x00591}, {1, 0x005be}, {0, 0x005bf}, {1, 0x005c0},
{0, 0x005c1}, {1, 0x005c3}, {0, 0x005c4}, {1, 0x005c6}, {0, 0x005c7},
@@ -709,9 +709,6 @@ int cli_wcwidth(int c){
int iFirst, iLast;
/* Fast path for common characters */
- if( c<0x20 ) return 0;
- if( c<0x7f ) return 1;
- if( c<0xa0 ) return 0;
if( c<=0x300 ) return 1;
/* The general case */
@@ -1451,6 +1448,7 @@ struct ShellState {
u8 bSafeMode; /* True to prohibit unsafe operations */
u8 bSafeModePersist; /* The long-term value of bSafeMode */
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
+ u8 crlfMode; /* Do NL-to-CRLF translations when enabled (maybe) */
ColModeOpts cmOpts; /* Option values affecting columnar mode output */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
@@ -1632,13 +1630,7 @@ static const char *modeDescr[] = {
#define SEP_Tab "\t"
#define SEP_Space " "
#define SEP_Comma ","
-#ifdef SQLITE_U8TEXT_ONLY
- /* With the SQLITE_U8TEXT_ONLY option, the output will always be in
- ** text mode. The \r will be inserted automatically. */
-# define SEP_CrLf "\n"
-#else
-# define SEP_CrLf "\r\n"
-#endif
+#define SEP_CrLf "\r\n"
#define SEP_Unit "\x1F"
#define SEP_Record "\x1E"
@@ -1723,7 +1715,7 @@ static void editFunc(
char *zCmd = 0;
int bBin;
int rc;
- int hasCRNL = 0;
+ int hasCRLF = 0;
FILE *f = 0;
sqlite3_int64 sz;
sqlite3_int64 x;
@@ -1768,7 +1760,7 @@ static void editFunc(
}else{
const char *z = (const char*)sqlite3_value_text(argv[0]);
/* Remember whether or not the value originally contained \r\n */
- if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
+ if( z && strstr(z,"\r\n")!=0 ) hasCRLF = 1;
x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
}
fclose(f);
@@ -1813,7 +1805,7 @@ static void editFunc(
sqlite3_result_blob64(context, p, sz, sqlite3_free);
}else{
sqlite3_int64 i, j;
- if( hasCRNL ){
+ if( hasCRLF ){
/* If the original contains \r\n then do no conversions back to \n */
}else{
/* If the file did not originally contain \r\n then convert any new
@@ -1855,6 +1847,21 @@ static void outputModePop(ShellState *p){
memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
}
+/*
+** Set output mode to text or binary for Windows.
+*/
+static void setCrlfMode(ShellState *p){
+#ifdef _WIN32
+ if( p->crlfMode ){
+ sqlite3_fsetmode(p->out, _O_TEXT);
+ }else{
+ sqlite3_fsetmode(p->out, _O_BINARY);
+ }
+#else
+ UNUSED_PARAMETER(p);
+#endif
+}
+
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
@@ -1905,9 +1912,10 @@ static const char *unused_string(
**
** See also: output_quoted_escaped_string()
*/
-static void output_quoted_string(FILE *out, const char *z){
+static void output_quoted_string(ShellState *p, const char *z){
int i;
char c;
+ FILE *out = p->out;
sqlite3_fsetmode(out, _O_BINARY);
if( z==0 ) return;
for(i=0; (c = z[i])!=0 && c!='\''; i++){}
@@ -1933,7 +1941,7 @@ static void output_quoted_string(FILE *out, const char *z){
}
sqlite3_fputs("'", out);
}
- sqlite3_fsetmode(out, _O_TEXT);
+ setCrlfMode(p);
}
/*
@@ -1945,9 +1953,10 @@ static void output_quoted_string(FILE *out, const char *z){
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
-static void output_quoted_escaped_string(FILE *out, const char *z){
+static void output_quoted_escaped_string(ShellState *p, const char *z){
int i;
char c;
+ FILE *out = p->out;
sqlite3_fsetmode(out, _O_BINARY);
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
if( c==0 ){
@@ -2000,7 +2009,7 @@ static void output_quoted_escaped_string(FILE *out, const char *z){
sqlite3_fprintf(out, ",'%s',char(10))", zNL);
}
}
- sqlite3_fsetmode(stdout, _O_TEXT);
+ setCrlfMode(p);
}
/*
@@ -2797,7 +2806,7 @@ static int shell_callback(
}
sqlite3_fputs(p->rowSeparator, p->out);
}
- sqlite3_fsetmode(p->out, _O_TEXT);
+ setCrlfMode(p);
break;
}
case MODE_Insert: {
@@ -2825,9 +2834,9 @@ static int shell_callback(
sqlite3_fputs("NULL", p->out);
}else if( aiType && aiType[i]==SQLITE_TEXT ){
if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
+ output_quoted_string(p, azArg[i]);
}else{
- output_quoted_escaped_string(p->out, azArg[i]);
+ output_quoted_escaped_string(p, azArg[i]);
}
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
sqlite3_fputs(azArg[i], p->out);
@@ -2856,9 +2865,9 @@ static int shell_callback(
}else if( isNumber(azArg[i], 0) ){
sqlite3_fputs(azArg[i], p->out);
}else if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
+ output_quoted_string(p, azArg[i]);
}else{
- output_quoted_escaped_string(p->out, azArg[i]);
+ output_quoted_escaped_string(p, azArg[i]);
}
}
sqlite3_fputs(");\n", p->out);
@@ -2911,7 +2920,7 @@ static int shell_callback(
if( p->cnt==0 && p->showHeader ){
for(i=0; i0 ) sqlite3_fputs(p->colSeparator, p->out);
- output_quoted_string(p->out, azCol[i]);
+ output_quoted_string(p, azCol[i]);
}
sqlite3_fputs(p->rowSeparator, p->out);
}
@@ -2921,7 +2930,7 @@ static int shell_callback(
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
sqlite3_fputs("NULL", p->out);
}else if( aiType && aiType[i]==SQLITE_TEXT ){
- output_quoted_string(p->out, azArg[i]);
+ output_quoted_string(p, azArg[i]);
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
sqlite3_fputs(azArg[i], p->out);
}else if( aiType && aiType[i]==SQLITE_FLOAT ){
@@ -2936,7 +2945,7 @@ static int shell_callback(
}else if( isNumber(azArg[i], 0) ){
sqlite3_fputs(azArg[i], p->out);
}else{
- output_quoted_string(p->out, azArg[i]);
+ output_quoted_string(p, azArg[i]);
}
}
sqlite3_fputs(p->rowSeparator, p->out);
@@ -4755,7 +4764,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
- if( !dataOnly ) sqlite3_fputs("DELETE FROM sqlite_sequence;\n", p->out);
+ /* no-op */
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
if( !dataOnly ) sqlite3_fputs("ANALYZE sqlite_schema;\n", p->out);
}else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
@@ -4940,10 +4949,7 @@ static const char *(azHelp[]) = {
".clone NEWDB Clone data into NEWDB from the existing database",
#endif
".connection [close] [#] Open or close an auxiliary database connection",
-#if defined(_WIN32) && !defined(SQLITE_U8TEXT_ONLY) \
- && !defined(SQLITE_U8TEXT_STDIO)
- ".crnl on|off Translate \\n to \\r\\n. Default ON",
-#endif /* _WIN32 && U8TEXT_ONLY && U8TEXT_STDIO */
+ ".crlf ?on|off? Whether or not to use \\r\\n line endings",
".databases List names and files of attached databases",
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
#if SQLITE_SHELL_HAVE_RECOVER
@@ -5953,7 +5959,7 @@ static void output_file_close(FILE *f){
** recognized and do the right thing. NULL is returned if the output
** filename is "off".
*/
-static FILE *output_file_open(const char *zFile, int bTextMode){
+static FILE *output_file_open(const char *zFile){
FILE *f;
if( cli_strcmp(zFile,"stdout")==0 ){
f = stdout;
@@ -5962,7 +5968,7 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
}else if( cli_strcmp(zFile, "off")==0 ){
f = 0;
}else{
- f = sqlite3_fopen(zFile, bTextMode ? "w" : "wb");
+ f = sqlite3_fopen(zFile, "w");
if( f==0 ){
sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile);
}
@@ -6435,6 +6441,7 @@ static void output_redir(ShellState *p, FILE *pfNew){
sqlite3_fputs("Output already redirected.\n", stderr);
}else{
p->out = pfNew;
+ setCrlfMode(p);
if( p->mode==MODE_Www ){
sqlite3_fputs(
"\n"
@@ -6490,6 +6497,7 @@ static void output_reset(ShellState *p){
}
p->outfile[0] = 0;
p->out = stdout;
+ setCrlfMode(p);
}
#else
# define output_redir(SS,pfO)
@@ -8711,9 +8719,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
- /* Undocumented. Legacy only. See "crnl" below */
+ /* Undocumented. Legacy only. See "crlf" below */
if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
- eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n");
+ eputz("The \".binary\" command is deprecated.\n");
rc = 1;
}else
@@ -8839,22 +8847,18 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
- if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
-#if !defined(_WIN32) || defined(SQLITE_U8TEXT_ONLY) \
- || defined(SQLITE_U8TEXT_STDIO)
- sqlite3_fputs("The \".crnl\" command is disable in this build.\n", p->out);
-#else
+ if( c=='c' && n==4
+ && (cli_strncmp(azArg[0], "crlf", n)==0
+ || cli_strncmp(azArg[0], "crnl",n)==0)
+ ){
if( nArg==2 ){
- if( booleanValue(azArg[1]) ){
- sqlite3_fsetmode(p->out, _O_TEXT);
- }else{
- sqlite3_fsetmode(p->out, _O_BINARY);
- }
- }else{
- eputz("Usage: .crnl on|off\n");
- rc = 1;
- }
+#ifdef _WIN32
+ p->crlfMode = booleanValue(azArg[1]);
+#else
+ p->crlfMode = 0;
#endif
+ }
+ sqlite3_fprintf(stderr, "crlf is %s\n", p->crlfMode ? "ON" : "OFF");
}else
if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
@@ -9934,7 +9938,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
output_file_close(p->pLog);
if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
- p->pLog = output_file_open(zFile, 0);
+ p->pLog = output_file_open(zFile);
}
}else
@@ -10189,7 +10193,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|| (c=='w' && n==3 && cli_strcmp(azArg[0],"www")==0)
){
char *zFile = 0;
- int bTxtMode = 0;
int i;
int eMode = 0;
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
@@ -10271,11 +10274,9 @@ static int do_meta_command(char *zLine, ShellState *p){
/* web-browser mode. */
newTempFile(p, "html");
if( !bPlain ) p->mode = MODE_Www;
- bTxtMode = 1;
}else{
/* text editor mode */
newTempFile(p, "txt");
- bTxtMode = 1;
}
sqlite3_free(zFile);
zFile = sqlite3_mprintf("%s", p->zTempFile);
@@ -10299,7 +10300,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
#endif
}else{
- FILE *pfFile = output_file_open(zFile, bTxtMode);
+ FILE *pfFile = output_file_open(zFile);
if( pfFile==0 ){
if( cli_strcmp(zFile,"off")!=0 ){
sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
@@ -10307,13 +10308,13 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
} else {
output_redir(p, pfFile);
+ if( zBom ) sqlite3_fputs(zBom, pfFile);
if( bPlain && eMode=='w' ){
sqlite3_fputs(
"\n\n\n",
pfFile
);
}
- if( zBom ) sqlite3_fputs(zBom, pfFile);
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
@@ -10510,7 +10511,6 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_OMIT_POPEN
eputz("Error: pipes are not supported in this OS\n");
rc = 1;
- p->out = stdout;
#else
p->in = sqlite3_popen(azArg[1]+1, "r");
if( p->in==0 ){
@@ -11504,7 +11504,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Begin redirecting output to the file "testcase-out.txt" */
if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
output_reset(p);
- p->out = output_file_open("testcase-out.txt", 0);
+ p->out = output_file_open("testcase-out.txt");
if( p->out==0 ){
eputz("Error: cannot open 'testcase-out.txt'\n");
}
@@ -11548,7 +11548,6 @@ static int do_meta_command(char *zLine, ShellState *p){
{"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
{"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
{"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
- {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
};
int testctrl = -1;
int iCtrl = -1;
@@ -11782,21 +11781,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}
break;
- /* sqlite3_test_control(int, int) */
- case SQLITE_TESTCTRL_USELONGDOUBLE: {
- int opt = -1;
- if( nArg==3 ){
- if( cli_strcmp(azArg[2],"default")==0 ){
- opt = 2;
- }else{
- opt = booleanValue(azArg[2]);
- }
- }
- rc2 = sqlite3_test_control(testctrl, opt);
- isOk = 1;
- break;
- }
-
/* sqlite3_test_control(sqlite3*) */
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
rc2 = sqlite3_test_control(testctrl, p->db);
@@ -12024,7 +12008,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else{
output_file_close(p->traceOut);
- p->traceOut = output_file_open(z, 0);
+ p->traceOut = output_file_open(z);
}
}
if( p->traceOut==0 ){
@@ -12901,6 +12885,9 @@ static void main_init(ShellState *data) {
memset(data, 0, sizeof(*data));
data->normalMode = data->cMode = data->mode = MODE_List;
data->autoExplain = 1;
+#ifdef _WIN32
+ data->crlfMode = 1;
+#endif
data->pAuxDb = &data->aAuxDb[0];
memcpy(data->colSeparator,SEP_Column, 2);
memcpy(data->rowSeparator,SEP_Row, 2);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 25ec01196d..f91e2eff3f 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -4233,7 +4233,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** is the number of bytes in the input string including
** the nul-terminator.
** Note that nByte measure the length of the input in bytes, not
-** characters, even for the UTF-16 inferfaces.
+** characters, even for the UTF-16 interfaces.
**
** ^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
@@ -5604,7 +5604,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.
@@ -8369,7 +8369,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 */
/*
@@ -9345,6 +9345,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+**
+** Alternatives To Using The Backup API
+**
+** Other techniques for safely creating a consistent backup of an SQLite
+** database include:
+**
+**
+** - The [VACUUM INTO] command.
+**
- The [sqlite3_rsync] utility program.
+**
*/
sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
@@ -10544,6 +10554,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
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 9601dac133..858c1aaecc 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -638,6 +638,7 @@
#include
#include
#include
+#include
/*
** 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 */
@@ -3127,7 +3124,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
- /* 0x80000000 // Available */
+#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
@@ -4286,7 +4283,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
@@ -4661,15 +4657,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
-#endif
-
/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 04df285cc9..4fab402529 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -3994,7 +3994,7 @@ static int SQLITE_TCLAPI DbMain(
** The EXTERN macros are required by TCL in order to work on windows.
*/
EXTERN int Sqlite3_Init(Tcl_Interp *interp){
- int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR;
+ int rc = Tcl_InitStubs(interp, "8.5-", 0) ? TCL_OK : TCL_ERROR;
if( rc==TCL_OK ){
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#ifndef SQLITE_3_SUFFIX_ONLY
@@ -4050,6 +4050,20 @@ EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
"if {[llength $argv]>=1} {\n"
+#ifdef WIN32
+ "set new [list]\n"
+ "foreach arg $argv {\n"
+ "if {[file exists $arg]} {\n"
+ "lappend new $arg\n"
+ "} else {\n"
+ "foreach match [lsort [glob -nocomplain $arg]] {\n"
+ "lappend new $match\n"
+ "}\n"
+ "}\n"
+ "}\n"
+ "set argv $new\n"
+ "unset new\n"
+#endif
"set argv0 [lindex $argv 0]\n"
"set argv [lrange $argv 1 end]\n"
"source $argv0\n"
diff --git a/src/test1.c b/src/test1.c
index 38ea6229ee..5af066c6b2 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -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",
diff --git a/src/test_config.c b/src/test_config.c
index 9d4c50ae21..183400260c 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -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
diff --git a/src/utf.c b/src/utf.c
index 083ada7882..c934bb234c 100644
--- a/src/utf.c
+++ b/src/utf.c
@@ -136,7 +136,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn0 ){
- 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;
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 27f03d8226..808ed9b978 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -4514,7 +4514,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 ar );
- testcase( x==r );
- return (xr);
}else{
i64 y;
if( r<-9223372036854775808.0 ) return +1;
diff --git a/src/wal.c b/src/wal.c
index 89106038b8..f4aa663fd3 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -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;
+ }
}
/*
diff --git a/src/where.c b/src/where.c
index 96b5663da3..36337578f0 100644
--- a/src/where.c
+++ b/src/where.c
@@ -6302,58 +6302,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
}
}
-/*
-** Expression Node callback for sqlite3ExprCanReturnSubtype().
-**
-** Only a function call is able to return a subtype. So if the node
-** is not a function call, return WRC_Prune immediately.
-**
-** A function call is able to return a subtype if it has the
-** SQLITE_RESULT_SUBTYPE property.
-**
-** Assume that every function is able to pass-through a subtype from
-** one of its argument (using sqlite3_result_value()). Most functions
-** are not this way, but we don't have a mechanism to distinguish those
-** that are from those that are not, so assume they all work this way.
-** That means that if one of its arguments is another function and that
-** other function is able to return a subtype, then this function is
-** able to return a subtype.
-*/
-static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
- int n;
- FuncDef *pDef;
- sqlite3 *db;
- if( pExpr->op!=TK_FUNCTION ){
- return WRC_Prune;
- }
- assert( ExprUseXList(pExpr) );
- db = pWalker->pParse->db;
- n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
- if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
- pWalker->eCode = 1;
- return WRC_Prune;
- }
- return WRC_Continue;
-}
-
-/*
-** Return TRUE if expression pExpr is able to return a subtype.
-**
-** A TRUE return does not guarantee that a subtype will be returned.
-** It only indicates that a subtype return is possible. False positives
-** are acceptable as they only disable an optimization. False negatives,
-** on the other hand, can lead to incorrect answers.
-*/
-static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.pParse = pParse;
- w.xExprCallback = exprNodeCanReturnSubtype;
- sqlite3WalkExpr(&w, pExpr);
- return w.eCode;
-}
-
/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression. iIdxCur is the cursor
@@ -6387,12 +6335,6 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
continue;
}
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
- if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
- /* Functions that might set a subtype should not be replaced by the
- ** value taken from an expression index since the index omits the
- ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
- continue;
- }
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
if( p==0 ) break;
p->pIENext = pParse->pIdxEpr;
diff --git a/src/whereexpr.c b/src/whereexpr.c
index 7ea2956a75..2b6eb6a78d 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -219,20 +219,25 @@ static int isLikeOrGlob(
z = (u8*)pRight->u.zToken;
}
if( z ){
-
- /* Count the number of prefix characters prior to the first wildcard.
- ** If the underlying database has a UTF16LE encoding, then only consider
- ** ASCII characters. Note that the encoding of z[] is UTF8 - we are
- ** dealing with only UTF8 here in this code, but the database engine
- ** itself might be processing content using a different encoding. */
+ /* Count the number of prefix bytes prior to the first wildcard.
+ ** or U+fffd character. If the underlying database has a UTF16LE
+ ** encoding, then only consider ASCII characters. Note that the
+ ** encoding of z[] is UTF8 - we are dealing with only UTF8 here in
+ ** this code, but the database engine itself might be processing
+ ** content using a different encoding. */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
- if( c==wc[3] && z[cnt]!=0 ){
+ if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){
cnt++;
- }else if( c>=0x80 && ENC(db)==SQLITE_UTF16LE ){
- cnt--;
- break;
+ }else if( c>=0x80 ){
+ const u8 *z2 = z+cnt-1;
+ if( sqlite3Utf8Read(&z2)==0xfffd || ENC(db)==SQLITE_UTF16LE ){
+ cnt--;
+ break;
+ }else{
+ cnt = (int)(z2-z);
+ }
}
}
@@ -244,7 +249,7 @@ static int isLikeOrGlob(
** range search. The third is because the caller assumes that the pattern
** consists of at least one character after all escapes have been
** removed. */
- if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){
+ if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){
Expr *pPrefix;
/* A "complete" match if the pattern ends with "*" or "%" */
diff --git a/test/atof1.test b/test/atof1.test
index 95f443ce0d..1a5db2cc79 100644
--- a/test/atof1.test
+++ b/test/atof1.test
@@ -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)}]
diff --git a/test/cast.test b/test/cast.test
index 7f48ed80bf..1c9071d775 100644
--- a/test/cast.test
+++ b/test/cast.test
@@ -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)}
diff --git a/test/corruptN.test b/test/corruptN.test
index 376325f5c5..8108609c09 100644
--- a/test/corruptN.test
+++ b/test/corruptN.test
@@ -276,4 +276,31 @@ do_catchsql_test 6.3 {
UPDATE t1 SET x='hello world' WHERE rowid=1;
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 7.0 {
+ BEGIN;
+ CREATE TABLE p1(x PRIMARY KEY);
+ CREATE TABLE c1(y);
+
+ PRAGMA schema_version = 0;
+ PRAGMA writable_schema = RESET;
+
+ INSERT INTO c1 VALUES(1000);
+ ROLLBACK;
+}
+
+do_execsql_test 7.1 {
+ PRAGMA table_info = p1;
+} {0 x {} 0 {} 1}
+
+do_catchsql_test 7.2 {
+ SELECT * FROM p1;
+} {1 {database disk image is malformed}}
+
+do_catchsql_test 7.3 {
+ PRAGMA integrity_check
+} {1 {database disk image is malformed}}
+
+
finish_test
diff --git a/test/fp-speed-1.c b/test/fp-speed-1.c
index 5eeb95d348..cb4e0409c3 100644
--- a/test/fp-speed-1.c
+++ b/test/fp-speed-1.c
@@ -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=0x80 && ($i<=0x9F || $tcl_version>=9.0)} continue
+ if {$i>=0x80} {
+ if {$i<=0x9F || $tcl_version>=9.0} continue
+ if {$tcl_platform(platform)=="windows"} continue
+ }
if {$i>=0xE0 && $tcl_platform(os)=="OpenBSD"} continue
if {$i>=0xE0 && $i<=0xEF && $tcl_platform(os)=="Linux"} continue
set hex [format %02X $i]
diff --git a/test/snapshot3.test b/test/snapshot3.test
index 4dca202b1c..470d463a66 100644
--- a/test/snapshot3.test
+++ b/test/snapshot3.test
@@ -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
diff --git a/test/speedtest1.c b/test/speedtest1.c
index 5709423818..b0817858ae 100644
--- a/test/speedtest1.c
+++ b/test/speedtest1.c
@@ -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 ){
diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl
index 3147738e10..0f0104ff6e 100644
--- a/test/testrunner_data.tcl
+++ b/test/testrunner_data.tcl
@@ -215,7 +215,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) {
@@ -355,7 +354,6 @@ namespace eval trd {
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_RTREE
-DSQLITE_ENABLE_HIDDEN_COLUMNS
- -DLONGDOUBLE_TYPE=double
-DCONFIG_SLOWDOWN_FACTOR=8.0
}
diff --git a/test/thread_common.tcl b/test/thread_common.tcl
index 6b17082ad4..1ebc6573a9 100644
--- a/test/thread_common.tcl
+++ b/test/thread_common.tcl
@@ -95,7 +95,7 @@ proc run_thread_tests {{print_warning 0}} {
if {[info commands sqlthread] eq ""} {
set zProblem "SQLite build is not threadsafe"
}
- if {![info exists ::tcl_platform(threaded)]} {
+ if {![tcl::pkgconfig get threaded]} {
set zProblem "Linked against a non-threadsafe Tcl build"
}
if {[info exists zProblem]} {
@@ -107,4 +107,3 @@ proc run_thread_tests {{print_warning 0}} {
}
return 0
-
diff --git a/tool/mktoolzip.tcl b/tool/mktoolzip.tcl
index 885bae960b..a5951168a8 100644
--- a/tool/mktoolzip.tcl
+++ b/tool/mktoolzip.tcl
@@ -54,16 +54,7 @@ close $in
scan $vers %d.%d.%d v1 v2 v3
set v2 [format 3%02d%02d00 $v2 $v3]
set name sqlite-tools-$OS-$ARCH-$v2.zip
-
-if {$OS=="win32"} {
- # The win32 tar.exe supports the -a ("auto-compress") option. This causes
- # tar to create an archive type based on the extension of the output file.
- # In this case, a zip file.
- puts "tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE"
- puts [exec tar -a -cf $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE]
- puts "$name: [file size $name] bytes"
-} else {
- puts "zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE"
- puts [exec zip $name sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE]
- puts [exec ls -l $name]
-}
+set toollist "sqlite3$EXE sqldiff$EXE sqlite3_analyzer$EXE sqlite3_rsync$EXE"
+puts "zip $name {*}$toollist"
+exec zip $name {*}$toollist
+puts "$name: [file size $name] bytes"
diff --git a/tool/speed-check.sh b/tool/speed-check.sh
index 5d425c3b37..8a9e67a38b 100644
--- a/tool/speed-check.sh
+++ b/tool/speed-check.sh
@@ -99,9 +99,6 @@ while test "$1" != ""; do
--stmtcache)
shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1"
;;
- --nolongdouble)
- SPEEDTEST_OPTS="$SPEEDTEST_OPTS --nolongdouble"
- ;;
--checkpoint)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint"
;;
diff --git a/tool/sqlite3-rsync.c b/tool/sqlite3_rsync.c
similarity index 98%
rename from tool/sqlite3-rsync.c
rename to tool/sqlite3_rsync.c
index 1be206a758..688ff1efe3 100644
--- a/tool/sqlite3-rsync.c
+++ b/tool/sqlite3_rsync.c
@@ -21,7 +21,7 @@
#include "sqlite3.h"
static const char zUsage[] =
- "sqlite3-rsync ORIGIN REPLICA ?OPTIONS?\n"
+ "sqlite3_rsync ORIGIN REPLICA ?OPTIONS?\n"
"\n"
"One of ORIGIN or REPLICA is a pathname to a database on the local\n"
"machine and the other is of the form \"USER@HOST:PATH\" describing\n"
@@ -30,7 +30,7 @@ static const char zUsage[] =
"\n"
"OPTIONS:\n"
"\n"
- " --exe PATH Name of the sqlite3-rsync program on the remote side\n"
+ " --exe PATH Name of the sqlite3_rsync program on the remote side\n"
" --help Show this help screen\n"
" --ssh PATH Name of the SSH program used to reach the remote side\n"
" -v Verbose. Multiple v's for increasing output\n"
@@ -1197,6 +1197,7 @@ static void originSide(SQLiteRsync *p){
int c = 0;
unsigned int nPage = 0;
unsigned int iPage = 0;
+ unsigned int lockBytePage = 0;
unsigned int szPg = 0;
sqlite3_stmt *pCkHash = 0;
char buf[200];
@@ -1235,6 +1236,7 @@ static void originSide(SQLiteRsync *p){
p->nPage = nPage;
p->szPage = szPg;
p->iProtocol = PROTOCOL_VERSION;
+ lockBytePage = (1<<30)/szPg + 1;
}
}
@@ -1290,6 +1292,7 @@ static void originSide(SQLiteRsync *p){
" INSERT INTO badHash SELECT n FROM c",
iPage+1, p->nPage);
}
+ runSql(p, "DELETE FROM badHash WHERE pgno=%d", lockBytePage);
pStmt = prepareStmt(p,
"SELECT pgno, data"
" FROM badHash JOIN sqlite_dbpage('main') USING(pgno)");
@@ -1456,15 +1459,18 @@ static void replicaSide(SQLiteRsync *p){
}else if( p->nErr ){
runSql(p, "ROLLBACK");
}else{
- int rc;
- sqlite3_bind_int64(pIns, 1, nOPage);
- sqlite3_bind_null(pIns, 2);
- rc = sqlite3_step(pIns);
- if( rc!=SQLITE_DONE ){
- reportError(p, "SQL statement [%s] failed (pgno=%u, data=NULL): %s",
- sqlite3_sql(pIns), nOPage, sqlite3_errmsg(p->db));
+ if( nOPage<0xffffffff ){
+ int rc;
+ sqlite3_bind_int64(pIns, 1, nOPage+1);
+ sqlite3_bind_null(pIns, 2);
+ rc = sqlite3_step(pIns);
+ if( rc!=SQLITE_DONE ){
+ reportError(p,
+ "SQL statement [%s] failed (pgno=%u, data=NULL): %s",
+ sqlite3_sql(pIns), nOPage, sqlite3_errmsg(p->db));
+ }
+ sqlite3_reset(pIns);
}
- sqlite3_reset(pIns);
p->nPage = nOPage;
runSql(p, "COMMIT");
}
@@ -1580,13 +1586,13 @@ static char *hostSeparator(const char *zIn){
**
** Input formats:
**
-** (1) sqlite3-rsync FILENAME1 USER@HOST:FILENAME2
+** (1) sqlite3_rsync FILENAME1 USER@HOST:FILENAME2
**
-** (2) sqlite3-rsync USER@HOST:FILENAME1 FILENAME2
+** (2) sqlite3_rsync USER@HOST:FILENAME1 FILENAME2
**
-** (3) sqlite3-rsync --origin FILENAME1
+** (3) sqlite3_rsync --origin FILENAME1
**
-** (4) sqlite3-rsync --replica FILENAME2
+** (4) sqlite3_rsync --replica FILENAME2
**
** The user types (1) or (2). SSH launches (3) or (4).
**
@@ -1610,7 +1616,7 @@ int main(int argc, char const * const *argv){
FILE *pOut = 0;
int childPid = 0;
const char *zSsh = "ssh";
- const char *zExe = "sqlite3-rsync";
+ const char *zExe = "sqlite3_rsync";
char *zCmd = 0;
sqlite3_int64 tmStart;
sqlite3_int64 tmEnd;
diff --git a/tool/src-verify.c b/tool/src-verify.c
index 7629046564..0c7ed6f4c4 100644
--- a/tool/src-verify.c
+++ b/tool/src-verify.c
@@ -854,12 +854,16 @@ int main(int argc, char **argv){
xErr = errorMsgNH;
continue;
}
+ usage:
fprintf(stderr, "Usage: %s DIRECTORY\n"
" or: %s --sha1 FILE ...\n"
" or: %s --sha3 FILE ...\n",
argv[0], argv[0], argv[0]);
return 1;
}
+ if( !zDir ){
+ goto usage;
+ }
if( strlen(zDir)>1000 ){
fprintf(stderr, "Directory argument too big: [%s]\n", zDir);
return 1;