diff --git a/Makefile.in b/Makefile.in
index 1ff791c8ab..7926aa84dd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -79,7 +79,7 @@ libdir = @libdir@
INSTALL = @BIN_INSTALL@
AR = @AR@
-AR.flags = cr # TODO? Add a configure test to determine this?
+AR.flags = cr
CC = @CC@
B.cc = @CC_FOR_BUILD@ @BUILD_CFLAGS@
T.cc = $(CC)
@@ -126,9 +126,14 @@ LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
# os-specific: see
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
# - https://sqlite.org/forum/forumpost/0c7fc097b2
-ENABLE_SHARED = @ENABLE_SHARED@
-ENABLE_STATIC = @ENABLE_STATIC@
+libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
+# DLL.basename: see https://sqlite.org/forum/forumpost/828fdfe904
+libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
+# libsqlite3.out.implib => the output filename part of LDFLAGS_OUT_IMPLIB.
+ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
+ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
HAVE_WASI_SDK = @HAVE_WASI_SDK@
+libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
diff --git a/Makefile.msc b/Makefile.msc
index 3a3995d7d8..80e294003d 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -294,6 +294,12 @@ SESSION = 0
RBU = 0
!ENDIF
+# Set this to non-0 to enable support for blocking locks.
+#
+!IFNDEF SETLK_TIMEOUT
+SETLK_TIMEOUT = 0
+!ENDIF
+
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -450,6 +456,10 @@ EXT_FEATURE_FLAGS =
!ENDIF
!ENDIF
+!IF $(SETLK_TIMEOUT)!=0
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
+!ENDIF
+
###############################################################################
############################### END OF OPTIONS ################################
###############################################################################
diff --git a/README.md b/README.md
index 689b52dabd..d6d41da3b9 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,7 @@ later. The "tclextension-install" target and the test targets that follow
all require TCL development libraries too. ("apt install tcl-dev"). It is
helpful, but is not required, to install the SQLite TCL extension (the
"tclextension-install" target) prior to running tests. The "releasetest"
-target has additional requiremenst, such as "valgrind".
+target has additional requirements, such as "valgrind".
On "make" command-lines, one can add "OPTIONS=..." to specify additional
compile-time options over and above those set by ./configure. For example,
diff --git a/auto.def b/auto.def
index 9df87f579a..e0f8be7bde 100644
--- a/auto.def
+++ b/auto.def
@@ -4,70 +4,45 @@
# This is the main autosetup-compatible configure script for the
# SQLite project.
#
-# This script should be kept compatible with JimTCL, a copy of which
-# is included in this source tree as ./autosetup/jimsh0.c. The number
-# of incompatibilities between canonical TCL and JimTCL is very low
-# and alternative formulations of incompatible constructs have, so
-# far, been easy to find.
+# This script and all of its dependencies must be kept compatible with
+# JimTCL, a copy of which is included in this source tree as
+# ./autosetup/jimsh0.c. The number of incompatibilities between
+# canonical TCL and JimTCL is very low and alternative formulations of
+# incompatible constructs have, so far, been easy to find.
#
# JimTCL: https://jim.tcl.tk
#
use sqlite-config
-sqlite-config-bootstrap canonical
-sqlite-setup-default-cflags
-proj-if-opt-truthy dev {
- # --enable-dev needs to come early so that the downstream tests
- # which check for the following flags use their updated state.
- proj-opt-set all 1
- proj-opt-set debug 1
- proj-opt-set amalgamation 0
- define CFLAGS [get-env CFLAGS {-O0 -g}]
- # -------------^^^^^^^ intentionally using [get-env] instead of
- # [proj-get-env] here because [sqlite-setup-default-cflags] uses
- # [proj-get-env] and we want this to supercede that.
+sqlite-configure canonical {
+ proj-if-opt-truthy dev {
+ # --enable-dev needs to come early so that the downstream tests
+ # which check for the following flags use their updated state.
+ proj-opt-set all 1
+ proj-opt-set debug 1
+ proj-opt-set amalgamation 0
+ define CFLAGS [get-env CFLAGS {-O0 -g}]
+ # -------------^^^^^^^ intentionally using [get-env] instead of
+ # [proj-get-env] here because [sqlite-setup-default-cflags] uses
+ # [proj-get-env] and we want this to supercede that.
+ sqlite-munge-cflags
+ }
+ sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
+ sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
+ sqlite-check-common-system-deps
+
+ proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
+
+ proj-define-for-opt gcov USE_GCOV "Use gcov?"
+
+ proj-define-for-opt test-status TSTRNNR_OPTS \
+ "test-runner flags:" {--status} {}
+
+ proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
+ "Use #line macros in the amalgamation:"
+
+ define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
+
+ sqlite-handle-tcl
+ sqlite-handle-emsdk
}
-
-sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
-sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
-sqlite-check-common-system-deps
-
-#
-# Enable large file support (if special flags are necessary)
-#
-define HAVE_LFS 0
-if {[opt-bool largefile]} {
- cc-check-lfs
-}
-
-proj-define-for-opt shared ENABLE_SHARED "Build shared library?"
-
-if {![proj-define-for-opt static ENABLE_STATIC \
- "Build static library?"]} {
- proj-warn "Static lib build may be implicitly re-activated by other components, e.g. some test apps."
-}
-
-proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
-
-proj-define-for-opt gcov USE_GCOV "Use gcov?"
-
-proj-define-for-opt test-status TSTRNNR_OPTS \
- "test-runner flags:" {--status} {}
-
-proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
- "Use #line macros in the amalgamation:"
-
-define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
-
-proj-check-rpath
-sqlite-handle-soname
-sqlite-handle-debug
-sqlite-handle-tcl
-sqlite-handle-threadsafe
-sqlite-handle-tempstore
-sqlite-handle-line-editing
-sqlite-handle-load-extension
-sqlite-handle-math
-sqlite-handle-icu
-sqlite-handle-emsdk
-sqlite-config-finalize
diff --git a/autoconf/Makefile.in b/autoconf/Makefile.in
index d494e9d1e0..f74c71d674 100644
--- a/autoconf/Makefile.in
+++ b/autoconf/Makefile.in
@@ -143,57 +143,76 @@ sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
libsqlite3.LIB = libsqlite3$(T.lib)
-libsqlite3.SO = libsqlite3$(T.dll)
+libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
+libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
+libsqlite3.DLL = $(libsqlite3.DLL.basename)$(T.dll)
+libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
-$(libsqlite3.SO): sqlite3.o
+$(libsqlite3.DLL): sqlite3.o
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
-all: $(libsqlite3.SO)
+$(libsqlite3.DLL)-1: $(libsqlite3.DLL)
+$(libsqlite3.DLL)-0:
+all: $(libsqlite3.DLL)-$(ENABLE_LIB_SHARED)
$(libsqlite3.LIB): sqlite3.o
$(AR) $(AR.flags) $@ sqlite3.o
-all: $(libsqlite3.LIB)
+$(libsqlite3.LIB)-1: $(libsqlite3.LIB)
+$(libsqlite3.LIB)-0:
+all: $(libsqlite3.LIB)-$(ENABLE_LIB_STATIC)
-install-so-1: $(install-dir.lib) $(libsqlite3.SO)
- $(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
- @if [ -f $(libsqlite3.SO).a ]; then \
- $(INSTALL) $(libsqlite3.SO).a "$(install-dir.lib)"; \
- fi
- @echo "Setting up $(libsqlite3.SO) version symlinks..."; \
- if [ x.dll = x$(T.dll) ]; then \
- echo "No library symlinks needed on this platform"; \
- elif [ x.dylib = x$(T.dll) ]; then \
- cd "$(install-dir.lib)" || exit $$?; \
- rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
- dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
- mv $(libsqlite3.SO) $$dllname || exit $$?; \
- ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
- ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
- ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
- else \
- cd "$(install-dir.lib)" || exit $$?; \
- rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
- mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
- ls -la $(libsqlite3.SO) $(libsqlite3.SO).[a03]*; \
- if [ -e $(libsqlite3.SO).0.8.6 ]; then \
- echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
- rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
- ls -la $(libsqlite3.SO).0.8.6; \
- elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
- echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
- rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
- ls -la $(libsqlite3.SO).0.8.6; \
- fi; \
+#
+# Maintenance reminder: the install-dll-... rules must be kept in sync
+# with the main copies rom /main.mk.
+#
+install-dll-out-implib: $(install-dir.lib) $(libsqlite3.DLL)
+ if [ x != "x$(libsqlite3.out.implib)" ] && [ -f "$(libsqlite3.out.implib)" ]; then \
+ $(INSTALL) $(libsqlite3.out.implib) "$(install-dir.lib)"; \
fi
-install-so-0 install-so-:
-install-so: install-so-$(ENABLE_LIB_SHARED)
-install: install-so
+install-dll-unix-generic: install-dll-out-implib
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
+ @echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
+ cd "$(install-dir.lib)" || exit $$?; \
+ rm -f $(libsqlite3.DLL).0 $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
+ mv $(libsqlite3.DLL) $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL) || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0 || exit $$?; \
+ ls -la $(libsqlite3.DLL) $(libsqlite3.DLL).[a03]*; \
+ if [ -e $(libsqlite3.DLL).0.8.6 ]; then \
+ echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
+ rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ls -la $(libsqlite3.DLL).0.8.6; \
+ elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
+ echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
+ rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ls -la $(libsqlite3.DLL).0.8.6; \
+ fi
+
+install-dll-msys: install-dll-out-implib $(install-dir.bin)
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.bin)"
+# ----------------------------------------------^^^ yes, bin
+install-dll-mingw: install-dll-msys
+install-dll-cygwin: install-dll-msys
+
+install-dll-darwin: $(install-dir.lib) $(libsqlite3.DLL)
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
+ @echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
+ cd "$(install-dir.lib)" || exit $$?; \
+ rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
+ dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
+ mv $(libsqlite3.DLL) $$dllname || exit $$?; \
+ ln -s $$dllname $(libsqlite3.DLL) || exit $$?; \
+ ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
+ ls -la $$dllname $(libsqlite3.DLL) libsqlite3.0$(T.dll)
+
+install-dll-1: install-dll-$(libsqlite3.DLL.install-rules)
+install-dll-0 install-dll-:
+install-dll: install-dll-$(ENABLE_LIB_SHARED)
+install: install-dll
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
@@ -209,7 +228,7 @@ ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3)
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib)
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
-sqlite3-shell-deps.0 = $(libsqlite3.SO)
+sqlite3-shell-deps.0 = $(libsqlite3.DLL)
sqlite3$(T.exe): $(TOP)/shell.c $(sqlite3-shell-deps.$(ENABLE_STATIC_SHELL))
$(CC) -o $@ \
$(TOP)/shell.c $(sqlite3-shell-link-flags.$(ENABLE_STATIC_SHELL)) \
@@ -237,7 +256,7 @@ install: install-man1
clean:
rm -f *.o sqlite3$(T.exe)
- rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
+ rm -f $(libsqlite3.LIB) $(libsqlite3.DLL) libsqlite3$(T.dll).a
distclean: clean
rm -f jimsh0$(T.exe) config.* sqlite3.pc sqlite_cfg.h Makefile
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index 538cc43a4b..d7284af23a 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -247,6 +247,12 @@ SESSION = 0
RBU = 0
!ENDIF
+# Set this to non-0 to enable support for blocking locks.
+#
+!IFNDEF SETLK_TIMEOUT
+SETLK_TIMEOUT = 0
+!ENDIF
+
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -372,6 +378,10 @@ EXT_FEATURE_FLAGS =
!ENDIF
!ENDIF
+!IF $(SETLK_TIMEOUT)!=0
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
+!ENDIF
+
###############################################################################
############################### END OF OPTIONS ################################
###############################################################################
diff --git a/autoconf/README.txt b/autoconf/README.txt
index 646c0a1215..1192a80fb1 100644
--- a/autoconf/README.txt
+++ b/autoconf/README.txt
@@ -27,7 +27,7 @@ the embedded copy of JimTCL).
REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE
==================================================================
- * the cononical build system allows you to run tests to verify that
+ * the canonical build system allows you to run tests to verify that
the build worked
* the canonical build system supports more compile-time options
* the canonical build system works for any arbitrary check-in to
diff --git a/autoconf/auto.def b/autoconf/auto.def
index 099b52aff7..3ba900d957 100644
--- a/autoconf/auto.def
+++ b/autoconf/auto.def
@@ -3,27 +3,8 @@
#
# This is the main autosetup-compatible configure script for the
# "autoconf" bundle of the SQLite project.
-#
-# This script must be kept compatible with JimTCL, a copy of which is
-# included in this source tree as ./autosetup/jimsh0.c.
-#
use sqlite-config
-sqlite-config-bootstrap autoconf
-sqlite-check-common-bins
-sqlite-check-common-system-deps
-proj-check-rpath
-sqlite-handle-soname
-sqlite-setup-default-cflags
-sqlite-handle-debug
-sqlite-handle-threadsafe
-sqlite-handle-tempstore
-sqlite-handle-line-editing
-sqlite-handle-load-extension
-sqlite-handle-math
-sqlite-handle-icu
-
-define ENABLE_STATIC_SHELL [opt-bool static-shell]
-define ENABLE_LIB_SHARED [opt-bool shared]
-define ENABLE_LIB_STATIC [opt-bool static]
-
-sqlite-config-finalize
+sqlite-configure autoconf {
+ sqlite-check-common-bins
+ sqlite-check-common-system-deps
+}
diff --git a/autoconf/tea/README.txt b/autoconf/tea/README.txt
index b50d4f29a8..05044173f5 100644
--- a/autoconf/tea/README.txt
+++ b/autoconf/tea/README.txt
@@ -26,7 +26,7 @@ SQLite that does not require first installing TCL and/or "tclsh".
The canonical Makefile in the SQLite source tree provides more
capabilities (such as the the ability to run test cases to ensure
that the build worked) and is better maintained. The only
-downside of the canonical Makfile is that it requires a TCL
+downside of the canonical Makefile is that it requires a TCL
installation. But if you are wanting to build the TCL extension for
SQLite, then presumably you already have a TCL installation. So why
not just use the more-capable and better-maintained canoncal Makefile?
diff --git a/autoconf/tea/configure.ac.in b/autoconf/tea/configure.ac.in
index a13a1e7615..95688b7c99 100644
--- a/autoconf/tea/configure.ac.in
+++ b/autoconf/tea/configure.ac.in
@@ -93,7 +93,7 @@ TEA_ADD_TCL_SOURCES([])
# The --with-system-sqlite causes the TCL bindings to SQLite to use
# the system shared library for SQLite rather than statically linking
# against its own private copy. This is dangerous and leads to
-# undersirable dependences and is not recommended.
+# undesirable dependences and is not recommended.
# Patchs from rmax.
#--------------------------------------------------------------------
AC_ARG_WITH([system-sqlite],
diff --git a/autosetup/autosetup b/autosetup/autosetup
index 1479fca407..239987554f 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -1634,8 +1634,8 @@ proc automf_command_reference {} {
if {[regexp {^#.*@section (.*)$} $line -> section]} {
lappend doc($current) [list section $section]
- continue
- }
+ continue
+ }
# Find embedded module names
if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
@@ -1651,7 +1651,7 @@ proc automf_command_reference {} {
if {$cmd eq "synopsis:"} {
set current $modulename
lappend doc($current) [list section "Module: $modulename"]
- } else {
+ } else {
lappend doc($current) [list subsection $cmd]
}
@@ -2088,8 +2088,12 @@ if {$autosetup(iswin)} {
proc split-path {} {
split [getenv PATH .] :
}
+ # Check for an executable file
proc file-isexec {exec} {
- file executable $exec
+ if {[file executable $exec] && [file isfile $exec]} {
+ return 1
+ }
+ return 0
}
}
diff --git a/autosetup/autosetup-find-tclsh b/autosetup/autosetup-find-tclsh
index 2b2006241c..9f6d6e9402 100755
--- a/autosetup/autosetup-find-tclsh
+++ b/autosetup/autosetup-find-tclsh
@@ -9,7 +9,7 @@ for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; d
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
- { $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
+ { $cc -o jimsh0 "$d/jimsh0.c"; } 2>/dev/null >/dev/null || continue
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
done
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index 0526b9a446..1a6453d0c8 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -1252,6 +1252,14 @@ int Jim_OpenForRead(const char *filename);
#endif
+# ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# else
+# define MAXPATHLEN JIM_PATH_LEN
+# endif
+# endif
+
int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb);
@@ -2088,10 +2096,6 @@ enum wbuftype {
#define UNIX_SOCKETS 0
#endif
-#ifndef MAXPATHLEN
-#define MAXPATHLEN JIM_PATH_LEN
-#endif
-
@@ -4173,14 +4177,6 @@ int Jim_regexpInit(Jim_Interp *interp)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
-# ifndef MAXPATHLEN
-# ifdef PATH_MAX
-# define MAXPATHLEN PATH_MAX
-# else
-# define MAXPATHLEN JIM_PATH_LEN
-# endif
-# endif
-
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
#define ISWINDOWS 1
diff --git a/autosetup/proj.tcl b/autosetup/proj.tcl
index fdfbf3a5ed..adf31a1ad6 100644
--- a/autosetup/proj.tcl
+++ b/autosetup/proj.tcl
@@ -197,16 +197,42 @@ proc proj-strip-hash-comments {val} {
return $x
}
+########################################################################
+# @proj-cflags-without-werror
+#
+# Fetches [define $var], strips out any -Werror entries, and returns
+# the new value. This is intended for temporarily stripping -Werror
+# from CFLAGS or CPPFLAGS within the scope of a [define-push] block.
+proc proj-cflags-without-werror {{var CFLAGS}} {
+ set rv {}
+ foreach f [get-define $var ""] {
+ switch -exact -- $f {
+ -Werror {}
+ default { lappend rv $f }
+ }
+ }
+ return [join $rv " "]
+}
+
########################################################################
# @proj-check-function-in-lib
#
-# A proxy for cc-check-function-in-lib which does not make any global
-# changes to the LIBS define. Returns the result of
-# cc-check-function-in-lib (i.e. true or false). The resulting linker
-# flags are stored in the [define] named lib_${function}.
+# A proxy for cc-check-function-in-lib with the following differences:
+#
+# - Does not make any global changes to the LIBS define.
+#
+# - Strips out -W... warning flags from CFLAGS before running the
+# test, as these feature tests will often fail if -Werror is used.
+#
+# Returns the result of cc-check-function-in-lib (i.e. true or false).
+# The resulting linker flags are stored in the [define] named
+# lib_${function}.
proc proj-check-function-in-lib {function libs {otherlibs {}}} {
set found 0
- define-push {LIBS} {
+ define-push {LIBS CFLAGS} {
+ #puts "CFLAGS before=[get-define CFLAGS]"
+ define CFLAGS [proj-cflags-without-werror]
+ #puts "CFLAGS after =[get-define CFLAGS]"
set found [cc-check-function-in-lib $function $libs $otherlibs]
}
return $found
@@ -353,7 +379,6 @@ proc proj-opt-was-provided {key} {
#
# Returns $val.
proc proj-opt-set {flag {val 1}} {
- global autosetup
if {$flag ni $::autosetup(options)} {
# We have to add this to autosetup(options) or else future calls
# to [opt-bool $flag] will fail validation of $flag.
@@ -363,6 +388,15 @@ proc proj-opt-set {flag {val 1}} {
return $val
}
+########################################################################
+# @proj-opt-exists flag
+#
+# Returns 1 if the given flag has been defined as a legal configure
+# option, else returns 0.
+proc proj-opt-exists {flag} {
+ expr {$flag in $::autosetup(options)};
+}
+
########################################################################
# @proj-val-truthy val
#
@@ -907,6 +941,35 @@ proc proj-check-emsdk {} {
return $rc
}
+########################################################################
+# @proj-cc-check-Wl-flag ?flag ?args??
+#
+# Checks whether the given linker flag (and optional arguments) can be
+# passed from the compiler to the linker using one of these formats:
+#
+# - -Wl,flag[,arg1[,...argN]]
+# - -Wl,flag -Wl,arg1 ...-Wl,argN
+#
+# If so, that flag string is returned, else an empty string is
+# returned.
+proc proj-cc-check-Wl-flag {args} {
+ cc-with {-link 1} {
+ # Try -Wl,flag,...args
+ set fli "-Wl"
+ foreach f $args { append fli ",$f" }
+ if {[cc-check-flags $fli]} {
+ return $fli
+ }
+ # Try -Wl,flag -Wl,arg1 ...-Wl,argN
+ set fli ""
+ foreach f $args { append fli "-Wl,$f " }
+ if {[cc-check-flags $fli]} {
+ return [string trim $fli]
+ }
+ return ""
+ }
+}
+
########################################################################
# @proj-check-rpath
#
@@ -918,12 +981,7 @@ proc proj-check-emsdk {} {
# --exec-prefix=... or --libdir=... are explicitly passed to
# configure then [get-define libdir] is used (noting that it derives
# from exec-prefix by default).
-#
-# Achtung: we have seen platforms which report that a given option
-# checked here will work but then fails at build-time, and the current
-# order of checks reflects that.
proc proj-check-rpath {} {
- set rc 1
if {[proj-opt-was-provided libdir]
|| [proj-opt-was-provided exec-prefix]} {
set lp "[get-define libdir]"
@@ -934,21 +992,18 @@ proc proj-check-rpath {} {
# CFLAGS or LIBS or whatever it is that cc-check-flags updates) then
# downstream tests may fail because the resulting rpath gets
# implicitly injected into them.
- cc-with {} {
+ cc-with {-link 1} {
if {[cc-check-flags "-rpath $lp"]} {
define LDFLAGS_RPATH "-rpath $lp"
- } elseif {[cc-check-flags "-Wl,-rpath,$lp"]} {
- define LDFLAGS_RPATH "-Wl,-rpath,$lp"
- } elseif {[cc-check-flags "-Wl,-rpath -Wl,$lp"]} {
- define LDFLAGS_RPATH "-Wl,-rpath -Wl,$lp"
- } elseif {[cc-check-flags -Wl,-R$lp]} {
- define LDFLAGS_RPATH "-Wl,-R$lp"
} else {
- define LDFLAGS_RPATH ""
- set rc 0
+ set wl [proj-cc-check-Wl-flag -rpath $lp]
+ if {"" eq $wl} {
+ set wl [proj-cc-check-Wl-flag -R$lp]
+ }
+ define LDFLAGS_RPATH $wl
}
}
- return $rc
+ expr {"" ne [get-define LDFLAGS_RPATH]}
}
########################################################################
@@ -965,7 +1020,7 @@ proc proj-check-rpath {} {
# potentially avoid some end-user confusion by using their own lib's
# name here (which shows up in the "checking..." output).
proc proj-check-soname {{libname "libfoo.so.0"}} {
- cc-with {} {
+ cc-with {-link 1} {
if {[cc-check-flags "-Wl,-soname,${libname}"]} {
define LDFLAGS_SONAME_PREFIX "-Wl,-soname,"
return 1
@@ -1138,7 +1193,7 @@ proc proj-xfer-options-aliases {mapping} {
########################################################################
# Arguable/debatable...
#
-# When _not_ cross-compiling and CC_FOR_BUILD is _not_ explcitely
+# When _not_ cross-compiling and CC_FOR_BUILD is _not_ explicitly
# specified, force CC_FOR_BUILD to be the same as CC, so that:
#
# ./configure CC=clang
@@ -1146,7 +1201,7 @@ proc proj-xfer-options-aliases {mapping} {
# will use CC_FOR_BUILD=clang, instead of cc, for building in-tree
# tools. This is based off of an email discussion and is thought to
# be likely to cause less confusion than seeing 'cc' invocations
-# will when the user passes CC=clang.
+# when when the user passes CC=clang.
#
# Sidebar: if we do this before the cc package is installed, it gets
# reverted by that package. Ergo, the cc package init will tell the
@@ -1191,11 +1246,11 @@ proc proj-which-linenoise {dotH} {
#
# In that make invocation, $(libdir) would, at make-time, normally be
# hard-coded to /foo/lib, rather than /blah/lib. That happens because
-# the autosetup exports conventional $prefix-based values for the
-# numerous autoconfig-compatible XYZdir vars at configure-time. What
-# we would normally want, however, is that --libdir derives from the
-# make-time $(prefix). The distinction between configure-time and
-# make-time is the significant factor there.
+# autosetup exports conventional $prefix-based values for the numerous
+# autoconfig-compatible XYZdir vars at configure-time. What we would
+# normally want, however, is that --libdir derives from the make-time
+# $(prefix). The distinction between configure-time and make-time is
+# the significant factor there.
#
# This function attempts to reconcile those vars in such a way that
# they will derive, at make-time, from $(prefix) in a conventional
diff --git a/autosetup/sqlite-config.tcl b/autosetup/sqlite-config.tcl
index 7d9a9ea84b..54daf7c8a3 100644
--- a/autosetup/sqlite-config.tcl
+++ b/autosetup/sqlite-config.tcl
@@ -12,7 +12,21 @@ if {[string first " " $autosetup(builddir)] != -1} {
may not contain space characters"
}
-use cc cc-db cc-shared cc-lib pkg-config proj
+use proj
+# We want this version info to be emitted up front, but we have to
+# 'use system' for --prefix=... to work. Ergo, this bit is up here
+# instead of in [sqlite-configure].
+define PACKAGE_VERSION [proj-file-content -trim $::autosetup(srcdir)/VERSION]
+if {"--help" ni $::argv} {
+ msg-result "Configuring SQLite version [get-define PACKAGE_VERSION]"
+}
+use system ; # Will output "Host System" and "Build System" lines
+if {"--help" ni $::argv} {
+ msg-result "Source dir = $::autosetup(srcdir)"
+ msg-result "Build dir = $::autosetup(builddir)"
+
+ use cc cc-db cc-shared cc-lib pkg-config
+}
#
# Object for communicating config-time state across various
@@ -49,11 +63,17 @@ set sqliteConfig(is-cross-compiling) [proj-is-cross-compiling]
########################################################################
# Processes all configure --flags for this build $buildMode must be
# either "canonical" or "autoconf", and others may be added in the
-# future.
-proc sqlite-config-bootstrap {buildMode} {
- if {$buildMode ni {canonical autoconf}} {
- user-error "Invalid build mode: $buildMode. Expecting one of: canonical, autoconf"
+# future. After bootstrapping, $configScript is eval'd in the caller's
+# scope, then post-configuration finalization is run. $configScript is
+# intended to hold configure code which is specific to the given
+# $buildMode, with the caveat that _some_ build-specific code is
+# encapsulated in the configuration finalization step.
+proc sqlite-configure {buildMode configScript} {
+ set allBuildModes {canonical autoconf}
+ if {$buildMode ni $allBuildModes} {
+ user-error "Invalid build mode: $buildMode. Expecting one of: $allBuildModes"
}
+ set ::sqliteConfig(build-mode) $buildMode
########################################################################
# A gentle introduction to flags handling in autosetup
#
@@ -131,8 +151,8 @@ proc sqlite-config-bootstrap {buildMode} {
# Options for how to build the library
build-modes {
{*} {
- shared=1 => {Disable build of shared libary}
- static=1 => {Disable build of static library (mostly)}
+ shared=1 => {Disable build of shared library}
+ static=1 => {Disable build of static library}
}
{canonical} {
amalgamation=1 => {Disable the amalgamation and instead build all files separately}
@@ -144,7 +164,9 @@ proc sqlite-config-bootstrap {buildMode} {
{*} {
threadsafe=1 => {Disable mutexing}
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
- largefile=1 => {Disable large file support}
+ largefile=1
+ => {This legacy flag has no effect on the library but may influence
+ the contents of the generated sqlite_cfg.h}
# ^^^ It's not clear that this actually does anything, as
# HAVE_LFS is not checked anywhere in the .c/.h/.in files.
load-extension=1 => {Disable loading of external extensions}
@@ -229,11 +251,14 @@ proc sqlite-config-bootstrap {buildMode} {
# Options for exotic/alternative build modes
alternative-builds {
{canonical} {
+ # Potential TODO: add --with-wasi-sdk support to the autoconf
+ # build
with-wasi-sdk:=/opt/wasi-sdk
=> {Top-most dir of the wasi-sdk for a WASI build}
+
with-emsdk:=auto
=> {Top-most dir of the Emscripten SDK installation.
- Default = EMSDK env var.}
+ Needed only by ext/wasm. Default=EMSDK env var.}
}
}
@@ -241,9 +266,12 @@ proc sqlite-config-bootstrap {buildMode} {
packaging {
{autoconf} {
# --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704
- static-shell=1 => {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c}
+ static-shell=1
+ => {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c}
}
{*} {
+ # A potential TODO without a current use case:
+ #rpath=1 => {Disable use of the rpath linker flag}
# soname: https://sqlite.org/src/forumpost/5a3b44f510df8ded
soname:=legacy
=> {SONAME for libsqlite3.so. "none", or not using this flag, sets no
@@ -252,10 +280,21 @@ proc sqlite-config-bootstrap {buildMode} {
it to that literal value. Any other value is assumed to be a
suffix which gets applied to "libsqlite3.so.",
e.g. --soname=9.10 equates to "libsqlite3.so.9.10".}
+ # dll-basename: https://sqlite.org/forum/forumpost/828fdfe904
+ dll-basename:=auto
+ => {Specifies the base name of the resulting DLL file.
+ If not provided, "libsqlite3" is usually assumed but on some platforms
+ a platform-dependent default is used. On some platforms this flag
+ gets automatically enabled if it is not provided. Use "default" to
+ explicitly disable platform-dependent activation on such systems.}
# out-implib: https://sqlite.org/forum/forumpost/0c7fc097b2
- out-implib=0
+ out-implib:=auto
=> {Enable use of --out-implib linker flag to generate an
- "import library" for the DLL}
+ "import library" for the DLL. The output's base name name is
+ specified by the value, with "auto" meaning to figure out a
+ name automatically. On some platforms this flag gets
+ automatically enabled if it is not provided. Use "none" to
+ explicitly disable this feature on such platforms.}
}
}
@@ -263,8 +302,9 @@ proc sqlite-config-bootstrap {buildMode} {
developer {
{*} {
# Note that using the --debug/--enable-debug flag here
- # requires patching autosetup/autosetup to rename the --debug
- # to --autosetup-debug.
+ # requires patching autosetup/autosetup to rename its builtin
+ # --debug to --autosetup-debug. See details in
+ # autosetup/README.md#patching.
with-debug=0
debug=0
=> {Enable debug build flags. This option will impact performance by
@@ -275,14 +315,21 @@ proc sqlite-config-bootstrap {buildMode} {
=> {Enable the SQLITE_ENABLE_STMT_SCANSTATUS feature flag}
}
{canonical} {
- dev => {Enable dev-mode build: automatically enables certain other flags}
- test-status => {Enable status of tests}
- gcov=0 => {Enable coverage testing using gcov}
- linemacros => {Enable #line macros in the amalgamation}
- dynlink-tools => {Dynamically link libsqlite3 to certain tools which normally statically embed it}
+ dev
+ => {Enable dev-mode build: automatically enables certain other flags}
+ test-status
+ => {Enable status of tests}
+ gcov=0
+ => {Enable coverage testing using gcov}
+ linemacros
+ => {Enable #line macros in the amalgamation}
+ dynlink-tools
+ => {Dynamically link libsqlite3 to certain tools which normally statically embed it}
}
{*} {
- dump-defines=0 => {Dump autosetup defines to $::sqliteConfig(dump-defines-txt) (for build debugging)}
+ dump-defines=0
+ => {Dump autosetup defines to $::sqliteConfig(dump-defines-txt)
+ (for build debugging)}
}
}
}; # $allOpts
@@ -300,14 +347,75 @@ proc sqlite-config-bootstrap {buildMode} {
}
}
#lappend opts "soname:=duplicateEntry => {x}"; #just testing
- if {[catch {options $opts}]} {
+ if {[catch {options $opts} msg xopts]} {
# Workaround for
# where [options] behaves oddly on _some_ TCL builds when it's
# called from deeper than the global scope.
- return -code break
+ dict incr xopts -level
+ return {*}$xopts $msg
}
sqlite-post-options-init
-}; # sqlite-config-bootstrap
+ uplevel 1 $configScript
+ sqlite-configure-finalize
+}; # sqlite-configure
+
+########################################################################
+# Performs late-stage config steps common to both the canonical and
+# autoconf bundle builds.
+proc sqlite-configure-finalize {} {
+ set buildMode $::sqliteConfig(build-mode)
+ set isCanonical [expr {$buildMode eq "canonical"}]
+ set isAutoconf [expr {$buildMode eq "autoconf"}]
+
+ define HAVE_LFS 0
+ if {[opt-bool largefile]} {
+ #
+ # Insofar as we can determine HAVE_LFS has no effect on the
+ # library. Perhaps it did back in the early 2000's. The
+ # --enable/disable-largefile flag is retained because it's
+ # harmless, but it doesn't do anything useful. It does have
+ # visible side-effects, though: the generated sqlite_cfg.h may (or
+ # may not) define HAVE_LFS.
+ #
+ cc-check-lfs
+ }
+
+ if {$isCanonical} {
+ if {![opt-bool static]} {
+ proj-indented-notice {
+ NOTICE: static lib build may be implicitly re-activated by
+ other components, e.g. some test apps.
+ }
+ }
+ } else {
+ proj-assert { $isAutoconf } "Invalid build mode"
+ proj-define-for-opt static-shell ENABLE_STATIC_SHELL \
+ "Link library statically into the CLI shell?"
+ if {![opt-bool shared] && ![opt-bool static-shell]} {
+ proj-opt-set shared 1
+ proj-indented-notice {
+ NOTICE: ignoring --disable-shared because --disable-static-shell
+ was specified.
+ }
+ }
+ }
+ proj-define-for-opt shared ENABLE_LIB_SHARED "Build shared library?"
+ proj-define-for-opt static ENABLE_LIB_STATIC "Build static library?"
+
+ sqlite-handle-debug
+ sqlite-handle-rpath
+ sqlite-handle-soname
+ sqlite-handle-threadsafe
+ sqlite-handle-tempstore
+ sqlite-handle-line-editing
+ sqlite-handle-load-extension
+ sqlite-handle-math
+ sqlite-handle-icu
+ sqlite-handle-env-quirks
+ sqlite-process-dot-in-files
+ sqlite-post-config-validation
+ sqlite-dump-defines
+}; # sqlite-configure-finalize
########################################################################
# Runs some common initialization which must happen immediately after
@@ -316,6 +424,10 @@ proc sqlite-config-bootstrap {buildMode} {
# top-level build and the "autoconf" build, but it's not intended to
# be a catch-all dumping ground for such.
proc sqlite-post-options-init {} {
+ define PACKAGE_NAME "sqlite"
+ define PACKAGE_URL {https://sqlite.org}
+ define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
+ define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
#
# Carry values from hidden --flag aliases over to their canonical
# flag forms. This list must include only options which are common
@@ -336,23 +448,7 @@ proc sqlite-post-options-init {} {
define SQLITE_OS_WIN 0
}
set ::sqliteConfig(msg-debug-enabled) [proj-val-truthy [get-env msg-debug 0]]
- sqlite-setup-package-info
-}
-
-########################################################################
-# Called by [sqlite-post-options-init] to set up PACKAGE_NAME and
-# related defines.
-proc sqlite-setup-package-info {} {
- set srcdir $::autosetup(srcdir)
- set PACKAGE_VERSION [proj-file-content -trim $srcdir/VERSION]
- define PACKAGE_NAME "sqlite"
- define PACKAGE_URL {https://sqlite.org}
- define PACKAGE_VERSION $PACKAGE_VERSION
- define PACKAGE_STRING "[get-define PACKAGE_NAME] $PACKAGE_VERSION"
- define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
- msg-result "Source dir = $srcdir"
- msg-result "Build dir = $::autosetup(builddir)"
- msg-result "Configuring SQLite version $PACKAGE_VERSION"
+ sqlite-setup-default-cflags
}
########################################################################
@@ -484,27 +580,12 @@ proc sqlite-check-common-system-deps {} {
}
}
-proc sqlite-setup-default-cflags {} {
- ########################################################################
- # We differentiate between two C compilers: the one used for binaries
- # which are to run on the build system (in autosetup it's called
- # CC_FOR_BUILD and in Makefile.in it's $(B.cc)) and the one used for
- # compiling binaries for the target system (CC a.k.a. $(T.cc)).
- # Normally they're the same, but they will differ when
- # cross-compiling.
- #
- # When cross-compiling we default to not using the -g flag, based on a
- # /chat discussion prompted by
- # https://sqlite.org/forum/forumpost/9a67df63eda9925c
- set defaultCFlags {-O2}
- if {!$::sqliteConfig(is-cross-compiling)} {
- lappend defaultCFlags -g
- }
- define CFLAGS [proj-get-env CFLAGS $defaultCFlags]
- # BUILD_CFLAGS is the CFLAGS for CC_FOR_BUILD.
- define BUILD_CFLAGS [proj-get-env BUILD_CFLAGS {-g}]
-
- # Copy all CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
+########################################################################
+# Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and
+# CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS.
+# This is derived from the legacy build but is still practical.
+proc sqlite-munge-cflags {} {
+ # Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
# -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
# from the legacy build and was missing the 3.48.0 release (the
# initial Autosetup port).
@@ -547,6 +628,30 @@ proc sqlite-setup-default-cflags {} {
define BUILD_CFLAGS $tmp
}
+#########################################################################
+# Set up the default CFLAGS and BUILD_CFLAGS values.
+proc sqlite-setup-default-cflags {} {
+ ########################################################################
+ # We differentiate between two C compilers: the one used for binaries
+ # which are to run on the build system (in autosetup it's called
+ # CC_FOR_BUILD and in Makefile.in it's $(B.cc)) and the one used for
+ # compiling binaries for the target system (CC a.k.a. $(T.cc)).
+ # Normally they're the same, but they will differ when
+ # cross-compiling.
+ #
+ # When cross-compiling we default to not using the -g flag, based on a
+ # /chat discussion prompted by
+ # https://sqlite.org/forum/forumpost/9a67df63eda9925c
+ set defaultCFlags {-O2}
+ if {!$::sqliteConfig(is-cross-compiling)} {
+ lappend defaultCFlags -g
+ }
+ define CFLAGS [proj-get-env CFLAGS $defaultCFlags]
+ # BUILD_CFLAGS is the CFLAGS for CC_FOR_BUILD.
+ define BUILD_CFLAGS [proj-get-env BUILD_CFLAGS {-g}]
+ sqlite-munge-cflags
+}
+
########################################################################
# Handle various SQLITE_ENABLE_... feature flags.
proc sqlite-handle-common-feature-flags {} {
@@ -798,6 +903,35 @@ proc sqlite-handle-emsdk {} {
}
}
+########################################################################
+# Internal helper for [sqlite-check-line-editing]. Returns a list of
+# potential locations under which readline.h might be found.
+proc sqlite-get-readline-dir-list {} {
+ # Historical note: the dirs list, except for the inclusion of
+ # $prefix and some platform-specific dirs, originates from the
+ # legacy configure script
+ set dirs [list [get-define prefix]]
+ switch -glob -- [get-define host] {
+ *-linux-android {
+ # Possibly termux
+ lappend dirs /data/data/com.termux/files/usr
+ }
+ *-mingw32 {
+ lappend dirs /mingw32 /mingw
+ }
+ *-mingw64 {
+ lappend dirs /mingw64 /mingw
+ }
+ }
+ lappend dirs /usr /usr/local /usr/local/readline /usr/contrib
+ set rv {}
+ foreach d $dirs {
+ if {[file isdir $d]} {lappend rv $d}
+ }
+ #msg-debug "sqlite-get-readline-dir-list dirs=$rv"
+ return $rv
+}
+
########################################################################
# sqlite-check-line-editing jumps through proverbial hoops to try to
# find a working line-editing library, setting:
@@ -934,7 +1068,7 @@ proc sqlite-check-line-editing {} {
# ^^^ this check is derived from the legacy configure script.
proj-warn "Skipping check for readline.h because we're cross-compiling."
} else {
- set dirs "[get-define prefix] /usr /usr/local /usr/local/readline /usr/contrib /mingw"
+ set dirs [sqlite-get-readline-dir-list]
set subdirs "include/$editLibName"
if {"editline" eq $editLibName} {
lappend subdirs include/readline
@@ -942,16 +1076,14 @@ proc sqlite-check-line-editing {} {
# and uses libreadline's header.
}
lappend subdirs include
- # ^^^ The dirs and subdirs lists are, except for the inclusion
- # of $prefix and editline, from the legacy configure script
set rlInc [proj-search-for-header-dir readline.h \
-dirs $dirs -subdirs $subdirs]
if {"" ne $rlInc} {
if {[string match */readline $rlInc]} {
- set rlInc [file dirname $rlInc]; # shell #include's
+ set rlInc [file dirname $rlInc]; # CLI shell: #include
} elseif {[string match */editline $rlInc]} {
set editLibDef HAVE_EDITLINE
- set rlInc [file dirname $rlInc]; # shell #include's
+ set rlInc [file dirname $rlInc]; # CLI shell: #include
}
set rlInc "-I${rlInc}"
}
@@ -970,7 +1102,7 @@ proc sqlite-check-line-editing {} {
set rlLib ""
if {"" ne $rlInc} {
set rlLib [opt-val with-readline-ldflags]
- if {"" eq $rlLib || "auto" eq $rlLib} {
+ if {$rlLib eq "auto" || $rlLib eq ""} {
set rlLib ""
set libTerm ""
if {[proj-check-function-in-lib tgetent "$editLibName ncurses curses termcap"]} {
@@ -995,7 +1127,7 @@ proc sqlite-check-line-editing {} {
# linking to the GPL'd libreadline. Presumably that distinction is
# significant for those using --editline.
proj-indented-notice {
- NOTE: the local libedit but uses so we
+ NOTE: the local libedit uses so we
will compile with -DHAVE_READLINE=1 but will link with
libedit.
}
@@ -1148,7 +1280,7 @@ proc sqlite-handle-icu {} {
# Handles the --enable-load-extension flag. Returns 1 if the support
# is enabled, else 0. If support for that feature is not found, a
# fatal error is triggered if --enable-load-extension is explicitly
-# provided, else a loud warning is instead emited. If
+# provided, else a loud warning is instead emitted. If
# --disable-load-extension is used, no check is performed.
#
# Makes the following environment changes:
@@ -1222,11 +1354,11 @@ proc sqlite-handle-math {} {
# libtool applied only on Mac platforms.
#
# Based on https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7.
-proc sqlite-check-mac-cversion {} {
+proc sqlite-handle-mac-cversion {} {
define LDFLAGS_MAC_CVERSION ""
set rc 0
if {[proj-looks-like-mac]} {
- cc-with {} {
+ cc-with {-link 1} {
# These version numbers are historical libtool-defined values, not
# library-defined ones
if {[cc-check-flags "-Wl,-current_version,9.6.0"]
@@ -1244,27 +1376,80 @@ proc sqlite-check-mac-cversion {} {
}
########################################################################
-# Define LDFLAGS_OUT_IMPLIB to either an empty string or to a
+# Handles the --dll-basename configure flag. [define]'s
+# SQLITE_DLL_BASENAME to the DLL's preferred base name (minus
+# extension). If --dll-basename is not provided (or programmatically
+# set - see [sqlite-handle-env-quirks]) then this is always
+# "libsqlite3", otherwise it may use a different value based on the
+# value of [get-define host].
+proc sqlite-handle-dll-basename {} {
+ if {[proj-opt-was-provided dll-basename]} {
+ set dn [join [opt-val dll-basename] ""]
+ if {$dn in {none default}} { set dn libsqlite3 }
+ } else {
+ set dn libsqlite3
+ }
+ if {$dn in {auto ""}} {
+ switch -glob -- [get-define host] {
+ *-*-cygwin { set dn cygsqlite3-0 }
+ *-*-ming* { set dn libsqlite3-0 }
+ *-*-msys { set dn msys-sqlite3-0 }
+ default { set dn libsqlite3 }
+ }
+ }
+ define SQLITE_DLL_BASENAME $dn
+}
+
+########################################################################
+# [define]s LDFLAGS_OUT_IMPLIB to either an empty string or to a
# -Wl,... flag for the platform-specific --out-implib flag, which is
# used for building an "import library .dll.a" file on some platforms
-# (e.g. mingw). Returns 1 if supported, else 0.
+# (e.g. msys2, mingw). Returns 1 if supported, else 0.
#
-# If the configure flag --out-implib is not used then this is a no-op.
-# The feature is specifically opt-in because on some platforms the
-# feature test will pass but using that flag will fail at link-time
-# (e.g. OpenBSD).
+# The name of the import library is [define]d in SQLITE_OUT_IMPLIB.
+#
+# If the configure flag --out-implib is not used (or programmatically
+# set) then this is a no-op (but see [sqliet-handle-env-quirks]). If
+# that flag is used but the capability is not available, a fatal error
+# is triggered.
+#
+# This feature is specifically opt-in because it's supported on far
+# more platforms than actually need it and enabling it causes creation
+# of libsqlite3.so.a files which are unnecessary in most environments.
#
# Added in response to: https://sqlite.org/forum/forumpost/0c7fc097b2
-proc sqlite-check-out-implib {} {
+#
+# Platform notes:
+#
+# - cygwin sqlite packages historically install no .dll.a file.
+#
+# - msys2 and mingw sqlite packages historically install
+# /usr/lib/libsqlite3.dll.a despite the DLL being in
+# /usr/bin.
+proc sqlite-handle-out-implib {} {
define LDFLAGS_OUT_IMPLIB ""
+ define SQLITE_OUT_IMPLIB ""
set rc 0
if {[proj-opt-was-provided out-implib]} {
- cc-with {} {
- set dll "libsqlite3[get-define TARGET_DLLEXT]"
- set flags "-Wl,--out-implib,${dll}.a"
- if {[cc-check-flags $flags]} {
- define LDFLAGS_OUT_IMPLIB $flags
- set rc 1
+ set olBaseName [join [opt-val out-implib] ""]
+ if {$olBaseName in {auto ""}} {
+ set olBaseName "libsqlite3" ;# [get-define SQLITE_DLL_BASENAME]
+ # Based on discussions with mingw/msys users, the import lib
+ # should always be called libsqlite3.dll.a even on platforms
+ # which rename libsqlite3.dll to something else.
+ }
+ if {$olBaseName ne "none"} {
+ cc-with {-link 1} {
+ set dll "${olBaseName}[get-define TARGET_DLLEXT]"
+ set flags [proj-cc-check-Wl-flag --out-implib ${dll}.a]
+ if {"" ne $flags} {
+ define LDFLAGS_OUT_IMPLIB $flags
+ define SQLITE_OUT_IMPLIB ${dll}.a
+ set rc 1
+ }
+ }
+ if {!$rc} {
+ user-error "--out-implib is not supported on this platform"
}
}
}
@@ -1272,14 +1457,94 @@ proc sqlite-check-out-implib {} {
}
########################################################################
-# Performs late-stage config steps common to both the canonical and
-# autoconf bundle builds.
-proc sqlite-config-finalize {} {
- sqlite-check-mac-cversion
- sqlite-check-out-implib
- sqlite-process-dot-in-files
- sqlite-post-config-validation
- sqlite-dump-defines
+# If the given platform identifier (defaulting to [get-define host])
+# appears to be one of the Unix-on-Windows environments, returns a
+# brief symbolic name for that environment, else returns an empty
+# string.
+#
+# It does not distinguish between msys and msys2, returning msys for
+# both. The build does not, as of this writing, specifically support
+# msys v1.
+proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
+ if {"" eq $envTuple} {
+ set envTuple [get-define host]
+ }
+ set name ""
+ switch -glob -- $envTuple {
+ *-*-cygwin { set name cygwin }
+ *-*-ming* { set name mingw }
+ *-*-msys { set name msys }
+ }
+ return $name;
+}
+
+########################################################################
+# Performs various tweaks to the build which are only relevant on
+# certain platforms, e.g. Mac and "Unix on Windows" platforms (msys2,
+# cygwin, ...).
+#
+# 1) DLL installation:
+#
+# [define]s SQLITE_DLL_INSTALL_RULES to a symbolic name suffix for a
+# set of "make install" rules to use for installation of the DLL
+# deliverable. The makefile is tasked with with providing rules named
+# install-dll-NAME which runs the installation for that set, as well
+# as providing a rule named install-dll which resolves to
+# install-dll-NAME (perhaps indirectly, depending on whether the DLL
+# is (de)activated).
+#
+# The default value is "unix-generic".
+#
+# 2) --out-implib:
+#
+# On platforms where an "import library" is conventionally used but
+# --out-implib was not explicitly used, automatically add that flag.
+# This conventionally applies to the "Unix on Windows" environments
+# like msys and cygwin.
+#
+# 3) --dll-basename:
+#
+# On the same platforms addressed by --out-implib, if --dll-basename
+# is not specified, --dll-basename=auto is implied.
+proc sqlite-handle-env-quirks {} {
+ set instName unix-generic; # name of installation rules set
+ set autoDll 0; # true if --out-implib/--dll-basename should be implied
+ set host [get-define host]
+ switch -glob -- $host {
+ *apple* -
+ *darwin* { set instName darwin }
+ default {
+ set x [sqlite-env-is-unix-on-windows $host]
+ if {"" ne $x} {
+ set instName $x
+ set autoDll 1
+ }
+ }
+ }
+ define SQLITE_DLL_INSTALL_RULES $instName
+ if {$autoDll} {
+ if {![proj-opt-was-provided out-implib]} {
+ # Imply --out-implib=auto
+ proj-indented-notice [subst -nocommands -nobackslashes {
+ NOTICE: auto-enabling --out-implib for environment [$host].
+ Use --out-implib=none to disable this special case
+ or --out-implib=auto to squelch this notice.
+ }]
+ proj-opt-set out-implib auto
+ }
+ if {![proj-opt-was-provided dll-basename]} {
+ # Imply --dll-basename=auto
+ proj-indented-notice [subst -nocommands -nobackslashes {
+ NOTICE: auto-enabling --dll-basename for environment [$host].
+ Use --dll-basename=default to disable this special case
+ or --dll-basename=auto to squelch this notice.
+ }]
+ proj-opt-set dll-basename auto
+ }
+ }
+ sqlite-handle-dll-basename
+ sqlite-handle-out-implib
+ sqlite-handle-mac-cversion
}
########################################################################
@@ -1397,7 +1662,7 @@ proc sqlite-handle-wasi-sdk {} {
proj-opt-set $opt ""
}
}
- # Remember that we now have a discrepancy beteween
+ # Remember that we now have a discrepancy between
# $::sqliteConfig(is-cross-compiling) and [proj-is-cross-compiling].
set ::sqliteConfig(is-cross-compiling) 1
@@ -1533,9 +1798,9 @@ proc sqlite-check-tcl {} {
proj-fatal "No tclConfig.sh found under ${with_tcl}"
}
} else {
- # If we have not yet found a tclConfig.sh file, look in
- # $libdir which is set automatically by autosetup or by the
- # --prefix command-line option. See
+ # If we have not yet found a tclConfig.sh file, look in $libdir
+ # which is set automatically by autosetup or via the --prefix
+ # command-line option. See
# https://sqlite.org/forum/forumpost/e04e693439a22457
set libdir [get-define libdir]
if {[file readable "${libdir}/tclConfig.sh"]} {
@@ -1721,7 +1986,7 @@ proc sqlite-determine-codegen-tcl {} {
}
define BTCLSH "\$(TCLSH_CMD)"
}
- }; # CC swap-out
+ }; # /define-push $flagsToRestore
return $cgtcl
}; # sqlite-determine-codegen-tcl
@@ -1732,6 +1997,26 @@ proc sqlite-handle-tcl {} {
msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
}
+########################################################################
+# Handle the --enable/disable-rpath flag.
+proc sqlite-handle-rpath {} {
+ proj-check-rpath
+ # autosetup/cc-shared.tcl sets the rpath flag definition in
+ # [get-define SH_LINKRPATH], but it does so on a per-platform basis
+ # rather than as a compiler check. Though we should do a proper
+ # compiler check (as proj-check-rpath does), we may want to consider
+ # adopting its approach of clearing the rpath flags for environments
+ # for which sqlite-env-is-unix-on-windows returns a non-empty
+ # string.
+
+# if {[proj-opt-truthy rpath]} {
+# proj-check-rpath
+# } else {
+# msg-result "Disabling use of rpath."
+# define LDFLAGS_RPATH ""
+# }
+}
+
########################################################################
# If the --dump-defines configure flag is provided then emit a list of
# all [define] values to config.defines.txt, else do nothing.
diff --git a/contrib/sqlitecon.tcl b/contrib/sqlitecon.tcl
index b5dbcafc2a..78463a1ffa 100644
--- a/contrib/sqlitecon.tcl
+++ b/contrib/sqlitecon.tcl
@@ -567,7 +567,7 @@ proc sqlitecon::Cut w {
}
}
-# Do a paste opeation.
+# Do a paste operation.
#
proc sqlitecon::Paste w {
if {[sqlitecon::canCut $w]==1} {
diff --git a/doc/jsonb.md b/doc/jsonb.md
index 5beed1631d..ce36f3ead1 100644
--- a/doc/jsonb.md
+++ b/doc/jsonb.md
@@ -281,7 +281,7 @@ happen if and when they are actually needed.
A valid JSONB BLOB consists of a single JSON element. The element must
exactly fill the BLOB. This one element is often a JSON object or array
and those usually contain additional elements as its payload, but the
-element can be a primite value such a string, number, boolean, or null.
+element can be a primitive value such a string, number, boolean, or null.
When the built-in JSON functions are attempting to determine if a BLOB
argument is a JSONB or just a random BLOB, they look at the header of
diff --git a/doc/lemon.html b/doc/lemon.html
index 4147d9b31e..24bccce082 100644
--- a/doc/lemon.html
+++ b/doc/lemon.html
@@ -881,7 +881,7 @@ is allowed between the "%" and the directive name.
Grammar text in between "%ifdef MACRO" and the next nested
"%endif" is
ignored unless the "-DMACRO" command-line option is used. Grammar text
-betwen "%ifndef MACRO" and the next nested "%endif" is
+between "%ifndef MACRO" and the next nested "%endif" is
included except when the "-DMACRO" command-line option is used.
The text in between "%ifCONDITIONAL" and its
diff --git a/doc/pager-invariants.txt b/doc/pager-invariants.txt
index 44444dad54..0fea0a698d 100644
--- a/doc/pager-invariants.txt
+++ b/doc/pager-invariants.txt
@@ -45,7 +45,7 @@
*** Definition: Two databases (or the same database at two points it time)
are said to be "logically equivalent" if they give the same answer to
all queries. Note in particular the content of freelist leaf
- pages can be changed arbitarily without effecting the logical equivalence
+ pages can be changed arbitrarily without effecting the logical equivalence
of the database.
(7) At any time, if any subset, including the empty set and the total set,
diff --git a/doc/vfs-shm.txt b/doc/vfs-shm.txt
index c1f125a120..a483e9b159 100644
--- a/doc/vfs-shm.txt
+++ b/doc/vfs-shm.txt
@@ -1,6 +1,6 @@
The 5 states of an historical rollback lock as implemented by the
xLock, xUnlock, and xCheckReservedLock methods of the sqlite3_io_methods
-objec are:
+object are:
UNLOCKED
SHARED
@@ -58,7 +58,7 @@ The meanings of the various wal-index locking states is as follows:
A particular lock manager implementation may coalesce one or more of
the wal-index locking states, though with a reduction in concurrency.
-For example, an implemention might implement only exclusive locking,
+For example, an implementation might implement only exclusive locking,
in which case all states would be equivalent to CHECKPOINT, meaning that
only one reader or one writer or one checkpointer could be active at a
time. Or, an implementation might combine READ and READ_FULL into
diff --git a/doc/wal-lock.md b/doc/wal-lock.md
index d74bb88b63..8df7cc836c 100644
--- a/doc/wal-lock.md
+++ b/doc/wal-lock.md
@@ -12,7 +12,7 @@ facilitates transfer of OS priority between processes when a high priority
process is blocked by a lower priority one.
Only read/write clients use blocking locks. Clients that have read-only access
-to the \*-shm file nevery use blocking locks.
+to the \*-shm file never use blocking locks.
Threads or processes that access a single database at a time never deadlock as
a result of blocking database locks. But it is of course possible for threads
diff --git a/ext/expert/sqlite3expert.c b/ext/expert/sqlite3expert.c
index 93693cfae9..ddb36714f7 100644
--- a/ext/expert/sqlite3expert.c
+++ b/ext/expert/sqlite3expert.c
@@ -2052,7 +2052,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
}
- /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
+ /* If an error has occurred, free the new object and return NULL. Otherwise,
** return the new sqlite3expert handle. */
if( rc!=SQLITE_OK ){
sqlite3_expert_destroy(pNew);
diff --git a/ext/fts3/README.syntax b/ext/fts3/README.syntax
index 01bc80c5fb..0cab8fa048 100644
--- a/ext/fts3/README.syntax
+++ b/ext/fts3/README.syntax
@@ -146,7 +146,7 @@
MATCH '(hello world) OR (simple example)'
matches documents that contain both "hello" and "world", and documents
- that contain both "simple" and "example". It is not possible to forumlate
+ that contain both "simple" and "example". It is not possible to formulate
such a query using the standard syntax.
2) Instead of separating tokens and phrases by whitespace, an AND operator
@@ -174,7 +174,7 @@
4) Unlike in the standard syntax, where the OR operator has a higher
precedence than the implicit AND operator, when using the enhanced
- syntax implicit and explict AND operators have a higher precedence
+ syntax implicit and explicit AND operators have a higher precedence
than OR operators. Using the enhanced syntax, the following two
queries are equivalent:
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index d5db2a3dd1..3771aa8ba2 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -87,7 +87,7 @@
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
-** in the same logical place as the position element, and act as sentinals
+** in the same logical place as the position element, and act as sentinels
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
** The positions numbers are not stored literally but rather as two more
** than the difference from the prior position, or the just the position plus
@@ -2639,7 +2639,7 @@ static int fts3DoclistOrMerge(
** sizes of the two inputs, plus enough space for exactly one of the input
** docids to grow.
**
- ** A symetric argument may be made if the doclists are in descending
+ ** A symmetric argument may be made if the doclists are in descending
** order.
*/
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
@@ -4737,7 +4737,7 @@ static int incrPhraseTokenNext(
**
** * does not contain any deferred tokens.
**
-** Advance it to the next matching documnent in the database and populate
+** Advance it to the next matching document in the database and populate
** the Fts3Doclist.pList and nList fields.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
@@ -5744,7 +5744,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
}
/*
-** Restart interation for expression pExpr so that the next call to
+** Restart iteration for expression pExpr so that the next call to
** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index 77e6737af4..06f3c6efec 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -306,7 +306,7 @@ struct Fts3Table {
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
- /* True to disable the incremental doclist optimization. This is controled
+ /* True to disable the incremental doclist optimization. This is controlled
** by special insert command 'test-no-incr-doclist'. */
int bNoIncrDoclist;
@@ -358,7 +358,7 @@ struct Fts3Cursor {
/*
** The Fts3Cursor.eSearch member is always set to one of the following.
-** Actualy, Fts3Cursor.eSearch can be greater than or equal to
+** Actually, Fts3Cursor.eSearch can be greater than or equal to
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
** of the column to be searched. For example, in
**
diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c
index ce4282dea5..ca857835e2 100644
--- a/ext/fts3/fts3_expr.c
+++ b/ext/fts3/fts3_expr.c
@@ -657,7 +657,7 @@ static int fts3ExprParse(
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
- ** binary operator (AND, OR, NOT or NEAR) is encounted when
+ ** binary operator (AND, OR, NOT or NEAR) is encountered when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
diff --git a/ext/fts3/fts3_hash.c b/ext/fts3/fts3_hash.c
index 63e55b3dc9..1918be4cb7 100644
--- a/ext/fts3/fts3_hash.c
+++ b/ext/fts3/fts3_hash.c
@@ -187,7 +187,7 @@ static void fts3HashInsertElement(
}
-/* Resize the hash table so that it cantains "new_size" buckets.
+/* Resize the hash table so that it contains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
**
diff --git a/ext/fts3/fts3_porter.c b/ext/fts3/fts3_porter.c
index fbe7913020..35e81b74af 100644
--- a/ext/fts3/fts3_porter.c
+++ b/ext/fts3/fts3_porter.c
@@ -256,7 +256,7 @@ static int star_oh(const char *z){
/*
** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
+** of the word that precedes the zFrom ending, then change the
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order. zTo
diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c
index 8a6ab8ea62..9ec7df3802 100644
--- a/ext/fts3/fts3_snippet.c
+++ b/ext/fts3/fts3_snippet.c
@@ -611,7 +611,7 @@ static int fts3StringAppend(
}
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
- ** to grow the buffer until so that it is big enough to accomadate the
+ ** to grow the buffer until so that it is big enough to accommodate the
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index 5a449dec1e..55a3f0a82f 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -3956,7 +3956,7 @@ static int fts3IncrmergePush(
**
** It is assumed that the buffer associated with pNode is already large
** enough to accommodate the new entry. The buffer associated with pPrev
-** is extended by this function if requrired.
+** is extended by this function if required.
**
** If an error (i.e. OOM condition) occurs, an SQLite error code is
** returned. Otherwise, SQLITE_OK.
@@ -5619,7 +5619,7 @@ int sqlite3Fts3DeferToken(
/*
** SQLite value pRowid contains the rowid of a row that may or may not be
** present in the FTS3 table. If it is, delete it and adjust the contents
-** of subsiduary data structures accordingly.
+** of subsidiary data structures accordingly.
*/
static int fts3DeleteByRowid(
Fts3Table *p,
diff --git a/ext/fts3/unicode/mkunicode.tcl b/ext/fts3/unicode/mkunicode.tcl
index 1306629da8..3bf866ef74 100644
--- a/ext/fts3/unicode/mkunicode.tcl
+++ b/ext/fts3/unicode/mkunicode.tcl
@@ -893,7 +893,7 @@ proc print_test_main {} {
puts "\}"
}
-# Proces the command line arguments. Exit early if they are not to
+# Process the command line arguments. Exit early if they are not to
# our liking.
#
proc usage {} {
diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c
index ad578156da..95b33ea318 100644
--- a/ext/fts5/fts5_aux.c
+++ b/ext/fts5/fts5_aux.c
@@ -667,7 +667,7 @@ static int fts5Bm25GetData(
** under consideration.
**
** The problem with this is that if (N < 2*nHit), the IDF is
- ** negative. Which is undesirable. So the mimimum allowable IDF is
+ ** negative. Which is undesirable. So the minimum allowable IDF is
** (1e-6) - roughly the same as a term that appears in just over
** half of set of 5,000,000 documents. */
double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c
index 891ef0203a..afcd83b6ba 100644
--- a/ext/fts5/fts5_buffer.c
+++ b/ext/fts5/fts5_buffer.c
@@ -308,7 +308,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
** * The 52 upper and lower case ASCII characters, and
** * The 10 integer ASCII characters.
** * The underscore character "_" (0x5F).
-** * The unicode "subsitute" character (0x1A).
+** * The unicode "substitute" character (0x1A).
*/
int sqlite3Fts5IsBareword(char t){
u8 aBareword[128] = {
diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c
index 877c3f79c5..dc2f7fb39c 100644
--- a/ext/fts5/fts5_expr.c
+++ b/ext/fts5/fts5_expr.c
@@ -3252,7 +3252,7 @@ int sqlite3Fts5ExprInstToken(
}
/*
-** Clear the token mappings for all Fts5IndexIter objects mannaged by
+** Clear the token mappings for all Fts5IndexIter objects managed by
** the expression passed as the only argument.
*/
void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c
index 5e0959aa8e..a33dec9a92 100644
--- a/ext/fts5/fts5_hash.c
+++ b/ext/fts5/fts5_hash.c
@@ -20,7 +20,7 @@ typedef struct Fts5HashEntry Fts5HashEntry;
/*
** This file contains the implementation of an in-memory hash table used
-** to accumuluate "term -> doclist" content before it is flused to a level-0
+** to accumulate "term -> doclist" content before it is flushed to a level-0
** segment.
*/
@@ -77,7 +77,7 @@ struct Fts5HashEntry {
};
/*
-** Eqivalent to:
+** Equivalent to:
**
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
*/
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 3ac5008502..70a4752e26 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -6451,7 +6451,7 @@ static void fts5TokendataIterAppendMap(
/*
** Sort the contents of the pT->aMap[] array.
**
-** The sorting algorithm requries a malloc(). If this fails, an error code
+** The sorting algorithm requires a malloc(). If this fails, an error code
** is left in Fts5Index.rc before returning.
*/
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
@@ -8667,7 +8667,7 @@ static void fts5DecodeRowid(
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
- int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
+ int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
if( iSegid==0 ){
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index a7a2ab3aa8..fee42b0df8 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -3802,8 +3802,8 @@ static int fts5Init(sqlite3 *db){
** its entry point to enable the matchinfo() demo. */
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
if( rc==SQLITE_OK ){
- extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
- rc = sqlite3Fts5TestRegisterMatchinfo(db);
+ extern int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api*);
+ rc = sqlite3Fts5TestRegisterMatchinfoAPI(&pGlobal->api);
}
#endif
diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c
index 6f2d6e7ea2..f56c890cd7 100644
--- a/ext/fts5/fts5_test_mi.c
+++ b/ext/fts5/fts5_test_mi.c
@@ -393,17 +393,13 @@ static void fts5MatchinfoFunc(
}
}
-int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
- int rc; /* Return code */
- fts5_api *pApi; /* FTS5 API functions */
+/*
+** Register "matchinfo" with global API object pApi.
+*/
+int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api *pApi){
+ int rc;
- /* Extract the FTS5 API pointer from the database handle. The
- ** fts5_api_from_db() function above is copied verbatim from the
- ** FTS5 documentation. Refer there for details. */
- rc = fts5_api_from_db(db, &pApi);
- if( rc!=SQLITE_OK ) return rc;
-
- /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
+ /* If fts5_api_from_db() returned NULL, then either FTS5 is not registered
** with this database handle, or an error (OOM perhaps?) has occurred.
**
** Also check that the fts5_api object is version 2 or newer.
@@ -418,4 +414,20 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
return rc;
}
+/*
+** Register "matchinfo" with database handle db.
+*/
+int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
+ int rc; /* Return code */
+ fts5_api *pApi; /* FTS5 API functions */
+
+ /* Extract the FTS5 API pointer from the database handle. The
+ ** fts5_api_from_db() function above is copied verbatim from the
+ ** FTS5 documentation. Refer there for details. */
+ rc = fts5_api_from_db(db, &pApi);
+ if( rc!=SQLITE_OK ) return rc;
+
+ return sqlite3Fts5TestRegisterMatchinfoAPI(pApi);
+}
+
#endif /* SQLITE_ENABLE_FTS5 */
diff --git a/ext/fts5/test/fts5matchinfo.test b/ext/fts5/test/fts5matchinfo.test
index 93361a5fe7..f81b076c18 100644
--- a/ext/fts5/test/fts5matchinfo.test
+++ b/ext/fts5/test/fts5matchinfo.test
@@ -520,4 +520,26 @@ do_execsql_test 15.3 {
{columnsize {1 1} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 16.0 {
+ CREATE TABLE t1(x);
+ BEGIN EXCLUSIVE;
+}
+
+sqlite3 db2 test.db
+do_test 16.1 {
+ catchsql { SELECT * FROM t1 } db2
+} {1 {database is locked}}
+
+do_execsql_test 16.2 {
+ ROLLBACK;
+}
+
+do_test 16.3 {
+ catchsql { SELECT * FROM t1 } db2
+} {0 {}}
+
finish_test
+
diff --git a/ext/fts5/test/fts5simple3.test b/ext/fts5/test/fts5simple3.test
index 680448081d..bc3ebfc7ca 100644
--- a/ext/fts5/test/fts5simple3.test
+++ b/ext/fts5/test/fts5simple3.test
@@ -81,7 +81,7 @@ do_execsql_test 3.0 {
}
#-------------------------------------------------------------------------
-# Test that a crash occuring when the second or subsequent tokens in a
+# Test that a crash occurring when the second or subsequent tokens in a
# phrase matched zero rows has been fixed.
#
do_execsql_test 4.0 {
diff --git a/ext/jni/GNUmakefile b/ext/jni/GNUmakefile
index 26a38dad9a..668b6e0841 100644
--- a/ext/jni/GNUmakefile
+++ b/ext/jni/GNUmakefile
@@ -79,7 +79,7 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
$(MAKE) -C $(dir.top) version-info
# Be explicit about which Java files to compile so that we can work on
-# in-progress files without requiring them to be in a compilable statae.
+# in-progress files without requiring them to be in a compilable state.
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
Experimental.java \
NotNull.java \
@@ -451,7 +451,7 @@ distclean: clean
-rm -fr $(dir.bld.c) $(dir.doc)
########################################################################
-# disttribution bundle rules...
+# distribution bundle rules...
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
dist-name-prefix := sqlite-jni
diff --git a/ext/jni/README.md b/ext/jni/README.md
index fc7b5f7611..5ad79fce9e 100644
--- a/ext/jni/README.md
+++ b/ext/jni/README.md
@@ -169,7 +169,7 @@ deliberately return an error code, instead of segfaulting, when passed
a `null`.
Client-defined callbacks _must never throw exceptions_ unless _very
-explitly documented_ as being throw-safe. Exceptions are generally
+explicitly documented_ as being throw-safe. Exceptions are generally
reserved for higher-level bindings which are constructed to
specifically deal with them and ensure that they do not leak C-level
resources. In some cases, callback handlers are permitted to throw, in
diff --git a/ext/jni/src/c/sqlite3-jni.c b/ext/jni/src/c/sqlite3-jni.c
index 5deff19ef1..6bd6daaec8 100644
--- a/ext/jni/src/c/sqlite3-jni.c
+++ b/ext/jni/src/c/sqlite3-jni.c
@@ -948,7 +948,7 @@ static JNIEnv * s3jni_env(void){
}
/*
-** Fetches the S3JniGlobal.envCache row for the given env, allocing a
+** Fetches the S3JniGlobal.envCache row for the given env, allocating a
** row if needed. When a row is allocated, its state is initialized
** insofar as possible. Calls (*env)->FatalError() if allocation of an
** entry fails. That's hypothetically possible but "shouldn't happen."
@@ -1603,7 +1603,7 @@ static void * NativePointerHolder__get(JNIEnv * env, jobject jNph,
** 2023-11-09: testing has not revealed any measurable performance
** difference between the approach of passing type T to C compared to
** passing pointer-to-T to C, and adding support for the latter
-** everywhere requires sigificantly more code. As of this writing, the
+** everywhere requires significantly more code. As of this writing, the
** older/simpler approach is being applied except for (A) where the
** newer approach has already been applied and (B) hot-spot APIs where
** a difference of microseconds (i.e. below our testing measurement
@@ -3290,7 +3290,7 @@ static void s3jni_rollback_hook_impl(void *pP){
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,
jlong jpDb, jobject jHook){
S3JniDb * ps;
- jobject pOld = 0; /* previous hoook */
+ jobject pOld = 0; /* previous hook */
S3JniHook * pHook; /* ps->hooks.commit|rollback */
S3JniDb_mutex_enter;
@@ -5696,7 +5696,7 @@ JniDeclFtsApi(jint,xCreateFunction)(JniArgsEnvObj, jstring jName,
typedef struct S3JniFts5AuxData S3JniFts5AuxData;
/*
-** TODO: this middle-man struct is no longer necessary. Conider
+** TODO: this middle-man struct is no longer necessary. Consider
** removing it and passing around jObj itself instead.
*/
struct S3JniFts5AuxData {
diff --git a/ext/jni/src/org/sqlite/jni/capi/CApi.java b/ext/jni/src/org/sqlite/jni/capi/CApi.java
index 3387282378..13367a6102 100644
--- a/ext/jni/src/org/sqlite/jni/capi/CApi.java
+++ b/ext/jni/src/org/sqlite/jni/capi/CApi.java
@@ -264,7 +264,7 @@ public final class CApi {
}
/**
- Convenience overload which is equivalant to passing its arguments
+ Convenience overload which is equivalent to passing its arguments
to sqlite3_bind_nio_buffer() with the values 0 and -1 for the
final two arguments.
*/
@@ -312,7 +312,7 @@ public final class CApi {
The byte range of the buffer may be restricted by providing a
start index and a number of bytes. beginPos may not be negative.
- Negative howMany is interpretated as the remainder of the buffer
+ Negative howMany is interpreted as the remainder of the buffer
past the given start position, up to the buffer's limit() (as
opposed its capacity()).
@@ -1076,7 +1076,7 @@ public final class CApi {
/**
Works like in the C API with the exception that it only supports
- the following subset of configution flags:
+ the following subset of configuration flags:
SQLITE_CONFIG_SINGLETHREAD
SQLITE_CONFIG_MULTITHREAD
diff --git a/ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java b/ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java
index 7df748e8d8..ffd7761190 100644
--- a/ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java
+++ b/ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java
@@ -18,7 +18,7 @@ package org.sqlite.jni.capi;
classes which have a call() method implementing some specific
callback interface on behalf of the C library.
-
Unless very explicitely documented otherwise, callbacks must
+
Unless very explicitly documented otherwise, callbacks must
never throw. Any which do throw but should not might trigger debug
output regarding the error, but the exception will not be
propagated. For callback interfaces which support returning error
diff --git a/ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java b/ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java
index 9f6dd478ce..af242fb3c1 100644
--- a/ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java
+++ b/ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java
@@ -20,7 +20,7 @@ public interface PrepareMultiCallback extends CallbackProxy {
/**
Gets passed a sqlite3_stmt which it may handle in arbitrary ways,
- transfering ownership of it to this function.
+ transferring ownership of it to this function.
sqlite3_prepare_multi() will _not_ finalize st - it is up
to the call() implementation how st is handled.
diff --git a/ext/jni/src/org/sqlite/jni/capi/SQLTester.java b/ext/jni/src/org/sqlite/jni/capi/SQLTester.java
index c68785e2c3..634f844c24 100644
--- a/ext/jni/src/org/sqlite/jni/capi/SQLTester.java
+++ b/ext/jni/src/org/sqlite/jni/capi/SQLTester.java
@@ -264,7 +264,7 @@ public class SQLTester {
threw = true;
outln("🔥EXCEPTION: ",e.getClass().getSimpleName(),": ",e.getMessage());
++nAbortedScript;
- if( keepGoing ) outln("Continuing anyway becaure of the keep-going option.");
+ if( keepGoing ) outln("Continuing anyway because of the keep-going option.");
else if( e.isFatal() ) throw e;
}finally{
final long timeEnd = System.currentTimeMillis();
diff --git a/ext/jni/src/org/sqlite/jni/test-script-interpreter.md b/ext/jni/src/org/sqlite/jni/test-script-interpreter.md
index 939f77e1be..c10122349e 100644
--- a/ext/jni/src/org/sqlite/jni/test-script-interpreter.md
+++ b/ext/jni/src/org/sqlite/jni/test-script-interpreter.md
@@ -101,7 +101,7 @@ interpreter is in a "verbose" mode, the interpreter might choose to emit
an informational message along the lines of "test script NAME abandoned
due to unsupported command: --whatever".
-The initial implemention will only recognize a few commands. Other
+The initial implementation will only recognize a few commands. Other
commands may be added later. The following is the initial set of
commands:
diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
index de131e8542..2855d4c25f 100644
--- a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
+++ b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java
@@ -661,7 +661,7 @@ public final class Sqlite implements AutoCloseable {
}
/**
- Equivallent to prepareMulti(X,prepFlags,visitor), where X is
+ Equivalent to prepareMulti(X,prepFlags,visitor), where X is
sql.getBytes(StandardCharsets.UTF_8).
*/
public void prepareMulti(String sql, int prepFlags, PrepareMulti visitor){
diff --git a/ext/lsm1/lsmInt.h b/ext/lsm1/lsmInt.h
index 5060366d0d..4e3c5e59ce 100644
--- a/ext/lsm1/lsmInt.h
+++ b/ext/lsm1/lsmInt.h
@@ -570,7 +570,7 @@ struct FreelistEntry {
/*
** A snapshot of a database. A snapshot contains all the information required
** to read or write a database file on disk. See the description of struct
-** Database below for futher details.
+** Database below for further details.
*/
struct Snapshot {
Database *pDatabase; /* Database this snapshot belongs to */
diff --git a/ext/lsm1/lsm_ckpt.c b/ext/lsm1/lsm_ckpt.c
index 1c4f788ad6..dbfa1a61ff 100644
--- a/ext/lsm1/lsm_ckpt.c
+++ b/ext/lsm1/lsm_ckpt.c
@@ -169,7 +169,7 @@
** The argument to this macro must be of type u32. On a little-endian
** architecture, it returns the u32 value that results from interpreting
** the 4 bytes as a big-endian value. On a big-endian architecture, it
-** returns the value that would be produced by intepreting the 4 bytes
+** returns the value that would be produced by interpreting the 4 bytes
** of the input value as a little-endian integer.
*/
#define BYTESWAP32(x) ( \
diff --git a/ext/lsm1/lsm_file.c b/ext/lsm1/lsm_file.c
index fd78835bbb..9f4144618a 100644
--- a/ext/lsm1/lsm_file.c
+++ b/ext/lsm1/lsm_file.c
@@ -793,7 +793,7 @@ void lsmFsClose(FileSystem *pFS){
**
** This function returns a pointer to an object that can be linked into
** the list described above. The returned object now 'owns' the database
-** file descriptr, so that when the FileSystem object is destroyed, it
+** file descriptor, so that when the FileSystem object is destroyed, it
** will not be closed.
**
** This function may be called at most once in the life-time of a
@@ -2293,7 +2293,7 @@ int lsmFsMetaPageGet(
);
}
#ifndef NDEBUG
- /* pPg->aData causes an uninitialized access via a downstreadm write().
+ /* pPg->aData causes an uninitialized access via a downstream write().
After discussion on this list, this memory should not, for performance
reasons, be memset. However, tracking down "real" misuse is more
difficult with this "false" positive, so it is set when NDEBUG.
diff --git a/ext/lsm1/lsm_log.c b/ext/lsm1/lsm_log.c
index a66e40bccd..3dcef42f70 100644
--- a/ext/lsm1/lsm_log.c
+++ b/ext/lsm1/lsm_log.c
@@ -758,7 +758,7 @@ void lsmLogTell(
}
/*
-** Seek (rewind) back to the log file offset stored by an ealier call to
+** Seek (rewind) back to the log file offset stored by an earlier call to
** lsmLogTell() in *pMark.
*/
void lsmLogSeek(
diff --git a/ext/lsm1/lsm_sorted.c b/ext/lsm1/lsm_sorted.c
index 6e5243e850..a72c8cafb2 100644
--- a/ext/lsm1/lsm_sorted.c
+++ b/ext/lsm1/lsm_sorted.c
@@ -2652,7 +2652,7 @@ int lsmSortedLoadFreelist(
void **ppVal, /* OUT: Blob containing LSM free-list */
int *pnVal /* OUT: Size of *ppVal blob in bytes */
){
- MultiCursor *pCsr; /* Cursor used to retreive free-list */
+ MultiCursor *pCsr; /* Cursor used to retrieve free-list */
int rc = LSM_OK; /* Return Code */
assert( pDb->pWorker );
@@ -2764,7 +2764,7 @@ static int mcursorLocationOk(MultiCursor *pCsr, int bDeleteOk){
}
/* If the cursor points to a system key (free-list entry), and the
- ** CURSOR_IGNORE_SYSTEM flag is set, skip thie entry. */
+ ** CURSOR_IGNORE_SYSTEM flag is set, skip this entry. */
if( (pCsr->flags & CURSOR_IGNORE_SYSTEM) && rtTopic(eType)!=0 ){
return 0;
}
@@ -3586,7 +3586,7 @@ static int mergeWorkerBtreeWrite(
Hierarchy *p = &pMW->hier;
lsm_db *pDb = pMW->pDb; /* Database handle */
int rc = LSM_OK; /* Return Code */
- int iLevel; /* Level of b-tree hierachy to write to */
+ int iLevel; /* Level of b-tree hierarchy to write to */
int nData; /* Size of aData[] in bytes */
u8 *aData; /* Page data for level iLevel */
int iOff; /* Offset on b-tree page to write record to */
diff --git a/ext/misc/amatch.c b/ext/misc/amatch.c
index dd9bee53d7..b3fcbac505 100644
--- a/ext/misc/amatch.c
+++ b/ext/misc/amatch.c
@@ -482,9 +482,9 @@ struct amatch_rule {
amatch_rule *pNext; /* Next rule in order of increasing rCost */
char *zFrom; /* Transform from (a string from user input) */
amatch_cost rCost; /* Cost of this transformation */
- amatch_langid iLang; /* The langauge to which this rule belongs */
+ amatch_langid iLang; /* The language to which this rule belongs */
amatch_len nFrom, nTo; /* Length of the zFrom and zTo strings */
- char zTo[4]; /* Tranform to V.W value (extra space appended) */
+ char zTo[4]; /* Transform to V.W value (extra space appended) */
};
/*
diff --git a/ext/misc/btreeinfo.c b/ext/misc/btreeinfo.c
index 02f8c0319c..9c726f5f17 100644
--- a/ext/misc/btreeinfo.c
+++ b/ext/misc/btreeinfo.c
@@ -49,7 +49,7 @@
** USAGE EXAMPLES:
**
** Show the table btrees in a schema order with the tables with the most
-** rows occuring first:
+** rows occurring first:
**
** SELECT name, nEntry
** FROM sqlite_btreeinfo
diff --git a/ext/misc/csv.c b/ext/misc/csv.c
index b38500f4b9..8331265aa0 100644
--- a/ext/misc/csv.c
+++ b/ext/misc/csv.c
@@ -315,7 +315,7 @@ typedef struct CsvTable {
} CsvTable;
/* Allowed values for tstFlags */
-#define CSVTEST_FIDX 0x0001 /* Pretend that constrained searchs cost less*/
+#define CSVTEST_FIDX 0x0001 /* Pretend that constrained search cost less*/
/* A cursor for the CSV virtual table */
typedef struct CsvCursor {
diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c
index 9365ae68b9..b0eeb96e33 100644
--- a/ext/misc/decimal.c
+++ b/ext/misc/decimal.c
@@ -731,7 +731,7 @@ static void decimalSubFunc(
decimal_free(pB);
}
-/* Aggregate funcion: decimal_sum(X)
+/* Aggregate function: decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
** precision.
diff --git a/ext/misc/fuzzer.c b/ext/misc/fuzzer.c
index 92b7c0dae0..e16d005d9c 100644
--- a/ext/misc/fuzzer.c
+++ b/ext/misc/fuzzer.c
@@ -68,7 +68,7 @@
** AND distance<200;
**
** This first query outputs the string "abcdefg" and all strings that
-** can be derived from that string by appling the specified transformations.
+** can be derived from that string by applying the specified transformations.
** The strings are output together with their total transformation cost
** (called "distance") and appear in order of increasing cost. No string
** is output more than once. If there are multiple ways to transform the
@@ -97,7 +97,7 @@
** LIMIT 20
**
** The query above gives the 20 closest words to the $word being tested.
-** (Note that for good performance, the vocubulary.w column should be
+** (Note that for good performance, the vocabulary.w column should be
** indexed.)
**
** A similar query can be used to find all words in the dictionary that
@@ -207,7 +207,7 @@ struct fuzzer_rule {
** Every stem is added to a hash table as it is output. Generation of
** duplicate stems is suppressed.
**
-** Active stems (those that might generate new outputs) are kepts on a linked
+** Active stems (those that might generate new outputs) are kept on a linked
** list sorted by increasing cost. The cost is the sum of rBaseCost and
** pRule->rCost.
*/
diff --git a/ext/misc/ieee754.c b/ext/misc/ieee754.c
index 99489fe9ca..5ddb4a2fe4 100644
--- a/ext/misc/ieee754.c
+++ b/ext/misc/ieee754.c
@@ -79,7 +79,7 @@
** WITH c(name,bin) AS (VALUES
** ('minimum positive value', x'0000000000000001'),
** ('maximum subnormal value', x'000fffffffffffff'),
-** ('mininum positive nornal value', x'0010000000000000'),
+** ('minimum positive normal value', x'0010000000000000'),
** ('maximum value', x'7fefffffffffffff'))
** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
diff --git a/ext/misc/normalize.c b/ext/misc/normalize.c
index 08d7733b96..800e129112 100644
--- a/ext/misc/normalize.c
+++ b/ext/misc/normalize.c
@@ -286,7 +286,7 @@ static const unsigned char sqlite3CtypeMap[256] = {
#define TK_VARIABLE TK_LITERAL
#define TK_BLOB TK_LITERAL
-/* Disable nuisence warnings about case fall-through */
+/* Disable nuisance warnings about case fall-through */
#if !defined(deliberate_fall_through) && defined(__GCC__) && __GCC__>=7
# define deliberate_fall_through __attribute__((fallthrough));
#else
diff --git a/ext/misc/percentile.c b/ext/misc/percentile.c
index 06865185df..98e45cc3a8 100644
--- a/ext/misc/percentile.c
+++ b/ext/misc/percentile.c
@@ -205,7 +205,7 @@ static int percentBinarySearch(Percentile *p, double y, int bExact){
/*
** Generate an error for a percentile function.
**
-** The error format string must have exactly one occurrance of "%%s()"
+** The error format string must have exactly one occurrence of "%%s()"
** (with two '%' characters). That substring will be replaced by the name
** of the function.
*/
diff --git a/ext/misc/series.c b/ext/misc/series.c
index aff9796922..d500842d56 100644
--- a/ext/misc/series.c
+++ b/ext/misc/series.c
@@ -139,7 +139,7 @@ static sqlite3_int64 genSeqMember(
smBase += (mxI64 - mxI64/2) * smStep;
}
/* Under UBSAN (or on 1's complement machines), must do this last term
- * in steps to avoid the dreaded (and harmless) signed multiply overlow. */
+ * in steps to avoid the dreaded (and harmless) signed multiply overflow. */
if( ix>=2 ){
sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
smBase += ix2*smStep;
diff --git a/ext/misc/shathree.c b/ext/misc/shathree.c
index fc05a3b73a..b08eb813e5 100644
--- a/ext/misc/shathree.c
+++ b/ext/misc/shathree.c
@@ -64,7 +64,7 @@
**
** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed
** by the binary content of the blob. The "nnn"
-** in the prefix is the mimimum-length decimal
+** in the prefix is the minimum-length decimal
** representation of the byte-length of the blob.
**
** According to the rules above, all of the following SELECT statements
diff --git a/ext/misc/totype.c b/ext/misc/totype.c
index 31c497a567..e35f33ae64 100644
--- a/ext/misc/totype.c
+++ b/ext/misc/totype.c
@@ -346,7 +346,7 @@ totype_atof_calc:
/* store the result */
*pResult = result;
- /* return true if number and no extra non-whitespace chracters after */
+ /* return true if number and no extra non-whitespace characters after */
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
}
diff --git a/ext/misc/uint.c b/ext/misc/uint.c
index 286314fefa..a527b2f077 100644
--- a/ext/misc/uint.c
+++ b/ext/misc/uint.c
@@ -16,7 +16,7 @@
** of digits compare in numeric order.
**
** * Leading zeros are handled properly, in the sense that
-** they do not mess of the maginitude comparison of embedded
+** they do not mess of the magnitude comparison of embedded
** strings of digits. "x00123y" is equal to "x123y".
**
** * Only unsigned integers are recognized. Plus and minus
diff --git a/ext/misc/vfsstat.c b/ext/misc/vfsstat.c
index ba22115ab8..b45193934f 100644
--- a/ext/misc/vfsstat.c
+++ b/ext/misc/vfsstat.c
@@ -24,7 +24,7 @@ SQLITE_EXTENSION_INIT1
** To use this module, first compile it as a loadable extension. See
** https://www.sqlite.org/loadext.html#build for compilations instructions.
**
-** After compliing, load this extension, then open database connections to be
+** After compiling, load this extension, then open database connections to be
** measured. Query usages status using the vfsstat virtual table:
**
** SELECT * FROM vfsstat;
diff --git a/ext/misc/vfstrace.c b/ext/misc/vfstrace.c
index c274558d17..a3cb121973 100644
--- a/ext/misc/vfstrace.c
+++ b/ext/misc/vfstrace.c
@@ -120,7 +120,7 @@
**
** Individual APIs can be enabled or disabled by name, with or without
** the initial "x" character. For example, to set up for tracing lock
-** primatives only:
+** primitives only:
**
** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
**
diff --git a/ext/misc/vtshim.c b/ext/misc/vtshim.c
index 0709a26a7f..3f7945724c 100644
--- a/ext/misc/vtshim.c
+++ b/ext/misc/vtshim.c
@@ -425,7 +425,7 @@ static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){
return rc;
}
-/* The destructor function for a disposible module */
+/* The destructor function for a disposable module */
static void vtshimAuxDestructor(void *pXAux){
vtshim_aux *pAux = (vtshim_aux*)pXAux;
assert( pAux->pAllVtab==0 );
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index 99dfead9a2..e99acdc68b 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -4826,7 +4826,7 @@ static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
/* If this is an RBU vacuum operation and this is the target database,
** pretend that it has at least one page. Otherwise, SQLite will not
- ** check for the existance of a *-wal file. rbuVfsRead() contains
+ ** check for the existence of a *-wal file. rbuVfsRead() contains
** similar logic. */
if( rc==SQLITE_OK && *pSize==0
&& p->pRbu && rbuIsVacuum(p->pRbu)
diff --git a/ext/rbu/sqlite3rbu.h b/ext/rbu/sqlite3rbu.h
index d156b3178a..1534877a94 100644
--- a/ext/rbu/sqlite3rbu.h
+++ b/ext/rbu/sqlite3rbu.h
@@ -49,7 +49,7 @@
**
** "RBU" stands for "Resumable Bulk Update". As in a large database update
** transmitted via a wireless network to a mobile device. A transaction
-** applied using this extension is hence refered to as an "RBU update".
+** applied using this extension is hence referred to as an "RBU update".
**
**
** LIMITATIONS
@@ -346,7 +346,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
** new RBU vacuum operation.
**
-** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
+** As with sqlite3rbu_open(), Zipvfs users should refer to the comment
** describing the sqlite3rbu_create_vfs() API function below for
** a description of the complications associated with using RBU with
** zipvfs databases.
@@ -442,7 +442,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
**
** If the RBU update has been completely applied, mark the RBU database
** as fully applied. Otherwise, assuming no error has occurred, save the
-** current state of the RBU update appliation to the RBU database.
+** current state of the RBU update application to the RBU database.
**
** If an error has already occurred as part of an sqlite3rbu_step()
** or sqlite3rbu_open() call, or if one occurs within this function, an
diff --git a/ext/repair/checkindex.c b/ext/repair/checkindex.c
index 5f6e646e44..ed30357e5d 100644
--- a/ext/repair/checkindex.c
+++ b/ext/repair/checkindex.c
@@ -110,7 +110,7 @@ static int cidxConnect(
" current_key TEXT," /* SQLite quote() text of key values */
" index_name HIDDEN," /* IN: name of the index being scanned */
" after_key HIDDEN," /* IN: Start scanning after this key */
- " scanner_sql HIDDEN" /* debuggingn info: SQL used for scanner */
+ " scanner_sql HIDDEN" /* debugging info: SQL used for scanner */
")"
);
pRet = cidxMalloc(&rc, sizeof(CidxTable));
diff --git a/ext/rtree/README b/ext/rtree/README
index 3736f45c5f..051fd1339f 100644
--- a/ext/rtree/README
+++ b/ext/rtree/README
@@ -24,7 +24,7 @@ and query r-tree structures using ordinary SQL statements.
3 and 11. Unlike regular SQLite tables, r-tree tables are strongly
typed.
- The leftmost column is always the pimary key and contains 64-bit
+ The leftmost column is always the primary key and contains 64-bit
integer values. Each subsequent column contains a 32-bit real
value. For each pair of real values, the first (leftmost) must be
less than or equal to the second. R-tree tables may be
diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c
index 3e9c2a2713..0ae42e7b72 100644
--- a/ext/rtree/geopoly.c
+++ b/ext/rtree/geopoly.c
@@ -771,7 +771,7 @@ static void geopolyBBoxFinal(
** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
** Returns:
**
-** +2 x0,y0 is on the line segement
+** +2 x0,y0 is on the line segment
**
** +1 x0,y0 is beneath line segment
**
@@ -877,7 +877,7 @@ static void geopolyWithinFunc(
sqlite3_free(p2);
}
-/* Objects used by the overlap algorihm. */
+/* Objects used by the overlap algorithm. */
typedef struct GeoEvent GeoEvent;
typedef struct GeoSegment GeoSegment;
typedef struct GeoOverlap GeoOverlap;
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index 8ed8978bde..21c87bdc76 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -2105,7 +2105,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
}
/*
-** Return the N-dimensional volumn of the cell stored in *p.
+** Return the N-dimensional volume of the cell stored in *p.
*/
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
RtreeDValue area = (RtreeDValue)1;
@@ -3871,7 +3871,7 @@ static sqlite3_stmt *rtreeCheckPrepare(
/*
** The second and subsequent arguments to this function are a printf()
** style format string and arguments. This function formats the string and
-** appends it to the report being accumuated in pCheck.
+** appends it to the report being accumulated in pCheck.
*/
static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
va_list ap;
diff --git a/ext/rtree/rtreedoc2.test b/ext/rtree/rtreedoc2.test
index ca0c6b31bd..6032f32fe4 100644
--- a/ext/rtree/rtreedoc2.test
+++ b/ext/rtree/rtreedoc2.test
@@ -116,7 +116,7 @@ set testprefix rtreedoc2-2
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
# 3-dimensional R*Tree, and so forth.
#
-# The second argument refered to above is the length of the list passed
+# The second argument referred to above is the length of the list passed
# as the 3rd parameter to the Tcl script.
#
do_execsql_test 1.0 {
diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c
index 6d3153230c..d2bbc2db0a 100644
--- a/ext/session/sqlite3session.c
+++ b/ext/session/sqlite3session.c
@@ -1198,7 +1198,7 @@ static int sessionTableInfo(
/*
** This function is called to initialize the SessionTable.nCol, azCol[]
** abPK[] and azDflt[] members of SessionTable object pTab. If these
-** fields are already initilialized, this function is a no-op.
+** fields are already initialized, this function is a no-op.
**
** If an error occurs, an error code is stored in sqlite3_session.rc and
** non-zero returned. Or, if no error occurs but the table has no primary
@@ -3021,7 +3021,7 @@ static int sessionGenerateChangeset(
){
sqlite3 *db = pSession->db; /* Source database handle */
SessionTable *pTab; /* Used to iterate through attached tables */
- SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
+ SessionBuffer buf = {0,0,0}; /* Buffer in which to accumulate changeset */
int rc; /* Return code */
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile
index c9852e389c..ec258099fc 100644
--- a/ext/wasm/GNUmakefile
+++ b/ext/wasm/GNUmakefile
@@ -103,7 +103,7 @@ else
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
$(info ==============================================================)
$(info == Development build. Make one of (dist, snapshot) for a)
- $(info == smaller release build.)
+ $(info == smaller and faster release build.)
$(info ==============================================================)
endif
endif
@@ -136,8 +136,9 @@ JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
# target of browsers.
#
# - node = for use by node.js for node.js, as opposed to by node.js on
-# behalf o browser-side code (use bundler-friendly for that). Note
+# behalf of browser-side code (use bundler-friendly for that). Note
# that persistent storage (OPFS) is not available in these builds.
+# These builds are UNTESTED and UNSUPPORTED!
#
JS_BUILD_MODES := vanilla esm bunder-friendly node
@@ -326,7 +327,7 @@ endif
# If the canonical build process finds the file
# sqlite3_wasm_extra_init.c in the main wasm build directory, it
# arranges to include that file in the build of sqlite3.wasm and
-# defines SQLITE_EXTRA_INIT=sqlite3_wasm_extra_init.
+# defines SQLITE_EXTRA_INIT_MUTEXED=sqlite3_wasm_extra_init.
#
# sqlite3_wasm_extra_init() must be a function with this signature:
#
@@ -358,7 +359,7 @@ endif
# Slight caveat: this uses the version info from the in-tree
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
# end result is that the generated JS files may have static version
-# info from $(bin.version-info) which differ from their runtime-emited
+# info from $(bin.version-info) which differ from their runtime-emitted
# version info (e.g. from sqlite3_libversion()).
bin.version-info := $(dir.top)/version-info
.NOTPARALLEL: $(bin.version-info)
@@ -512,7 +513,7 @@ sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
# sqlite3-api.jses = the list of JS files which make up
# $(sqlite3-api.js.in), in the order they need to be assembled.
sqlite3-api.jses := $(sqlite3-license-version.js)
-# sqlite3-api-prologue.js: initial boostrapping bits:
+# sqlite3-api-prologue.js: initial bootstrapping bits:
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
# Emscripten glue:
@@ -891,12 +892,13 @@ EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
########################################################################
########################################################################
# We have to ensure that we do not build $(sqlite3*.*js) in parallel
-# because they all result in the creation of $(sqlite3.wasm). We have
-# no way to build just a .[m]js file without also building the .wasm
-# file because the generated .[m]js file has to include info about the
-# imports needed by the wasm file, so they have to be built
+# for any builds which result in the creation of $(sqlite3.wasm). We
+# have no way to build just a .[m]js file without also building the
+# .wasm file because the generated .[m]js file has to include info
+# about the imports needed by the wasm file, so they have to be built
# together. i.e. we're building $(sqlite3.wasm) multiple times, but
-# that's unavoidable (and harmless, just a waste of build time).
+# that's unavoidable (and harmless, but is a significant waste of
+# build time).
$(sqlite3.wasm): $(sqlite3.js)
$(sqlite3.mjs): $(sqlite3.js)
$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
@@ -907,7 +909,7 @@ $(sqlite3-node.mjs): $(sqlite3.mjs)
# We need separate copies of certain supplementary JS files for the
# bundler-friendly build. Concretely, any supplemental JS files which
# themselves use importScripts() or Workers or URL() constructors
-# which refer to other in-tree (m)JS files quire a bundler-friendly
+# which refer to other in-tree (m)JS files require a bundler-friendly
# copy.
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
diff --git a/ext/wasm/api/sqlite3-api-glue.c-pp.js b/ext/wasm/api/sqlite3-api-glue.c-pp.js
index a40b832824..a38b9cb5ee 100644
--- a/ext/wasm/api/sqlite3-api-glue.c-pp.js
+++ b/ext/wasm/api/sqlite3-api-glue.c-pp.js
@@ -1835,7 +1835,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
if(!(tgt instanceof StructBinder.StructType)){
toss("Usage error: target object is-not-a StructType.");
}else if(!(func instanceof Function) && !wasm.isPtr(func)){
- toss("Usage errror: expecting a Function or WASM pointer to one.");
+ toss("Usage error: expecting a Function or WASM pointer to one.");
}
if(1===arguments.length){
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js
index 6b032be84d..719e307e81 100644
--- a/ext/wasm/api/sqlite3-api-prologue.js
+++ b/ext/wasm/api/sqlite3-api-prologue.js
@@ -124,7 +124,7 @@
globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
apiConfig = (globalThis.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
){
- if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
+ if(sqlite3ApiBootstrap.sqlite3){ /* already initialized */
(sqlite3ApiBootstrap.sqlite3.config || console).warn(
"sqlite3ApiBootstrap() called multiple times.",
"Config and external initializers are ignored on calls after the first."
@@ -869,7 +869,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Emscripten -sWASM_BIGINT flag, else false. When
enabled, certain 64-bit sqlite3 APIs are enabled which
are not otherwise enabled due to JS/WASM int64
- impedence mismatches.
+ impedance mismatches.
*/
bigIntEnabled: !!config.bigIntEnabled,
/**
@@ -880,7 +880,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
/**
When Emscripten compiles with `-sIMPORTED_MEMORY`, it
- initalizes the heap and imports it into wasm, as opposed to
+ initializes the heap and imports it into wasm, as opposed to
the other way around. In this case, the memory is not
available via this.exports.memory.
*/
@@ -1453,7 +1453,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
creates (or overwrites) the given file using those APIs. This is
primarily intended for use in Emscripten-based builds where the POSIX
APIs are transparently proxied by an in-memory virtual filesystem.
- It may behave diffrently in other environments.
+ It may behave differently in other environments.
The first argument must be either a JS string or WASM C-string
holding the filename. Note that this routine does _not_ create
@@ -1555,7 +1555,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
- "memdb": results are undefined.
- "kvvfs": will fail with an I/O error due to strict internal
- requirments of that VFS's xTruncate().
+ requirements of that VFS's xTruncate().
- "unix" and related: will use the WASM build's equivalent of the
POSIX I/O APIs. This will work so long as neither a specific
diff --git a/ext/wasm/api/sqlite3-opfs-async-proxy.js b/ext/wasm/api/sqlite3-opfs-async-proxy.js
index 0028c1025f..e10d0dd505 100644
--- a/ext/wasm/api/sqlite3-opfs-async-proxy.js
+++ b/ext/wasm/api/sqlite3-opfs-async-proxy.js
@@ -61,7 +61,7 @@ const installAsyncProxy = function(){
}
/**
- Will hold state copied to this object from the syncronous side of
+ Will hold state copied to this object from the synchronous side of
this API.
*/
const state = Object.create(null);
@@ -722,7 +722,7 @@ const installAsyncProxy = function(){
https://github.com/tomayac/sqlite-wasm/issues/12
- is reporting that this occassionally, under high loads,
+ is reporting that this occasionally, under high loads,
returns 'ok', which leads to the whichOp being 0 (which
isn't a valid operation ID and leads to an exception,
along with a corresponding ugly console log
diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
index 6551b5c89c..95843a35dc 100644
--- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
+++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
@@ -501,22 +501,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
currently-opened client-specified filenames. */
getFileNames(){
const rc = [];
- const iter = this.#mapFilenameToSAH.keys();
- for(const n of iter) rc.push(n);
+ for(const n of this.#mapFilenameToSAH.keys()) rc.push(n);
return rc;
}
-// #createFileObject(sah,clientName,opaqueName){
-// const f = Object.assign(Object.create(null),{
-// clientName, opaqueName
-// });
-// this.#mapSAHToMeta.set(sah, f);
-// return f;
-// }
-// #unmapFileObject(sah){
-// this.#mapSAHToMeta.delete(sah);
-// }
-
/**
Adds n files to the pool's capacity. This change is
persistent across settings. Returns a Promise which resolves
@@ -557,8 +545,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
/**
- Releases all currently-opened SAHs. The only legal
- operation after this is acquireAccessHandles().
+ Releases all currently-opened SAHs. The only legal operation
+ after this is acquireAccessHandles() or (if this is called from
+ pauseVfs()) either of isPaused() or unpauseVfs().
*/
releaseAccessHandles(){
for(const ah of this.#mapSAHToName.keys()) ah.close();
@@ -568,17 +557,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
/**
- Opens all files under this.vfsDir/this.#dhOpaque and acquires
- a SAH for each. returns a Promise which resolves to no value
- but completes once all SAHs are acquired. If acquiring an SAH
- throws, SAHPool.$error will contain the corresponding
- exception.
+ Opens all files under this.vfsDir/this.#dhOpaque and acquires a
+ SAH for each. Returns a Promise which resolves to no value but
+ completes once all SAHs are acquired. If acquiring an SAH
+ throws, this.$error will contain the corresponding Error
+ object.
+
+ If it throws, it releases any SAHs which it may have
+ acquired before the exception was thrown, leaving the VFS in a
+ well-defined but unusable state.
If clearFiles is true, the client-stored state of each file is
cleared when its handle is acquired, including its name, flags,
and any data stored after the metadata block.
*/
- async acquireAccessHandles(clearFiles){
+ async acquireAccessHandles(clearFiles=false){
const files = [];
for await (const [name,h] of this.#dhOpaque){
if('file'===h.kind){
@@ -832,12 +825,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Removes this object's sqlite3_vfs registration and shuts down
this object, releasing all handles, mappings, and whatnot,
including deleting its data directory. There is currently no
- way to "revive" the object and reaquire its resources.
+ way to "revive" the object and reaquire its
+ resources. Similarly, there is no recovery strategy if removal
+ of any given SAH fails, so such errors are ignored by this
+ function.
This function is intended primarily for testing.
Resolves to true if it did its job, false if the
VFS has already been shut down.
+
+ @see pauseVfs()
+ @see unpauseVfs()
*/
async removeVfs(){
if(!this.#cVfs.pointer || !this.#dhOpaque) return false;
@@ -853,13 +852,77 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
);
this.#dhVfsRoot = this.#dhVfsParent = undefined;
}catch(e){
- sqlite3.config.error(this.vfsName,"removeVfs() failed:",e);
+ sqlite3.config.error(this.vfsName,"removeVfs() failed with no recovery strategy:",e);
/*otherwise ignored - there is no recovery strategy*/
}
return true;
}
+ /**
+ "Pauses" this VFS by unregistering it from SQLite and
+ relinquishing all open SAHs, leaving the associated files
+ intact. If this object is already paused, this is a
+ no-op. Returns this object.
+
+ This function throws if SQLite has any opened file handles
+ hosted by this VFS, as the alternative would be to invoke
+ Undefined Behavior by closing file handles out from under the
+ library. Similarly, automatically closing any database handles
+ opened by this VFS would invoke Undefined Behavior in
+ downstream code which is holding those pointers.
+
+ If this function throws due to open file handles then it has
+ no side effects. If the OPFS API throws while closing handles
+ then the VFS is left in an undefined state.
+
+ @see isPaused()
+ @see unpauseVfs()
+ */
+ pauseVfs(){
+ if(this.#mapS3FileToOFile_.size>0){
+ sqlite3.SQLite3Error.toss(
+ capi.SQLITE_MISUSE, "Cannot pause VFS",
+ this.vfsName,"because it has opened files."
+ );
+ }
+ if(this.#mapSAHToName.size>0){
+ capi.sqlite3_vfs_unregister(this.vfsName);
+ this.releaseAccessHandles();
+ }
+ return this;
+ }
+
+ /**
+ Returns true if this pool is currently paused else false.
+
+ @see pauseVfs()
+ @see unpauseVfs()
+ */
+ isPaused(){
+ return 0===this.#mapSAHToName.size;
+ }
+
+ /**
+ "Unpauses" this VFS, reacquiring all SAH's and (if successful)
+ re-registering it with SQLite. This is a no-op if the VFS is
+ not currently paused.
+
+ The returned Promise resolves to this object. See
+ acquireAccessHandles() for how it behaves if it throws due to
+ SAH acquisition failure.
+
+ @see isPaused()
+ @see pauseVfs()
+ */
+ async unpauseVfs(){
+ if(0===this.#mapSAHToName.size){
+ return this.acquireAccessHandles(false).
+ then(()=>capi.sqlite3_vfs_register(this.#cVfs, 0),this);
+ }
+ return this;
+ }
+
//! Documented elsewhere in this file.
exportFile(name){
const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name);
@@ -984,6 +1047,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
async removeVfs(){ return this.#p.removeVfs() }
+ pauseVfs(){ this.#p.pauseVfs(); return this; }
+ async unpauseVfs(){ return this.#p.unpauseVfs().then(()=>this); }
+ isPaused(){ return this.#p.isPaused() }
+
}/* class OpfsSAHPoolUtil */;
/**
@@ -1038,7 +1105,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- `clearOnInit`: (default=false) if truthy, contents and filename
mapping are removed from each SAH it is acquired during
- initalization of the VFS, leaving the VFS's storage in a pristine
+ initialization of the VFS, leaving the VFS's storage in a pristine
state. Use this only for databases which need not survive a page
reload.
@@ -1165,7 +1232,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
VFS-hosted database file. The result of the resolved Promise when
called this way is the size of the resulting database.
- On succes this routine rewrites the database header bytes in the
+ On success this routine rewrites the database header bytes in the
output file (not the input array) to force disabling of WAL mode.
On a write error, the handle is removed from the pool and made
@@ -1217,6 +1284,41 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Clears all client-defined state of all SAHs and makes all of them
available for re-use by the pool. Results are undefined if any such
handles are currently in use, e.g. by an sqlite3 db.
+
+ APIs specific to the "pause" capability (added in version 3.49):
+
+ Summary: "pausing" the VFS disassociates it from SQLite and
+ relinquishes its SAHs so that they may be opened by another
+ instance of this VFS (running in a separate tab/page or Worker).
+ "Unpausing" it takes back control, if able.
+
+ - pauseVfs()
+
+ "Pauses" this VFS by unregistering it from SQLite and
+ relinquishing all open SAHs, leaving the associated files intact.
+ This enables pages/tabs to coordinate semi-concurrent usage of
+ this VFS. If this object is already paused, this is a
+ no-op. Returns this object. Throws if SQLite has any opened file
+ handles hosted by this VFS. If this function throws due to open
+ file handles then it has no side effects. If the OPFS API throws
+ while closing handles then the VFS is left in an undefined state.
+
+ - isPaused()
+
+ Returns true if this VFS is paused, else false.
+
+ - [async] unpauseVfs()
+
+ Restores the VFS to an active state after having called
+ pauseVfs() on it. This is a no-op if the VFS is not paused. The
+ returned Promise resolves to this object on success. A rejected
+ Promise means there was a problem reacquiring the SAH handles
+ (possibly because they're in use by another instance or have
+ since been removed). Generically speaking, there is no recovery
+ strategy for that type of error, but if the problem is simply
+ that the OPFS files are locked, then a later attempt to unpause
+ it, made after the concurrent instance releases the SAHs, may
+ recover from the situation.
*/
sqlite3.installOpfsSAHPoolVfs = async function(options=Object.create(null)){
options = Object.assign(Object.create(null), optionDefaults, (options||{}));
diff --git a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
index 27f1bfae7c..9cacae788c 100644
--- a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
+++ b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
@@ -459,7 +459,7 @@ const installOpfsVfs = function callee(options){
Runs the given operation (by name) in the async worker
counterpart, waits for its response, and returns the result
which the async worker writes to SAB[state.opIds.rc]. The
- 2nd and subsequent arguments must be the aruguments for the
+ 2nd and subsequent arguments must be the arguments for the
async op.
*/
const opRun = (op,...args)=>{
diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c
index 461afe0663..d9f0f08ebd 100644
--- a/ext/wasm/api/sqlite3-wasm.c
+++ b/ext/wasm/api/sqlite3-wasm.c
@@ -128,7 +128,9 @@
#endif
#ifdef SQLITE_WASM_EXTRA_INIT
-# define SQLITE_EXTRA_INIT sqlite3_wasm_extra_init
+/* SQLITE_EXTRA_INIT vs SQLITE_EXTRA_INIT_MUTEXED:
+** see https://sqlite.org/forum/forumpost/14183b98fc0b1dea */
+# define SQLITE_EXTRA_INIT_MUTEXED sqlite3_wasm_extra_init
#endif
/*
@@ -284,7 +286,7 @@ SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_alloc(int n){
/*
** State for the "pseudo-stack" allocator implemented in
** sqlite3__wasm_pstack_xyz(). In order to avoid colliding with
-** Emscripten-controled stack space, it carves out a bit of stack
+** Emscripten-controlled stack space, it carves out a bit of stack
** memory to use for that purpose. This memory ends up in the
** WASM-managed memory, such that routines which manipulate the wasm
** heap can also be used to manipulate this memory.
@@ -311,7 +313,7 @@ SQLITE_WASM_EXPORT void * sqlite3__wasm_pstack_ptr(void){
return PStack.pPos;
}
/*
-** Sets the pstack position poitner to p. Results are undefined if the
+** Sets the pstack position pointer to p. Results are undefined if the
** given value did not come from sqlite3__wasm_pstack_ptr().
*/
SQLITE_WASM_EXPORT void sqlite3__wasm_pstack_restore(unsigned char * p){
@@ -980,7 +982,7 @@ const char * sqlite3__wasm_enum_json(void){
#undef _DefGroup
/*
- ** Emit an array of "StructBinder" struct descripions, which look
+ ** Emit an array of "StructBinder" struct descriptions, which look
** like:
**
** {
@@ -1417,7 +1419,7 @@ int sqlite3__wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
** NULL), or nData is negative, SQLITE_MISUSE are returned.
**
** On success, it creates a new file with the given name, populated
-** with the fist nData bytes of pData. If pData is NULL, the file is
+** with the first nData bytes of pData. If pData is NULL, the file is
** created and/or truncated to nData bytes.
**
** Whether or not directory components of zFilename are created
diff --git a/ext/wasm/c-pp.c b/ext/wasm/c-pp.c
index c67881dd3e..318325e93e 100644
--- a/ext/wasm/c-pp.c
+++ b/ext/wasm/c-pp.c
@@ -36,7 +36,7 @@
** - `#pragma` is in place for adding "meta-commands", but it does not
** yet have any concrete list of documented commands.
**
-* - `#stderr` outputs its file name, line number, and the remaininder
+* - `#stderr` outputs its file name, line number, and the remainder
** of that line to stderr.
**
** - `#//` acts as a single-line comment, noting that there must be as
@@ -1215,7 +1215,7 @@ static void cmpp_kwd_if(CmppKeyword const * pKw, CmppTokenizer *t){
CmppLevel_push(t);
break;
default:
- cmpp_kwd__misuse(pKw, t, "Unpexected keyword token type");
+ cmpp_kwd__misuse(pKw, t, "Unexpected keyword token type");
break;
}
buul = db_define_has((char const *)t->args.argv[1]);
diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js
index 509d33b371..b4d8f691b8 100644
--- a/ext/wasm/common/whwasmutil.js
+++ b/ext/wasm/common/whwasmutil.js
@@ -798,7 +798,7 @@ globalThis.WhWasmUtilInstaller = function(target){
*/
target.peek8 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i8' );
/**
- Convience form of poke() intended for setting individual bytes.
+ Convenience form of poke() intended for setting individual bytes.
Its difference from poke() is that it always writes to the
i8-sized heap view.
*/
@@ -1769,7 +1769,7 @@ globalThis.WhWasmUtilInstaller = function(target){
/** If true, the constructor emits a warning. The intent is that
this be set to true after bootstrapping of the higher-level
client library is complete, to warn downstream clients that
- they shouldn't be relying on this implemenation detail which
+ they shouldn't be relying on this implementation detail which
does not have a stable interface. */
xArg.FuncPtrAdapter.warnOnUse = false;
@@ -1949,7 +1949,7 @@ globalThis.WhWasmUtilInstaller = function(target){
- `json:dealloc` (results): works exactly like `string:dealloc` but
returns the same thing as the `json` adapter. Note the
- warning in `string:dealloc` regarding maching allocators and
+ warning in `string:dealloc` regarding matching allocators and
deallocators.
The type names for results and arguments are validated when
diff --git a/ext/wasm/demo-jsstorage.js b/ext/wasm/demo-jsstorage.js
index cf820e4033..587aa9cc58 100644
--- a/ext/wasm/demo-jsstorage.js
+++ b/ext/wasm/demo-jsstorage.js
@@ -103,7 +103,7 @@
if(0===db.selectValue('select count(*) from sqlite_master')){
log("DB is empty. Use the init button to populate it.");
}else{
- log("DB contains data from a previous session. Use the Clear Ctorage button to delete it.");
+ log("DB contains data from a previous session. Use the Clear Storage button to delete it.");
btnSelect.click();
}
};
diff --git a/ext/wasm/fiddle/fiddle.js b/ext/wasm/fiddle/fiddle.js
index d28589835c..f0a89f25d6 100644
--- a/ext/wasm/fiddle/fiddle.js
+++ b/ext/wasm/fiddle/fiddle.js
@@ -112,7 +112,7 @@
/**
A proxy for localStorage or sessionStorage or a
- page-instance-local proxy, if neither one is availble.
+ page-instance-local proxy, if neither one is available.
Which exact storage implementation is uses is unspecified, and
apps must not rely on it.
diff --git a/ext/wasm/fiddle/index.html b/ext/wasm/fiddle/index.html
index f779749319..ca6788ef0b 100644
--- a/ext/wasm/fiddle/index.html
+++ b/ext/wasm/fiddle/index.html
@@ -5,7 +5,7 @@
WASMFS-specific tests which require that
diff --git a/ext/wasm/jaccwabyt/jaccwabyt.js b/ext/wasm/jaccwabyt/jaccwabyt.js
index 1846441e55..8144e8d620 100644
--- a/ext/wasm/jaccwabyt/jaccwabyt.js
+++ b/ext/wasm/jaccwabyt/jaccwabyt.js
@@ -561,7 +561,7 @@ globalThis.Jaccwabyt = function StructBinderFactory(config){
const dbg = ctor.prototype.debugFlags.__flags;
/*
TODO?: set prototype of descr to an object which can set/fetch
- its prefered representation, e.g. conversion to string or mapped
+ its preferred representation, e.g. conversion to string or mapped
function. Advantage: we can avoid doing that via if/else if/else
in the get/set methods.
*/
diff --git a/ext/wasm/jaccwabyt/jaccwabyt.md b/ext/wasm/jaccwabyt/jaccwabyt.md
index 431741edca..17bba78cc7 100644
--- a/ext/wasm/jaccwabyt/jaccwabyt.md
+++ b/ext/wasm/jaccwabyt/jaccwabyt.md
@@ -176,7 +176,7 @@ essentially boils down to:
3. [Feed (2) to the function generated by (1)](#step-3) to create JS
constuctor functions for each struct. This is done at runtime, as
opposed to during a build-process step, and can be set up in such a
- way that it does not require any maintenace after its initial
+ way that it does not require any maintenance after its initial
setup.
4. [Create and use instances of those structs](#step-4).
@@ -950,7 +950,7 @@ const char * wasm__ctype_json(void){
assert(LEVEL<5); memset(pos, '}', LEVEL); pos+=LEVEL; lenCheck
////////////////////////////////////////////////////////////////////
- // Macros for emiting StructBinders...
+ // Macros for emitting StructBinders...
#define StructBinder__(TYPE) \
n = 0; \
outf("%s{", (structCount++ ? ", " : "")); \
diff --git a/ext/wasm/mkwasmbuilds.c b/ext/wasm/mkwasmbuilds.c
index 91c03b6d42..e3cd34b00d 100644
--- a/ext/wasm/mkwasmbuilds.c
+++ b/ext/wasm/mkwasmbuilds.c
@@ -135,6 +135,28 @@ static void mk_prologue(void){
}
}
+/*
+** Flags for use with the 3rd argument to mk_pre_post() and
+** mk_lib_mode().
+**
+** Maintenance reminder: do not combine flags within this enum,
+** e.g. LIBMODE_BUNDLER_FRIEND=0x02|LIBMODE_ESM, as that will lead to
+** breakage in some of the flag checks.
+*/
+enum LibModeFlags {
+ /* Indicates an ESM module build. */
+ LIBMODE_ESM = 0x01,
+ /* Indicates a "bundler-friendly" build mode. */
+ LIBMODE_BUNDLER_FRIENDLY = 0x02,
+ /* Indicates to _not_ add this build to the 'all' target. */
+ LIBMODE_DONT_ADD_TO_ALL = 0x04,
+ /* Indicates a node.js-for-node.js build (untested and
+ ** unsupported). */
+ LIBMODE_NODEJS = 0x08,
+ /* Indicates a wasmfs build (untested and unsupported). */
+ LIBMODE_WASMFS = 0x10
+};
+
/*
** Emits makefile code for setting up values for the --pre-js=FILE,
** --post-js=FILE, and --extern-post-js=FILE emcc flags, as well as
@@ -142,6 +164,7 @@ static void mk_prologue(void){
*/
static void mk_pre_post(const char *zName /* build name */,
const char *zMode /* build mode */,
+ int flags /* LIBMODE_... mask */,
const char *zCmppD /* optional -D flags for c-pp for the
** --pre/--post-js files. */){
pf("%s# Begin --pre/--post flags for %s-%s\n", zBanner, zNM);
@@ -166,9 +189,10 @@ static void mk_pre_post(const char *zName /* build name */,
pf("\tcp $(pre-js.js.%s-%s.intermediary) $@\n", zNM);
/* Amend $(pre-js.js.zName-zMode) for all targets except the plain
- ** "sqlite3" build... */
+ ** "sqlite3" and the "sqlite3-wasmfs" builds... */
if( 0!=strcmp("sqlite3-wasmfs", zName)
&& 0!=strcmp("sqlite3", zName) ){
+#error "This part ^^^ is needs adapting for use with the LIBMODE_... flags"
pf("\t@echo 'Module[xNameOfInstantiateWasm].uri = "
"\"%s.wasm\";' >> $@\n", zName);
}
@@ -209,7 +233,7 @@ static void mk_pre_post(const char *zName /* build name */,
static void mk_fiddle(){
int i = 0;
- mk_pre_post("fiddle-module","vanilla", 0);
+ mk_pre_post("fiddle-module","vanilla", 0, 0);
for( ; i < 2; ++i ){
const char *zTail = i ? ".debug" : "";
const char *zDir = i ? "$(dir.fiddle-debug)" : "$(dir.fiddle)";
@@ -257,7 +281,7 @@ static void mk_fiddle(){
*/
static void mk_lib_mode(const char *zName /* build name */,
const char *zMode /* build mode */,
- int bIsEsm /* true only for ESM build */,
+ int flags /* LIBMODE_... mask */,
const char *zApiJsOut /* name of generated sqlite3-api.js/.mjs */,
const char *zJsOut /* name of generated sqlite3.js/.mjs */,
const char *zCmppD /* extra -D flags for c-pp */,
@@ -276,7 +300,7 @@ static void mk_lib_mode(const char *zName /* build name */,
pf("%s# Begin build [%s-%s]\n", zBanner, zNM);
pf("# zApiJsOut=%s\n# zJsOut=%s\n# zCmppD=%s\n", zApiJsOut, zJsOut, zCmppD);
pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut);
- mk_pre_post(zNM, zCmppD);
+ mk_pre_post(zNM, flags, zCmppD);
pf("\nemcc.flags.%s.%s ?=\n", zNM);
if( zEmcc[0] ){
pf("emcc.flags.%s.%s += %s\n", zNM, zEmcc);
@@ -303,13 +327,13 @@ static void mk_lib_mode(const char *zName /* build name */,
pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n"
"\t\t$(cflags.%s) $(cflags.%s.%s) \\\n"
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM);
- if( bIsEsm ){
+ if( LIBMODE_ESM & flags ){
/* TODO? Replace this $(call) with the corresponding makefile
** code. OTOH, we also use this $(call) in the speedtest1-wasmfs
** build, which is not part of the rules emitted by this
** program. */
pf("\t@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,%d)\n",
- 0==strcmp("sqlite3-wasmfs", zName) ? 1 : 0);
+ (LIBMODE_WASMFS & flags) ? 1 : 0);
}
pf("\t@chmod -x %s; \\\n"
"\t\t$(maybe-wasm-strip) %s;\n",
@@ -331,16 +355,16 @@ static void mk_lib_mode(const char *zName /* build name */,
** resulting .wasm file is identical for all builds for which zEmcc
** is empty.
*/
- if( 0==strcmp("bundler-friendly", zMode)
- || 0==strcmp("node", zMode) ){
+ if( (LIBMODE_BUNDLER_FRIENDLY & flags)
+ || (LIBMODE_NODEJS & flags) ){
pf("\t@echo 'Patching $@ for %s.wasm...'; \\\n", zName);
pf("\t\trm -f %s; \\\n", zWasmOut);
pf("\t\tsed -i -e 's/%s-%s.wasm/%s.wasm/g' $@ || exit;\n",
/* ^^^^^^ reminder: Mac/BSD sed has no -i flag */
zNM, zName);
pf("\t@ls -la $@\n");
- if( 0==strcmp("bundler-friendly", zMode) ){
- /* Avoid a 3rd occurance of the bug fixed by 65798c09a00662a3,
+ if( LIBMODE_BUNDLER_FRIENDLY & flags ){
+ /* Avoid a 3rd occurrence of the bug fixed by 65798c09a00662a3,
** which was (in two cases) caused by makefile refactoring and
** not recognized until after a release was made with the broken
** sqlite3-bundler-friendly.mjs: */
@@ -352,9 +376,7 @@ static void mk_lib_mode(const char *zName /* build name */,
}else{
pf("\t@ls -la %s $@\n", zWasmOut);
}
- if( 0!=strcmp("sqlite3-wasmfs", zName) ){
- /* The sqlite3-wasmfs build is optional and needs to be invoked
- ** conditionally using info we don't have here. */
+ if( 0==(LIBMODE_DONT_ADD_TO_ALL & flags) ){
pf("all: %s\n", zJsOut);
}
pf("# End build [%s-%s]%s", zNM, zBanner);
@@ -366,22 +388,29 @@ int main(void){
mk_prologue();
mk_lib_mode("sqlite3", "vanilla", 0,
"$(sqlite3-api.js)", "$(sqlite3.js)", 0, 0);
- mk_lib_mode("sqlite3", "esm", 1,
+ mk_lib_mode("sqlite3", "esm", LIBMODE_ESM,
"$(sqlite3-api.mjs)", "$(sqlite3.mjs)",
"-Dtarget=es6-module", 0);
- mk_lib_mode("sqlite3", "bundler-friendly", 1,
- "$(sqlite3-api-bundler-friendly.mjs)", "$(sqlite3-bundler-friendly.mjs)",
+ mk_lib_mode("sqlite3", "bundler-friendly",
+ LIBMODE_BUNDLER_FRIENDLY | LIBMODE_ESM,
+ "$(sqlite3-api-bundler-friendly.mjs)",
+ "$(sqlite3-bundler-friendly.mjs)",
"$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly", 0);
- mk_lib_mode("sqlite3" , "node", 1,
+ mk_lib_mode("sqlite3" , "node",
+ LIBMODE_NODEJS | LIBMODE_DONT_ADD_TO_ALL,
"$(sqlite3-api-node.mjs)", "$(sqlite3-node.mjs)",
"$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node", 0);
- mk_lib_mode("sqlite3-wasmfs", "esm" ,1,
+ mk_lib_mode("sqlite3-wasmfs", "esm" ,
+ LIBMODE_WASMFS | LIBMODE_ESM | LIBMODE_DONT_ADD_TO_ALL,
+ /* The sqlite3-wasmfs build is optional and needs to be invoked
+ ** conditionally using info we don't have here. */
"$(sqlite3-api-wasmfs.mjs)", "$(sqlite3-wasmfs.mjs)",
"$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs",
"-sEXPORT_ES6 -sUSE_ES6_IMPORT_META");
mk_fiddle();
- mk_pre_post("speedtest1","vanilla", 0);
- mk_pre_post("speedtest1-wasmfs","esm", "$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs");
+ mk_pre_post("speedtest1","vanilla", 0, 0);
+ mk_pre_post("speedtest1-wasmfs","esm", 0,
+ "$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs");
return rc;
}
diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js
index 28d61de071..8638845a76 100644
--- a/ext/wasm/tester1.c-pp.js
+++ b/ext/wasm/tester1.c-pp.js
@@ -3189,8 +3189,25 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
db.close();
T.assert(1 === u1.getFileCount());
db = new u2.OpfsSAHPoolDb(dbName);
- T.assert(1 === u1.getFileCount());
+ T.assert(1 === u1.getFileCount())
+ .mustThrowMatching(
+ ()=>u1.pauseVfs(),
+ (err)=>{
+ return capi.SQLITE_MISUSE===err.resultCode
+ && /^SQLITE_MISUSE: Cannot pause VFS /.test(err.message);
+ },
+ "Cannot pause VFS with opened db."
+ );
db.close();
+ T.assert( u2===u2.pauseVfs() )
+ .assert( u2.isPaused() )
+ .assert( 0===capi.sqlite3_vfs_find(u2.vfsName) )
+ .mustThrowMatching(()=>new u2.OpfsSAHPoolDb(dbName),
+ /.+no such vfs: .+/,
+ "VFS is not available")
+ .assert( u2===await u2.unpauseVfs() )
+ .assert( u2===await u1.unpauseVfs(), "unpause is a no-op if the VFS is not paused" )
+ .assert( 0!==capi.sqlite3_vfs_find(u2.vfsName) );
const fileNames = u1.getFileNames();
T.assert(1 === fileNames.length)
.assert(dbName === fileNames[0])
diff --git a/ext/wasm/tests/opfs/sahpool/index.html b/ext/wasm/tests/opfs/sahpool/index.html
new file mode 100644
index 0000000000..f3d07f456a
--- /dev/null
+++ b/ext/wasm/tests/opfs/sahpool/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+ sqlite3 tester: OpfsSAHPool Pausing
+
+
+
+
+
+ This page provides a very basic demonstration of
+ "pausing" and "unpausing" the OPFS SAHPool VFS such that
+ multiple pages or workers can use it by coordinating which
+ handler may have it open at any given time.
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/wasm/tests/opfs/sahpool/sahpool-pausing.js b/ext/wasm/tests/opfs/sahpool/sahpool-pausing.js
new file mode 100644
index 0000000000..1aa98d3cb3
--- /dev/null
+++ b/ext/wasm/tests/opfs/sahpool/sahpool-pausing.js
@@ -0,0 +1,183 @@
+/*
+ 2025-01-31
+
+ The author disclaims copyright to this source code. In place of a
+ legal notice, here is a blessing:
+
+ * May you do good and not evil.
+ * May you find forgiveness for yourself and forgive others.
+ * May you share freely, never taking more than you give.
+
+ ***********************************************************************
+
+ These tests are specific to the opfs-sahpool VFS and are limited to
+ demonstrating its pause/unpause capabilities.
+
+ Most of this file is infrastructure for displaying results to the
+ user. Search for runTests() to find where the work actually starts.
+*/
+'use strict';
+(function(){
+ let logClass;
+
+ const mapToString = (v)=>{
+ switch(typeof v){
+ case 'number': case 'string': case 'boolean':
+ case 'undefined': case 'bigint':
+ return ''+v;
+ default: break;
+ }
+ if(null===v) return 'null';
+ if(v instanceof Error){
+ v = {
+ message: v.message,
+ stack: v.stack,
+ errorClass: v.name
+ };
+ }
+ return JSON.stringify(v,undefined,2);
+ };
+ const normalizeArgs = (args)=>args.map(mapToString);
+ const logTarget = document.querySelector('#test-output');
+ logClass = function(cssClass,...args){
+ const ln = document.createElement('div');
+ if(cssClass){
+ for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
+ ln.classList.add(c);
+ }
+ }
+ ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
+ logTarget.append(ln);
+ };
+ const cbReverse = document.querySelector('#cb-log-reverse');
+ //cbReverse.setAttribute('checked','checked');
+ const cbReverseKey = 'tester1:cb-log-reverse';
+ const cbReverseIt = ()=>{
+ logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
+ //localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
+ };
+ cbReverse.addEventListener('change', cbReverseIt, true);
+ /*if(localStorage.getItem(cbReverseKey)){
+ cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
+ }*/
+ cbReverseIt();
+
+ const log = (...args)=>{
+ //console.log(...args);
+ logClass('',...args);
+ }
+ const warn = (...args)=>{
+ console.warn(...args);
+ logClass('warning',...args);
+ }
+ const error = (...args)=>{
+ console.error(...args);
+ logClass('error',...args);
+ };
+
+ const toss = (...args)=>{
+ error(...args);
+ throw new Error(args.join(' '));
+ };
+
+ const endOfWork = (passed=true)=>{
+ const eH = document.querySelector('#color-target');
+ const eT = document.querySelector('title');
+ if(passed){
+ log("End of work chain. If you made it this far, you win.");
+ eH.innerText = 'PASS: '+eH.innerText;
+ eH.classList.add('tests-pass');
+ eT.innerText = 'PASS: '+eT.innerText;
+ }else{
+ eH.innerText = 'FAIL: '+eH.innerText;
+ eH.classList.add('tests-fail');
+ eT.innerText = 'FAIL: '+eT.innerText;
+ }
+ };
+
+ const nextHandlerQueue = [];
+
+ const nextHandler = function(workerId,...msg){
+ log(workerId,...msg);
+ (nextHandlerQueue.shift())();
+ };
+
+ const postThen = function(W, msgType, callback){
+ nextHandlerQueue.push(callback);
+ W.postMessage({type:msgType});
+ };
+
+ /**
+ Run a series of operations on an sahpool db spanning two workers.
+ This would arguably be more legible with Promises, but creating a
+ Promise-based communication channel for this purpose is left as
+ an exercise for the reader. An example of such a proxy can be
+ found in the SQLite source tree:
+
+ https://sqlite.org/src/file/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
+ */
+ const runPyramidOfDoom = function(W1, W2){
+ postThen(W1, 'vfs-acquire', function(){
+ postThen(W1, 'db-init', function(){
+ postThen(W1, 'db-query', function(){
+ postThen(W1, 'vfs-pause', function(){
+ postThen(W2, 'vfs-acquire', function(){
+ postThen(W2, 'db-query', function(){
+ postThen(W2, 'vfs-remove', endOfWork);
+ });
+ });
+ });
+ });
+ });
+ });
+ };
+
+ const runTests = function(){
+ log("Running opfs-sahpool pausing tests...");
+ const wjs = 'sahpool-worker.js?sqlite3.dir=../../../jswasm';
+ const W1 = new Worker(wjs+'&workerId=w1'),
+ W2 = new Worker(wjs+'&workerId=w2');
+ W1.workerId = 'w1';
+ W2.workerId = 'w2';
+ let initCount = 0;
+ const onmessage = function({data}){
+ //log("onmessage:",data);
+ switch(data.type){
+ case 'vfs-acquired':
+ nextHandler(data.workerId, "VFS acquired");
+ break;
+ case 'vfs-paused':
+ nextHandler(data.workerId, "VFS paused");
+ break;
+ case 'vfs-unpaused':
+ nextHandler(data.workerId, 'VFS unpaused');
+ break;
+ case 'vfs-removed':
+ nextHandler(data.workerId, 'VFS removed');
+ break;
+ case 'db-inited':
+ nextHandler(data.workerId, 'db initialized');
+ break;
+ case 'query-result':
+ nextHandler(data.workerId, 'query result', data.payload);
+ break;
+ case 'log':
+ log(data.workerId, ':', ...data.payload);
+ break;
+ case 'error':
+ error(data.workerId, ':', ...data.payload);
+ endOfWork(false);
+ break;
+ case 'initialized':
+ log(data.workerId, ': Worker initialized',...data.payload);
+ if( 2===++initCount ){
+ runPyramidOfDoom(W1, W2);
+ }
+ break;
+ }
+ };
+ W1.onmessage = W2.onmessage = onmessage;
+ };
+
+ runTests();
+})();
diff --git a/ext/wasm/tests/opfs/sahpool/sahpool-worker.js b/ext/wasm/tests/opfs/sahpool/sahpool-worker.js
new file mode 100644
index 0000000000..592f159551
--- /dev/null
+++ b/ext/wasm/tests/opfs/sahpool/sahpool-worker.js
@@ -0,0 +1,104 @@
+/*
+ 2025-01-31
+
+ The author disclaims copyright to this source code. In place of a
+ legal notice, here is a blessing:
+
+ * May you do good and not evil.
+ * May you find forgiveness for yourself and forgive others.
+ * May you share freely, never taking more than you give.
+
+ ***********************************************************************
+
+ This file is part of sahpool-pausing.js's demonstration of the
+ pause/unpause feature of the opfs-sahpool VFS.
+*/
+const searchParams = new URL(self.location.href).searchParams;
+const workerId = searchParams.get('workerId');
+const wPost = (type,...args)=>postMessage({type, workerId, payload:args});
+const log = (...args)=>wPost('log',...args);
+let capi, wasm, S, poolUtil;
+
+const sahPoolConfig = {
+ name: 'opfs-sahpool-pausable',
+ clearOnInit: false,
+ initialCapacity: 3
+};
+
+importScripts(searchParams.get('sqlite3.dir') + '/sqlite3.js');
+
+const sqlExec = function(sql){
+ const db = new poolUtil.OpfsSAHPoolDb('/my.db');
+ try{
+ return db.exec(sql);
+ }finally{
+ db.close();
+ }
+};
+
+const clog = console.log.bind(console);
+globalThis.onmessage = function({data}){
+ clog(workerId+": onmessage:",data);
+ switch(data.type){
+ case 'vfs-acquire':
+ if( poolUtil ){
+ poolUtil.unpauseVfs().then(()=>wPost('vfs-unpaused'));
+ }else{
+ S.installOpfsSAHPoolVfs(sahPoolConfig).then(pu=>{
+ poolUtil = pu;
+ wPost('vfs-acquired');
+ });
+ }
+ break;
+ case 'db-init':
+ try{
+ sqlExec([
+ "DROP TABLE IF EXISTS mytable;",
+ "CREATE TABLE mytable(a);",
+ "INSERT INTO mytable(a) VALUES(11),(22),(33)"
+ ]);
+ wPost('db-inited');
+ }catch(e){
+ wPost('error',e.message);
+ }
+ break;
+ case 'db-query': {
+ const rc = sqlExec({
+ sql: 'select * from mytable order by a',
+ rowMode: 'array',
+ returnValue: 'resultRows'
+ });
+ wPost('query-result',rc);
+ break;
+ }
+ case 'vfs-remove':
+ poolUtil.removeVfs().then(()=>wPost('vfs-removed'));
+ break;
+ case 'vfs-pause':
+ poolUtil.pauseVfs();
+ wPost('vfs-paused');
+ break;
+ }
+};
+
+const hasOpfs = ()=>{
+ return globalThis.FileSystemHandle
+ && globalThis.FileSystemDirectoryHandle
+ && globalThis.FileSystemFileHandle
+ && globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle
+ && navigator?.storage?.getDirectory;
+};
+if( !hasOpfs() ){
+ wPost('error',"OPFS not detected");
+}else{
+ globalThis.sqlite3InitModule().then(async function(sqlite3){
+ S = sqlite3;
+ capi = S.capi;
+ wasm = S.wasm;
+ log("sqlite3 version:",capi.sqlite3_libversion(),
+ capi.sqlite3_sourceid());
+ //return sqlite3.installOpfsSAHPoolVfs(sahPoolConfig).then(pu=>poolUtil=pu);
+ }).then(()=>{
+ wPost('initialized');
+ });
+}
diff --git a/main.mk b/main.mk
index 6cce2fb841..6a03c2f541 100644
--- a/main.mk
+++ b/main.mk
@@ -189,25 +189,25 @@ CFLAGS.readline ?= -I$(prefix)/include
#
INSTALL ?= install
#
-# $(ENABLE_SHARED) =
+# $(ENABLE_LIB_SHARED) =
#
-# 1 if libsqlite3.$(T.dll) should be built.
+# 1 if libsqlite3$(T.dll) should be built.
#
-ENABLE_SHARED ?= 1
+ENABLE_LIB_SHARED ?= 1
#
-# $(ENABLE_STATIC) =
+# $(ENABLE_LIB_STATIC) =
#
-# 1 if libsqlite3.$(T.lib) should be built. Some components,
+# 1 if libsqlite3$(T.lib) should be built. Some components,
# e.g. libtclsqlite3 and some test apps, implicitly require the static
# library and will ignore this preference.
#
-ENABLE_STATIC ?= 1
+ENABLE_LIB_STATIC ?= 1
#
# $(USE_AMALGAMATION)
#
# 1 if the amalgamation (sqlite3.c/h) should be built/used, otherwise
# the library is built from all of its original source files.
-# Certaint tools, like sqlite3$(T.exe), require the amalgamation and
+# Certain tools, like sqlite3$(T.exe), require the amalgamation and
# will ignore this preference.
#
USE_AMALGAMATION ?= 1
@@ -220,7 +220,7 @@ USE_AMALGAMATION ?= 1
# may require that the user specifically prepend "." to their
# $LD_LIBRARY_PATH so that the dynamic linker does not pick up a
# libsqlite3.so from outside the source tree. Alternately, symlinking
-# the in-build-tree $(libsqlite3.SO) to some dir in the system's
+# the in-build-tree $(libsqlite3.DLL) to some dir in the system's
# library path will work for giving the apps access to the in-tree
# DLL.
#
@@ -1054,8 +1054,35 @@ T.link.tcl = $(T.tcl.env.source); $(T.link)
cp fts5.c fts5.h tsrc
touch .target_source
+#
+# libsqlite3.DLL.basename = the base name of the resulting DLL. This
+# is typically libsqlite3 but varies wildly on Unix-like Windows
+# environments (msys, cygwin, and friends). Conversely, the base name
+# of the static library ($(libsqlite3.LIB)) is constant on all tested
+# platforms.
+#
+libsqlite3.DLL.basename ?= libsqlite3
+#
+# libsqlite3.DLL => the DLL library
+#
+libsqlite3.DLL = $(libsqlite3.DLL.basename)$(T.dll)
+#
+# libsqlite3.out.implib => "import library" file generated by the
+# --out-implib linker flag. Not commonly used on Unix systems but is
+# on the Windows-side Unix-esque environments and typically as a value
+# of "libsqlite3.dll.a". It is expected to match the filename, if any,
+# provided by the -Wl,--out-implib,FILENAME flag.
+#
+libsqlite3.out.implib ?=
+#
+# libsqlite3.LIB => the static library
+#
libsqlite3.LIB = libsqlite3$(T.lib)
-libsqlite3.SO = libsqlite3$(T.dll)
+
+#
+# libsqlite3.DLL.install-rules => the suffix of the symoblic name of
+# the makefile rules for installing the DLL.
+libsqlite3.DLL.install-rules ?= unix-generic
# Rules to build the LEMON compiler generator
#
@@ -1362,9 +1389,9 @@ tclsqlite-shell.o: $(T.tcl.env.sh) $(TOP)/src/tclsqlite.c $(DEPS_OBJ_COMMON)
tclsqlite-stubs.o: $(T.tcl.env.sh) $(TOP)/src/tclsqlite.c $(DEPS_OBJ_COMMON)
$(T.compile.tcl) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c $$TCL_INCLUDE_SPEC
-tclsqlite3$(T.exe): $(T.tcl.env.sh) tclsqlite-shell.o $(libsqlite3.SO)
+tclsqlite3$(T.exe): $(T.tcl.env.sh) tclsqlite-shell.o $(libsqlite3.DLL)
$(T.link.tcl) -o $@ tclsqlite-shell.o \
- $(libsqlite3.SO) $$TCL_INCLUDE_SPEC $$TCL_LIB_SPEC \
+ $(libsqlite3.DLL) $$TCL_INCLUDE_SPEC $$TCL_LIB_SPEC \
$(LDFLAGS.libsqlite3)
tclsqlite3$(T.exe)-1: tclsqlite3$(T.exe)
tclsqlite3$(T.exe)-0 tclsqlite3$(T.exe)-:
@@ -1414,32 +1441,33 @@ $(libsqlite3.LIB): $(LIBOBJ)
$(AR) $(AR.flags) $@ $(LIBOBJ)
$(libsqlite3.LIB)-1: $(libsqlite3.LIB)
$(libsqlite3.LIB)-0 $(libsqlite3.LIB)-:
-lib: $(libsqlite3.LIB)-$(ENABLE_STATIC)
+lib: $(libsqlite3.LIB)-$(ENABLE_LIB_STATIC)
all: lib
#
# Dynamic libsqlite3
#
-$(libsqlite3.SO): $(LIBOBJ)
+$(libsqlite3.DLL): $(LIBOBJ)
$(T.link.shared) -o $@ $(LIBOBJ) $(LDFLAGS.libsqlite3) \
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
-$(libsqlite3.SO)-1: $(libsqlite3.SO)
-$(libsqlite3.SO)-0 $(libsqlite3.SO)-:
-so: $(libsqlite3.SO)-$(ENABLE_SHARED)
+$(libsqlite3.DLL)-1: $(libsqlite3.DLL)
+$(libsqlite3.DLL)-0 $(libsqlite3.DLL)-:
+so: $(libsqlite3.DLL)-$(ENABLE_LIB_SHARED)
all: so
#
-# On most Unix-like platforms, install the $(libsqlite3.SO) as
-# $(libsqlite3.SO).$(PACKAGE_VERSION) and create symlinks which point
+# DLL installation...
+#
+# On most Unix-like platforms, install the $(libsqlite3.DLL) as
+# $(libsqlite3.DLL).$(PACKAGE_VERSION) and create symlinks which point
# to it:
#
# - libsqlite3.so.$(PACKAGE_VERSION)
# - libsqlite3.so.0 =symlink-> libsqlite3.so.$(PACKAGE_VERSION) (see below)
# - libsqlite3.so =symlink-> libsqlite3.so.3
#
-# The symlinks are not added on platforms where $(T.dll) is ".dll",
-# and different transformations take place on platforms where $(T.dll)
-# is ".dylib".
+# Different rules apply for platforms where $(T.dll)==.dylib and for
+# the "Unix on Windows" environments.
#
# The link named libsqlite3.so.0 is provided in an attempt to reduce
# downstream disruption when performing upgrades from pre-3.48 to a
@@ -1461,7 +1489,7 @@ all: so
# 1) If libsqlite3.so.0.8.6 is found in the target installation
# directory then it is re-linked to point to the newer-style
# names. We cannot retain both the old and new installation because
-# they both share the high-level name $(libsqlite3.SO). The
+# they both share the high-level name $(libsqlite3.DLL). The
# down-side of this is that it may upset packaging tools when we
# replace libsqlite3.so (from a legacy package) with a new symlink.
#
@@ -1473,47 +1501,56 @@ all: so
# still expect to see the legacy file names.
#
# In either case, libsqlite3.la, if found, is deleted because it would
-# contain stale state, refering to non-libtool-generated libraries.
+# contain stale state, referring to non-libtool-generated libraries.
#
-install-so-1: $(install-dir.lib) $(libsqlite3.SO)
- $(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
- @if [ -f $(libsqlite3.SO).a ]; then \
- $(INSTALL) $(libsqlite3.SO).a "$(install-dir.lib)"; \
- fi
- @echo "Setting up $(libsqlite3.SO) version symlinks..."; \
- if [ x.dll = x$(T.dll) ]; then \
- echo "No library symlinks needed on this platform"; \
- elif [ x.dylib = x$(T.dll) ]; then \
- cd "$(install-dir.lib)" || exit $$?; \
- rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
- dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
- mv $(libsqlite3.SO) $$dllname || exit $$?; \
- ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
- ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
- ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
- else \
- cd "$(install-dir.lib)" || exit $$?; \
- rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
- mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
- ls -la $(libsqlite3.SO) $(libsqlite3.SO).[a03]*; \
- if [ -e $(libsqlite3.SO).0.8.6 ]; then \
- echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
- rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
- ls -la $(libsqlite3.SO).0.8.6; \
- elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
- echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
- rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
- ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
- ls -la $(libsqlite3.SO).0.8.6; \
- fi; \
+
+install-dll-out-implib: $(install-dir.lib) $(libsqlite3.DLL)
+ if [ x != "x$(libsqlite3.out.implib)" ] && [ -f "$(libsqlite3.out.implib)" ]; then \
+ $(INSTALL) $(libsqlite3.out.implib) "$(install-dir.lib)"; \
fi
-install-so-0 install-so-:
-install-so: install-so-$(ENABLE_SHARED)
-install: install-so
+install-dll-unix-generic: install-dll-out-implib
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
+ @echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
+ cd "$(install-dir.lib)" || exit $$?; \
+ rm -f $(libsqlite3.DLL).0 $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
+ mv $(libsqlite3.DLL) $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL) || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0 || exit $$?; \
+ ls -la $(libsqlite3.DLL) $(libsqlite3.DLL).[a03]*; \
+ if [ -e $(libsqlite3.DLL).0.8.6 ]; then \
+ echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
+ rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ls -la $(libsqlite3.DLL).0.8.6; \
+ elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
+ echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
+ rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
+ ls -la $(libsqlite3.DLL).0.8.6; \
+ fi
+
+install-dll-msys: install-dll-out-implib $(install-dir.bin)
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.bin)"
+# ----------------------------------------------^^^ yes, bin
+install-dll-mingw: install-dll-msys
+install-dll-cygwin: install-dll-msys
+
+install-dll-darwin: $(install-dir.lib) $(libsqlite3.DLL)
+ $(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
+ @echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
+ cd "$(install-dir.lib)" || exit $$?; \
+ rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
+ dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
+ mv $(libsqlite3.DLL) $$dllname || exit $$?; \
+ ln -s $$dllname $(libsqlite3.DLL) || exit $$?; \
+ ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
+ ls -la $$dllname $(libsqlite3.DLL) libsqlite3.0$(T.dll)
+
+install-dll-1: install-dll-$(libsqlite3.DLL.install-rules)
+install-dll-0 install-dll-:
+install-dll: install-dll-$(ENABLE_LIB_SHARED)
+install: install-dll
#
# Install $(libsqlite3.LIB)
@@ -1521,7 +1558,7 @@ install: install-so
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
install-lib-0 install-lib-:
-install-lib: install-lib-$(ENABLE_STATIC)
+install-lib: install-lib-$(ENABLE_LIB_STATIC)
install: install-lib
#
@@ -1806,7 +1843,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl \
#
sqlite3_analyzer.flags.1 = -L. -lsqlite3
sqlite3_analyzer.flags.0 = $(LDFLAGS.libsqlite3)
-sqlite3_analyzer.deps.1 = $(libsqlite3.SO)
+sqlite3_analyzer.deps.1 = $(libsqlite3.DLL)
sqlite3_analyzer.deps.0 =
sqlite3_analyzer$(T.exe): $(T.tcl.env.sh) sqlite3_analyzer.c \
$(sqlite3_analyzer.deps.$(LINK_TOOLS_DYNAMICALLY))
@@ -1954,7 +1991,7 @@ checksymbols: sqlite3.o
nm -g --defined-only sqlite3.o | egrep -v $(VALIDIDS); test $$? -ne 0
echo '0 errors out of 1 tests'
-# Build the amalgamation-autoconf package. The amalamgation-tarball target builds
+# Build the amalgamation-autoconf package. The amalgamation-tarball target builds
# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
# The snapshot-tarball target builds a tarball named by the SHA3 hash
#
@@ -1969,7 +2006,7 @@ snapshot-tarball: sqlite3.c sqlite3rc.h
sqlite-src.zip: $(TOP)/tool/mksrczip.tcl
$(TCLSH_CMD) $(TOP)/tool/mksrczip.tcl
-# Build a ZIP archive of the amaglamation
+# Build a ZIP archive of the amalgamation
#
sqlite-amalgamation.zip: $(TOP)/tool/mkamalzip.tcl sqlite3.c sqlite3.h shell.c sqlite3ext.h
$(TCLSH_CMD) $(TOP)/tool/mkamalzip.tcl
@@ -2053,7 +2090,7 @@ install: install-shell-$(HAVE_WASI_SDK)
#
sqldiff.0.deps = $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h sqlite3.o sqlite3.h
sqldiff.0.rules = $(T.link) -o $@ $(TOP)/tool/sqldiff.c sqlite3.o $(LDFLAGS.libsqlite3)
-sqldiff.1.deps = $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h $(libsqlite3.SO)
+sqldiff.1.deps = $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h $(libsqlite3.DLL)
sqldiff.1.rules = $(T.link) -o $@ $(TOP)/tool/sqldiff.c -L. -lsqlite3 $(LDFLAGS.configure)
sqldiff$(T.exe): $(sqldiff.$(LINK_TOOLS_DYNAMICALLY).deps)
$(sqldiff.$(LINK_TOOLS_DYNAMICALLY).rules)
@@ -2346,7 +2383,7 @@ tidy: tidy-.
rm -f lemon$(B.exe) sqlite*.tar.gz
rm -f mkkeywordhash$(B.exe) mksourceid$(B.exe)
rm -f parse.* fts5parse.*
- rm -f $(libsqlite3.SO) $(libsqlite3.LIB) $(libtclsqlite3.SO) $(libsqlite3.SO).a
+ rm -f $(libsqlite3.DLL) $(libsqlite3.LIB) $(libtclsqlite3.SO) libsqlite3$(T.dll).a
rm -f tclsqlite3$(T.exe) $(TESTPROGS)
rm -f LogEst$(T.exe) fts3view$(T.exe) rollback-test$(T.exe) showdb$(T.exe)
rm -f showjournal$(T.exe) showstat4$(T.exe) showwal$(T.exe) speedtest1$(T.exe)
diff --git a/manifest b/manifest
index c2c5437bfe..7db998da1e 100644
--- a/manifest
+++ b/manifest
@@ -1,12 +1,12 @@
-C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sbedrock\sbranch.
-D 2025-02-18T14:48:14.586
+C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sbedrock\sbranch\sthrough\sthe\swal2\nintermediary.
+D 2025-03-03T16:01:11.837
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
-F Makefile.in 80be2e281d4647ac15a5bac15d5d20fc76d1cfb3f3f6dc01d1a26e3346a5042a
+F Makefile.in 4ff9b301b59c66ef9d11c8d133cc62e09173bad4abc7d5eb801e45d5527f8fe6
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
-F Makefile.msc 3d99d3c10e7f39f0188475be56026994312b42adb6c6d7dc8ab521b3837c9a9c
-F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
+F Makefile.msc e21d24292743154ff41a1fa7d8b7d5fb5005581af89231d3197395bb7654953e
+F README.md a953c0cffd6e4f2501a306c00ee2b6e1e6630c25031e094629307fe99dd003d1
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
@@ -14,17 +14,17 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
-F auto.def eddf6aef976e2c1a56c0accc3244945e0b22ec6799074c40be160e5a9a5662b0
+F auto.def f39c4f3e58c8c2853555c7ec65c20701f8a42554d23dcb175a346a4f5ee5a36d
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.in 844bc155e1c02075821530b2b4d996ab3d162e647352bb6e2895f3d0e64ad988
-F autoconf/Makefile.msc 1249e425a24859c7b3f17575275247df9eec3bddc0d1d7e73941f1abdbb95a92
+F autoconf/Makefile.in c9a7007181df2a07d08bd63c6ba395ed38705aa218789726951aabebec32ee27
+F autoconf/Makefile.msc 5bc67d3912444c40c6f96d003e5c90663e51abb83d204a520110b1b2038dcd8b
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
-F autoconf/README.txt 7f01dc3915e2d68f329011073662369e62a0938a2c69398807823c57591cb288
-F autoconf/auto.def 3a318c4898024b35ed61a4876a42e3dcc313f93bd8486874d1ad498b88643d1a
+F autoconf/README.txt 1a32296d8bbdd67110c79d224c92c05545a0b5bd0c272950025fe3c7c7b49580
+F autoconf/auto.def 8d81c1d728d8462a9b6c1ca0714013bbb097aee0ae5e79309d7939cead98e295
F autoconf/tea/Makefile.in ba0556fee8da09c066bad85a4457904e46ee2c2eabaa309c0e83a78f2f151a8e
-F autoconf/tea/README.txt 61e62e519579e4a112791354d6d440f8b51ea6db3b0bab58d59f29df42d2dfe3
+F autoconf/tea/README.txt 6c396709b45eb2b3be0ae6dc7e40a140d231962e3a2354da6c4dd48b1d9999bc
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
-F autoconf/tea/configure.ac.in da18360dfdeac7414fa8deb549f3d65aeca0ae1150ff1a8b902019b39ce019a4 w autoconf/tea/configure.ac
+F autoconf/tea/configure.ac.in f49cd68ed9ab7870ce5d67b8463bcf944232d96ce19dd01461f31098ff688634
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in 55aec3c6d7e9a1de9b8d2fdc9c27fd055da3ac3a51b572195e2ae7300bcfd3a2
@@ -38,58 +38,58 @@ F autoconf/tea/win/targets.vc 96a25a1fa6e9e9cfb348fd3760a5395b4ce8acafc8ed10f041
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e
F autosetup/README.md b306314e8a87ccf873cb5b2a360c4a27bbf841df5b76f3acbd65322cff165476
-F autosetup/autosetup df8b53928b1fe3c67db5bc77c8e1eb8160c1b6a26c370e9a06c68748f803b7e4 x
+F autosetup/autosetup 74a9782b68d07934510190fbd03fc6ad92e63f0ea3b5cbffa5f0bd271ad60f01 x
F autosetup/autosetup-config.guess dfa101c5e8220e864d5e9c72a85e87110df60260d36cb951ad0a85d6d9eaa463 x
F autosetup/autosetup-config.sub a38fb074d0dece01cf919e9fb534a26011608aa8fa606490864295328526cd73 x
-F autosetup/autosetup-find-tclsh 25905f6c302959db80c2951aa267b4411c5645b598ce761cfc24a166141e2c4c x
+F autosetup/autosetup-find-tclsh b08f883f5753cfff1ecb8581f98b314e190b7e3f3059798e274ae5f5aad571af x
F autosetup/autosetup-test-tclsh 749d20defee533a3842139df47d700fc7a334a5da7bdbd444ae5331744b06c5f
F autosetup/cc-db.tcl 6e0ed90146197a5a05b245e649975c07c548e30926b218ca3e1d4dc034b10a7b
F autosetup/cc-lib.tcl 493c5935b5dd3bf9bd4eca89b07c8b1b1a9356d61783035144e21795facf7360
F autosetup/cc-shared.tcl 4f024e94a47f427ba61de1739f6381ef0080210f9fae89112d5c1de1e5460d78
F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f
-F autosetup/jimsh0.c 6573f6bc6ff204de0139692648d7037ca0b6c067bac83a7b4e087f20a86866a4
+F autosetup/jimsh0.c a57c16e65dcffc9c76e496757cb3f7fb47e01ecbd1631a0a5e01751fc856f049
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
-F autosetup/proj.tcl cef1e0aa0f2dee2042af66f28c97a9445f84d55d858ba9db4f6116846a1a325f
-F autosetup/sqlite-config.tcl e1d65cc632e1de94ff39618ac82b649f2062f674ca36dae78ab3573cab096761
+F autosetup/proj.tcl e69b91f814ea510057ce7663845de703c3746d71cff9a0db6b2563ee3e7fd25e
+F autosetup/sqlite-config.tcl 1d0c70f372c464c9849dde898b5e778f73c72d8183c6e62634a45ee123e37f89
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
-F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
+F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/begin_concurrent.md 4bee2c3990d1eb800f1ce3726a911292a8e4b889300b2ffd4b08d357370db299
F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8af4a0f4adbc
F doc/compile-for-windows.md 5141661e783c9ca9e3fd30e813345898712f5c311d71316f183db87038fa28a6
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
-F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
-F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
-F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
+F doc/jsonb.md ede3238186e3a90bb79d20b2a6a06d0f9429a38e069e9da0efbad0f2ed48b924
+F doc/lemon.html 7504a6dc9b56dd376a046833ea9cc8b08def93f19bfad6eab9f1a365a4b5f49a
+F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
F doc/tcl-extension-testing.md 864875c3b672db79e7d42348dd726f9a4fbd852b1d8e5efcf09fe3d1ff6bf2a2
F doc/testrunner.md 15583cf8c7d8a1c3378fd5d4319ca769a14c4d950a5df9b015d01d5be290dc69
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
-F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
-F doc/wal-lock.md 781726aaba20bafeceb7ba9f91d5c98c6731691b30c954e37cf0b49a053d461d
+F doc/vfs-shm.txt 1a55f3f0e7b6745931b117ba5c9df3640d7a0536f532ef0052563100f4416f86
+F doc/wal-lock.md 7db0cd61e2000b545b78ce89b0c2a9a8dd8d64c097839258ac10d7c5c4156ec1
F doc/wal2.md a807405a05e19a4945c5905a9ffa0fe45b8560dd7572461192501f565c19cdb5
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 1d2da6606623b57bb47064e02140823ce1daecd4cacbf402c73ad3473d7f000c
-F ext/expert/sqlite3expert.c 494a6b7d4e0ead6dec6a50109dd78fcc054bb1a3fcc29c6f25e06a3685ed557e
+F ext/expert/sqlite3expert.c cf4b1e5584862f486a4c6014ddb081831f1c512065dcf35644638d57179979d6
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
-F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
+F ext/fts3/README.syntax 6d0cbd8caa7ea34ecb0f0ae8278217180a8b7f24a1ea50ddf765383669f494a9
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 1da0265e8798f335165d54959459eeb69b6d32f586f85cf8795ab5d3b1292dcb
+F ext/fts3/fts3.c fd2a8642fa4701ef5dd6bce7947ecb3c7ae472e1d44022772454a8b74a13155d
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 2fe7c76dfd7d46dff964d17d3f4c53bca2116cf5d6252552ebbc22e38afdf4e0
+F ext/fts3/fts3Int.h 75b9cf37c93d3c56d8e569d64527c927cb54a5279afb3823740ca1e29e481c15
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
-F ext/fts3/fts3_expr.c ebf7f2adead8cc54bc91deb41cb4a156874003078116f76631d65b87ff47464d
-F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
+F ext/fts3/fts3_expr.c 673bf600655f5080239ff0e1e80eaae0176389f7e7d3af54c6d51491280ca360
+F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
-F ext/fts3/fts3_porter.c e19807ce0ae31c1c6e9898e89ecc93183d7ec224ea101af039722a4f49e5f2b8
-F ext/fts3/fts3_snippet.c 7a3d5e2cefbb1cb51fb9c65458670cc269647ede18e1ffd57b513f9b4ec10c3e
+F ext/fts3/fts3_porter.c 024417020c57dd1ab39816f5fe6cf45222a857b78a1f6412f040ada1ceabd4ff
+F ext/fts3/fts3_snippet.c ac402ba81ce9503a54238f975d870384f8b9fb3680f6b86eb7a1be44829a1cee
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
F ext/fts3/fts3_test.c 7a9cb3d61774134211bf4bfdf1adcb581a1a0377f2d050a121ae7ab44baef0e3
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
@@ -98,27 +98,27 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
-F ext/fts3/fts3_write.c 81cd8f7e8003e427a1801e04842776b731af26dd93af206e4e66ea5ae319cad1
+F ext/fts3/fts3_write.c 4e967e31f34447b5e5a52583250cd22660cd5774c3ba3054d2eb6725f562b45f
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
-F ext/fts3/unicode/mkunicode.tcl 63db9624ccf70d4887836c320eda93ab552f21008f3be7ede551eac3ead62baa
+F ext/fts3/unicode/mkunicode.tcl cbf5f7b5c8ce8014bad731f246f2e520eece908465de4778c951ca17003381f1
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
F ext/fts5/fts5Int.h 6abff7dd770dc5969c994c281e6e77fc277ce414d56cc4a62c145cc7036b0b67
-F ext/fts5/fts5_aux.c 65a0468dd177d6093aa9ae1622e6d86b0136b8d267c62c0ad6493ad1e9a3d759
-F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70673cb6f09
+F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
+F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
-F ext/fts5/fts5_expr.c 69b8d976058512c07dfe86e229521b7a871768157bd1607cedf1a5038dfd72c9
-F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
-F ext/fts5/fts5_index.c b7827b32e0e1e1ff7d7cb27c5d0480426a01c8ec4e89fd7e106bb463e2b63dd1
-F ext/fts5/fts5_main.c 47e7a63a936b5573570be299c13e9eaf2651eb25dce41b3e16430142e682e2c8
+F ext/fts5/fts5_expr.c 4a35c6edc4a36862597532ace43db20f5dfd4a2f789d4fa1dd7786b677b73036
+F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
+F ext/fts5/fts5_index.c 2f35dd8408946f0e0bfea8f3bfbe8dfaafe90a5345885b43d678546c19266673
+F ext/fts5/fts5_main.c 931e59db9c3052b787a486a70a3d5167b153f37c6e7c5674f4d607c6effb536b
F ext/fts5/fts5_storage.c 1ad05dab4830a4e2eaf2900bb143477f93bc17437093582f36f4b818809e88d8
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
-F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
+F ext/fts5/fts5_test_mi.c d35fdd50db99a775a040fb57127a45adc968e97da94ae784eec664256ac86db2
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
F ext/fts5/fts5_tokenize.c 49aea8cc400a690a6c4f83c4cedc67f4f8830c6789c4ee343404f62bcaebca7b
F ext/fts5/fts5_unicode2.c 6f9b0fb79a8facaed76628ffd4eb9c16d7f2b84b52872784f617cf3422a9b043
@@ -206,7 +206,7 @@ F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
F ext/fts5/test/fts5locale.test 83ba7ee12628b540d3098f39c39c1de0c0440eddff8f7512c8c698d0c4a3ae3c
-F ext/fts5/test/fts5matchinfo.test 877520582feb86bbfd95ab780099bcba4526f18ac75ee34979144cf86ba3a5a3
+F ext/fts5/test/fts5matchinfo.test 7806f6d521bb49bcb54fff88a50f137866f7000c96ccfd28500caa47b63cb0aa
F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test f4dee7da898d605a6488c5b7afaace3158ed6bb9addff78faa1b37b402b77fb9
@@ -246,7 +246,7 @@ F ext/fts5/test/fts5secure8.test 808ade9d172ed07b24b85c57dd53b6d2b1aba018b4e634d
F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08df2d951422bcef8e2ebc5
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
-F ext/fts5/test/fts5simple3.test 146ec3dc8f5763d6212641c9f0a2f1cba41679353d2add7b963beceb115dc7f4
+F ext/fts5/test/fts5simple3.test 4e03b82e669dc07bf9c9a04c306fa493764bc49c93e539896d87d88bd374fece
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a743bfe7d7b96895bdd87
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
@@ -287,10 +287,10 @@ F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028
F ext/intck/sqlite3intck.c 0d10df36e2b7b438aa80ecd3f5e584d41b747586b038258fe6b407f66b81e7c5
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
F ext/intck/test_intck.c 4f9eaadaedccb9df1d26ba41116a0a8e5b0c5556dc3098c8ff68633adcccdea8
-F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
-F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
+F ext/jni/GNUmakefile 7e3d3ea6571f035d26ed1b82e9bb7811e665ba95e3b9b91005547458417cd311
+F ext/jni/README.md e3fbd47c774683539b7fdc95a667eb9cd6e64d8510f3ee327e7fa0c61c8aa787
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
-F ext/jni/src/c/sqlite3-jni.c c1292e690a20c7787a63e8d8ac6e2dfed49c97282ed056a7cfda5da461f0b7d8
+F ext/jni/src/c/sqlite3-jni.c 4b2cd08c46a649b6369f4f1b63a38f10ef481b7a72e8230bb6c8d63d8c62e0df
F ext/jni/src/c/sqlite3-jni.h 913ab8e8fee432ae40f0e387c8231118d17053714703f5ded18202912a8a3fbf
F ext/jni/src/org/sqlite/jni/annotation/Experimental.java 8603498634e41d0f7c70f661f64e05df64376562ea8f126829fd1e0cdd47e82b
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java 38e7e58a69b26dc100e458b31dfa3b2a7d67bc36d051325526ef1987d5bc8a24
@@ -301,8 +301,8 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
-F ext/jni/src/org/sqlite/jni/capi/CApi.java 8620c652138b84af795fd65bc200028590f533407c093d4355f9524dc594c004
-F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b
+F ext/jni/src/org/sqlite/jni/capi/CApi.java 0c199e8e68c25f4b69cc583b73d9f329ed999a37d7a20d11fc4c2c7c0626d5fa
+F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 709e41af15ae6523b6b6d4a3a29d64be4fac42d5b2199074a04ddbb42aa92a15
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
F ext/jni/src/org/sqlite/jni/capi/CommitHookCallback.java 482f53dfec9e3ac2a9070d3fceebd56250932aaaf7c4f5bc8de29fc011416e0c
@@ -310,13 +310,13 @@ F ext/jni/src/org/sqlite/jni/capi/ConfigLogCallback.java b995ca412f59b631803b93a
F ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java e5723900b6458bc6288f52187090a78ebe0a20f403ac7c887ec9061dfe51aba7
F ext/jni/src/org/sqlite/jni/capi/NativePointerHolder.java b7036dcb1ef1b39f1f36ac605dde0ff1a24a9a01ade6aa1a605039443e089a61
F ext/jni/src/org/sqlite/jni/capi/OutputPointer.java 246b0e66c4603f41c567105a21189d138aaf8c58203ecd4928802333da553e7c
-F ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java 97352091abd7556167f4799076396279a51749fdae2b72a6ba61cd39b3df0359
+F ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java 7c96133a1542126374b39a65b2eaf4e01f97000e84b68812c475a7a8095414ed
F ext/jni/src/org/sqlite/jni/capi/PreupdateHookCallback.java efcf57545c5e282d1dd332fa63329b3b218d98f356ef107a9dbe3979be82213a
F ext/jni/src/org/sqlite/jni/capi/ProgressHandlerCallback.java 01bc0c238eed2d5f93c73522cb7849a445cc9098c2ed1e78248fa20ed1cfde5b
F ext/jni/src/org/sqlite/jni/capi/ResultCode.java 8141171f1bcf9f46eef303b9d3c5dc2537a25ad1628f3638398d8a60cacefa7f
F ext/jni/src/org/sqlite/jni/capi/RollbackHookCallback.java e172210a2080e851ebb694c70e9f0bf89284237795e38710a7f5f1b61e3f6787
F ext/jni/src/org/sqlite/jni/capi/SQLFunction.java 0d1e9afc9ff8a2adb94a155b72385155fa3b8011a5cca0bb3c28468c7131c1a5
-F ext/jni/src/org/sqlite/jni/capi/SQLTester.java 0b25cde8c5fa77f3e7ad92368acf195c5c64fb1c5273b8ee71b2d7ab812aab34
+F ext/jni/src/org/sqlite/jni/capi/SQLTester.java e2e63c92992c412b381e5577319c81e4f6c73b185ba15a85931ff5d5c3eb2600
F ext/jni/src/org/sqlite/jni/capi/ScalarFunction.java 93b9700fca4c68075ccab12fe0fbbc76c91cafc9f368e835b9bd7cd7732c8615
F ext/jni/src/org/sqlite/jni/capi/TableColumnMetadata.java addf120e0e76e5be1ff2260daa7ce305ff9b5fafd64153a7a28e9d8f000a815f
F ext/jni/src/org/sqlite/jni/capi/Tester1.java e5fa17301b7266c1cbe4bcce67788e08e45871c7c72c153d515abb37e501de0a
@@ -342,11 +342,11 @@ F ext/jni/src/org/sqlite/jni/fts5/XTokenizeCallback.java 1efd1220ea328a32f2d2a1b
F ext/jni/src/org/sqlite/jni/fts5/fts5_api.java a8e88c3783d21cec51b0748568a96653fead88f8f4953376178d9c7385b197ea
F ext/jni/src/org/sqlite/jni/fts5/fts5_extension_function.java 9e2b954d210d572552b28aca523b272fae14bd41e318921b22f65b728d5bf978
F ext/jni/src/org/sqlite/jni/fts5/fts5_tokenizer.java 92bdaa3893bd684533004d64ade23d329843f809cd0d0f4f1a2856da6e6b4d90
-F ext/jni/src/org/sqlite/jni/test-script-interpreter.md 9bf7e9cab1183287b048bb77baee4b266f0c15baf1b624feec12fbf00cfa7e94
+F ext/jni/src/org/sqlite/jni/test-script-interpreter.md 620754d59d97022198d0dcdd366b8c56dca07b080880a7618b33620cfd3d4a56
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 27b141f5914c7cb0e40e90a301d5e05b77f3bd42236834a68031b7086381fafd
-F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java ada39f18e4e3e9d4868dadbc3f7bfe1c6c7fde74fb1fb2954c3f0f70120b805c
+F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 1d6fbdb7bd875e861f0c52ae131c087ff09804face19587c3971ac72af626196
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 982538ddb4c0719ef87dfa664cd137b09890b546029a7477810bd64d4c47ee35
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java ce45f2ec85facbb73690096547ed166e7be82299e3d92eaa206f82b60a6ec969
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java a84e90c43724a69c2ecebd601bc8e5139f869b7d08cb705c77ef757dacdd0593
@@ -381,15 +381,15 @@ F ext/lsm1/lsm-test/lsmtest_tdb4.c cbe230727b9413d244062943371af1421ace472ccb023
F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001
-F ext/lsm1/lsmInt.h 3bcc280347196e4ed14925b64a07685415238bf41317db0598c8d3f6aaceb9c1
-F ext/lsm1/lsm_ckpt.c ad9a8028d401be9e76f20c4d86d49f33f4fc27785577b452ca955094314a72b4
-F ext/lsm1/lsm_file.c 5486f4a63b19e4d7d972ee2482f29ebdf06c29544f31845f713cccb5199f9ad1
-F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c
+F ext/lsm1/lsmInt.h 8e4ead919951d700c2d065326b22c8bf055b7fec6e75514c6151b5bb5d9d3030
+F ext/lsm1/lsm_ckpt.c 702a08e9fd92695976d759b259e2258330da99b3f8ac845f145e418cb70902ee
+F ext/lsm1/lsm_file.c 4bbc4cb1a558089d884e1e5a17b021d9056ae62add32dd6906d070954c7fe954
+F ext/lsm1/lsm_log.c 9450d193db7a50c96805f10f393ac8b08b2009b6330b7df7ae1e4b442ed219a7
F ext/lsm1/lsm_main.c 87770a9c7e73859fce7620cb79623776ba4b30369086229ad82c3e6eeaf45457
F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
F ext/lsm1/lsm_shared.c c67282a4f2c91e2a3362bdd40a81f9041cd587973ffc4bca8b8fbdab5470dee1
-F ext/lsm1/lsm_sorted.c bc276055afc21e7f23538d39d7cf2722379b56c79778ab7232f710e3374d501c
+F ext/lsm1/lsm_sorted.c 1bae85469458793adf753f7c5e695d8d15e33f28bc0ca07ebc9f1b58e853c56c
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
F ext/lsm1/lsm_unix.c 11e0a5c19d754a4e1d93dfad06de8cc201f10f886b8e61a4c599ed34e334fc24
@@ -400,7 +400,7 @@ F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1ded
F ext/lsm1/test/lsm1_simple.test a04d08e8661ae6fc53786c67f0bd102c6692f003e859dde03ed9ac3f12e066e5
F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
-F ext/misc/amatch.c 5001711cbecdd57b288cb613386789f3034e5beb58fbe0c79f2b3d643ffd4e03
+F ext/misc/amatch.c 2db45b1499b275d8340af6337a13d6216e4ceb2ddb41f4042b9801be7b5e593d
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c 73c31eb325c71bae2e27276565e3f674fc095d8b0d7a651becb3b241a4d2fa57
@@ -408,31 +408,31 @@ F ext/misc/base85.c a70c885c5c9350261ea6e7b166038eab21a09cf4fceae856ce41fae9c221
F ext/misc/basexx.c 89ad6b76558efbceb627afd5e2ef1d84b2e96d9aaf9b7ecb20e3d00b51be6fcf
F ext/misc/bgckpt.c 18cfc9c39ffab3299f730f86ae2991c8574c0bd9ec80efd2f89196798a7b7181
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
-F ext/misc/btreeinfo.c cb952620eedf5c0b7625b678f0f08e54d2ec0011d4e50efda5ebdc97f3df7d04
+F ext/misc/btreeinfo.c 8f5e6da2c82ec2f06ee0216e922370a436dafdbb06ffa7a552203515ff9e7ddf
F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c76a5
F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e98a5
F ext/misc/cksumvfs.c 3a7931dd30667be6348af919f3f9e6188dfd7646b42af8e399a499b327f5bd63
F ext/misc/closure.c 87e0967772e0087e709887ce7ca9cf13aa32d2096e33b5d3382c8b8d477c6cb1
F ext/misc/completion.c cb978c88d5577821323617a8ea775ce1b920e02dcdb593858f02044a4d008eea
F ext/misc/compress.c 2c79a74330e0e0ba6cb3f7397f8ba5af12d46377ef5d3ee075e12dd8a6ed57f0
-F ext/misc/csv.c 575c2c05fba0a451586a4d42c2c81e711780c41e797126f198d8d9e0a308dcdb
+F ext/misc/csv.c 7cae8c2666a058a58fb8994ed2457339a06c97d31c251d9a8445cdd966629890
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
-F ext/misc/decimal.c 172cf81a8634e6a0f0bedaf71a8372fee63348cf5a3c4e1b78bb233c35889fdc
+F ext/misc/decimal.c 0e6edab8b055230e0ad0787d2e4b84b01f302168c7621042f7e6d7a3c1d98230
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 07cf3109ec6452789e3a989a010234e2a17b599ce82ea29212c948572456abac
F ext/misc/fossildelta.c 8c026e086e406e2b69947f1856fa3b848fff5379962276430d10085b8756b05a
-F ext/misc/fuzzer.c 8b28acf1a7e95d50e332bdd47e792ff27054ad99d3f9bc2e91273814d4b31a5a
-F ext/misc/ieee754.c 62a90978204d2c956d5036eb89e548e736ca5fac0e965912867ddd7bb833256d
+F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
+F ext/misc/ieee754.c c9dd9d77c8e8e18e0a5706f8ffcccf4ccb6562073709f7453d4d73f5122f4362
F ext/misc/memstat.c 5b284b78be431c1f5fa154b18eade2407e42c65ed32ec9e9fbf195d114778d7d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
-F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
+F ext/misc/normalize.c 4782be3b74b9bd9f67281036ff1f41e5edcad20ad486171a2d671c4bb2586011
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
-F ext/misc/percentile.c 82531c62cd015b9cdca95ad6bb10c3a907ceb570d21ebd4fb7d634c809cfb089
+F ext/misc/percentile.c 72e05a21db20a2fa85264b99515941f00ae698824c9db82d7edfbb16cea8ec80
F ext/misc/prefixes.c 82645f79229877afab08c8b08ca1e7fa31921280906b90a61c294e4f540cd2a6
F ext/misc/qpvtab.c fc189e127f68f791af90a487f4460ec91539a716daf45a0c357e963fd47cc06c
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
@@ -440,9 +440,9 @@ F ext/misc/regexp.c 388e7f237307c7dfbfb8dde44e097946f6c437801d63f0d7ad63f3320d4e
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c cbdda2e2eb8159a1331974d246984c6e2693c6ea93930e6165046c8dbb8db0e9
+F ext/misc/series.c 13c13768db923313c561851c7feb0adf5c456a40d01bf7c57051895f3e4b81c7
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
-F ext/misc/shathree.c f3a778f27bf3e71b666a77f28e463a3b931c4dbe4219447e61bb678b4bc121c3
+F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c bcc42ef3fd29429bc01a83e751332b8d4690e65d45008449bdffe7656371487f
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
@@ -451,16 +451,16 @@ F ext/misc/sqlite3_stdio.h f05eaf5e0258f0573910324a789a9586fc360a57678c57a6d63cf
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
-F ext/misc/totype.c 75ed9827d19cc3b434fc2aeb60725d4d46e1534373615612a4d1cfdcc3d60922
-F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
+F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762bc3a8
+F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
-F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d
-F ext/misc/vfstrace.c a73386403c350b210dc788a2d23a0f5cc89c49b176109a66af11b5078c116331
+F ext/misc/vfsstat.c 20850f7c32c80b34b2095c06e1f7875e3614c5895b80e2969d9d50509ddce211
+F ext/misc/vfstrace.c 5264aedaa27967483f8bed0a2b42fce56d370f0af1559e5703329966ed742ddd
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
-F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
+F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
F ext/misc/zipfile.c b62147ac4985eaac4e368d529b1f4f43ad6bc9ac13d6805d907fff3afdac64d3
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
@@ -508,8 +508,8 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
F ext/rbu/rbuvacuum2.test ae097d04feb041446a74fac94b24bffeb3fdd60e32b848c5611e507ab702b81b
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
-F ext/rbu/sqlite3rbu.c 6b8ea18fec17cb9a2eb2a14eac98602a3ab9420cc102011be231b576c55542ed
-F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
+F ext/rbu/sqlite3rbu.c a2cdb71d9142a4a147abe1730cccf8f299f78dd07dbbb9b9056d907354e27a0f
+F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
F ext/rbu/test_rbu.c b9727c3394307d058e806c1da0f8bb7b24daf3c6bb94cb10cca88ea4d5c806c0
F ext/recover/dbdata.c 5295f4f922b60d7035b6b9fd5846b13071b9d97ed7fad8496837bb7640d24771
F ext/recover/recover1.test e16d78e94183562abff569967b18b7c77451d7044365516cd0fe14713a284851
@@ -532,16 +532,16 @@ F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0
F ext/recover/test_recover.c 072260d7452a3b81aba995b2b3269e7ec2aa7f06725544ba4c25b1b0a1dbc61a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
-F ext/repair/checkindex.c af5c66463f51462d8a6f796b2c44ef8cfa1116bbdc35a15da07c67a705388bfd
+F ext/repair/checkindex.c 7639b4f8928f82c10b950169e60cc45a7f6798df0b299771d17bef025736f657
F ext/repair/sqlite3_checker.c.in 445118c5f7fea958b36fba1b2c464283e60ed4842039ddee3265f1698115ebf7
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
-F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c 0dd4775e896cee6067979d67aff7c998e75c2c9d9cd8d62a1a790c09cde7adca
-F ext/rtree/rtree.c 4c58755830a0902435322bf61b2994ae02951a039daefb31cff9457d3e2aa201
+F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
+F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
+F ext/rtree/rtree.c 980f84e9fecfa99f80ae066e13b198505790449542f802d6b6466ed839149af4
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -568,7 +568,7 @@ F ext/rtree/rtreecheck.test 84eedb43b25b3edf591125266d0bb1cebdfcdcc9c4a56b27d85b
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
F ext/rtree/rtreedoc.test d633982d61542f3bc0a0a2df0382a02cc699ac56cbda01130cde6da44a228490
-F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c7daf8284d93
+F ext/rtree/rtreedoc2.test 0102b4e60f1baf0039bef7c1c4b39f1d3d77a68a5741513a0c190db28b884835
F ext/rtree/rtreedoc3.test 555a878c4d79c4e37fa439a1c3b02ee65d3ebaf75d9e8d96a9c55d66db3efbf8
F ext/rtree/rtreefuzz001.test 44f680a23dbe00d1061dbde381d711119099846d166580c4381e402b9d62cb74
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
@@ -623,11 +623,11 @@ F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3changebatch.c d488b42d8fd49fb013a1e9c4535232680dabeb28ae8f9421b65ea0ccc3b430f7
F ext/session/sqlite3changebatch.h e72016998c9a22d439ddfd547b69e1ebac810c24
-F ext/session/sqlite3session.c e33ff7bed8537a2fa6913711fbd4f3defd24c56a400a10da379b8a172bb7fee5
+F ext/session/sqlite3session.c dd612f40a615704b26a0d2ebec1221e0807774eba2903c74197b2b860a09b470
F ext/session/sqlite3session.h 223b853b34f86e1b7b501223ba1dfe2800e46c50c27ff8c40bb6bf15c3e70b30
F ext/session/test_session.c 3e9a06d0840013d6411fd17bf7948282224d4c54626cda3a1faa39ac89f0c056
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
-F ext/wasm/GNUmakefile 06e0556e9840fd3d8870997025c2507ace9ba7bf11195f770295fc7947dfc1b5
+F ext/wasm/GNUmakefile 24d7e6f446528fa67f5ade6c3c7d7e46e1ac52649d6264cbe24539c1dab608e1
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -646,34 +646,34 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
-F ext/wasm/api/sqlite3-api-glue.c-pp.js 5c0209e6a28164b4c2c1a34b0bb4aee3b7b1a264988d7e71fac08b8ede5b7ae3
+F ext/wasm/api/sqlite3-api-glue.c-pp.js bd8ae059bb3ea489666b2f167025833e55dc5941be99c129a56fc25e541d37ce
F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
-F ext/wasm/api/sqlite3-api-prologue.js 9e7d89a2c0d02b8b2052a62757a89f1e7e4dbcc0d9cd3f2dafa896786954dad2
+F ext/wasm/api/sqlite3-api-prologue.js 6fe109961d51a326ec3de065a4813c5c6928b6c5ae996712327c7dfcf4d42741
F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
-F ext/wasm/api/sqlite3-opfs-async-proxy.js 3774befd97cd1a5e2895c8225a894aad946848c6d9b4028acc988b5d123475af
+F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
-F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js bb5e96cd0fd6e1e54538256433f1c60a4e3095063c4d1a79a8a022fc59be9571
-F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 9b86ca2d8276cf919fbc9ba2a10e9786033b64f92c2db844d951804dee6c4b4e
+F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 16d80af915bfd2529824b999b304425503094eedf34fb113d0791e002b13e5cf
+F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
-F ext/wasm/api/sqlite3-wasm.c 6f9d8529072d072359cd22dc5dfb0572c524684686569cfbd0f9640d7619fc10
+F ext/wasm/api/sqlite3-wasm.c 6a4cd40267eaf08400895c5b9de39c56976c3b97b3c1bbe53fc2e80fa074e9c7
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46f303ba8ddd1b2f0a391798837beddfa72e8c897038c8047eda49ce7d5ed46b
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
F ext/wasm/batch-runner.js 05ec254f5dbfe605146d9640b3db17d6ef8c3fbef6aa8396051ca72bb5884e3f
-F ext/wasm/c-pp.c 6d131069644964223305582a80973477fa8b06b57306781690d7874ebd3a4f84
+F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e9a
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
-F ext/wasm/common/whwasmutil.js c2e459286c1ada789cda6b17761bb1eea6034be572468eed78c049354f1051ba
+F ext/wasm/common/whwasmutil.js 5e7fe4a2547831e003356c201ca28d9a0d6a19ab1fe2c8f63f82464fecd2cef7
F ext/wasm/config.make.in 4bc43443f768a61efd43cf995a5e618f58ac9afc0936706014193537d82c41cb
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32e7be5bf
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
-F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
+F ext/wasm/demo-jsstorage.js 42131ddfa18e817d0e39ac63745e9ea31553980a5ebd2222e04d4fac60c19837
F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a9ef7c42ff04d7a125ddca7e5db8
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
@@ -682,13 +682,13 @@ F ext/wasm/dist.make 92ef4ffe33022a50f92d602acabad10bd8dd91759f3eb7df27fc6d7d370
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
F ext/wasm/fiddle.make c6d7a3d6cc03bb5f21acb295c1233820d0dbf5c6a89b28dc2e093edcc001c45a
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
-F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
-F ext/wasm/fiddle/index.html c79b1741cbeba78f88af0a84cf5ec7de87a909a6a8d10a369b1f4824c66c2088
+F ext/wasm/fiddle/fiddle.js 2a2f27b4be2674f501fff61c4a09e44dcf2295731a26b5c28e439f3a573bd269
+F ext/wasm/fiddle/index.html 7fcfb221165183bef0e05d5af9ceb79b527e799b1708ab05de0ec0eaebd5b7bf
F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730
-F ext/wasm/index.html e4bbffdb3d40eff12b3f9c7abedef91787e2935620b7f8d40f2c774b80ad8fa9
-F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
-F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
-F ext/wasm/mkwasmbuilds.c baf6636e139e2c1e3b56e8dc26073ec80f6d14ae1876b023985315f43ccf312b
+F ext/wasm/index.html bcaa00eca521b372a6a62c7e7b17a870b0fcdf3e418a5921df1fd61e5344080d
+F ext/wasm/jaccwabyt/jaccwabyt.js 6e4f26d0edb5c2e7d381b7eff1924832a040a12274afab2d1e1789027e9f6c5c
+F ext/wasm/jaccwabyt/jaccwabyt.md 1128e3563e7eff90b5a373395251fc76cb32386fad1fea6075b0f34a8f1b9bdf
+F ext/wasm/mkwasmbuilds.c 082b7372db68c2d4cd9f55e7cde8eb1b83e9569e520984e6b08cb62606f3bf38
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
@@ -704,13 +704,16 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
-F ext/wasm/tester1.c-pp.js 05a0143c44a4114aad0ed40ce73c528febc3e0d6b69f48a51c895d7030015b74
+F ext/wasm/tester1.c-pp.js f3a3cbf0207287c4caa9f84b4e2934804e4b5720c71eaf143f33c8122bd3c9f2
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
+F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca01385e2732294b53f4c842328
+F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
+F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk ce22facb893e7c6d6416f718591b6e818a7ae946cca1648857cd3b625fa5a311
+F main.mk 095d20b12406d08c55101d75757b637e81dd230a92e2039909fbeb717b5e4d97
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -720,37 +723,37 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
-F src/alter.c 1751e231d8385067fa0d0145f0d461a092db6bd3d7edbfc3172db625aceccd9a
-F src/analyze.c e5b0ad463758b59b3e8426dc6f21ed9ba352fa45eccebbad469420413330fa73
-F src/attach.c c36d9d82811e2274bd06bf3b34459e36d8ae8a7f32efa5cbf3f890eef08a9987
+F src/alter.c 0d2122ade76617b7cca383428d0881a9821ef8ddaf9cce6ff91d69a215614b95
+F src/analyze.c 8ebb9ae6dca90f6e0ee5db97a1ef8a3aad018218bc3a083fcd52c742e4bc3edb
+F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
-F src/bitvec.c 1028c37a0a08a2204beab7d9f5a48e0e18de8fde280ab7098a2f149fdc692b38
-F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
-F src/btree.c dd0a6c8600eedc27a7f40d7f5c034c42c916b9802e3660e7225d4c9ae05bbae7
+F src/bitvec.c 93c1fb3e5d8fbfed7daacfc2210555ebbddb1b04efb12763b46189a76106e1c1
+F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
+F src/btree.c 3fd1729b8d17e2ae6f2a73818e7feb905150449e796ac662925722fabe064b39
F src/btree.h df26089b055c4cffe243e5bc98edc729c4ad880bfeb8f229fd16248e4cec10ff
-F src/btreeInt.h bb28bf05e6206befd5f5fd2ed3825fc6382979fa4a83bf50f1875a0d3404111b
-F src/build.c 94e1a3347e90ad2ba708501d3572af069e443f1d8b2667279a12bc7dc0ec4218
+F src/btreeInt.h c3b8750a8dd8bc9a38840be463e7d23899b9da08276fa442e2bb8efd1052bc48
+F src/build.c 56e9426add88babcb8ee9e039b5ccd55e0400f75bcafe62a34f9c6cdbc865f64
F src/callback.c bd1ecfce052f6a5854497b16e6cae4f39f314d62fe43bd4cdaa452ab93623f3c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/date.c 842c08ac143a56a627b05ac51d68624f2b7b03e3b4cba596205e735eed64ee57
+F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c 6e0635f3e3761f368d10e77d26d29a1a521ab208f1be66e84c13354ffbcf5ad2
+F src/expr.c f27e2692e65f0600cf4c989ec2af36bdfab52ada6365c0cc0f434630157b877f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
-F src/func.c de7970100bba7dd46ffc90dbdd50034864f2fe9144edae52545ec77f050bcf40
+F src/func.c c7f750bbf0ac3174fe280571d09ca1385b74bca7b1168f19c902fc65631959f7
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 05e04ef637cbc0dccb9a5c5d188a5a2608891e554c8ec17c7a71afe2cf896a06
-F src/json.c 5abb5cb782e74451a8882f6b7ee4d5e629246642262660bd1980a5e1b796258d
+F src/insert.c a5f0366266be993ebf533808f22cb7a788624805b55bc45424ceed3f48c54a16
+F src/json.c 81e2012796a0e139b18c50ee3444c8ef86a020ab360511882216f5b610657e0c
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
-F src/main.c 20b0b613b4a81354394ec90f942514ae6f1c12b30779a027ba080eaa9812e270
+F src/main.c dab3f7449d3ff2ff5b8f809de68e99231fcc453882de3164370c39e6cf89c488
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -771,33 +774,33 @@ 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 447cfc845acfd6369556a2295f69c1a7fe8260e91b97cf1b162d959328ed3437
-F src/os_win.c 2423a45e70c2cda01bfc84106f7e9f34feb1add42121ab2e35a67ba24589ac52
+F src/os_unix.c 0c7933e24ba1fe59b6f52f2ae85c62d25e81ae8ad32631afc0190b6138468641
+F src/os_win.c ab9912a2c1cb39a6429b8de919a5b63ad1c7775e511d748391c57bf9ad03bd29
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c c7ef086ba3f90b675d240489b5448e731973ce8a5b1026479df73758c12e43c5
+F src/pager.c 67197fa41300ba1f2ff5d5ef11171f8a599c922ccd98cf0ad4f0a3174ced9f1f
F src/pager.h dd6ade22dd303a8ca6c34f1ff0f299add7191c1bff65f0289b7fd7c3460f9551
-F src/parse.y 0248f0250118de917396f4e181d78cf16634cbf23d725262f238b5b30ee7f7c4
+F src/parse.y 4829520938e08f824c343cbafaf17f959e28ac106801d62722f722a6ce525c50
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c dc4e5b90947e42a2d9c0d5f38cf7649f49dfe228162a8a6df3d093ca21bf6be4
-F src/pragma.c 0a26a652ae91f8ca355b1cfbf9556b8b2c3834df4bfad939fa2b3b9f2c1f686f
+F src/pragma.c c6dbc66743689d2a7a8073a49ee0440df939fca8e1c5ab38c8ea5a0d8c0a2a85
F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
-F src/printf.c b9ac740dfaf68552f5da1266be28ae2824b53a6b73d93425f7c6b2ef62457cbb
+F src/printf.c 33fc0d7643c848a098afdcb6e1db6de12379d47084b1cd0912cfce1d09345e44
F src/random.c 9bd018738ec450bf35d28050b4b33fa9a6eebf3aaefb1a1cff42dc14a7725673
F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c 2a728386716408aaef0b94a449ad8ee385b10e0b5bea437b9cdc7c101df2c280
-F src/shell.c.in b377a59822f207106424f08aead37e78b609222e98f86f04cc8a03563ccf3237
-F src/sqlite.h.in 8bbd003968210d90edd8390717cbd7a3c9e9403ca4c698f9ffee8bc3c5eab6b9
+F src/select.c dd7cd5cbc5567a312612f028dbcd1bac0dab0e2400f3c50e2dbaff3d057094b6
+F src/shell.c.in 6bb2abfb5cbeb5b017b8d0e94e39dd1efd101b22aca07a6734b155b6d4d03f62
+F src/sqlite.h.in 92023fda13b0d3bca0c520b25520155f1a755abda1530e91dcc1432ca61d26ca
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h 47ab9050a25858b348f01d825c636b5eeae7dc9d2b8d406cd80a1635f628f4c0
-F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523
-F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
+F src/sqliteInt.h 0da73bba15bd828d6097e46302326bf87ba550f3d0e660ff8a227071c38452e6
+F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
+F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 5c1e367e26711044730c93d4b81312170918a8d1fe811f45be740ab48f7de8c1
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
-F src/test1.c 8aacd293374b9428e4a7de7e19aed8bbed07aa8e6001b3f915666a04d19bbea2
+F src/test1.c f3ed699eb0d1e332d6ab95081d4176a209e2acbe2a54b310b4df9470f817c101
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
F src/test4.c 13e57ae7ec7a959ee180970aef09deed141252fe9bb07c61054f0dfa4f1dfd5d
@@ -810,7 +813,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 39a37de458a3082ee194dd65e71f596889b4ff0d7b5018aa60f796b96068c0b6
+F src/test_config.c 7bd467660d36ce56cea4a291cf75b3018effea87b6cc8f58a8873d65be1e1bc4
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -830,7 +833,7 @@ F src/test_mutex.c f10fcbc2086b19c7b0ddf2752caf2095e42be74d8d7f6093619445b43b1f7
F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
F src/test_osinst.c 7aa3feaa3a1da1b5f75bde2ce958dbfe14ec484f065bb2b5b9727d8851fa089b
F src/test_pcache.c 496da3f7e2ca66aefbc36bbf22138b1eff43ba0dff175c228b760fa020a37bd0
-F src/test_quota.c 07369655d24c3f3fbdbd8fd8f42e856a054a7497846ca1c83ed4be68152a251f
+F src/test_quota.c 744552848d9c5c5de3920d1c44b03d425a4123a223310567a199c7e0d3fe80bf
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c d844d746a3cc027247318b970025a927f14772339c991f40e7911583ea5ed0d9
F src/test_schema.c b06d3ddc3edc173c143878f3edb869dd200d57d918ae2f38820534f9a5e3d7d9
@@ -841,7 +844,7 @@ F src/test_tclsh.c 179e8c9fc722240275d5d9c5d9ff0d8e652c7614f601b8699c41d9c703f7e
F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e048424
F src/test_thread.c d7a8bcea7445f37cc2a1f7f81dd6059634f45e0c61bfe80182b02872fb0328bb
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
-F src/test_vfs.c f298475e468c7e14945b20af885917181090c265aa3c4ade897849c9fbd396f2
+F src/test_vfs.c a19728c5930b5f5f415c664c57b029cba98c459fe70639aefcbfc4f70d544335
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb775ebc50
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
@@ -852,8 +855,8 @@ F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc6227
F src/trigger.c da3c25786870d8bf97cd46b493374c2375d1abaf20a9b0f5f8629a3f2f2ce383
F src/update.c e1a8b1876e6f2a1824a6b9f1999a03d5dd50ce250a1bb86ea133e5b4b359488b
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
-F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
-F src/util.c 9ff6470dabcf943fd796d2da766c98bd328c8f6fe036a31e5b338e628603f989
+F src/utf.c d4d55ca95106a2029ec1cdbd2497a34e69ea1d338f1a9d80ef15ebf4ff01690d
+F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c 25e407a6dc8b288fa4295b3d92fa9ce9318503e84df53cdf403a50fccbc1ba31
F src/vdbe.c 8548b7aa0d74fa16628c0b4306e4e337d60175809f6b362b862af4aa2cdbcb04
F src/vdbe.h 3d26d5c7660c5c7bd33ffb0d8784615072d8b23c81f8110870efe2631136bc89
@@ -862,19 +865,19 @@ F src/vdbeapi.c cb8eb9e41a16f5fa3ce5b8f3910edfbba336d10156cfb7a79f92cf7bf443977b
F src/vdbeaux.c 8ead261b9236a6d4be538dc163a21cb07d9d6e93e0e482feb538888025d84aab
F src/vdbeblob.c 9166b6eb7054e5da82e35255892fb1ed551355a4716452539e8e3ac14f25fbe3
F src/vdbemem.c 571ae3116dbf840a62c4aaa6bc09d577dfef8ad4d3978cf37275bb5f9653217b
-F src/vdbesort.c 3e8e6340ec5f68909a975031081102471300eaec9791d081b5443822e1061cda
+F src/vdbesort.c f7ce6eb4c0e8b0273329d2f43b8b6e5ebe8f2d853fc323d5787dada702ea0b66
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c d477a0bd88f1519f58e50a8d61f3df90302b57df3bc2e2e89299828d63ece7f3
+F src/wal.c 4da2e9a7f9e96993133c62d87de4750477bb66d611619f527eef3c37c95fa0a3
F src/wal.h 8d02ab8c2a93a941f5898eb3345bf711c1d3f8f86f4be8d5428fb6c074962d8a
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c 09dc313e7223ca1217c39c7026b00f16ff449a8323511a762fcba7863a00f4cd
+F src/where.c 12cca5dfbe96e2589f951c43c0720fc58e52611787c37d85a0d9c10376202e8b
F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1
F src/wherecode.c 5baa06f0daae7d38aca1d4814030b82ad4f127fe6bad18f0644776a474f6088b
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
-F src/window.c 2bf01f9941a64fbcead61a0e3cb5db3fca5094b30d2ff0d23274c2a81d2e2385
+F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
@@ -886,8 +889,8 @@ F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
F test/alter.test 3c00eff1e2036b9f93e9cd0f3d3e63750ac87ecb5bc71b9d7bd07cbf2ac4c494
F test/alter2.test 7e3d26ab409df52df887b366a63902c3429b935c41cb962fd58ffc25784f2f19
-F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680fba3
-F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
+F test/alter3.test dcdd5f850f30656a45a0f05e41abfb52b74bbf6ccba165d0f7adf6b0116e4fd6
+F test/alter4.test da7a702818ac9696d8a5c048ae3505e3b659ac0e6ad16f5bff53c1ed95dfa7fc
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc
F test/altercol.test 29fed774747777fbbaacdd865b4413ed2d0844a4c824f8af531b5c7d4a832087
@@ -906,7 +909,7 @@ F test/altertab3.test b331ae34e69594e19605e3297805202d6156fcc8f75379dfd972a2e51c
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
-F test/analyze3.test 03f4b3d794760cf15da2d85a52df9bae300e51c8fefe9c36cfae1f86dc10d23f
+F test/analyze3.test c5156cef33f04b90a6b9e9d5d0bbc273a0fb44147d4508407bf1080811e2c6c8
F test/analyze4.test 68bd069f3ac7ac1e652ddd9f04f57d5606ddb4208450f5297005db7aa0dd707d
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
F test/analyze6.test 028f5bdfc9e5b5294768fa9a7185b8cd1d019aa7aab5b2f8ee42d7271d9a3b28
@@ -1014,7 +1017,7 @@ F test/cksumvfs.test 6f05dc95847c06a3dc10eee6b5ab1351d78314a52d0db15717c9388f4cb
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
-F test/collate1.test 71a6f27fdc93a92f14d8ab80c05e1937656a5a03197e1a10157314554d630ce8
+F test/collate1.test 0890fa372753b59eba53832d37328af815f6b8e4b16761823180eeb62c8e8f64
F test/collate2.test 471c6f74573382b89b0f8b88a05256faa52f7964f9e4799e76708a3b1ece6ba4
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
@@ -1024,8 +1027,8 @@ F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334
F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
-F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
-F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
+F test/collateB.test 9c840e21f9aead6fc533cea310f0bd202d5c11511088811b7e93ae7b47fccb24
+F test/colmeta.test 248a644cec4c7c371cf1e107fd8fdba708dc290866c572672b6260e3466cce79
F test/colname.test 387e880eeac0889900f7b3e9703c375515f5d323f71fd4f2bb5428a4ac8e2023
F test/columncount.test 6fe99c2f35738b0129357a1cf3fa483f76140f4cd8a89014c88c33c876d2638f
F test/commitstatus.test d5a871506ce5944a29afb7e65ce47ca7f76cadc1d09775022830258fdd6168a1
@@ -1094,7 +1097,7 @@ F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64a
F test/date4.test 75dc8401e8c0639a228cd26a6eaa4ff5ea8ccda912b9853d1c9462c476670e17
F test/date5.test 14ba189bc4d03efc371dd5302e035764f6633355a3e13acb4a45e7b33530231e
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
-F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
+F test/dbfuzz.c fc566102f72c8af84ae8077b4faf7f056c571e6fa7a32e98b66e42b7505f47b6
F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8ba8e9c3
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
@@ -1143,7 +1146,7 @@ F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
F test/e_walhook.test 01b494287ba9e60b70f6ebf3c6c62e0ffe01788e344a4846b08e5de0b344cb66
F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
F test/enc.test b5503a87b31cea8a5084c6e447383f9ca08933bd2f29d97b6b6201081b2343eb
-F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
+F test/enc2.test 872afe58db772e7dfa1ad8e0759f8cc820e9efc8172d460fae83023101c2e435
F test/enc3.test 55ef64416d72975c66167310a51dc9fc544ba3ae4858b8d5ab22f4cb6500b087
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 82f221e8cd588434d7f3bba9a0f4c78cbe7a541615a41632e12f50608bfb4a99
@@ -1163,7 +1166,7 @@ F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/external_reader.test c7d34694f1b25c32d866f56ac80c1e29edddc42b4ef90cad589263ffac2cde0c
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
-F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
+F test/filectrl.test 7e6788759997139632eb700765d5f73d53fc5ff5d9d778e773911750ab134321
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/filter1.test 590f8ba9a0cd0823b80d89ac75c5ce72276189cef9225d2436adaf1ee87f3727
F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
@@ -1216,7 +1219,7 @@ F test/fts3corrupt4.test bf9eabf113474f0ae73c9e001aeb3fcf2150b260f2309f300379cbd
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
F test/fts3corrupt7.test 1da31776e24bb91d3c028e663456b61280b121a74496ccf2fef3fe33790ad2b0
-F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
+F test/fts3cov.test 1e5ecea0e4c1394cea97adcfb9fd3d2d5998fd563dacf465f413e6c7fa5cffb3
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
F test/fts3defer2.test 3bbe54a7fca7d548bb7ac4f59447ee591070bfbe0c9f3e279defa0b898e9afbb
@@ -1225,7 +1228,7 @@ F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3dropmod.test 7de242ea1c8a713a8b143ea54468f4b1c4953fa068349e23ac178e2c90c59889
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526
-F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
+F test/fts3expr2.test ef381978b9bdcfc6d4b47c86270ba356a75dbff164ce52ff5d18a5924a788614
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
F test/fts3expr4.test 6c7675bbdbffe6ffc95e9e861500b8ac3f739c4d004ffda812f138eeb1b45529
F test/fts3expr5.test a5b9a053becbdb8e973fbf4d6d3abaabeb42d511d1848bd57931f3e0a1cf983e
@@ -1263,7 +1266,7 @@ F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4intck1.test 54e7f28e34b72fb0c614d414bb1f568154d463c5a00b20944e893df858372ed4
-F test/fts4langid.test 4be912f42454998e239a2e877600263e0394afbaba03e06cedcc5a08693a345a
+F test/fts4langid.test 1cc6fe045f094f1695d0b20e6b817a2ce22ec470cb7c6577470cd71ed0256e90
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
F test/fts4merge.test 57d093660a5093ae6e9fbd2d17592a88b45bbd66db2703c4b640b28828dbe38b
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
@@ -1288,15 +1291,15 @@ F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d8
F test/func6.test 3bc89ec0f2605736d3a118f43d25ef58115a7db4dba8ae939a363917d815c0bb
F test/func7.test 7e009275f52c52954c8c028fdb62f8bc16cc47276fcc8753c1d2b22c6e074598
F test/func8.test c4e2ecacf9f16e47a245e7a25fbabcc7e78f9c7c41a80f158527cdfdc6dd299d
-F test/func9.test b32d313f679aa9698d52f39519d301c3941823cb72b4e23406c210eadd82c824
+F test/func9.test 62750dbbbcc9a2d241918b5f999f59e2126084d5f81904f9e1d8ee466666a19d
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
-F test/fuzz.test 4608c1310cff4c3014a84bcced6278139743e080046e5f6784b0de7b069371d8
+F test/fuzz.test 819ea7e483bcee91209aacbe6f9eaf3287baa1841479ee5f639f57c5e7c42b86
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce313
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 6fc952750a69168dd5fea38b9d35cb38475bfda15c8acfd156ac09cd03ddbd3e
+F test/fuzzcheck.c 97eab1b916d576a0f734b921598bdac05ff04d1f15c494dbe40ca71a772c56bb
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1323,7 +1326,7 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test d1cad4ededd425568b2e39fb0c31fa9a3772311dd595801ff13ba3912b69bba6
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f
+F test/in4.test e7b1456d423453884aeb9d68fafe9c8e7be7abddc8f028c04205e67820f10772
F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a
F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
F test/in7.test d9efdee00b074a60c6343993b2eda78bc369ab080dad864513c73f8aca89d566
@@ -1348,7 +1351,7 @@ F test/index7.test b238344318e0b4e42126717f6554f0e7dfd0b39cecad4b736039b43e1e3b6
F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a912a3
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
-F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
+F test/indexedby.test 444fb04ce0b21a3daf79f84e6735b49e5a5b3396623b37df5431eb09c8b8f557
F test/indexexpr1.test 928671af9d7374bb56ed4dcfbc157f4eeddb1e86ab5615ceb3ac97a713c2dd8f
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
F test/indexexpr3.test 47b91bc7999805c9a34d356f672259bc49295ecc797448511cae554a309b47cd
@@ -1400,7 +1403,7 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json/README.md de59d5ba0bd2796d797115688630a6405bbf43a2891bad445ac6b9f38b83f236
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
-F test/json/json-speed-check.sh 912ee03e700a65c827ee0c7b4752c21ec5ef69cf7679d2f482ca817042bead52 x
+F test/json/json-speed-check.sh 7d5898808ce7542762318306ae6075a30f5e7ee115c4a409f487e123afe91d88 x
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
F test/json101.test 30db5b055b103ccabc53a29cfe6cda3345d07e171aeb25403dafa04f19e98b19
F test/json102.test 9b2e5ada10845ff84853b3feaae2ce51ce7145ae458f74c6a6cecc6ef6ee3ae1
@@ -1435,7 +1438,7 @@ F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37
F test/lock5.test 583cae05992af0f66607286917f7d5f8aed3b6053c52df5994efb98f2a8fdbaf
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
-F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
+F test/lock_common.tcl f0a1f7b8f3fbb8629dc6231613a02841736f86ef72151429d5ffc12c7f613fb3
F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083
F test/main.test e8752d76233b1c8906cd2c98ad920dba868bd63c87d51d8a2ea5e9cba55dd496
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
@@ -1486,7 +1489,7 @@ F test/misc5.test 02fcaf4d42405be02ec975e946270a50b0282dac98c78303ade0d1392839d2
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
-F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
+F test/misuse.test 46d42ffdf375833ea5828796e56f84660344f7548659b493059f152f00e66840
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
@@ -1655,7 +1658,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 5d84e415adf7cc4edd5913c4f23c761104ff135b9c190fcf7b430a4cbca6cb65
+F test/shell1.test 573942b8d0e444956445993d5a5275c6912bc49b654441eec0b5e1e735f2e5b7
F test/shell2.test 01a01f76ed98088ce598794fbf5b359e148271541a8ddbf79d21cc353cc67a24
F test/shell3.test db1953a8e59d08e9240b7cc5948878e184f7eb2623591587f8fd1f1a5bd536d8
F test/shell4.test 522fdc628c55eff697b061504fb0a9e4e6dfc5d9087a633ab0f3dd11bcc4f807
@@ -1664,6 +1667,7 @@ F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bd
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
+F test/shellA.test 079c05c11947ade4ea8d51053d3abb687ec96a3dce6680d01838519b705190c5
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1745,9 +1749,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl b1ffedf6bc6e0044448813e37f3ec3496e35268c35802a508f2f013cf5f74247
-F test/testrunner.tcl 90ed8b6c2b26dc1f6af08aeb04670a5df86172f3d9828d8af000f972afa50061 x
-F test/testrunner_data.tcl 63ff9eba1d11a3b0a6fc8446d5fa32da21aabda55b994e8fcbd4a8ce81f48378
+F test/tester.tcl 779d5a928fa7b5d7ac0f8d91182b0d0ea5f06dba8ac7baab4add0268b3864058
+F test/testrunner.tcl 0ffa67806e75aa2c186c63d7d00b16bb45adb91ed6560461fda6dbe3e18c885e x
+F test/testrunner_data.tcl 6d7e7824bb36278ea65c33f7da6dd3ca101fc7d6f7a765b807dce0aa68c52521
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -2059,7 +2063,9 @@ F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
F test/walrofault.test 5a25f91c16a68bae65edec7cdef4495e5c6494c8408743fe9b29045fa6665cd0
F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b
-F test/walsetlk.test 34c901443b31ab720afc463f5b236c86ca5c4134402573dce91aa0761de8db5a
+F test/walsetlk.test 9c5b92f9a20252540fedf9ffa6ee3d1b8af08ea4b80d0144d9b88e6c0c1de80d
+F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
+F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
@@ -2095,7 +2101,7 @@ F test/wherelimit3.test 22d73e046870cf8bbe15573eda6b432b07ebe64a88711f9f849c6b36
F test/widetab1.test c296a98e123762de79917350e45fa33fdf88577a2571eb3a64c8bf7e44ef74d1
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
-F test/win32longpath.test 304006024ca47104bf5a7415ef31ca83ecfc29351af202baf8588b880cffc116
+F test/win32longpath.test c5d149ab60a3052fa84b3df12ff655d703bfdfd48eed9854b14945d4d0bf3ddd
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 79dc3b9a2226f622d7e104a1fc750d1c4c3c08d6147b59085bdbe05352947ffa
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
@@ -2127,7 +2133,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
F test/with6.test 281e4861b5e517f6c3c2f08517a520c1e2ee7c11966545d3901f258a4fe8ef76
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test a5210b8770dc4736bca4e74bc96588f43025ad03ad6a80f885afd36d9890e217
+F test/without_rowid1.test 545a98bde0dc641cce8d361cd589677a70561f36f9033ae48de8ae37418d6ce2
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -2145,7 +2151,7 @@ F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a1688
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
-F tool/build-all-msvc.bat c817b716e0edeecaf265a6775b63e5f45c34a6544f1d4114a222701ed5ac79ab x
+F tool/build-all-msvc.bat 1960a7a3e5d8176c4329e31476f6e3dfa9543675355fa9020a569f4452628458 x
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
F tool/buildtclext.tcl 20726b6b73c7911baa8519a9467b4062104339a5ce57947819884525c56d79e3
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
@@ -2164,13 +2170,13 @@ F tool/fast_vacuum.c c129ae2924a48310c7b766810391da9e8fda532b9f6bd3f9a9e3a799a1b
F tool/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c 41480c8a1e4749351f381431ecfdfceba645396c5d836f8d26b51a33c4a21b33
-F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
+F tool/genfkey.README e550911fa984c8255ebed2ef97824125d83806eb5232582700de949edf836eb1
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 2418ee31f65764d150f7dd87ef00b4408f1b01a55db0b30bed673a3e336ae718
-F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f
+F tool/lemon.c f51a488369046cd4f4212d755a214a57673ded400cbeb01e298cbf63539e1d8c
+F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
@@ -2179,20 +2185,20 @@ F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a19
F tool/mkamalzip.tcl 8aa5ebe7973c8b8774062d34e15fea9815c4cc2ceea3a9b184695f005910876a
F tool/mkautoconfamal.sh c5e65fa1c922f2e3b3e4f6cd0331ec7d84bdef085f32cb1c46673cdf95ec8090
F tool/mkccode.tcl 210159febe0ef0ecbc53c79833500663ceaba0115b2b374405818dc835b5f84b x
-F tool/mkctimec.tcl 4b8824c28883a12c4ef7c6aeabd7f7068e0815613374e9cb9206866938af38b6 x
+F tool/mkctimec.tcl a384e7613db2a46e346cb4593731239a9239e942ff00aabd0c2b5d9e7afae840 x
F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559
F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14ebb7a
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl a2995a2d1a94cfd51a423b2a35f003905a7128b82623bdacf92ea962a0146923
+F tool/mkpragmatab.tcl 10694206dfe9d1f6e24d5876d52bb56e67706ef20bc479002bb88b67b90be045
F tool/mkshellc.tcl 9ce74de0fa904a2c56a96f8d8b5261246bacb0eaa8d7e184f9e18ff94145ebbc
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 351c55256213154cabb051a3c870ef9f4487de905015141ae50dc7578a901b84
F tool/mksqlite3c.tcl ba13086555b3cb835eba5e47a9250300ab85304d23fd1081abd3f29d8ab71a2b
-F tool/mksqlite3h.tcl b05b85c32295bad3fe64807729693d1f19faed3c464c5faac6c53bb6b972ac2f
-F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
+F tool/mksqlite3h.tcl 989948c6a26e188e673d7c2f2f093ea3acd816ad6ac65bab596280075c8f3a45
+F tool/mksqlite3internalh.tcl 46ef6ed6ccd3c36e23051109dd25085d8edef3887635cea25afa81c4adf4d4db
F tool/mksrczip.tcl 81efd9974dbb36005383f2cd655520057a2ae5aa85ac2441a80c7c28f803ac52
F tool/mktoolzip.tcl 34b4e92be544f820e2cc26f143f7d5aec511e826ec394cc82969a5dcf7c7a27c
F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e540a
@@ -2204,16 +2210,16 @@ F tool/pagesig.c f98909b4168d9cac11a2de7f031adea0e2f3131faa7515a72807c03ec58eafe
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
F tool/restore_jrnl.tcl 1079ecba47cc82fa82115b81c1f68097ab1f956f357ee8da5fc4b2589af6bd98
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
-F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
+F tool/run-speed-test.sh df9686c0991ea7c617b2cb5467d89d34b561f198ab91cb87735e27030ede92e8
F tool/showdb.c 3956d71e5193162609a60e8c9edfcf09274c00cfea2b1d221261427adb2b5cca
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3d
-F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
+F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdaddf
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
-F tool/speed-check.sh e566ab3934d7d78631743a984ad3f67c331c911bb18ff5d0a6c616a2afee7f91
+F tool/speed-check.sh 2d9e337449f8eb9f5ab4c1ce7433024e334ea03a68d48aa9caee6229c7cf0774
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -2221,7 +2227,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 07e18a1d8cc3f6b3a4a1f3528e63c9b29a5c8a7bca0b8d394b231da464ce1247
-F tool/sqldiff.c 2a0987d183027c795ced13d6749061c1d2f38e24eddb428f56fa64c3a8f51e4b
+F tool/sqldiff.c 134be7866be19f8beb32043d5aea5657f01aaeae2df8d33d758ff722c78666b9
F tool/sqlite3_analyzer.c.in fc7735c499d226a49d843d8209b2543e4e5229eeb71a674c331323a2217b65b4
F tool/sqlite3_rsync.c 9a1cca2ab1271c59b37a6493c15dc1bcd0ab9149197a9125926bc08dd26b83fb
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
@@ -2230,7 +2236,7 @@ F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/srctree-check.tcl fa4d82dd3e8a38d5cbce7d6ade8abef2f42b9eca0394484d521dc8d086739460
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
-F tool/stripccomments.c dfe9cc03cf87728ac9836be30763f8aa52b82caca0780b3d3f3572e4643b01d3
+F tool/stripccomments.c 68d2aa8cb504439f541ce66b8f128067612bdd16f5fb7bfe540f3fcb67c9c197
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9b9
F tool/tclConfigShToAutoDef.sh 44ec55046d86a3febb2cb3e099399b41794e80e9cd138eee7b9b016f819e882b x
@@ -2244,8 +2250,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P e0f898f356e50568ebf62f18f39b05d2428038b88e277613bbed818dac1b0fd0 bd4651659548bfa523dd99f0c771b7d3c9f5dc41d0412f4f939710c4f4c6e17d
-R fc291289df97b3287f937a94973f5401
+P c09656c62155a6e82d0fa6c27bf8ec40a14854845adfa53db3cb42a0b1b29101 6baea938f0230f8b81b33373f948857fc44c2b3788bf8d4ee6e863b045632b82
+R 9b5b182d3e757a134dc7fd2660d623f9
U drh
-Z 9cbb9b042987efe615bef13a49da10ea
+Z 063d922da06754a7aed08c70efa95784
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 6a4eefdf04..f52c614475 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-c09656c62155a6e82d0fa6c27bf8ec40a14854845adfa53db3cb42a0b1b29101
+203376300781167f3e96da0197a9c8e8da6fed15c56c8980a4c283ef34478a07
diff --git a/src/alter.c b/src/alter.c
index 5f706b513f..8192571662 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -531,13 +531,13 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
+ pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc);
pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
if( !pNew->aCol || !pNew->zName ){
assert( db->mallocFailed );
goto exit_begin_add_column;
}
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol);
for(i=0; inCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
@@ -1144,7 +1144,13 @@ static int renameParseSql(
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
return SQLITE_CORRUPT_BKPT;
}
- db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
+ if( bTemp ){
+ db->init.iDb = 1;
+ }else{
+ int iDb = sqlite3FindDbName(db, zDb);
+ assert( iDb>=0 && iDb<=0xff );
+ db->init.iDb = (u8)iDb;
+ }
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
@@ -1211,10 +1217,11 @@ static int renameEditSql(
nQuot = sqlite3Strlen30(zQuot)-1;
}
- assert( nQuot>=nNew );
- zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
+ zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1));
}else{
- zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ assert( nSql>0 );
+ zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
@@ -1226,16 +1233,17 @@ static int renameEditSql(
** with the new column name, or with single-quoted versions of themselves.
** All that remains is to construct and return the edited SQL string. */
if( zOut ){
- int nOut = nSql;
- memcpy(zOut, zSql, nSql);
+ i64 nOut = nSql;
+ assert( nSql>0 );
+ memcpy(zOut, zSql, (size_t)nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- u32 nReplace;
+ i64 nReplace;
const char *zReplace;
RenameToken *pBest = renameColumnTokenNext(pRename);
if( zNew ){
- if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
+ if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){
nReplace = nNew;
zReplace = zNew;
}else{
@@ -1253,14 +1261,15 @@ static int renameEditSql(
memcpy(zBuf1, pBest->t.z, pBest->t.n);
zBuf1[pBest->t.n] = 0;
sqlite3Dequote(zBuf1);
- sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ assert( nSql < 0x15555554 /* otherwise malloc would have failed */ );
+ sqlite3_snprintf((int)(nSql*2), zBuf2, "%Q%s", zBuf1,
pBest->t.z[pBest->t.n]=='\'' ? " " : ""
);
zReplace = zBuf2;
nReplace = sqlite3Strlen30(zReplace);
}
- iOff = pBest->t.z - zSql;
+ iOff = (int)(pBest->t.z - zSql);
if( pBest->t.n!=nReplace ){
memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n],
nOut - (iOff + pBest->t.n)
@@ -1286,11 +1295,12 @@ static int renameEditSql(
** Set all pEList->a[].fg.eEName fields in the expression-list to val.
*/
static void renameSetENames(ExprList *pEList, int val){
+ assert( val==ENAME_NAME || val==ENAME_TAB || val==ENAME_SPAN );
if( pEList ){
int i;
for(i=0; inExpr; i++){
assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME );
- pEList->a[i].fg.eEName = val;
+ pEList->a[i].fg.eEName = val&0x3;
}
}
}
@@ -1547,7 +1557,7 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -1765,7 +1775,7 @@ static void renameTableFunc(
sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View );
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
if( sParse.nErr ){
rc = sParse.rc;
@@ -1938,7 +1948,7 @@ static void renameQuotefixFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -2037,7 +2047,7 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- int flags = db->flags;
+ u64 flags = db->flags;
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
diff --git a/src/analyze.c b/src/analyze.c
index fcea024771..4a36b596b9 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -450,7 +450,7 @@ static void statInit(
p->db = db;
p->nEst = sqlite3_value_int64(argv[2]);
p->nRow = 0;
- p->nLimit = sqlite3_value_int64(argv[3]);
+ p->nLimit = sqlite3_value_int(argv[3]);
p->nCol = nCol;
p->nKeyCol = nKeyCol;
p->nSkipAhead = 0;
diff --git a/src/attach.c b/src/attach.c
index f6c224710d..085e1b0ecc 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -227,6 +227,13 @@ static void attachFunc(
sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){
+ int val = 1;
+ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt));
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val);
+ }
+#endif
if( !REOPEN_AS_MEMDB(db) ){
rc = sqlite3Init(db, &zErrDyn);
}
diff --git a/src/bitvec.c b/src/bitvec.c
index 6eddb7f87e..8ab5f6e288 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -67,7 +67,7 @@
** no fewer collisions than the no-op *1. */
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
-#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
+#define BITVEC_NPTR ((u32)(BITVEC_USIZE/sizeof(Bitvec *)))
/*
@@ -256,7 +256,7 @@ void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
}
}
if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1)));
}else{
unsigned int j;
u32 *aiValues = pBuf;
@@ -307,7 +307,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
** individual bits within V.
*/
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
/*
diff --git a/src/btmutex.c b/src/btmutex.c
index 232831e037..620047c151 100644
--- a/src/btmutex.c
+++ b/src/btmutex.c
@@ -185,7 +185,7 @@ int sqlite3BtreeHoldsMutex(Btree *p){
*/
static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
- int skipOk = 1;
+ u8 skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; inDb; i++){
diff --git a/src/btree.c b/src/btree.c
index b1ecc95778..0417b5e540 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -1252,7 +1252,7 @@ void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
*/
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
- pCur->hints = x;
+ pCur->hints = (u8)x;
}
@@ -1453,14 +1453,15 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
int maxLocal; /* Maximum amount of payload held locally */
maxLocal = pPage->maxLocal;
+ assert( nPayload>=0 );
if( nPayload<=maxLocal ){
- return nPayload;
+ return (int)nPayload;
}else{
int minLocal; /* Minimum amount of payload held locally */
int surplus; /* Overflow payload available for local storage */
minLocal = pPage->minLocal;
- surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
- return ( surplus <= maxLocal ) ? surplus : minLocal;
+ surplus = (int)(minLocal +(nPayload - minLocal)%(pPage->pBt->usableSize-4));
+ return (surplus <= maxLocal) ? surplus : minLocal;
}
}
@@ -1570,11 +1571,13 @@ static void btreeParseCellPtr(
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==(u32)pPage->maxLocal+1 );
+ assert( nPayload>=0 );
+ assert( pPage->maxLocal <= BT_MAX_LOCAL );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -1607,11 +1610,13 @@ static void btreeParseCellPtrIndex(
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==(u32)pPage->maxLocal+1 );
+ assert( nPayload>=0 );
+ assert( pPage->maxLocal <= BT_MAX_LOCAL );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -2150,14 +2155,14 @@ static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
-static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
- u16 iPtr; /* Address of ptr to next freeblock */
- u16 iFreeBlk; /* Address of the next freeblock */
+static int freeSpace(MemPage *pPage, int iStart, int iSize){
+ int iPtr; /* Address of ptr to next freeblock */
+ int iFreeBlk; /* Address of the next freeblock */
u8 hdr; /* Page header size. 0 or 100 */
- u8 nFrag = 0; /* Reduction in fragmentation */
- u16 iOrigSize = iSize; /* Original value of iSize */
- u16 x; /* Offset to cell content area */
- u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
+ int nFrag = 0; /* Reduction in fragmentation */
+ int iOrigSize = iSize; /* Original value of iSize */
+ int x; /* Offset to cell content area */
+ int iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
u8 *pTmp; /* Temporary ptr into data[] */
@@ -2184,7 +2189,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
+ if( iFreeBlk>(int)pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
@@ -2199,7 +2204,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ){
+ if( iEnd > (int)pPage->pBt->usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
iSize = iEnd - iStart;
@@ -2220,7 +2225,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
}
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
- data[hdr+7] -= nFrag;
+ data[hdr+7] -= (u8)nFrag;
}
pTmp = &data[hdr+5];
x = get2byte(pTmp);
@@ -2241,7 +2246,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* Insert the new freeblock into the freelist */
put2byte(&data[iPtr], iStart);
put2byte(&data[iStart], iFreeBlk);
- put2byte(&data[iStart+2], iSize);
+ assert( iSize>=0 && iSize<=0xffff );
+ put2byte(&data[iStart+2], (u16)iSize);
}
pPage->nFree += iOrigSize;
return SQLITE_OK;
@@ -2467,7 +2473,7 @@ static int btreeInitPage(MemPage *pPage){
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
pPage->maskPage = (u16)(pBt->pageSize - 1);
pPage->nOverflow = 0;
- pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+ pPage->cellOffset = (u16)(pPage->hdrOffset + 8 + pPage->childPtrSize);
pPage->aCellIdx = data + pPage->childPtrSize + 8;
pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
@@ -2501,8 +2507,8 @@ static int btreeInitPage(MemPage *pPage){
static void zeroPage(MemPage *pPage, int flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
- u8 hdr = pPage->hdrOffset;
- u16 first;
+ int hdr = pPage->hdrOffset;
+ int first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
@@ -2519,7 +2525,7 @@ static void zeroPage(MemPage *pPage, int flags){
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
- pPage->cellOffset = first;
+ pPage->cellOffset = (u16)first;
pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
@@ -3316,7 +3322,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
BtShared *pBt = p->pBt;
assert( nReserve>=0 && nReserve<=255 );
sqlite3BtreeEnter(p);
- pBt->nReserveWanted = nReserve;
+ pBt->nReserveWanted = (u8)nReserve;
x = pBt->pageSize - pBt->usableSize;
if( nReservebtsFlags & BTS_PAGESIZE_FIXED ){
@@ -3422,7 +3428,7 @@ int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
if( newFlag>=0 ){
p->pBt->btsFlags &= ~BTS_FAST_SECURE;
- p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
+ p->pBt->btsFlags |= (u16)(BTS_SECURE_DELETE*newFlag);
}
b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
sqlite3BtreeLeave(p);
@@ -8127,7 +8133,8 @@ static int rebuildPage(
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
- pPg->nCell = nCell;
+ assert( nCell < 10922 );
+ pPg->nCell = (u16)nCell;
pPg->nOverflow = 0;
put2byte(&aData[hdr+1], 0);
@@ -8374,9 +8381,13 @@ static int editPage(
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iNew+nCell, nNew-nCell, pCArray
- ) ) goto editpage_fail;
+ )
+ ){
+ goto editpage_fail;
+ }
- pPg->nCell = nNew;
+ assert( nNew < 10922 );
+ pPg->nCell = (u16)nNew;
pPg->nOverflow = 0;
put2byte(&aData[hdr+3], pPg->nCell);
@@ -8686,7 +8697,7 @@ static int balance_nonroot(
int pageFlags; /* Value of pPage->aData[0] */
int iSpace1 = 0; /* First unused byte of aSpace1[] */
int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
- int szScratch; /* Size of scratch memory requested */
+ u64 szScratch; /* Size of scratch memory requested */
MemPage *apOld[NB]; /* pPage and up to two siblings */
MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
u8 *pRight; /* Location in parent of right-sibling pointer */
@@ -9973,7 +9984,7 @@ int sqlite3BtreeInsert(
if( pCur->info.nKey==pX->nKey ){
BtreePayload x2;
x2.pData = pX->pKey;
- x2.nData = pX->nKey;
+ x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff );
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
@@ -10155,7 +10166,7 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
getCellInfo(pSrc);
if( pSrc->info.nPayload<0x80 ){
- *(aOut++) = pSrc->info.nPayload;
+ *(aOut++) = (u8)pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
@@ -10168,7 +10179,7 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
nRem = pSrc->info.nPayload;
if( nIn==nRem && nInpPage->maxLocal ){
memcpy(aOut, aIn, nIn);
- pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace);
return SQLITE_OK;
}else{
int rc = SQLITE_OK;
@@ -10180,7 +10191,7 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
u32 nOut; /* Size of output buffer aOut[] */
nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
- pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = (int)nOut + (int)(aOut - pBt->pTmpSpace);
if( nOutinfo.nPayload ){
pPgnoOut = &aOut[nOut];
pBt->nPreformatSize += 4;
diff --git a/src/btreeInt.h b/src/btreeInt.h
index 7a806638bd..431b1e2c09 100644
--- a/src/btreeInt.h
+++ b/src/btreeInt.h
@@ -509,6 +509,12 @@ struct CellInfo {
*/
#define BTCURSOR_MAX_DEPTH 20
+/*
+** Maximum amount of storage local to a database page, regardless of
+** page size.
+*/
+#define BT_MAX_LOCAL 65501 /* 65536 - 35 */
+
/*
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
diff --git a/src/build.c b/src/build.c
index 77aa93409a..0375d03903 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1067,10 +1067,16 @@ Index *sqlite3PrimaryKeyIndex(Table *pTab){
** find the (first) offset of that column in index pIdx. Or return -1
** if column iCol is not used in index pIdx.
*/
-i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
+int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
int i;
+ i16 iCol16;
+ assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
+ assert( pIdx->nColumn<=SQLITE_MAX_COLUMN );
+ iCol16 = iCol;
for(i=0; inColumn; i++){
- if( iCol==pIdx->aiColumn[i] ) return i;
+ if( iCol16==pIdx->aiColumn[i] ){
+ return i;
+ }
}
return -1;
}
@@ -2167,12 +2173,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){
** Resize an Index object to hold N columns total. Return SQLITE_OK
** on success and SQLITE_NOMEM on an OOM error.
*/
-static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
+static int resizeIndexObject(Parse *pParse, Index *pIdx, int N){
char *zExtra;
- int nByte;
+ u64 nByte;
+ sqlite3 *db;
if( pIdx->nColumn>=N ) return SQLITE_OK;
+ db = pParse->db;
+ assert( N>0 );
+ assert( N <= SQLITE_MAX_COLUMN*2 /* tag-20250221-1 */ );
+ testcase( N==2*pParse->db->aLimit[SQLITE_LIMIT_COLUMN] );
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*(u64)N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
@@ -2186,7 +2197,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
zExtra += sizeof(i16)*N;
memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
pIdx->aSortOrder = (u8*)zExtra;
- pIdx->nColumn = N;
+ pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */
pIdx->isResized = 1;
return SQLITE_OK;
}
@@ -2440,7 +2451,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pIdx->nColumn = pIdx->nKeyCol;
continue;
}
- if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
+ if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return;
for(i=0, j=pIdx->nKeyCol; inKeyCol, pPk, i) ){
testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
@@ -2464,7 +2475,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !hasColumn(pPk->aiColumn, nPk, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
}
- if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
+ if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; inCol; i++){
if( !hasColumn(pPk->aiColumn, j, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
@@ -3848,13 +3859,14 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
*/
Index *sqlite3AllocateIndexObject(
sqlite3 *db, /* Database connection */
- i16 nCol, /* Total number of columns in the index */
+ int nCol, /* Total number of columns in the index */
int nExtra, /* Number of bytes of extra space to alloc */
char **ppExtra /* Pointer to the "extra" space */
){
Index *p; /* Allocated index object */
i64 nByte; /* Bytes of space for Index object + arrays */
+ assert( nCol <= 2*db->aLimit[SQLITE_LIMIT_COLUMN] );
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
@@ -3867,8 +3879,9 @@ Index *sqlite3AllocateIndexObject(
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
- p->nColumn = nCol;
- p->nKeyCol = nCol - 1;
+ assert( nCol>0 );
+ p->nColumn = (u16)nCol;
+ p->nKeyCol = (u16)(nCol - 1);
*ppExtra = ((char*)p) + nByte;
}
return p;
diff --git a/src/date.c b/src/date.c
index de27366370..1b4f10fb40 100644
--- a/src/date.c
+++ b/src/date.c
@@ -1357,7 +1357,7 @@ static int daysAfterMonday(DateTime *pDate){
** In other words, return the day of the week according
** to this code:
**
-** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
+** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
*/
static int daysAfterSunday(DateTime *pDate){
assert( pDate->validJD );
diff --git a/src/expr.c b/src/expr.c
index 0f86e126de..a3c41a1f57 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1963,7 +1963,7 @@ Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
@@ -4672,7 +4672,7 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
/*
-** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This
+** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
** function checks the Parse.pIdxPartExpr list to see if this column
** can be replaced with a constant value. If so, it generates code to
** put the constant value in a register (ideally, but not necessarily,
diff --git a/src/func.c b/src/func.c
index dd564fef59..a019c85aa6 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1092,7 +1092,7 @@ static const char hexdigits[] = {
** Append to pStr text that is the SQL literal representation of the
** value contained in pValue.
*/
-void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
+void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){
/* As currently implemented, the string must be initially empty.
** we might relax this requirement in the future, but that will
** require enhancements to the implementation. */
@@ -1140,7 +1140,7 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
case SQLITE_TEXT: {
const unsigned char *zArg = sqlite3_value_text(pValue);
- sqlite3_str_appendf(pStr, "%Q", zArg);
+ sqlite3_str_appendf(pStr, bEscape ? "%#Q" : "%Q", zArg);
break;
}
default: {
@@ -1151,6 +1151,105 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
}
+/*
+** Return true if z[] begins with N hexadecimal digits, and write
+** a decoding of those digits into *pVal. Or return false if any
+** one of the first N characters in z[] is not a hexadecimal digit.
+*/
+static int isNHex(const char *z, int N, u32 *pVal){
+ int i;
+ int v = 0;
+ for(i=0; i0 ){
+ memmove(&zOut[j], &zIn[i], n);
+ j += n;
+ i += n;
+ }
+ if( zIn[i+1]=='\\' ){
+ i += 2;
+ zOut[j++] = '\\';
+ }else if( sqlite3Isxdigit(zIn[i+1]) ){
+ if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error;
+ i += 5;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='+' ){
+ if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error;
+ i += 8;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='u' ){
+ if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error;
+ i += 6;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='U' ){
+ if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error;
+ i += 10;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else{
+ goto unistr_error;
+ }
+ }
+ zOut[j] = 0;
+ sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8);
+ return;
+
+unistr_error:
+ sqlite3_free(zOut);
+ sqlite3_result_error(context, "invalid Unicode escape", -1);
+ return;
+}
+
+
/*
** Implementation of the QUOTE() function.
**
@@ -1160,6 +1259,10 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
** embedded NUL characters cannot be represented as string literals in SQL
** and hence the returned string literal is truncated prior to the first NUL.
+**
+** If sqlite3_user_data() is non-zero, then the UNISTR_QUOTE() function is
+** implemented instead. The difference is that UNISTR_QUOTE() uses the
+** UNISTR() function to escape control characters.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_str str;
@@ -1167,7 +1270,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
UNUSED_PARAMETER(argc);
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
- sqlite3QuoteValue(&str,argv[0]);
+ sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context)));
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
SQLITE_DYNAMIC);
if( str.accError!=SQLITE_OK ){
@@ -1818,7 +1921,7 @@ static void kahanBabuskaNeumaierInit(
** that it returns NULL if it sums over no inputs. TOTAL returns
** 0.0 in that case. In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
-** value. TOTAL never fails, but SUM might through an exception if
+** value. TOTAL never fails, but SUM might throw an exception if
** it overflows an integer.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
@@ -2738,7 +2841,9 @@ void sqlite3RegisterBuiltinFunctions(void){
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
+ FUNCTION(unistr, 1, 0, 0, unistrFunc ),
FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(unistr_quote, 1, 1, 0, quoteFunc ),
VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
VFUNCTION(changes, 0, 0, 0, changes ),
VFUNCTION(total_changes, 0, 0, 0, total_changes ),
diff --git a/src/insert.c b/src/insert.c
index c1ca1897ed..7dc9bfd8b1 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -693,7 +693,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
f = (f & pLeft->selFlags);
}
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
- pLeft->selFlags &= ~SF_MultiValue;
+ pLeft->selFlags &= ~(u32)SF_MultiValue;
if( pSelect ){
pSelect->op = TK_ALL;
pSelect->pPrior = pLeft;
diff --git a/src/json.c b/src/json.c
index 97bf25b2dd..5360831af0 100644
--- a/src/json.c
+++ b/src/json.c
@@ -419,7 +419,7 @@ static int jsonCacheInsert(
** most-recently used entry if it isn't so already.
**
** The JsonParse object returned still belongs to the Cache and might
-** be deleted at any moment. If the caller whants the JsonParse to
+** be deleted at any moment. If the caller wants the JsonParse to
** linger, it needs to increment the nPJRef reference counter.
*/
static JsonParse *jsonCacheSearch(
@@ -3464,7 +3464,7 @@ rebuild_from_cache:
** JSON functions were suppose to work. From the beginning, blob was
** reserved for expansion and a blob value should have raised an error.
** But it did not, due to a bug. And many applications came to depend
- ** upon this buggy behavior, espeically when using the CLI and reading
+ ** upon this buggy behavior, especially when using the CLI and reading
** JSON text using readfile(), which returns a blob. For this reason
** we will continue to support the bug moving forward.
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
diff --git a/src/main.c b/src/main.c
index 3e03debbae..a10655ae59 100644
--- a/src/main.c
+++ b/src/main.c
@@ -303,6 +303,14 @@ int sqlite3_initialize(void){
if( rc==SQLITE_OK ){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
+ {
+ int SQLITE_EXTRA_INIT_MUTEXED(const char*);
+ rc = SQLITE_EXTRA_INIT_MUTEXED(0);
+ }
+#endif
+ }
+ if( rc==SQLITE_OK ){
sqlite3MemoryBarrier();
sqlite3GlobalConfig.isInit = 1;
#ifdef SQLITE_EXTRA_INIT
@@ -1779,6 +1787,9 @@ int sqlite3_busy_handler(
db->busyHandler.pBusyArg = pArg;
db->busyHandler.nBusy = 0;
db->busyTimeout = 0;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ db->setlkTimeout = 0;
+#endif
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -1828,12 +1839,47 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
(void*)db);
db->busyTimeout = ms;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ db->setlkTimeout = ms;
+#endif
}else{
sqlite3_busy_handler(db, 0, 0);
}
return SQLITE_OK;
}
+/*
+** Set the setlk timeout value.
+*/
+int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int iDb;
+ int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0);
+#endif
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+#endif
+ if( ms<-1 ) return SQLITE_RANGE;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ db->setlkTimeout = ms;
+ db->setlkFlags = flags;
+ sqlite3BtreeEnterAll(db);
+ for(iDb=0; iDbnDb; iDb++){
+ Btree *pBt = db->aDb[iDb].pBt;
+ if( pBt ){
+ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt));
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC);
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+#endif
+#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(flags);
+#endif
+ return SQLITE_OK;
+}
+
/*
** Cause any pending operation to stop at its earliest opportunity.
*/
@@ -4165,8 +4211,8 @@ int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
**
** If b is true, then activate the SQLITE_FkNoAction setting. If b is
- ** false then clearn that setting. If the SQLITE_FkNoAction setting is
- ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if
+ ** false then clear that setting. If the SQLITE_FkNoAction setting is
+ ** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if
** they were NO ACTION, regardless of how they are defined.
**
** NB: One must usually run "PRAGMA writable_schema=RESET" after
diff --git a/src/os_unix.c b/src/os_unix.c
index 8580337f00..de972a845b 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -294,6 +294,7 @@ struct unixFile {
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
unsigned iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect; /* True to block for SHARED locks */
#endif
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID */
@@ -1698,6 +1699,13 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
rc = 0;
}
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
+ && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE
+ ){
+ rc = osFcntl(pFile->h, F_SETLKW, pLock);
+ }else
+#endif
rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
}
return rc;
@@ -4067,8 +4075,9 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
- pFile->iBusyTimeout = *(int*)pArg;
+ pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew;
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
pFile->iBusyTimeout = !!(*(int*)pArg);
#else
@@ -4077,7 +4086,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = iOld;
return SQLITE_OK;
}
-#endif
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -5185,7 +5199,7 @@ static int unixShmLock(
**
** It is not permitted to block on the RECOVER lock.
*/
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
@@ -7026,7 +7040,7 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
/* Almost all modern unix systems support nanosleep(). But if you are
** compiling for one of the rare exceptions, you can use
- ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
** usleep() is available) in order to bypass the use of nanosleep() */
nanosleep(&sp, NULL);
diff --git a/src/os_win.c b/src/os_win.c
index 4258b8d8a3..dab8af34c4 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -287,8 +287,18 @@ struct winFile {
sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ DWORD iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect;
+#endif
};
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout
+#else
+# define winFileBusyTimeout(pDbFd) 0
+#endif
+
/*
** The winVfsAppData structure is used for the pAppData member for all of the
** Win32 VFS variants.
@@ -722,6 +732,12 @@ static struct win_syscall {
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].pCurrent)
+/*
+** For GetLastError(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "GetLastError", (SYSCALL)GetLastError, 0 },
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
@@ -1004,11 +1020,13 @@ static struct win_syscall {
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
DWORD,DWORD))aSyscall[62].pCurrent)
-#if !SQLITE_OS_WINRT
+/*
+** For WaitForSingleObject(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-#else
- { "WaitForSingleObject", (SYSCALL)0, 0 },
-#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[63].pCurrent)
@@ -1155,6 +1173,40 @@ static struct win_syscall {
#define osFlushViewOfFile \
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
+** to implement blocking locks with timeouts. MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CreateEvent", (SYSCALL)CreateEvent, 0 },
+#else
+ { "CreateEvent", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateEvent ( \
+ (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
+ aSyscall[80].pCurrent \
+)
+
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
+** for the case where a timeout expires and a lock request must be
+** cancelled.
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CancelIo", (SYSCALL)CancelIo, 0 },
+#else
+ { "CancelIo", (SYSCALL)0, 0 },
+#endif
+
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent)
+
}; /* End of the overrideable system calls */
/*
@@ -1453,7 +1505,9 @@ int sqlite3_win32_is_nt(void){
}
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+ return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2
+ || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0
+ ;
#else
/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
@@ -2540,6 +2594,85 @@ static BOOL winLockFile(
#endif
}
+/*
+** Lock a region of nByte bytes starting at offset offset of file hFile.
+** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock
+** otherwise. If nMs is greater than zero and the lock cannot be obtained
+** immediately, block for that many ms before giving up.
+**
+** This function returns SQLITE_OK if the lock is obtained successfully. If
+** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or
+** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR.
+*/
+static int winHandleLockTimeout(
+ HANDLE hFile,
+ DWORD offset,
+ DWORD nByte,
+ int bExcl,
+ DWORD nMs
+){
+ DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0);
+ int rc = SQLITE_OK;
+ BOOL ret;
+
+ if( !osIsNT() ){
+ ret = winLockFile(&hFile, flags, offset, 0, nByte, 0);
+ }else{
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offset;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( nMs!=0 ){
+ flags &= ~LOCKFILE_FAIL_IMMEDIATELY;
+ }
+ ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL);
+ if( ovlp.hEvent==NULL ){
+ return SQLITE_IOERR_LOCK;
+ }
+#endif
+
+ ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp);
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was
+ ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to
+ ** LockFileEx() may fail because the request is still pending. This can
+ ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified.
+ **
+ ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags
+ ** passed to LockFileEx(). In this case, if the operation is pending,
+ ** block indefinitely until it is finished.
+ **
+ ** Otherwise, wait for up to nMs ms for the operation to finish. nMs
+ ** may be set to INFINITE.
+ */
+ if( !ret && GetLastError()==ERROR_IO_PENDING ){
+ DWORD nDelay = (nMs==0 ? INFINITE : nMs);
+ DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay);
+ if( res==WAIT_OBJECT_0 ){
+ ret = TRUE;
+ }else if( res==WAIT_TIMEOUT ){
+ rc = SQLITE_BUSY_TIMEOUT;
+ }else{
+ /* Some other error has occurred */
+ rc = SQLITE_IOERR_LOCK;
+ }
+
+ /* If it is still pending, cancel the LockFileEx() call. */
+ osCancelIo(hFile);
+ }
+
+ osCloseHandle(ovlp.hEvent);
+#endif
+ }
+
+ if( rc==SQLITE_OK && !ret ){
+ rc = SQLITE_BUSY;
+ }
+ return rc;
+}
+
/*
** Unlock a file region.
*/
@@ -2571,6 +2704,14 @@ static BOOL winUnlockFile(
#endif
}
+/*
+** Remove an nByte lock starting at offset iOff from HANDLE h.
+*/
+static int winHandleUnlock(HANDLE h, int iOff, int nByte){
+ BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0);
+ return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK);
+}
+
/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
@@ -2584,66 +2725,70 @@ static BOOL winUnlockFile(
#endif
/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
-** Otherwise, set pFile->lastErrno and return non-zero.
+** Seek the file handle h to offset nByte of the file.
+**
+** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
+** error code.
*/
-static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
+ int rc = SQLITE_OK; /* Return value */
+
#if !SQLITE_OS_WINRT
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
DWORD dwRet; /* Value returned by SetFilePointer() */
- DWORD lastErrno; /* Value returned by GetLastError() */
-
- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
+ dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
+
/* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
** whether an error has actually occurred, it is also necessary to call
- ** GetLastError().
- */
- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-
- if( (dwRet==INVALID_SET_FILE_POINTER
- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ ** GetLastError(). */
+ if( dwRet==INVALID_SET_FILE_POINTER ){
+ DWORD lastErrno = osGetLastError();
+ if( lastErrno!=NO_ERROR ){
+ rc = SQLITE_IOERR_SEEK;
+ }
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#else
- /*
- ** Same as above, except that this implementation works for WinRT.
- */
-
+ /* This implementation works for WinRT. */
LARGE_INTEGER x; /* The new offset */
BOOL bRet; /* Value returned by SetFilePointerEx() */
x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+ bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN);
if(!bRet){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ rc = SQLITE_IOERR_SEEK;
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#endif
+
+ OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc)));
+ return rc;
}
+/*
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
+** Otherwise, set pFile->lastErrno and return non-zero.
+*/
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+ int rc;
+
+ rc = winHandleSeek(pFile->h, iOffset);
+ if( rc!=SQLITE_OK ){
+ pFile->lastErrno = osGetLastError();
+ winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath);
+ }
+ return rc;
+}
+
+
#if SQLITE_MAX_MMAP_SIZE>0
/* Forward references to VFS helper methods used for memory mapped files */
static int winMapfile(winFile*, sqlite3_int64);
@@ -2903,6 +3048,60 @@ static int winWrite(
return SQLITE_OK;
}
+/*
+** Truncate the file opened by handle h to nByte bytes in size.
+*/
+static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){
+ int rc = SQLITE_OK; /* Return code */
+ rc = winHandleSeek(h, nByte);
+ if( rc==SQLITE_OK ){
+ if( 0==osSetEndOfFile(h) ){
+ rc = SQLITE_IOERR_TRUNCATE;
+ }
+ }
+ return rc;
+}
+
+/*
+** Determine the size in bytes of the file opened by the handle passed as
+** the first argument.
+*/
+static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
+ int rc = SQLITE_OK;
+
+#if SQLITE_OS_WINRT
+ FILE_STANDARD_INFO info;
+ BOOL b;
+ b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info));
+ if( b ){
+ *pnByte = info.EndOfFile.QuadPart;
+ }else{
+ rc = SQLITE_IOERR_FSTAT;
+ }
+#else
+ DWORD upperBits = 0;
+ DWORD lowerBits = 0;
+
+ assert( pnByte );
+ lowerBits = osGetFileSize(h, &upperBits);
+ *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
+ rc = SQLITE_IOERR_FSTAT;
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** Close the handle passed as the only argument.
+*/
+static void winHandleClose(HANDLE h){
+ if( h!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(h);
+ }
+}
+
/*
** Truncate an open file to a specified size
*/
@@ -3158,8 +3357,9 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
-static int winGetReadLock(winFile *pFile){
+static int winGetReadLock(winFile *pFile, int bBlock){
int res;
+ DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0);
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
if( osIsNT() ){
#if SQLITE_OS_WINCE
@@ -3169,7 +3369,7 @@ static int winGetReadLock(winFile *pFile){
*/
res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
SHARED_SIZE, 0);
#endif
}
@@ -3178,7 +3378,7 @@ static int winGetReadLock(winFile *pFile){
int lk;
sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask,
SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
}
#endif
@@ -3273,46 +3473,62 @@ static int winLock(sqlite3_file *id, int locktype){
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+ /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
** the PENDING_LOCK byte is temporary.
*/
newLocktype = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
){
int cnt = 3;
- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- PENDING_BYTE, 0, 1, 0))==0 ){
+
+ /* Flags for the LockFileEx() call. This should be an exclusive lock if
+ ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to
+ ** obtain SHARED. */
+ int flags = LOCKFILE_FAIL_IMMEDIATELY;
+ if( locktype==EXCLUSIVE_LOCK ){
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ while( cnt>0 ){
/* Try 3 times to get the pending lock. This is needed to work
** around problems caused by indexing and/or anti-virus software on
** Windows systems.
+ **
** If you are using this code as a model for alternative VFSes, do not
- ** copy this retry logic. It is a hack intended for Windows only.
- */
+ ** copy this retry logic. It is a hack intended for Windows only. */
+ res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0);
+ if( res ) break;
+
lastErrno = osGetLastError();
- OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
- pFile->h, cnt, res));
+ OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
+ pFile->h, cnt, res
+ ));
+
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
- OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
- pFile->h, cnt, sqlite3ErrName(rc)));
+ OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
+ pFile->h, cnt, sqlite3ErrName(rc)
+ ));
return rc;
}
- if( cnt ) sqlite3_win32_sleep(1);
+
+ cnt--;
+ if( cnt>0 ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
- if( !res ){
- lastErrno = osGetLastError();
- }
}
/* Acquire a shared lock
*/
if( locktype==SHARED_LOCK && res ){
assert( pFile->locktype==NO_LOCK );
- res = winGetReadLock(pFile);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ res = winGetReadLock(pFile, pFile->bBlockOnConnect);
+#else
+ res = winGetReadLock(pFile, 0);
+#endif
if( res ){
newLocktype = SHARED_LOCK;
}else{
@@ -3350,7 +3566,7 @@ static int winLock(sqlite3_file *id, int locktype){
newLocktype = EXCLUSIVE_LOCK;
}else{
lastErrno = osGetLastError();
- winGetReadLock(pFile);
+ winGetReadLock(pFile, 0);
}
}
@@ -3430,7 +3646,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
+ if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
@@ -3640,6 +3856,28 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return rc;
}
#endif
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = (DWORD)(!!iNew);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
+ *(int*)pArg = iOld;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
return SQLITE_NOTFOUND;
@@ -3720,23 +3958,27 @@ static int winShmMutexHeld(void) {
**
** The following fields are read-only after the object is created:
**
-** fid
** zFilename
**
** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
+** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate
+** the *-shm file if the DMS-locking protocol demands it, and (c) map
+** regions of the *-shm file into memory using MapViewOfFile() or
+** similar. Other locks are taken by individual clients using the
+** winShm.hShm handles.
*/
struct winShmNode {
sqlite3_mutex *mutex; /* Mutex to access this object */
char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
+ HANDLE hSharedShm; /* File handle open on zFilename */
+ int isUnlocked; /* DMS lock has not yet been obtained */
+ int isReadonly; /* True if read-only */
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
@@ -3745,7 +3987,6 @@ struct winShmNode {
DWORD lastErrno; /* The Windows errno from the last I/O error */
int nRef; /* Number of winShm objects pointing to this */
- winShm *pFirst; /* All winShm objects pointing to this */
winShmNode *pNext; /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
@@ -3761,23 +4002,15 @@ static winShmNode *winShmNodeList = 0;
/*
** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** winShm.pShmNode
-** winShm.id
-**
-** All other fields are read/write. The winShm.pShmNode->mutex must be held
-** while accessing any read/write fields.
+** open shared memory connection. There is one such structure for each
+** winFile open on a wal mode database.
*/
struct winShm {
winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
+ HANDLE hShm; /* File-handle on *-shm file. For locking. */
+ int bReadonly; /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
@@ -3789,50 +4022,6 @@ struct winShm {
#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define WINSHM_UNLCK 1
-#define WINSHM_RDLCK 2
-#define WINSHM_WRLCK 3
-static int winShmSystemLock(
- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
- int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
- int ofst, /* Offset to first byte to be locked/unlocked */
- int nByte /* Number of bytes to lock or unlock */
-){
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
-
- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
- pFile->hFile.h, lockType, ofst, nByte));
-
- /* Release/Acquire the system-level lock */
- if( lockType==WINSHM_UNLCK ){
- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
- }else{
- /* Initialize the locking parameters */
- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
-
- if( rc!= 0 ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = SQLITE_BUSY;
- }
-
- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
- pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-
- return rc;
-}
-
/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);
@@ -3864,11 +4053,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
}
- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
- SimulateIOErrorBenign(1);
- winClose((sqlite3_file *)&p->hFile);
- SimulateIOErrorBenign(0);
- }
+ winHandleClose(p->hSharedShm);
if( deleteFlag ){
SimulateIOErrorBenign(1);
sqlite3BeginBenignMalloc();
@@ -3886,42 +4071,162 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** take it now. Return SQLITE_OK if successful, or an SQLite error
-** code otherwise.
-**
-** If the DMS cannot be locked because this is a readonly_shm=1
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+** The DMS lock has not yet been taken on the shm file associated with
+** pShmNode. Take the lock. Truncate the *-shm file if required.
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
-static int winLockSharedMemory(winShmNode *pShmNode){
- int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
+static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){
+ HANDLE h = pShmNode->hSharedShm;
+ int rc = SQLITE_OK;
+
+ assert( sqlite3_mutex_held(pShmNode->mutex) );
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0);
+ if( rc==SQLITE_OK ){
+ /* We have an EXCLUSIVE lock on the DMS byte. This means that this
+ ** is the first process to open the file. Truncate it to zero bytes
+ ** in this case. */
+ if( pShmNode->isReadonly ){
+ rc = SQLITE_READONLY_CANTINIT;
+ }else{
+ rc = winHandleTruncate(h, 0);
+ }
+
+ /* Release the EXCLUSIVE lock acquired above. */
+ winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0);
+ }else if( (rc & 0xFF)==SQLITE_BUSY ){
+ rc = SQLITE_OK;
+ }
if( rc==SQLITE_OK ){
- if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return SQLITE_READONLY_CANTINIT;
- }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winLockSharedMemory", pShmNode->zFilename);
+ /* Take a SHARED lock on the DMS byte. */
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs);
+ if( rc==SQLITE_OK ){
+ pShmNode->isUnlocked = 0;
}
}
- if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- }
+ return rc;
+}
- return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
+
+/*
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from malloc and must be freed by the calling
+** function.
+*/
+static void *winConvertFromUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( osIsNT() ){
+ zConverted = winUtf8ToUnicode(zFilename);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
}
/*
-** Open the shared-memory area associated with database file pDbFd.
+** This function is used to open a handle on a *-shm file.
**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file
+** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not.
+*/
+static int winHandleOpen(
+ const char *zUtf8, /* File to open */
+ int *pbReadonly, /* IN/OUT: True for readonly handle */
+ HANDLE *ph /* OUT: New HANDLE for file */
+){
+ int rc = SQLITE_OK;
+ void *zConverted = 0;
+ int bReadonly = *pbReadonly;
+ HANDLE h = INVALID_HANDLE_VALUE;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED;
+#else
+ const DWORD flag_overlapped = 0;
+#endif
+
+ /* Convert the filename to the system encoding. */
+ zConverted = winConvertFromUtf8Filename(zUtf8);
+ if( zConverted==0 ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8));
+ rc = SQLITE_IOERR_NOMEM_BKPT;
+ goto winopenfile_out;
+ }
+
+ /* Ensure the file we are trying to open is not actually a directory. */
+ if( winIsDir(zConverted) ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8));
+ rc = SQLITE_CANTOPEN_ISDIR;
+ goto winopenfile_out;
+ }
+
+ /* TODO: platforms.
+ ** TODO: retry-on-ioerr.
+ */
+ if( osIsNT() ){
+#if SQLITE_OS_WINRT
+ CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
+ memset(&extendedParameters, 0, sizeof(extendedParameters));
+ extendedParameters.dwSize = sizeof(extendedParameters);
+ extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ extendedParameters.dwFileFlags = flag_overlapped;
+ extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ h = osCreateFile2((LPCWSTR)zConverted,
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ &extendedParameters
+ );
+#else
+ h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+#endif
+ }else{
+ /* Due to pre-processor directives earlier in this file,
+ ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */
+#ifdef SQLITE_WIN32_HAS_ANSI
+ h = osCreateFileA((LPCSTR)zConverted,
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+#endif
+ }
+
+ if( h==INVALID_HANDLE_VALUE ){
+ if( bReadonly==0 ){
+ bReadonly = 1;
+ rc = winHandleOpen(zUtf8, &bReadonly, &h);
+ }else{
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ winopenfile_out:
+ sqlite3_free(zConverted);
+ *pbReadonly = bReadonly;
+ *ph = h;
+ return rc;
+}
+
+
+/*
+** Open the shared-memory area associated with database file pDbFd.
*/
static int winOpenSharedMemory(winFile *pDbFd){
struct winShm *p; /* The connection to be opened */
@@ -3933,8 +4238,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
assert( pDbFd->pShm==0 ); /* Not previously opened */
/* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
+ ** allocate space for a new winShmNode and filename. */
p = sqlite3MallocZero( sizeof(*p) );
if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
nName = sqlite3Strlen30(pDbFd->zPath);
@@ -3944,87 +4248,73 @@ static int winOpenSharedMemory(winFile *pDbFd){
return SQLITE_IOERR_NOMEM_BKPT;
}
pNew->zFilename = (char*)&pNew[1];
+ pNew->hSharedShm = INVALID_HANDLE_VALUE;
+ pNew->isUnlocked = 1;
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
+ /* Open a file-handle on the *-shm file for this connection. This file-handle
+ ** is only used for locking. The mapping of the *-shm file is created using
+ ** the shared file handle in winShmNode.hSharedShm. */
+ p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
+ rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm);
+
/* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
+ ** If no matching winShmNode currently exists, then create a new one. */
winShmEnterMutex();
for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
/* TBD need to come up with better match here. Perhaps
- ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
+ ** use FILE_ID_BOTH_DIR_INFO Structure. */
if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
}
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- int inFlags = SQLITE_OPEN_WAL;
- int outFlags = 0;
-
+ if( pShmNode==0 ){
pShmNode = pNew;
- pNew = 0;
- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
- pShmNode->pNext = winShmNodeList;
- winShmNodeList = pShmNode;
+ /* Allocate a mutex for this winShmNode object, if one is required. */
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shm_open_err;
+ if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
+ }
+
+ /* Open a file-handle to use for mappings, and for the DMS lock. */
+ if( rc==SQLITE_OK ){
+ HANDLE h = INVALID_HANDLE_VALUE;
+ pShmNode->isReadonly = p->bReadonly;
+ rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
+ pShmNode->hSharedShm = h;
+ }
+
+ /* If successful, link the new winShmNode into the global list. If an
+ ** error occurred, free the object. */
+ if( rc==SQLITE_OK ){
+ pShmNode->pNext = winShmNodeList;
+ winShmNodeList = pShmNode;
+ pNew = 0;
+ }else{
+ sqlite3_mutex_free(pShmNode->mutex);
+ if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(pShmNode->hSharedShm);
}
}
-
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- }else{
- inFlags |= SQLITE_OPEN_READONLY;
- }
- rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
- (sqlite3_file*)&pShmNode->hFile,
- inFlags, &outFlags);
- if( rc!=SQLITE_OK ){
- rc = winLogError(rc, osGetLastError(), "winOpenShm",
- pShmNode->zFilename);
- goto shm_open_err;
- }
- if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
-
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
}
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
+ /* If no error has occurred, link the winShm object to the winShmNode and
+ ** the winShm to pDbFd. */
+ if( rc==SQLITE_OK ){
+ p->pShmNode = pShmNode;
+ pShmNode->nRef++;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- p->id = pShmNode->nextShmId++;
+ p->id = pShmNode->nextShmId++;
#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
+ pDbFd->pShm = p;
+ }else if( p ){
+ winHandleClose(p->hShm);
+ sqlite3_free(p);
+ }
+
+ assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
winShmLeaveMutex();
-
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the winShmEnterMutex() mutex and the pointer from the
- ** new (struct winShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
- sqlite3_free(p);
sqlite3_free(pNew);
- winShmLeaveMutex();
return rc;
}
@@ -4039,27 +4329,19 @@ static int winShmUnmap(
winFile *pDbFd; /* Database holding shared-memory */
winShm *p; /* The connection to be closed */
winShmNode *pShmNode; /* The underlying shared-memory file */
- winShm **pp; /* For looping over sibling connections */
pDbFd = (winFile*)fd;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_OK;
+ if( p->hShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(p->hShm);
+ }
+
pShmNode = p->pShmNode;
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
-
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
+ winShmEnterMutex();
/* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- winShmEnterMutex();
+ ** shared-memory file, too. */
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
@@ -4067,6 +4349,9 @@ static int winShmUnmap(
}
winShmLeaveMutex();
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
return SQLITE_OK;
}
@@ -4081,10 +4366,9 @@ static int winShmLock(
){
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
- winShm *pX; /* For looping over all siblings */
winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (u16)((1U<<(ofst+n)) - (1U<pShmNode;
@@ -4098,85 +4382,82 @@ static int winShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- mask = (u16)((1U<<(ofst+n)) - (1U<1 || mask==(1<mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ /* Check that, if this to be a blocking lock, no locks that occur later
+ ** in the following list than the lock being obtained are already held:
+ **
+ ** 1. Checkpointer lock (ofst==1).
+ ** 2. Write lock (ofst==0).
+ ** 3. Read locks (ofst>=3 && ofstexclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2) /* not RECOVER */
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ /* Check if there is any work to do. There are three cases:
+ **
+ ** a) An unlock operation where there are locks to unlock,
+ ** b) An shared lock where the requested lock is not already held
+ ** c) An exclusive lock where the requested lock is not already held
+ **
+ ** The SQLite core never requests an exclusive lock that it already holds.
+ ** This is assert()ed immediately below. */
+ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
+ || 0==(p->exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
+ rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n);
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
- }
-
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
+ /* If successful, also clear the bits in sharedMask/exclMask */
if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ p->exclMask = (p->exclMask & ~mask);
+ p->sharedMask = (p->sharedMask & ~mask);
+ }
+ }else{
+ int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
+ DWORD nMs = winFileBusyTimeout(pDbFd);
+ rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs);
+ if( rc==SQLITE_OK ){
+ if( bExcl ){
+ p->exclMask = (p->exclMask | mask);
+ }else{
+ p->sharedMask = (p->sharedMask | mask);
+ }
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
- sqlite3ErrName(rc)));
+
+ OSTRACE((
+ "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x,"
+ " rc=%s\n",
+ ofst, n, flags,
+ osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+ sqlite3ErrName(rc))
+ );
return rc;
}
@@ -4238,13 +4519,15 @@ static int winShmMap(
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->isUnlocked ){
- rc = winLockSharedMemory(pShmNode);
+ /* Take the DMS lock. */
+ assert( pShmNode->nRegion==0 );
+ rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd));
if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
}
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
+ HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
sqlite3_int64 sz; /* Current size of wal-index file */
@@ -4255,10 +4538,9 @@ static int winShmMap(
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+ rc = winHandleSize(hShared, &sz);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath);
goto shmpage_out;
}
@@ -4267,19 +4549,17 @@ static int winShmMap(
** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
**
** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
- ** the requested memory region.
- */
+ ** the requested memory region. */
if( !isWrite ) goto shmpage_out;
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+ rc = winHandleTruncate(hShared, nByte);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath);
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc64(
+ apNew = (struct ShmRegion*)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@@ -4298,18 +4578,13 @@ static int winShmMap(
void *pMap = 0; /* Mapped memory region */
#if SQLITE_OS_WINRT
- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, protect, nByte, NULL
- );
+ hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
+
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
@@ -4352,7 +4627,9 @@ shmpage_out:
}else{
*pp = 0;
}
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+ if( pShmNode->isReadonly && rc==SQLITE_OK ){
+ rc = SQLITE_READONLY;
+ }
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
@@ -4693,26 +4970,6 @@ static char *winConvertToUtf8Filename(const void *zFilename){
}
#endif
-/*
-** Convert a UTF-8 filename into whatever form the underlying
-** operating system wants filenames in. Space to hold the result
-** is obtained from malloc and must be freed by the calling
-** function.
-*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUtf8ToUnicode(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -6166,7 +6423,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==80 );
+ assert( ArraySize(aSyscall)==82 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
diff --git a/src/pager.c b/src/pager.c
index 9640355364..0b5cd4ecd3 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -1900,6 +1900,15 @@ static void pager_unlock(Pager *pPager){
if( pagerUseWal(pPager) ){
assert( !isOpen(pPager->jfd) );
+ if( pPager->eState==PAGER_ERROR ){
+ /* If an IO error occurs in wal.c while attempting to wrap the wal file,
+ ** then the Wal object may be holding a write-lock but no read-lock.
+ ** This call ensures that the write-lock is dropped as well. We cannot
+ ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once
+ ** did, because this would break "BEGIN EXCLUSIVE" handling for
+ ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */
+ sqlite3WalEndWriteTransaction(pPager->pWal);
+ }
sqlite3WalEndReadTransaction(pPager->pWal);
pPager->eState = PAGER_OPEN;
}else if( !pPager->exclusiveMode ){
diff --git a/src/parse.y b/src/parse.y
index d88d3c040b..215af94b82 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -331,7 +331,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
// keywords. Any non-standard keyword can also be an identifier.
//
%token_class id ID|INDEXED.
-// And "ids" is an identifer-or-string.
+// And "ids" is an identifier-or-string.
//
%token_class ids ID|STRING.
@@ -625,8 +625,8 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
if( pRhs ){
pRhs->op = (u8)Y;
pRhs->pPrior = pLhs;
- if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
- pRhs->selFlags &= ~SF_MultiValue;
+ if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue;
+ pRhs->selFlags &= ~(u32)SF_MultiValue;
if( Y!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
@@ -846,7 +846,7 @@ joinop(X) ::= JOIN_KW(A) nm(B) JOIN.
joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
{X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
-// There is a parsing abiguity in an upsert statement that uses a
+// There is a parsing ambiguity in an upsert statement that uses a
// SELECT on the RHS of a the INSERT:
//
// INSERT INTO tab SELECT * FROM aaa JOIN bbb ON CONFLICT ...
@@ -1227,7 +1227,7 @@ expr(A) ::= idj(X) LP STAR RP. {
** The purpose of this function is to generate an Expr node from the first syntax
** into a TK_FUNCTION node that looks like it came from the second syntax.
**
- ** Only functions that have the SQLITE_SELFORDER1 perperty are allowed to do this
+ ** Only functions that have the SQLITE_SELFORDER1 property are allowed to do this
** transformation. Because DISTINCT is not allowed in the ordered-set aggregate
** syntax, an error is raised if DISTINCT is used.
*/
diff --git a/src/pragma.c b/src/pragma.c
index c353cd6349..9463228a54 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -36,7 +36,7 @@
** the following macro or to the actual analysis_limit if it is non-zero,
** in order to prevent PRAGMA optimize from running for too long.
**
-** The value of 2000 is chosen emperically so that the worst-case run-time
+** The value of 2000 is chosen empirically so that the worst-case run-time
** for PRAGMA optimize does not exceed 100 milliseconds against a variety
** of test databases on a RaspberryPI-4 compiled using -Os and without
** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
diff --git a/src/printf.c b/src/printf.c
index 97f93dc157..166c11194e 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -25,17 +25,17 @@
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
-#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
-#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
- NULL pointers replaced by SQL NULL. %Q */
-#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCITEM 12 /* a pointer to a SrcItem */
-#define etPOINTER 13 /* The %p conversion */
-#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
-#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-#define etDECIMAL 16 /* %d or %u, but not %x, %o */
+#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */
+#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '',
+ NULL pointers replaced by SQL NULL. %Q */
+#define etTOKEN 11 /* a pointer to a Token structure */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
+#define etPOINTER 13 /* The %p conversion */
+#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
+#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-#define etINVALID 17 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -74,9 +74,9 @@ static const et_info fmtinfo[] = {
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
+ { 'q', 0, 4, etESCAPE_q, 0, 0 },
+ { 'Q', 0, 4, etESCAPE_Q, 0, 0 },
+ { 'w', 0, 4, etESCAPE_w, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etDECIMAL, 0, 0 },
@@ -673,25 +673,7 @@ void sqlite3_str_vappendf(
}
}else{
unsigned int ch = va_arg(ap,unsigned int);
- if( ch<0x00080 ){
- buf[0] = ch & 0xff;
- length = 1;
- }else if( ch<0x00800 ){
- buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
- buf[1] = 0x80 + (u8)(ch & 0x3f);
- length = 2;
- }else if( ch<0x10000 ){
- buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
- buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[2] = 0x80 + (u8)(ch & 0x3f);
- length = 3;
- }else{
- buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
- buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
- buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[3] = 0x80 + (u8)(ch & 0x3f);
- length = 4;
- }
+ length = sqlite3AppendOneUtf8Character(buf, ch);
}
if( precision>1 ){
i64 nPrior = 1;
@@ -771,22 +753,31 @@ void sqlite3_str_vappendf(
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
}
break;
- case etSQLESCAPE: /* %q: Escape ' characters */
- case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* %w: Escape " characters */
+ case etESCAPE_q: /* %q: Escape ' characters */
+ case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
+ case etESCAPE_w: { /* %w: Escape " characters */
i64 i, j, k, n;
- int needQuote, isnull;
+ int needQuote = 0;
char ch;
- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
+ char q;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
- isnull = escarg==0;
- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+ if( escarg==0 ){
+ escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");
+ }else if( xtype==etESCAPE_Q ){
+ needQuote = 1;
+ }
+ if( xtype==etESCAPE_w ){
+ q = '"';
+ flag_alternateform = 0;
+ }else{
+ q = '\'';
+ }
/* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
@@ -799,7 +790,30 @@ void sqlite3_str_vappendf(
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
}
}
- needQuote = !isnull && xtype==etSQLESCAPE2;
+ if( flag_alternateform ){
+ /* For %#q, do unistr()-style backslash escapes for
+ ** all control characters, and for backslash itself.
+ ** For %#Q, do the same but only if there is at least
+ ** one control character. */
+ u32 nBack = 0;
+ u32 nCtrl = 0;
+ for(k=0; ketBUFSIZE ){
bufpt = zExtra = printfTempBuf(pAccum, n);
@@ -808,13 +822,41 @@ void sqlite3_str_vappendf(
bufpt = buf;
}
j = 0;
- if( needQuote ) bufpt[j++] = q;
- k = i;
- for(i=0; i=0x10 ? '1' : '0';
+ bufpt[j++] = "0123456789abcdef"[ch&0xf];
+ }
+ }
+ }else{
+ for(i=0; ipWinDefn = 0;
#endif
- p->selFlags &= ~SF_Compound;
+ p->selFlags &= ~(u32)SF_Compound;
assert( (p->selFlags & SF_Converted)==0 );
p->selFlags |= SF_Converted;
assert( pNew->pPrior!=0 );
@@ -7252,7 +7252,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pSub->pPrior = 0;
pSub->pNext = 0;
pSub->selFlags |= SF_Aggregate;
- pSub->selFlags &= ~SF_Compound;
+ pSub->selFlags &= ~(u32)SF_Compound;
pSub->nSelectRow = 0;
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList);
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
@@ -7267,7 +7267,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
- p->selFlags &= ~SF_Aggregate;
+ p->selFlags &= ~(u32)SF_Aggregate;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x200 ){
@@ -7474,7 +7474,7 @@ int sqlite3Select(
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
@@ -7513,7 +7513,7 @@ int sqlite3Select(
** and leaving this flag set can cause errors if a compound sub-query
** in p->pSrc is flattened into this query and this function called
** again as part of compound SELECT processing. */
- p->selFlags &= ~SF_UFSrcCheck;
+ p->selFlags &= ~(u32)SF_UFSrcCheck;
}
if( pDest->eDest==SRT_Output ){
@@ -8002,7 +8002,7 @@ int sqlite3Select(
&& p->pWin==0
#endif
){
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
if( pGroupBy ){
for(i=0; inExpr; i++){
diff --git a/src/shell.c.in b/src/shell.c.in
index fcc9316b00..586782f01f 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -218,6 +218,8 @@ typedef unsigned char u8;
#define IsSpace(X) isspace((unsigned char)X)
#define IsDigit(X) isdigit((unsigned char)X)
#define ToLower(X) (char)tolower((unsigned char)X)
+#define IsAlnum(X) isalnum((unsigned char)X)
+#define IsAlpha(X) isalpha((unsigned char)X)
#if defined(_WIN32) || defined(WIN32)
#if SQLITE_OS_WINRT
@@ -470,7 +472,7 @@ static char *Argv0;
** Prompt strings. Initialized in main. Settable with
** .prompt main continue
*/
-#define PROMPT_LEN_MAX 20
+#define PROMPT_LEN_MAX 128
/* First line prompt. default: "sqlite> " */
static char mainPrompt[PROMPT_LEN_MAX];
/* Continuation prompt. default: " ...> " */
@@ -1127,9 +1129,9 @@ static void appendText(ShellText *p, const char *zAppend, char quote){
static char quoteChar(const char *zName){
int i;
if( zName==0 ) return '"';
- if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
+ if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"';
for(i=0; zName[i]; i++){
- if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
+ if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"';
}
return sqlite3_keyword_check(zName, i) ? '"' : 0;
}
@@ -1446,6 +1448,7 @@ struct ShellState {
u8 bSafeModePersist; /* The long-term value of bSafeMode */
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
u8 crlfMode; /* Do NL-to-CRLF translations when enabled (maybe) */
+ u8 eEscMode; /* Escape mode for text output */
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 */
@@ -1546,6 +1549,15 @@ static ShellState shellState;
** top-level SQL statement */
#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
+/* Allowed values for ShellState.eEscMode. The default value should
+** be 0, so to change the default, reorder the names.
+*/
+#define SHELL_ESC_ASCII 0 /* Substitute ^Y for X where Y=X+0x40 */
+#define SHELL_ESC_SYMBOL 1 /* Substitute U+2400 graphics */
+#define SHELL_ESC_OFF 2 /* Send characters verbatim */
+
+static const char *shell_EscModeNames[] = { "ascii", "symbol", "off" };
+
/*
** These are the allowed shellFlgs values
*/
@@ -1883,59 +1895,75 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
}
/*
-** Find a string that is not found anywhere in z[]. Return a pointer
-** to that string.
+** Output the given string as a quoted string using SQL quoting conventions:
**
-** Try to use zA and zB first. If both of those are already found in z[]
-** then make up some string and store it in the buffer zBuf.
-*/
-static const char *unused_string(
- const char *z, /* Result must not appear anywhere in z */
- const char *zA, const char *zB, /* Try these first */
- char *zBuf /* Space to store a generated string */
-){
- unsigned i = 0;
- if( strstr(z, zA)==0 ) return zA;
- if( strstr(z, zB)==0 ) return zB;
- do{
- sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
- }while( strstr(z,zBuf)!=0 );
- return zBuf;
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
+** (1) Single quotes (') within the string are doubled
+** (2) The whle string is enclosed in '...'
+** (3) Control characters other than \n, \t, and \r\n are escaped
+** using \u00XX notation and if such substitutions occur,
+** the whole string is enclosed in unistr('...') instead of '...'.
+**
+** Step (3) is omitted if the control-character escape mode is OFF.
**
-** See also: output_quoted_escaped_string()
+** See also: output_quoted_escaped_string() which does the same except
+** that it does not make exceptions for \n, \t, and \r\n in step (3).
*/
-static void output_quoted_string(ShellState *p, const char *z){
+static void output_quoted_string(ShellState *p, const char *zInX){
int i;
- char c;
+ int needUnistr = 0;
+ int needDblQuote = 0;
+ const unsigned char *z = (const unsigned char*)zInX;
+ unsigned char c;
FILE *out = p->out;
sqlite3_fsetmode(out, _O_BINARY);
if( z==0 ) return;
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c==0 ){
+ for(i=0; (c = z[i])!=0; i++){
+ if( c=='\'' ){ needDblQuote = 1; }
+ if( c>0x1f ) continue;
+ if( c=='\t' || c=='\n' ) continue;
+ if( c=='\r' && z[i+1]=='\n' ) continue;
+ needUnistr = 1;
+ break;
+ }
+ if( (needDblQuote==0 && needUnistr==0)
+ || (needDblQuote==0 && p->eEscMode==SHELL_ESC_OFF)
+ ){
sqlite3_fprintf(out, "'%s'",z);
+ }else if( p->eEscMode==SHELL_ESC_OFF ){
+ char *zEncoded = sqlite3_mprintf("%Q", z);
+ sqlite3_fputs(zEncoded, out);
+ sqlite3_free(zEncoded);
}else{
- sqlite3_fputs("'", out);
+ if( needUnistr ){
+ sqlite3_fputs("unistr('", out);
+ }else{
+ sqlite3_fputs("'", out);
+ }
while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c=='\'' ) i++;
+ for(i=0; (c = z[i])!=0; i++){
+ if( c=='\'' ) break;
+ if( c>0x1f ) continue;
+ if( c=='\t' || c=='\n' ) continue;
+ if( c=='\r' && z[i+1]=='\n' ) continue;
+ break;
+ }
if( i ){
sqlite3_fprintf(out, "%.*s", i, z);
z += i;
}
+ if( c==0 ) break;
if( c=='\'' ){
- sqlite3_fputs("'", out);
- continue;
- }
- if( c==0 ){
- break;
+ sqlite3_fputs("''", out);
+ }else{
+ sqlite3_fprintf(out, "\\u%04x", c);
}
z++;
}
- sqlite3_fputs("'", out);
+ if( needUnistr ){
+ sqlite3_fputs("')", out);
+ }else{
+ sqlite3_fputs("'", out);
+ }
}
setCrlfMode(p);
}
@@ -1950,61 +1978,15 @@ static void output_quoted_string(ShellState *p, const char *z){
** escape mechanism.
*/
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 ){
- sqlite3_fprintf(out, "'%s'",z);
+ char *zEscaped;
+ sqlite3_fsetmode(p->out, _O_BINARY);
+ if( p->eEscMode==SHELL_ESC_OFF ){
+ zEscaped = sqlite3_mprintf("%Q", z);
}else{
- const char *zNL = 0;
- const char *zCR = 0;
- int nNL = 0;
- int nCR = 0;
- char zBuf1[20], zBuf2[20];
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) nNL++;
- if( z[i]=='\r' ) nCR++;
- }
- if( nNL ){
- sqlite3_fputs("replace(", out);
- zNL = unused_string(z, "\\n", "\\012", zBuf1);
- }
- if( nCR ){
- sqlite3_fputs("replace(", out);
- zCR = unused_string(z, "\\r", "\\015", zBuf2);
- }
- sqlite3_fputs("'", out);
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- sqlite3_fprintf(out, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- sqlite3_fputs("'", out);
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- if( c=='\n' ){
- sqlite3_fputs(zNL, out);
- continue;
- }
- sqlite3_fputs(zCR, out);
- }
- sqlite3_fputs("'", out);
- if( nCR ){
- sqlite3_fprintf(out, ",'%s',char(13))", zCR);
- }
- if( nNL ){
- sqlite3_fprintf(out, ",'%s',char(10))", zNL);
- }
+ zEscaped = sqlite3_mprintf("%#Q", z);
}
+ sqlite3_fputs(zEscaped, p->out);
+ sqlite3_free(zEscaped);
setCrlfMode(p);
}
@@ -2154,6 +2136,93 @@ static void output_json_string(FILE *out, const char *z, i64 n){
sqlite3_fputs(zq, out);
}
+/*
+** Escape the input string if it is needed and in accordance with
+** eEscMode.
+**
+** Escaping is needed if the string contains any control characters
+** other than \t, \n, and \r\n
+**
+** If no escaping is needed (the common case) then set *ppFree to NULL
+** and return the original string. If escapingn is needed, write the
+** escaped string into memory obtained from sqlite3_malloc64() or the
+** equivalent, and return the new string and set *ppFree to the new string
+** as well.
+**
+** The caller is responsible for freeing *ppFree if it is non-NULL in order
+** to reclaim memory.
+*/
+static const char *escapeOutput(
+ ShellState *p,
+ const char *zInX,
+ char **ppFree
+){
+ i64 i, j;
+ i64 nCtrl = 0;
+ unsigned char *zIn;
+ unsigned char c;
+ unsigned char *zOut;
+
+
+ /* No escaping if disabled */
+ if( p->eEscMode==SHELL_ESC_OFF ){
+ *ppFree = 0;
+ return zInX;
+ }
+
+ /* Count the number of control characters in the string. */
+ zIn = (unsigned char*)zInX;
+ for(i=0; (c = zIn[i])!=0; i++){
+ if( c<=0x1f
+ && c!='\t'
+ && c!='\n'
+ && (c!='\r' || zIn[i+1]!='\n')
+ ){
+ nCtrl++;
+ }
+ }
+ if( nCtrl==0 ){
+ *ppFree = 0;
+ return zInX;
+ }
+ if( p->eEscMode==SHELL_ESC_SYMBOL ) nCtrl *= 2;
+ zOut = sqlite3_malloc64( i + nCtrl + 1 );
+ shell_check_oom(zOut);
+ for(i=j=0; (c = zIn[i])!=0; i++){
+ if( c>0x1f
+ || c=='\t'
+ || c=='\n'
+ || (c=='\r' && zIn[i+1]=='\n')
+ ){
+ continue;
+ }
+ if( i>0 ){
+ memcpy(&zOut[j], zIn, i);
+ j += i;
+ }
+ zIn += i+1;
+ i = -1;
+ switch( p->eEscMode ){
+ case SHELL_ESC_SYMBOL:
+ zOut[j++] = 0xe2;
+ zOut[j++] = 0x90;
+ zOut[j++] = 0x80+c;
+ break;
+ case SHELL_ESC_ASCII:
+ zOut[j++] = '^';
+ zOut[j++] = 0x40+c;
+ break;
+ }
+ }
+ if( i>0 ){
+ memcpy(&zOut[j], zIn, i);
+ j += i;
+ }
+ zOut[j] = 0;
+ *ppFree = (char*)zOut;
+ return (char*)zOut;
+}
+
/*
** Output the given string with characters that are special to
** HTML escaped.
@@ -2597,8 +2666,12 @@ static int shell_callback(
}
if( p->cnt++>0 ) sqlite3_fputs(p->rowSeparator, p->out);
for(i=0; inullValue, &pFree);
sqlite3_fprintf(p->out, "%*s = %s%s", w, azCol[i],
- azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
+ pDisplay, p->rowSeparator);
+ if( pFree ) sqlite3_free(pFree);
}
break;
}
@@ -2730,15 +2803,23 @@ static int shell_callback(
case MODE_List: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; iout, "%s%s", azCol[i],
+ char *z = azCol[i];
+ char *pFree;
+ const char *zOut = escapeOutput(p, z, &pFree);
+ sqlite3_fprintf(p->out, "%s%s", zOut,
i==nArg-1 ? p->rowSeparator : p->colSeparator);
+ if( pFree ) sqlite3_free(pFree);
}
}
if( azArg==0 ) break;
for(i=0; inullValue;
- sqlite3_fputs(z, p->out);
+ zOut = escapeOutput(p, z, &pFree);
+ sqlite3_fputs(zOut, p->out);
+ if( pFree ) sqlite3_free(pFree);
sqlite3_fputs((icolSeparator : p->rowSeparator, p->out);
}
break;
@@ -3857,6 +3938,7 @@ static void print_box_row_separator(
** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
*/
static char *translateForDisplayAndDup(
+ ShellState *p, /* To access current settings */
const unsigned char *z, /* Input text to be transformed */
const unsigned char **pzTail, /* OUT: Tail of the input for next line */
int mxWidth, /* Max width. 0 means no limit */
@@ -3891,6 +3973,7 @@ static char *translateForDisplayAndDup(
j++;
continue;
}
+ if( c==0 || c=='\n' || (c=='\r' && z[i+1]=='\n') ) break;
if( c=='\t' ){
do{
n++;
@@ -3899,16 +3982,18 @@ static char *translateForDisplayAndDup(
i++;
continue;
}
- break;
+ n++;
+ j += 3;
+ i++;
}
if( n>=mxWidth && bWordWrap ){
/* Perhaps try to back up to a better place to break the line */
for(k=i; k>i/2; k--){
- if( isspace(z[k-1]) ) break;
+ if( IsSpace(z[k-1]) ) break;
}
if( k<=i/2 ){
for(k=i; k>i/2; k--){
- if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
+ if( IsAlnum(z[k-1])!=IsAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
}
}
if( k<=i/2 ){
@@ -3946,6 +4031,7 @@ static char *translateForDisplayAndDup(
zOut[j++] = z[i++];
continue;
}
+ if( c==0 ) break;
if( z[i]=='\t' ){
do{
n++;
@@ -3954,12 +4040,36 @@ static char *translateForDisplayAndDup(
i++;
continue;
}
- break;
+ switch( p->eEscMode ){
+ case SHELL_ESC_SYMBOL:
+ zOut[j++] = 0xe2;
+ zOut[j++] = 0x90;
+ zOut[j++] = 0x80 + c;
+ break;
+ case SHELL_ESC_ASCII:
+ zOut[j++] = '^';
+ zOut[j++] = 0x40 + c;
+ break;
+ case SHELL_ESC_OFF:
+ zOut[j++] = c;
+ break;
+ }
+ i++;
}
zOut[j] = 0;
return (char*)zOut;
}
+/* Return true if the text string z[] contains characters that need
+** unistr() escaping.
+*/
+static int needUnistr(const unsigned char *z){
+ unsigned char c;
+ if( z==0 ) return 0;
+ while( (c = *z)>0x1f || c=='\t' || c=='\n' || (c=='\r' && z[1]=='\n') ){ z++; }
+ return c!=0;
+}
+
/* Extract the value of the i-th current column for pStmt as an SQL literal
** value. Memory is obtained from sqlite3_malloc64() and must be freed by
** the caller.
@@ -3974,7 +4084,8 @@ static char *quoted_column(sqlite3_stmt *pStmt, int i){
return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
}
case SQLITE_TEXT: {
- return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
+ const unsigned char *zText = sqlite3_column_text(pStmt,i);
+ return sqlite3_mprintf(needUnistr(zText)?"%#Q":"%Q",zText);
}
case SQLITE_BLOB: {
int j;
@@ -4066,7 +4177,7 @@ static void exec_prepared_stmt_columnar(
if( wx<0 ) wx = -wx;
uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
if( uz==0 ) uz = (u8*)"";
- azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
+ azData[i] = translateForDisplayAndDup(p, uz, &zNotUsed, wx, bw);
}
do{
int useNextLine = bNextLine;
@@ -4090,6 +4201,7 @@ static void exec_prepared_stmt_columnar(
uz = azNextLine[i];
if( uz==0 ) uz = (u8*)zEmpty;
}else if( p->cmOpts.bQuote ){
+ assert( azQuoted!=0 );
sqlite3_free(azQuoted[i]);
azQuoted[i] = quoted_column(pStmt,i);
uz = (const unsigned char*)azQuoted[i];
@@ -4098,7 +4210,7 @@ static void exec_prepared_stmt_columnar(
if( uz==0 ) uz = (u8*)zShowNull;
}
azData[nRow*nColumn + i]
- = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
+ = translateForDisplayAndDup(p, uz, &azNextLine[i], wx, bw);
if( azNextLine[i] ){
bNextLine = 1;
abRowDiv[nRow-1] = 0;
@@ -5021,7 +5133,7 @@ static const char *(azHelp[]) = {
#else
".log on|off Turn logging on or off.",
#endif
- ".mode MODE ?OPTIONS? Set output mode",
+ ".mode ?MODE? ?OPTIONS? Set output mode",
" MODE is one of:",
" ascii Columns/rows delimited by 0x1F and 0x1E",
" box Tables using unicode box-drawing characters",
@@ -5039,6 +5151,7 @@ static const char *(azHelp[]) = {
" tabs Tab-separated values",
" tcl TCL list elements",
" OPTIONS: (for columnar modes or insert mode):",
+ " --escape T ctrl-char escape; T is one of: symbol, ascii, off",
" --wrap N Wrap output lines to no longer than N characters",
" --wordwrap B Wrap or not at word boundaries per B (on/off)",
" --ww Shorthand for \"--wordwrap 1\"",
@@ -5814,7 +5927,7 @@ static void linenoise_completion(
#endif
if( nLine>(i64)sizeof(zBuf)-30 ) return;
if( zLine[0]=='.' || zLine[0]=='#') return;
- for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
+ for(i=nLine-1; i>=0 && (IsAlnum(zLine[i]) || zLine[i]=='_'); i--){}
if( i==nLine-1 ) return;
iStart = i+1;
memcpy(zBuf, zLine, iStart);
@@ -9779,24 +9892,52 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zMode = 0;
const char *zTabname = 0;
int i, n2;
+ int chng = 0; /* 0x01: change to cmopts. 0x02: Any other change */
ColModeOpts cmOpts = ColModeOpts_default;
for(i=1; ieEscMode = k;
+ chng |= 2;
+ break;
+ }
+ }
+ if( k>=ArraySize(shell_EscModeNames) ){
+ sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\""
+ " - choices:", zEsc);
+ for(k=0; kmode==MODE_Column
|| (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
){
sqlite3_fprintf(p->out,
- "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
+ "current output mode: %s --wrap %d --wordwrap %s "
+ "--%squote --escape %s\n",
modeDescr[p->mode], p->cmOpts.iWrap,
p->cmOpts.bWordWrap ? "on" : "off",
- p->cmOpts.bQuote ? "" : "no");
+ p->cmOpts.bQuote ? "" : "no",
+ shell_EscModeNames[p->eEscMode]
+ );
}else{
sqlite3_fprintf(p->out,
- "current output mode: %s\n", modeDescr[p->mode]);
+ "current output mode: %s --escape %s\n",
+ modeDescr[p->mode],
+ shell_EscModeNames[p->eEscMode]
+ );
}
+ }
+ if( zMode==0 ){
zMode = modeDescr[p->mode];
+ if( (chng&1)==0 ) cmOpts = p->cmOpts;
}
n2 = strlen30(zMode);
if( cli_strncmp(zMode,"lines",n2)==0 ){
@@ -9866,6 +10017,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}else if( cli_strncmp(zMode,"insert",n2)==0 ){
p->mode = MODE_Insert;
set_table_name(p, zTabname ? zTabname : "table");
+ if( p->eEscMode==SHELL_ESC_OFF ){
+ ShellSetFlag(p, SHFLG_Newlines);
+ }else{
+ ShellClearFlag(p, SHFLG_Newlines);
+ }
}else if( cli_strncmp(zMode,"quote",n2)==0 ){
p->mode = MODE_Quote;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
@@ -12102,7 +12258,7 @@ static int line_is_command_terminator(char *zLine){
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
*/
#ifdef SQLITE_OMIT_COMPLETE
-# error the CLI application is imcompatable with SQLITE_OMIT_COMPLETE.
+# error the CLI application is incompatable with SQLITE_OMIT_COMPLETE.
#endif
/*
@@ -12281,7 +12437,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
if(!z || !*z){
return 0;
}
- while(*z && isspace(*z)) ++z;
+ while(*z && IsSpace(*z)) ++z;
zBegin = z;
for(; *z && '\n'!=*z; ++nZ, ++z){}
if(nZ>0 && '\r'==zBegin[nZ-1]){
@@ -12586,6 +12742,7 @@ static const char zOptions[] =
" -deserialize open the database using sqlite3_deserialize()\n"
#endif
" -echo print inputs before execution\n"
+ " -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
" -init FILENAME read/process named file\n"
" -[no]header turn headers on or off\n"
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
@@ -12633,7 +12790,7 @@ static const char zOptions[] =
#endif
;
static void usage(int showDetail){
- sqlite3_fprintf(stderr,"Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
+ sqlite3_fprintf(stderr,"Usage: %s [OPTIONS] [FILENAME [SQL...]]\n"
"FILENAME is the name of an SQLite database. A new database is created\n"
"if the file does not previously exist. Defaults to :memory:.\n", Argv0);
if( showDetail ){
@@ -13019,6 +13176,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
ShellSetFlag(&data,SHFLG_TestingMode);
}else if( cli_strcmp(z,"-safe")==0 ){
/* no-op - catch this on the second pass */
+ }else if( cli_strcmp(z,"-escape")==0 && i+1=ArraySize(shell_EscModeNames) ){
+ sqlite3_fprintf(stderr, "unknown control character escape mode \"%s\""
+ " - choices:", zEsc);
+ for(k=0; k[[SQLITE_FCNTL_BLOCK_ON_CONNECT]]
+** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the
+** VFS to block when taking a SHARED lock to connect to a wal mode database.
+** This is used to implement the functionality associated with
+** SQLITE_SETLK_BLOCK_ON_CONNECT.
+**
**
[[SQLITE_FCNTL_DATA_VERSION]]
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
** a database file. The argument is a pointer to a 32-bit unsigned integer.
@@ -1259,6 +1265,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
#define SQLITE_FCNTL_NULL_IO 43
+#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -3015,6 +3022,44 @@ int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
*/
int sqlite3_busy_timeout(sqlite3*, int ms);
+/*
+** CAPI3REF: Set the Setlk Timeout
+** METHOD: sqlite3
+**
+** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If
+** the VFS supports blocking locks, it sets the timeout in ms used by
+** eligible locks taken on wal mode databases by the specified database
+** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does
+** not support blocking locks, this function is a no-op.
+**
+** Passing 0 to this function disables blocking locks altogether. Passing
+** -1 to this function requests that the VFS blocks for a long time -
+** indefinitely if possible. The results of passing any other negative value
+** are undefined.
+**
+** Internally, each SQLite database handle store two timeout values - the
+** busy-timeout (used for rollback mode databases, or if the VFS does not
+** support blocking locks) and the setlk-timeout (used for blocking locks
+** on wal-mode databases). The sqlite3_busy_timeout() method sets both
+** values, this function sets only the setlk-timeout value. Therefore,
+** to configure separate busy-timeout and setlk-timeout values for a single
+** database handle, call sqlite3_busy_timeout() followed by this function.
+**
+** Whenever the number of connections to a wal mode database falls from
+** 1 to 0, the last connection takes an exclusive lock on the database,
+** then checkpoints and deletes the wal file. While it is doing this, any
+** new connection that tries to read from the database fails with an
+** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is
+** passed to this API, the new connection blocks until the exclusive lock
+** has been released.
+*/
+int sqlite3_setlk_timeout(sqlite3*, int ms, int flags);
+
+/*
+** CAPI3REF: Flags for sqlite3_setlk_timeout()
+*/
+#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01
+
/*
** CAPI3REF: Convenience Routines For Running Queries
** METHOD: sqlite3
@@ -5130,7 +5175,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 6d88b811c0..6569369a55 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1775,6 +1775,10 @@ struct sqlite3 {
Savepoint *pSavepoint; /* List of active savepoints */
int nAnalysisLimit; /* Number of index rows to ANALYZE */
int busyTimeout; /* Busy handler timeout, in msec */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */
+ int setlkFlags; /* Flags passed to setlk_timeout() */
+#endif
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
@@ -2787,7 +2791,7 @@ struct Index {
Pgno tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nKeyCol; /* Number of columns forming the key */
- u16 nColumn; /* Number of columns stored in the index */
+ u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
@@ -3125,10 +3129,10 @@ struct Expr {
/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
+#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0)
+#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P))
+#define ExprSetProperty(E,P) (E)->flags|=(u32)(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P)
#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
@@ -4936,7 +4940,7 @@ void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenSchemaTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
-i16 sqlite3TableColumnToIndex(Index*, i16);
+int sqlite3TableColumnToIndex(Index*, int);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
@@ -5034,7 +5038,7 @@ void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(sqlite3*, IdList*);
void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
void sqlite3SrcListDelete(sqlite3*, SrcList*);
-Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
+Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
void sqlite3DropIndex(Parse*, SrcList*, int);
@@ -5172,7 +5176,8 @@ Select *sqlite3SelectDup(sqlite3*,const Select*,int);
FuncDef *sqlite3FunctionSearch(int,const char*);
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
-void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
+void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int);
+int sqlite3AppendOneUtf8Character(char*, u32);
void sqlite3RegisterBuiltinFunctions(void);
void sqlite3RegisterDateTimeFunctions(void);
void sqlite3RegisterJsonFunctions(void);
diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h
index 620b0f8e5a..ec774889b5 100644
--- a/src/sqliteLimit.h
+++ b/src/sqliteLimit.h
@@ -36,14 +36,22 @@
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
** * Terms in the VALUES clause of an INSERT statement
**
-** The hard upper limit here is 32676. Most database people will
+** The hard upper limit here is 32767. Most database people will
** tell you that in a well-normalized database, you usually should
** not have more than a dozen or so columns in any table. And if
** that is the case, there is no point in having more than a few
** dozen values in any of the other situations described above.
+**
+** An index can only have SQLITE_MAX_COLUMN columns from the user
+** point of view, but the underlying b-tree that implements the index
+** might have up to twice as many columns in a WITHOUT ROWID table,
+** since must also store the primary key at the end. Hence the
+** column count for Index is u16 instead of i16.
*/
-#ifndef SQLITE_MAX_COLUMN
+#if !defined(SQLITE_MAX_COLUMN)
# define SQLITE_MAX_COLUMN 2000
+#elif SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN may not exceed 32767
#endif
/*
diff --git a/src/status.c b/src/status.c
index a462c94293..b0a47c7f85 100644
--- a/src/status.c
+++ b/src/status.c
@@ -192,8 +192,9 @@ int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
nInit += countLookasideSlots(db->lookaside.pSmallInit);
nFree += countLookasideSlots(db->lookaside.pSmallFree);
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
- if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
- return db->lookaside.nSlot - (nInit+nFree);
+ assert( db->lookaside.nSlot >= nInit+nFree );
+ if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit);
+ return (int)(db->lookaside.nSlot - (nInit+nFree));
}
/*
@@ -246,7 +247,7 @@ int sqlite3_db_status(
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
*pCurrent = 0;
- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
+ *pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT];
if( resetFlag ){
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
}
diff --git a/src/test1.c b/src/test1.c
index a3f29ce2ea..5697d7dd99 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -6023,6 +6023,42 @@ static int SQLITE_TCLAPI test_busy_timeout(
return TCL_OK;
}
+/*
+** Usage: sqlite3_setlk_timeout ?-blockonconnect? DB MS
+**
+** Set the setlk timeout.
+*/
+static int SQLITE_TCLAPI test_setlk_timeout(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ int rc, ms;
+ sqlite3 *db;
+ int bBlockOnConnect = 0;
+
+ if( argc==4 ){
+ const char *zArg = argv[1];
+ int nArg = strlen(zArg);
+ if( nArg>=2 && nArg<=15 && memcmp(zArg, "-blockonconnect", nArg)==0 ){
+ bBlockOnConnect = 1;
+ }
+ }
+ if( argc!=(3+bBlockOnConnect) ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " ?-blockonconnect? DB MS", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, argv[argc-2], &db) ) return TCL_ERROR;
+ if( Tcl_GetInt(interp, argv[argc-1], &ms) ) return TCL_ERROR;
+ rc = sqlite3_setlk_timeout(
+ db, ms, (bBlockOnConnect ? SQLITE_SETLK_BLOCK_ON_CONNECT : 0)
+ );
+ Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+ return TCL_OK;
+}
+
/*
** Usage: tcl_variable_type VARIABLENAME
**
@@ -8016,7 +8052,7 @@ static int SQLITE_TCLAPI test_getrusage(
*/
struct win32FileLocker {
char *evName; /* Name of event to signal thread startup */
- HANDLE h; /* Handle of the file to be locked */
+ sqlite3_file *pFd; /* Handle of the file to be locked */
int delay1; /* Delay before locking */
int delay2; /* Delay before unlocking */
int ok; /* Finished ok */
@@ -8032,6 +8068,8 @@ struct win32FileLocker {
*/
static void SQLITE_CDECL win32_file_locker(void *pAppData){
struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
+ sqlite3_file *pFd = p->pFd;
+ HANDLE h = INVALID_HANDLE_VALUE;
if( p->evName ){
HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
if ( ev ){
@@ -8040,15 +8078,17 @@ static void SQLITE_CDECL win32_file_locker(void *pAppData){
}
}
if( p->delay1 ) Sleep(p->delay1);
- if( LockFile(p->h, 0, 0, 100000000, 0) ){
+ pFd->pMethods->xFileControl(pFd, SQLITE_FCNTL_WIN32_GET_HANDLE, (void*)&h);
+ if( LockFile(h, 0, 0, 100000000, 0) ){
Sleep(p->delay2);
- UnlockFile(p->h, 0, 0, 100000000, 0);
+ UnlockFile(h, 0, 0, 100000000, 0);
p->ok = 1;
}else{
p->err = 1;
}
- CloseHandle(p->h);
- p->h = 0;
+ pFd->pMethods->xClose(pFd);
+ sqlite3_free(pFd);
+ p->pFd = 0;
p->delay1 = 0;
p->delay2 = 0;
}
@@ -8068,37 +8108,56 @@ static int SQLITE_TCLAPI win32_file_lock(
Tcl_Obj *CONST objv[]
){
static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
- const char *zFilename;
+ const char *zFilename = 0;
+ Tcl_Size nFilename = 0;
+ char *zTerm = 0;
char zBuf[200];
int retry = 0;
HANDLE ev;
DWORD wResult;
+ sqlite3_vfs *pVfs = 0;
+ int flags = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE;
+ int rc = SQLITE_OK;
if( objc!=4 && objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
return TCL_ERROR;
}
if( objc==1 ){
+ HANDLE h = INVALID_HANDLE_VALUE;
+ if( x.pFd ){
+ x.pFd->pMethods->xFileControl(
+ x.pFd, SQLITE_FCNTL_WIN32_GET_HANDLE, (void*)&h
+ );
+ }
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
- x.ok, x.err, x.delay1, x.delay2, x.h);
+ x.ok, x.err, x.delay1, x.delay2, h);
Tcl_AppendResult(interp, zBuf, (char*)0);
return TCL_OK;
}
- while( x.h && retry<30 ){
+ while( x.pFd && retry<30 ){
retry++;
Sleep(100);
}
- if( x.h ){
+ if( x.pFd ){
Tcl_AppendResult(interp, "busy", (char*)0);
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
- zFilename = Tcl_GetString(objv[1]);
- x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, 0);
- if( !x.h ){
+ pVfs = sqlite3_vfs_find(0);
+ x.pFd = (sqlite3_file*)sqlite3_malloc(pVfs->szOsFile);
+
+ /* xOpen() must be passed a dual-nul-terminated string preceded in memory
+ ** by 4 0x00 bytes. */
+ zFilename = Tcl_GetStringFromObj(objv[1], &nFilename);
+ zTerm = (char*)sqlite3_malloc(nFilename+6);
+ memset(zTerm, 0, nFilename+6);
+ memcpy(&zTerm[4], zFilename, nFilename);
+ rc = pVfs->xOpen(pVfs, &zTerm[4], x.pFd, flags, &flags);
+ sqlite3_free(zTerm);
+
+ if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
return TCL_ERROR;
}
@@ -8960,6 +9019,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
{ "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
{ "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
+ { "sqlite3_setlk_timeout", (Tcl_CmdProc*)test_setlk_timeout },
{ "printf", (Tcl_CmdProc*)test_printf },
{ "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
{ "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
diff --git a/src/test_config.c b/src/test_config.c
index f70a667b41..dad952985c 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -88,6 +88,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "win32malloc", "0", TCL_GLOBAL_ONLY);
#endif
+#if defined(SQLITE_OS_WINRT) && SQLITE_OS_WINRT
+ Tcl_SetVar2(interp, "sqlite_options", "winrt", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "winrt", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_DEBUG
Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
#else
@@ -799,6 +805,13 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
#endif
+#if !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ Tcl_SetVar2(interp, "sqlite_options", "setlk_timeout", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "setlk_timeout",
+ STRINGVALUE(SQLITE_ENABLE_SETLK_TIMEOUT), TCL_GLOBAL_ONLY);
+#endif
+
#define LINKVAR(x) { \
static const int cv_ ## x = SQLITE_ ## x; \
Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
diff --git a/src/test_quota.c b/src/test_quota.c
index 1bfc5ce11c..62d808a22b 100644
--- a/src/test_quota.c
+++ b/src/test_quota.c
@@ -389,7 +389,11 @@ static char *quota_utf8_to_mbcs(const char *zUtf8){
zTmpWide = (LPWSTR)sqlite3_malloc( (nWide+1)*sizeof(zTmpWide[0]) );
if( zTmpWide==0 ) return 0;
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zTmpWide, nWide);
+#ifdef SQLITE_OS_WINRT
+ codepage = CP_ACP;
+#else
codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+#endif
nMbcs = WideCharToMultiByte(codepage, 0, zTmpWide, nWide, 0, 0, 0, 0);
zMbcs = nMbcs ? (char*)sqlite3_malloc( nMbcs+1 ) : 0;
if( zMbcs ){
diff --git a/src/test_vfs.c b/src/test_vfs.c
index 9f84b4f801..f75ef956b6 100644
--- a/src/test_vfs.c
+++ b/src/test_vfs.c
@@ -130,8 +130,9 @@ struct Testvfs {
#define TESTVFS_LOCK_MASK 0x00040000
#define TESTVFS_CKLOCK_MASK 0x00080000
#define TESTVFS_FCNTL_MASK 0x00100000
+#define TESTVFS_SLEEP_MASK 0x00200000
-#define TESTVFS_ALL_MASK 0x001FFFFF
+#define TESTVFS_ALL_MASK 0x003FFFFF
#define TESTVFS_MAX_PAGES 1024
@@ -813,6 +814,10 @@ static int tvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
** actually slept.
*/
static int tvfsSleep(sqlite3_vfs *pVfs, int nMicro){
+ Testvfs *p = (Testvfs *)pVfs->pAppData;
+ if( p->pScript && (p->mask&TESTVFS_SLEEP_MASK) ){
+ tvfsExecTcl(p, "xSleep", Tcl_NewIntObj(nMicro), 0, 0, 0);
+ }
return sqlite3OsSleep(PARENTVFS(pVfs), nMicro);
}
@@ -1197,6 +1202,7 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
{ "xLock", TESTVFS_LOCK_MASK },
{ "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
{ "xFileControl", TESTVFS_FCNTL_MASK },
+ { "xSleep", TESTVFS_SLEEP_MASK },
};
Tcl_Obj **apElem = 0;
Tcl_Size nElem = 0;
diff --git a/src/utf.c b/src/utf.c
index c934bb234c..57700bf20d 100644
--- a/src/utf.c
+++ b/src/utf.c
@@ -105,6 +105,35 @@ static const unsigned char sqlite3Utf8Trans1[] = {
} \
}
+/*
+** Write a single UTF8 character whose value is v into the
+** buffer starting at zOut. zOut must be sized to hold at
+** least for bytes. Return the number of bytes needed
+** to encode the new character.
+*/
+int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
+ if( v<0x00080 ){
+ zOut[0] = (u8)(v & 0xff);
+ return 1;
+ }
+ if( v<0x00800 ){
+ zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f);
+ zOut[1] = 0x80 + (u8)(v & 0x3f);
+ return 2;
+ }
+ if( v<0x10000 ){
+ zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f);
+ zOut[1] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[2] = 0x80 + (u8)(v & 0x3f);
+ return 3;
+ }
+ zOut[0] = 0xf0 + (u8)((v>>18) & 0x07);
+ zOut[1] = 0x80 + (u8)((v>>12) & 0x3f);
+ zOut[2] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[3] = 0x80 + (u8)(v & 0x3f);
+ return 4;
+}
+
/*
** Translate a single UTF-8 character. Return the unicode value.
**
diff --git a/src/util.c b/src/util.c
index 703ef0a23a..8e4fd516ef 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1639,7 +1639,7 @@ int sqlite3MulInt64(i64 *pA, i64 iB){
}
/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** Compute the absolute value of a 32-bit signed integer, if possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
int sqlite3AbsInt32(int x){
diff --git a/src/vdbesort.c b/src/vdbesort.c
index 5774537b81..c9da88f6e1 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -1431,6 +1431,10 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
p->u.pNext = 0;
for(i=0; aSlot[i]; i++){
p = vdbeSorterMerge(pTask, p, aSlot[i]);
+ /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use
+ ** | up all 64 aSlots[] with only a 64-bit address space.
+ ** v */
+ assert( idb ){
- int tmout = pWal->db->busyTimeout;
+ int tmout = pWal->db->setlkTimeout;
if( tmout ){
res = walEnableBlockingMs(pWal, tmout);
}
@@ -3061,7 +3066,9 @@ static int walHandleException(Wal *pWal){
static const int S = 1;
static const int E = (1<lockMask & ~(
+ u32 mUnlock;
+ if( pWal->writeLock==2 ) pWal->writeLock = 0;
+ mUnlock = pWal->lockMask & ~(
(pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
| (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
| (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
@@ -3358,7 +3365,12 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
if( bWriteLock
|| SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
){
- pWal->writeLock = 1;
+ /* If the write-lock was just obtained, set writeLock to 2 instead of
+ ** the usual 1. This causes walIndexPage() to behave as if the
+ ** write-lock were held (so that it allocates new pages as required),
+ ** and walHandleException() to unlock the write-lock if a SEH exception
+ ** is thrown. */
+ if( !bWriteLock ) pWal->writeLock = 2;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
@@ -4191,8 +4203,11 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** read-lock.
*/
void sqlite3WalEndReadTransaction(Wal *pWal){
- sqlite3WalEndWriteTransaction(pWal);
+#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
+ assert( pWal->writeLock==0 || pWal->readLock<0 );
+#endif
if( pWal->readLock!=WAL_LOCK_NONE ){
+ sqlite3WalEndWriteTransaction(pWal);
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
pWal->readLock = WAL_LOCK_NONE;
}
@@ -4506,7 +4521,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
** read-transaction was even opened, making this call a no-op.
** Return early. */
if( pWal->writeLock ){
- assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
+ assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) );
return SQLITE_OK;
}
#endif
diff --git a/src/where.c b/src/where.c
index 5cb52b8adb..1275250067 100644
--- a/src/where.c
+++ b/src/where.c
@@ -1104,6 +1104,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}
/* Construct the Index object to describe this index */
+ assert( nKeyCol <= pTable->nCol + MAX(0, pTable->nCol - BMS + 1) );
+ /* ^-- This guarantees that the number of index columns will fit in the u16 */
pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable),
0, &zNotUsed);
if( pIdx==0 ) goto end_auto_index_create;
diff --git a/src/window.c b/src/window.c
index 8373e36413..948b0728af 100644
--- a/src/window.c
+++ b/src/window.c
@@ -995,7 +995,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pWhere = 0;
p->pGroupBy = 0;
p->pHaving = 0;
- p->selFlags &= ~SF_Aggregate;
+ p->selFlags &= ~(u32)SF_Aggregate;
p->selFlags |= SF_WinRewrite;
/* Create the ORDER BY clause for the sub-select. This is the concatenation
diff --git a/test/alter3.test b/test/alter3.test
index c6f26b0c50..464e20aee2 100644
--- a/test/alter3.test
+++ b/test/alter3.test
@@ -101,7 +101,7 @@ do_test alter3-1.7 {
} {{CREATE TABLE t3(a, b, c VARCHAR(10, 20), UNIQUE(a, b))}}
do_test alter3-1.99 {
catchsql {
- # May not exist if foriegn-keys are omitted at compile time.
+ # May not exist if foreign-keys are omitted at compile time.
DROP TABLE t2;
}
execsql {
diff --git a/test/alter4.test b/test/alter4.test
index c63ba6b072..f6ada8f3fb 100644
--- a/test/alter4.test
+++ b/test/alter4.test
@@ -110,7 +110,7 @@ do_test alter4-1.7 {
} {{CREATE TABLE t3(a, b, c VARCHAR(10, 20), UNIQUE(a, b))}}
do_test alter4-1.99 {
catchsql {
- # May not exist if foriegn-keys are omitted at compile time.
+ # May not exist if foreign-keys are omitted at compile time.
DROP TABLE t2;
}
execsql {
diff --git a/test/analyze3.test b/test/analyze3.test
index c5d7a7cb13..033dfa5dff 100644
--- a/test/analyze3.test
+++ b/test/analyze3.test
@@ -48,7 +48,7 @@ if {[permutation]=="prepare"} {
# query plan when there is no way in which replanning the
# query may produce a superior outcome.
#
-# analyze3-4.*: Test that SQL or authorization callback errors occuring
+# analyze3-4.*: Test that SQL or authorization callback errors occurring
# within sqlite3Reprepare() are handled correctly.
#
# analyze3-5.*: Check that the query plans of applicable statements are
diff --git a/test/collate1.test b/test/collate1.test
index b65b850474..da662bee62 100644
--- a/test/collate1.test
+++ b/test/collate1.test
@@ -23,7 +23,7 @@ set testprefix collate1
# collate1-1.* - Single-field ORDER BY with an explicit COLLATE clause.
# collate1-2.* - Multi-field ORDER BY with an explicit COLLATE clause.
# collate1-3.* - ORDER BY using a default collation type. Also that an
-# explict collate type overrides a default collate type.
+# explicit collate type overrides a default collate type.
# collate1-4.* - ORDER BY using a data type.
#
diff --git a/test/collateB.test b/test/collateB.test
index 3c8d50d8e6..678eb5af0f 100644
--- a/test/collateB.test
+++ b/test/collateB.test
@@ -62,7 +62,7 @@ do_execsql_test collateB-1.17 {
} {1 11 1 11 |}
#-------------------------------------------------------------------------
-# Test an assert() failure that was occuring if an index were created
+# Test an assert() failure that was occurring if an index were created
# on a column explicitly declared "COLLATE binary".
reset_db
do_execsql_test 2.1 {
diff --git a/test/colmeta.test b/test/colmeta.test
index 21b0e0f38a..43d2c83cb6 100644
--- a/test/colmeta.test
+++ b/test/colmeta.test
@@ -97,7 +97,7 @@ foreach {tn params results} $tests {
}
# Calling sqlite3_table_column_metadata with a NULL column name merely
-# checks for the existance of the table.
+# checks for the existence of the table.
#
do_test colmeta-300 {
catch {sqlite3_table_column_metadata $::DB main xyzzy} res
diff --git a/test/dbfuzz.c b/test/dbfuzz.c
index ca1c6ea217..1587bacbbd 100644
--- a/test/dbfuzz.c
+++ b/test/dbfuzz.c
@@ -368,7 +368,7 @@ static int inmemDelete(
return SQLITE_IOERR_DELETE;
}
-/* Check for the existance of a file
+/* Check for the existence of a file
*/
static int inmemAccess(
sqlite3_vfs *pVfs,
diff --git a/test/enc2.test b/test/enc2.test
index 81e7bfd68c..f7446a40ef 100644
--- a/test/enc2.test
+++ b/test/enc2.test
@@ -63,7 +63,7 @@ set dbcontents {
INSERT INTO t1 VALUES('one', 'I', 1);
}
# This proc tests that we can open and manipulate the test.db
-# database, and that it is possible to retreive values in
+# database, and that it is possible to retrieve values in
# various text encodings.
#
proc run_test_script {t enc} {
diff --git a/test/filectrl.test b/test/filectrl.test
index 460b71e257..fee29e0442 100644
--- a/test/filectrl.test
+++ b/test/filectrl.test
@@ -36,11 +36,13 @@ do_test filectrl-1.5 {
sqlite3 db test_control_lockproxy.db
file_control_lockproxy_test db [get_pwd]
} {}
-do_test filectrl-1.6 {
- sqlite3 db test.db
- set fn [file_control_tempfilename db]
- set fn
-} {/etilqs_/}
+ifcapable !winrt {
+ do_test filectrl-1.6 {
+ sqlite3 db test.db
+ set fn [file_control_tempfilename db]
+ set fn
+ } {/etilqs_/}
+}
db close
forcedelete .test_control_lockproxy.db-conch test.proxy
forcedelete test.db test2.db
diff --git a/test/fts3cov.test b/test/fts3cov.test
index 5d83836576..d01791bbe5 100644
--- a/test/fts3cov.test
+++ b/test/fts3cov.test
@@ -25,7 +25,7 @@ set testprefix fts3cov
# When it first needs to read a block from the %_segments table, the FTS3
# module compiles an SQL statement for that purpose. The statement is
# stored and reused each subsequent time a block is read. This test case
-# tests the effects of an OOM error occuring while compiling the statement.
+# tests the effects of an OOM error occurring while compiling the statement.
#
# Similarly, when FTS3 first needs to scan through a set of segment leaves
# to find a set of documents that matches a term, it allocates a string
@@ -277,7 +277,7 @@ do_test fts3cov-7.2 {
# pending-terms table must be flushed each time a document with a docid
# less than or equal to the previous docid is modified.
#
-# This test checks the effects of an OOM error occuring when the
+# This test checks the effects of an OOM error occurring when the
# pending-terms table is flushed for this reason as part of a DELETE
# statement.
#
diff --git a/test/fts3expr2.test b/test/fts3expr2.test
index c3d161730b..6fb133f17f 100644
--- a/test/fts3expr2.test
+++ b/test/fts3expr2.test
@@ -46,7 +46,7 @@ ifcapable !fts3 {
# * Whether or not superflous parenthesis are included. i.e. if
# "a OR b AND (c OR d)" or "a OR (b AND (c OR d))" is generated.
#
-# * Whether or not explict AND operators are used. i.e. if
+# * Whether or not explicit AND operators are used. i.e. if
# "a OR b AND c" or "a OR b c" is generated.
#
diff --git a/test/fts4langid.test b/test/fts4langid.test
index 7be594bd5f..84424ff3c7 100644
--- a/test/fts4langid.test
+++ b/test/fts4langid.test
@@ -435,7 +435,7 @@ do_test 5.3.2 {
for {set i 0} {$i < 20} {incr i} {
execsql {
INSERT INTO t6(content, lid) VALUES(
- 'I (row '||$i||') belong to langauge N!', $lid
+ 'I (row '||$i||') belong to language N!', $lid
);
}
}
diff --git a/test/func9.test b/test/func9.test
index 6cf9fc31ec..42138ab2e1 100644
--- a/test/func9.test
+++ b/test/func9.test
@@ -9,7 +9,7 @@
#
#*************************************************************************
#
-# Test cases for SQL newer functions
+# Test cases for some newer SQL functions
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -36,5 +36,15 @@ do_catchsql_test func9-160 {
SELECT concat_ws(',');
} {1 {wrong number of arguments to function concat_ws()}}
+# https://sqlite.org/forum/forumpost/4c344ca61f (2025-03-02)
+do_execsql_test func9-200 {
+ SELECT unistr('G\u00e4ste');
+} {Gäste}
+do_execsql_test func9-210 {
+ SELECT unistr_quote(unistr('G\u00e4ste'));
+} {'Gäste'}
+do_execsql_test func9-220 {
+ SELECT format('%#Q',unistr('G\u00e4ste'));
+} {'Gäste'}
finish_test
diff --git a/test/fuzz.test b/test/fuzz.test
index 83dc79bc78..7002054be9 100644
--- a/test/fuzz.test
+++ b/test/fuzz.test
@@ -130,7 +130,7 @@ do_test fuzz-1.12.1 {
# The following query was crashing. The later subquery (in the FROM)
# clause was flattened into the parent, but the code was not repairng
# the "b" reference in the other sub-query. When the query was executed,
- # that "b" refered to a non-existant vdbe table-cursor.
+ # that "b" referred to a non-existant vdbe table-cursor.
#
execsql {
SELECT 1 IN ( SELECT b UNION SELECT 1 ) FROM (SELECT b FROM abc);
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index 84e3f32895..140ad6944d 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -1594,7 +1594,7 @@ static int inmemDelete(
return SQLITE_IOERR_DELETE;
}
-/* Check for the existance of a file
+/* Check for the existence of a file
*/
static int inmemAccess(
sqlite3_vfs *pVfs,
diff --git a/test/in4.test b/test/in4.test
index 71993e7003..07cd3e284d 100644
--- a/test/in4.test
+++ b/test/in4.test
@@ -442,7 +442,7 @@ do_execsql_test 10.0 {
} {10}
# 2021-06-13 dbsqlfuzz e41762333a4d6e90a49e628f488d0873b2dba4c5
-# The opcode that preceeds OP_SeekScan is usually OP_IdxGT, but can
+# The opcode that precedes OP_SeekScan is usually OP_IdxGT, but can
# sometimes be OP_IdxGE
#
reset_db
diff --git a/test/indexedby.test b/test/indexedby.test
index 6a371112b3..de4bdaf185 100644
--- a/test/indexedby.test
+++ b/test/indexedby.test
@@ -187,7 +187,7 @@ do_test indexedby-4.4 {
} {0 {}}
# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
-# also tests that nothing bad happens if an index refered to by
+# also tests that nothing bad happens if an index referred to by
# a CREATE VIEW statement is dropped and recreated.
#
do_execsql_test indexedby-5.1 {
diff --git a/test/json/json-speed-check.sh b/test/json/json-speed-check.sh
index 682a7aeedd..1eabbb3db2 100755
--- a/test/json/json-speed-check.sh
+++ b/test/json/json-speed-check.sh
@@ -5,7 +5,7 @@
#
# sh speed-check.sh trunk # Baseline measurement of trunk
# sh speed-check.sh x1 # Measure some experimental change
-# fossil xdiff --tk jout-trunk.txt jout-x1.txt # View chanages
+# fossil xdiff --tk jout-trunk.txt jout-x1.txt # View changes
#
# There are multiple output files, all with a base name given by
# the first argument:
diff --git a/test/lock_common.tcl b/test/lock_common.tcl
index 3e1821bab0..7c79e4b4c5 100644
--- a/test/lock_common.tcl
+++ b/test/lock_common.tcl
@@ -145,6 +145,7 @@ proc testfixture_nb_cb {varname chan} {
}
if { $line == "OVER" } {
+ if {[string range $varname 0 1]!="::"} { global $varname }
set $varname [lindex $::tfnb($chan) 1]
unset ::tfnb($chan)
close $chan
diff --git a/test/misuse.test b/test/misuse.test
index e15cf3357e..2ba61f9eb5 100644
--- a/test/misuse.test
+++ b/test/misuse.test
@@ -172,7 +172,11 @@ do_test misuse-4.3 {
lappend v $msg $r
} {0 {} SQLITE_BUSY}
-if {[clang_sanitize_address]==0} {
+# All of the following tests can potentially (though rarely)
+# lead to segfaults, which is unsettling. So they are disabled
+# for now__________________________
+# v
+if {[clang_sanitize_address]==0 && 0} {
do_test misuse-4.4 {
# Flush the TCL statement cache here, otherwise the sqlite3_close() will
# fail because there are still un-finalized() VDBEs.
diff --git a/test/shell1.test b/test/shell1.test
index a272295f55..598005a900 100644
--- a/test/shell1.test
+++ b/test/shell1.test
@@ -296,7 +296,9 @@ do_test shell1-3.2.4 {
catchcmd "test.db" ".bail OFF BAD"
} {1 {Usage: .bail on|off}}
-ifcapable vtab {
+# This test will not work on winrt, as winrt has no concept of the absolute
+# paths that the test expects in the result. It uses relative paths only.
+ifcapable vtab&&!winrt {
# .databases List names and files of attached databases
do_test shell1-3.3.1 {
catchcmd "-csv test.db" ".databases"
@@ -450,7 +452,7 @@ do_test shell1-3.12.3 {
# tcl TCL list elements
do_test shell1-3.13.1 {
catchcmd "test.db" ".mode"
-} {0 {current output mode: list}}
+} {0 {current output mode: list --escape ascii}}
do_test shell1-3.13.2 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl}}
@@ -744,9 +746,12 @@ do_test shell1-3.26.6 {
do_test shell1-3.27.1 {
catchcmd "test.db" ".timer"
} {1 {Usage: .timer on|off}}
-do_test shell1-3.27.2 {
- catchcmd "test.db" ".timer ON"
-} {0 {}}
+ifcapable !winrt {
+ # No timer support on winrt.
+ do_test shell1-3.27.2 {
+ catchcmd "test.db" ".timer ON"
+ } {0 {}}
+}
do_test shell1-3.27.3 {
catchcmd "test.db" ".timer OFF"
} {0 {}}
diff --git a/test/shellA.test b/test/shellA.test
new file mode 100644
index 0000000000..1a8161bf38
--- /dev/null
+++ b/test/shellA.test
@@ -0,0 +1,257 @@
+# 2025-02-24
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# TESTRUNNER: shell
+#
+# Test cases for the command-line shell - focusing on .mode and
+# especially control-character escaping and the --escape option.
+#
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set CLI [test_cli_invocation]
+
+do_execsql_test shellA-1.0 {
+ CREATE TABLE t1(a INT, x TEXT);
+ INSERT INTO t1 VALUES
+ (1, 'line with '' single quote'),
+ (2, concat(char(0x1b),'[31mVT-100 codes',char(0x1b),'[0m')),
+ (3, NULL),
+ (4, 1234),
+ (5, 568.25),
+ (6, unistr('new\u000aline')),
+ (7, unistr('carriage\u000dreturn')),
+ (8, 'last line');
+} {}
+
+# Initial verification that the database created correctly
+# and that our calls to the CLI are working.
+#
+do_test shellA-1.2 {
+ exec {*}$CLI test.db {.mode box --escape symbol} {SELECT * FROM t1;}
+} {
+┌───┬──────────────────────────┐
+│ a │ x │
+├───┼──────────────────────────┤
+│ 1 │ line with ' single quote │
+├───┼──────────────────────────┤
+│ 2 │ ␛[31mVT-100 codes␛[0m │
+├───┼──────────────────────────┤
+│ 3 │ │
+├───┼──────────────────────────┤
+│ 4 │ 1234 │
+├───┼──────────────────────────┤
+│ 5 │ 568.25 │
+├───┼──────────────────────────┤
+│ 6 │ new │
+│ │ line │
+├───┼──────────────────────────┤
+│ 7 │ carriage␍return │
+├───┼──────────────────────────┤
+│ 8 │ last line │
+└───┴──────────────────────────┘
+}
+
+# ".mode list"
+#
+do_test shellA-1.3 {
+ exec {*}$CLI test.db {SELECT x FROM t1 WHERE a=2;}
+} {
+^[[31mVT-100 codes^[[0m
+}
+do_test shellA-1.4 {
+ exec {*}$CLI test.db --escape symbol {SELECT x FROM t1 WHERE a=2;}
+} {
+␛[31mVT-100 codes␛[0m
+}
+do_test shellA-1.5 {
+ exec {*}$CLI test.db --escape ascii {SELECT x FROM t1 WHERE a=2;}
+} {
+^[[31mVT-100 codes^[[0m
+}
+do_test shellA-1.6 {
+ exec {*}$CLI test.db {.mode list --escape symbol} {SELECT x FROM t1 WHERE a=2;}
+} {
+␛[31mVT-100 codes␛[0m
+}
+do_test shellA-1.7 {
+ exec {*}$CLI test.db {.mode list --escape ascii} {SELECT x FROM t1 WHERE a=2;}
+} {
+^[[31mVT-100 codes^[[0m
+}
+do_test shellA-1.8 {
+ file delete -force out.txt
+ exec {*}$CLI test.db {.mode list --escape off} {SELECT x FROM t1 WHERE a=7;} \
+ >out.txt
+ set fd [open out.txt rb]
+ set res [read $fd]
+ close $fd
+ string trim $res
+} "carriage\rreturn"
+do_test shellA-1.9 {
+ set rc [catch {
+ exec {*}$CLI test.db {.mode test --escape xyz}
+ } msg]
+ lappend rc $msg
+} {1 {unknown control character escape mode "xyz" - choices: ascii symbol off}}
+do_test shellA-1.10 {
+ set rc [catch {
+ exec {*}$CLI --escape abc test.db .q
+ } msg]
+ lappend rc $msg
+} {1 {unknown control character escape mode "abc" - choices: ascii symbol off}}
+
+# ".mode quote"
+#
+do_test shellA-2.1 {
+ exec {*}$CLI test.db --quote {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+1,'line with '' single quote'
+2,unistr('\u001b[31mVT-100 codes\u001b[0m')
+6,'new
+line'
+7,unistr('carriage\u000dreturn')
+8,'last line'
+}
+do_test shellA-2.2 {
+ exec {*}$CLI test.db --quote {.mode}
+} {current output mode: quote --escape ascii}
+do_test shellA-2.3 {
+ exec {*}$CLI test.db --quote --escape SYMBOL {.mode}
+} {current output mode: quote --escape symbol}
+do_test shellA-2.4 {
+ exec {*}$CLI test.db --quote --escape OFF {.mode}
+} {current output mode: quote --escape off}
+
+
+# ".mode line"
+#
+do_test shellA-3.1 {
+ exec {*}$CLI test.db --line --escape symbol \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+ a = 1
+ x = line with ' single quote
+
+ a = 2
+ x = ␛[31mVT-100 codes␛[0m
+
+ a = 6
+ x = new
+line
+
+ a = 7
+ x = carriage␍return
+
+ a = 8
+ x = last line
+}
+do_test shellA-3.2 {
+ exec {*}$CLI test.db --line --escape ascii \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+ a = 1
+ x = line with ' single quote
+
+ a = 2
+ x = ^[[31mVT-100 codes^[[0m
+
+ a = 6
+ x = new
+line
+
+ a = 7
+ x = carriage^Mreturn
+
+ a = 8
+ x = last line
+}
+
+# ".mode box"
+#
+do_test shellA-4.1 {
+ exec {*}$CLI test.db --box --escape ascii \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+┌───┬──────────────────────────┐
+│ a │ x │
+├───┼──────────────────────────┤
+│ 1 │ line with ' single quote │
+├───┼──────────────────────────┤
+│ 2 │ ^[[31mVT-100 codes^[[0m │
+├───┼──────────────────────────┤
+│ 6 │ new │
+│ │ line │
+├───┼──────────────────────────┤
+│ 7 │ carriage^Mreturn │
+├───┼──────────────────────────┤
+│ 8 │ last line │
+└───┴──────────────────────────┘
+}
+do_test shellA-4.2 {
+ exec {*}$CLI test.db {.mode qbox} {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+┌───┬───────────────────────────────────────────┐
+│ a │ x │
+├───┼───────────────────────────────────────────┤
+│ 1 │ 'line with '' single quote' │
+├───┼───────────────────────────────────────────┤
+│ 2 │ unistr('\u001b[31mVT-100 codes\u001b[0m') │
+├───┼───────────────────────────────────────────┤
+│ 6 │ 'new │
+│ │ line' │
+├───┼───────────────────────────────────────────┤
+│ 7 │ unistr('carriage\u000dreturn') │
+├───┼───────────────────────────────────────────┤
+│ 8 │ 'last line' │
+└───┴───────────────────────────────────────────┘
+}
+
+# ".mode insert"
+#
+do_test shellA-5.1 {
+ exec {*}$CLI test.db {.mode insert t1 --escape ascii} \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+INSERT INTO t1 VALUES(1,'line with '' single quote');
+INSERT INTO t1 VALUES(2,unistr('\u001b[31mVT-100 codes\u001b[0m'));
+INSERT INTO t1 VALUES(6,unistr('new\u000aline'));
+INSERT INTO t1 VALUES(7,unistr('carriage\u000dreturn'));
+INSERT INTO t1 VALUES(8,'last line');
+}
+do_test shellA-5.2 {
+ exec {*}$CLI test.db {.mode insert t1 --escape symbol} \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
+} {
+INSERT INTO t1 VALUES(1,'line with '' single quote');
+INSERT INTO t1 VALUES(2,unistr('\u001b[31mVT-100 codes\u001b[0m'));
+INSERT INTO t1 VALUES(6,unistr('new\u000aline'));
+INSERT INTO t1 VALUES(7,unistr('carriage\u000dreturn'));
+INSERT INTO t1 VALUES(8,'last line');
+}
+do_test shellA-5.3 {
+ file delete -force out.txt
+ exec {*}$CLI test.db {.mode insert t1 --escape off} \
+ {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} >out.txt
+ set fd [open out.txt rb]
+ set res [read $fd]
+ close $fd
+ string trim [string map [list \r\n \n] $res]
+} "
+INSERT INTO t1 VALUES(1,'line with '' single quote');
+INSERT INTO t1 VALUES(2,'\033\13331mVT-100 codes\033\1330m');
+INSERT INTO t1 VALUES(6,'new
+line');
+INSERT INTO t1 VALUES(7,'carriage\rreturn');
+INSERT INTO t1 VALUES(8,'last line');
+"
+
+finish_test
diff --git a/test/tester.tcl b/test/tester.tcl
index f9b9638a7c..331888acb7 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -1777,6 +1777,11 @@ proc crashsql {args} {
# cfSync(), which can be different then what TCL uses by
# default, so here we force it to the "nativename" format.
set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
+ ifcapable winrt {
+ # Except on winrt. Winrt has no way to transform a relative path into
+ # an absolute one, so it just uses the relative paths.
+ set cfile $crashfile
+ }
set f [open crash.tcl w]
puts $f "sqlite3_initialize ; sqlite3_shutdown"
diff --git a/test/testrunner.tcl b/test/testrunner.tcl
index d365092e05..6ff414c4bd 100755
--- a/test/testrunner.tcl
+++ b/test/testrunner.tcl
@@ -30,8 +30,8 @@ proc find_interpreter {} {
&& [file executable ./testfixture]
} {
puts "Failed to find tcl package sqlite3. Restarting with ./testfixture.."
- set status [catch {
- exec ./testfixture [info script] {*}$::argv >@ stdout
+ set status [catch {
+ exec [trd_get_bin_name testfixture] [info script] {*}$::argv >@ stdout
} msg]
exit $status
}
@@ -237,7 +237,7 @@ switch -nocase -glob -- $tcl_platform(os) {
set TRG(run) run.sh
set TRG(runcmd) "bash run.sh"
}
- *linux* {
+ *linux* - MSYS_NT* - MINGW64_NT* - MINGW32_NT* {
set TRG(platform) linux
set TRG(make) make.sh
set TRG(makecmd) "bash make.sh"
@@ -265,9 +265,10 @@ switch -nocase -glob -- $tcl_platform(os) {
set TRG(runcmd) "run.bat"
}
default {
+ puts "tcl_platform(os)=$::tcl_platform(os)"
error "cannot determine platform!"
}
-}
+}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl
index 2cfa7f3b31..2597cbe478 100644
--- a/test/testrunner_data.tcl
+++ b/test/testrunner_data.tcl
@@ -37,6 +37,7 @@ namespace eval trd {
set tcltest(win.Windows-Memdebug) veryquick
set tcltest(win.Windows-Win32Heap) veryquick
set tcltest(win.Windows-Sanitize) veryquick
+ set tcltest(win.Windows-WinRT) veryquick
set tcltest(win.Default) full
# Extra [make xyz] tests that should be run for various builds.
@@ -358,11 +359,17 @@ namespace eval trd {
set build(Windows-Win32Heap) {
WIN32HEAP=1
DEBUG=4
+ ENABLE_SETLK=1
}
set build(Windows-Sanitize) {
ASAN=1
}
+ set build(Windows-WinRT) {
+ FOR_WINRT=1
+ ENABLE_SETLK=1
+ -DSQLITE_TEMP_STORE=3
+ }
}
@@ -452,7 +459,7 @@ proc trd_fuzztest_data {} {
return [list fuzzcheck.exe $lFuzzDb]
}
- return [list fuzzcheck $lFuzzDb {sessionfuzz run} $lSessionDb]
+ return [list [trd_get_bin_name fuzzcheck] $lFuzzDb {sessionfuzz run} $lSessionDb]
}
@@ -681,3 +688,15 @@ proc trd_test_script_properties {path} {
set trd_test_script_properties_cache($path)
}
+
+# Usage:
+#
+# trd_get_bin_name executable-file-name
+#
+# If the tcl platform is "unix", return $bin, else return
+# ${bin}.exe.
+proc trd_get_bin_name {bin} {
+ global tcl_platform
+ if {"unix" eq $tcl_platform(platform)} {return $bin}
+ return $bin.exe
+}
diff --git a/test/walsetlk.test b/test/walsetlk.test
index 1e09238226..d3fd050a63 100644
--- a/test/walsetlk.test
+++ b/test/walsetlk.test
@@ -80,6 +80,19 @@ db2 close
#-------------------------------------------------------------------------
do_multiclient_test tn {
+
+ testvfs tvfs -fullshm 1
+ db close
+ sqlite3 db test.db -vfs tvfs
+ tvfs script xSleep_callback
+ tvfs filter xSleep
+
+ set ::sleep_count 0
+ proc xSleep_callback {xSleep nMs} {
+ after [expr $nMs / 1000]
+ incr ::sleep_count
+ }
+
do_test 2.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
@@ -132,7 +145,6 @@ do_multiclient_test tn {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
-
do_test 2.$tn.9 {
sql3 {
INSERT INTO t1 VALUES(11, 12);
@@ -178,13 +190,50 @@ do_multiclient_test tn {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
-
+
+ db close
+ tvfs delete
+
+ # Set bSleep to true if it is expected that the above used xSleep() to
+ # wait for locks. bSleep is true unless SQLITE_ENABLE_SETLK_TIMEOUT is
+ # set to 1 and either:
+ #
+ # * the OS is windows, or
+ # * the OS is unix and the tests were run with each connection
+ # in a separate process.
+ #
+ set bSleep 1
+ if {$::sqlite_options(setlk_timeout)==1} {
+ if {$::tcl_platform(platform)=="windows"} {
+ set bSleep 0
+ }
+ if {$::tcl_platform(platform)=="unix"} {
+ set bSleep [expr $tn==2]
+ }
+ }
+
+ do_test 2.$tn.15.$bSleep {
+ expr $::sleep_count > 0
+ } $bSleep
}
#-------------------------------------------------------------------------
reset_db
-sqlite3 db2 test.db
+
+testvfs tvfs -fullshm 1
+tvfs script xSleep_callback
+tvfs filter xSleep
+
+set ::sleep_count 0
+proc xSleep_callback {xSleep nMs} {
+ after [expr $nMs / 1000]
+ incr ::sleep_count
+ breakpoint
+}
+
+sqlite3 db2 test.db -vfs tvfs
db2 timeout 1000
+
do_execsql_test 3.0 {
PRAGMA journal_mode = wal;
CREATE TABLE x1(x, y);
@@ -192,8 +241,109 @@ do_execsql_test 3.0 {
INSERT INTO x1 VALUES(1, 2);
} {wal}
-do_test 3.1 {
+do_execsql_test -db db2 3.1a {
+ SELECT * FROM x1
+} {}
+
+do_test 3.1b {
list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$tcl_platform(platform)=="windows" && $::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.2 {
+ expr {$::sleep_count > 0}
+} $bExpect
+set ::sleep_count 0
+
+do_execsql_test 3.3 {
+ COMMIT;
+}
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO x1 VALUES(3, 4);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+after 500 {set ok 1}
+vwait ok
+
+db2 timeout 5000
+do_test 3.4 {
+ set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
+ expr ($t>1000000)
+} {1}
+
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.5 {
+ expr {$::sleep_count > 0}
+} $bExpect
+
+do_execsql_test -db db2 3.6 {
+ INSERT INTO x1 VALUES(5, 6);
+ COMMIT;
+ SELECT * FROM x1;
+} {1 2 3 4 5 6}
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO x1 VALUES(7, 8);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+after 500 {set ok 1}
+vwait ok
+
+db2 timeout 0x7FFFFFFF
+do_test 3.7 {
+ set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
+ expr ($t>1000000)
+} {1}
+
+# Set bExpect to true if calls to xSleep() are expected. Such calls are
+# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
+set bExpect 1
+if {$::sqlite_options(setlk_timeout)==1} {
+ set bExpect 0
+}
+do_test 3.8 {
+ expr {$::sleep_count > 0}
+} $bExpect
+
+do_execsql_test -db db2 3.9 {
+ INSERT INTO x1 VALUES(9, 10);
+ COMMIT;
+ SELECT * FROM x1;
+} {1 2 3 4 5 6 7 8 9 10}
+
+db2 close
+tvfs delete
+
finish_test
+
diff --git a/test/walsetlk2.test b/test/walsetlk2.test
new file mode 100644
index 0000000000..92630b3fdf
--- /dev/null
+++ b/test/walsetlk2.test
@@ -0,0 +1,267 @@
+# 2025 Jan 24
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# TESTRUNNER: slow
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix walsetlk2
+
+ifcapable !wal {finish_test ; return }
+ifcapable !setlk_timeout {finish_test ; return }
+
+#-------------------------------------------------------------------------
+# Check that xShmLock calls are as expected for write transactions in
+# setlk mode.
+#
+reset_db
+
+do_execsql_test 1.0 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(1, 2, 3);
+} {wal}
+db close
+
+testvfs tvfs
+tvfs script xShmLock_callback
+tvfs filter xShmLock
+
+set ::xshmlock [list]
+proc xShmLock_callback {method path name detail} {
+ lappend ::xshmlock $detail
+}
+
+sqlite3 db test.db -vfs tvfs
+db timeout 1000
+
+do_execsql_test 1.1 {
+ SELECT * FROM t1
+} {1 2 3}
+
+do_execsql_test 1.2 {
+ INSERT INTO t1 VALUES(4, 5, 6);
+}
+
+set ::xshmlock [list]
+do_execsql_test 1.3 {
+ INSERT INTO t1 VALUES(7, 8, 9);
+}
+
+do_test 1.4 {
+ set ::xshmlock
+} [list \
+ {0 1 lock exclusive} \
+ {4 1 lock exclusive} {4 1 unlock exclusive} \
+ {4 1 lock shared} \
+ {0 1 unlock exclusive} \
+ {4 1 unlock shared}
+]
+
+do_execsql_test 1.5.1 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9}
+set ::xshmlock [list]
+do_execsql_test 1.5.2 {
+ INSERT INTO t1 VALUES(10, 11, 12);
+}
+do_test 1.5.3 {
+ set ::xshmlock
+} [list \
+ {0 1 lock exclusive} \
+ {4 1 lock shared} \
+ {0 1 unlock exclusive} \
+ {4 1 unlock shared}
+]
+
+db close
+tvfs delete
+
+#-------------------------------------------------------------------------
+# Check that if sqlite3_setlk_timeout() is used, blocking locks timeout
+# but other operations do not use the retry mechanism.
+#
+reset_db
+
+do_execsql_test 2.0 {
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES(1, 2), (3, 4);
+}
+
+sqlite3_setlk_timeout db 2000
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(5, 6);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.1 {
+ INSERT INTO t1 VALUES(7, 8);
+} {1 {database is locked}}
+
+sqlite3_busy_timeout db 2000
+
+do_catchsql_test 2.2 {
+ INSERT INTO t1 VALUES(7, 8);
+} {0 {}}
+
+do_execsql_test 2.3 {
+ SELECT * FROM t1
+} {1 2 3 4 5 6 7 8}
+
+do_execsql_test 2.4 {
+ PRAGMA journal_mode = wal;
+} {wal}
+
+db close
+sqlite3 db test.db
+
+do_execsql_test 2.5 {
+ INSERT INTO t1 VALUES(9, 10);
+}
+
+if {$::sqlite_options(setlk_timeout)==1} {
+
+sqlite3_setlk_timeout db 2000
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(11, 12);
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.6 {
+ INSERT INTO t1 VALUES(13, 14);
+} {0 {}}
+
+do_execsql_test 2.7 {
+ SELECT * FROM t1
+} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
+
+}
+
+
+#-------------------------------------------------------------------------
+# Check that if sqlite3_setlk_timeout(-1) is called, blocking locks are
+# enabled and last for a few seconds at least. Difficult to test that they
+# really do block indefinitely.
+#
+reset_db
+
+if {$::sqlite_options(setlk_timeout)==1} {
+do_execsql_test 3.0 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t1 VALUES(1, 'one'), (3, 'three');
+} {wal}
+
+sqlite3_setlk_timeout db -1
+
+# Launch a non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(5, 'five');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+breakpoint
+do_catchsql_test 3.1 {
+ INSERT INTO t1 VALUES(7, 'seven');
+} {0 {}}
+
+# Launch another non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(9, 'nine');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+ db close
+}
+
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 3.2 {
+ INSERT INTO t1 VALUES(9, 'ten');
+} {1 {UNIQUE constraint failed: t1.a}}
+
+do_execsql_test 3.3 {
+ SELECT * FROM t1
+} {1 one 3 three 5 five 7 seven 9 nine}
+
+db close
+
+# Launch another non-blocking testfixture process to write-lock the
+# database for 2000 ms.
+testfixture_nb done {
+ sqlite3 db test.db
+ db eval {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(11, 'eleven');
+ }
+ after 2000
+ db eval {
+ COMMIT
+ }
+}
+
+sqlite3 db test.db
+sqlite3_setlk_timeout db -1
+do_catchsql_test 3.4 {
+ INSERT INTO t1 VALUES(13, 'thirteen');
+} {0 {}}
+
+}
+
+finish_test
+
diff --git a/test/walsetlk3.test b/test/walsetlk3.test
new file mode 100644
index 0000000000..b091b183d8
--- /dev/null
+++ b/test/walsetlk3.test
@@ -0,0 +1,135 @@
+# 2020 May 06
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# TESTRUNNER: slow
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix walsetlk3
+
+ifcapable !wal {finish_test ; return }
+ifcapable !setlk_timeout {finish_test ; return }
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(x, y);
+ PRAGMA journal_mode = wal;
+ INSERT INTO t1 VALUES(1, 2);
+ INSERT INTO t1 VALUES(3, 4);
+} {wal}
+
+db close
+
+proc sql_block_on_close {sql} {
+ testfixture_nb done [string map [list %SQL% $sql] {
+ testvfs tvfs
+ tvfs script xWrite
+ tvfs filter xWrite
+
+ set ::delay_done 0
+ proc xWrite {method fname args} {
+ if {[file tail $fname]=="test.db" && $::delay_done==0} {
+ after 3000
+ set ::delay_done 1
+ }
+ return 0
+ }
+
+ sqlite3 db test.db -vfs tvfs
+ db eval {%SQL%}
+ db close
+ }]
+}
+
+# Start a second process that writes to the db, then blocks within the
+# [db close] holding an EXCLUSIVE on the db in order to checkpoint and
+# delete the wal file. Then try to read the db.
+#
+# Without the SQLITE_SETLK_BLOCK_ON_CONNECT flag, this should fail with
+# SQLITE_BUSY.
+#
+sql_block_on_close {
+ INSERT INTO t1 VALUES(5, 6);
+ INSERT INTO t1 VALUES(7, 8);
+}
+after 500 {set ok 1}
+vwait ok
+sqlite3 db test.db
+sqlite3_setlk_timeout db 2000
+do_catchsql_test 1.1 {
+ SELECT * FROM t1
+} {1 {database is locked}}
+
+vwait ::done
+
+# But with SQLITE_SETLK_BLOCK_ON_CONNECT flag, it should succeed.
+#
+sql_block_on_close {
+ INSERT INTO t1 VALUES(9, 10);
+ INSERT INTO t1 VALUES(11, 12);
+}
+after 500 {set ok 1}
+vwait ok
+sqlite3 db test.db
+sqlite3_setlk_timeout -block db 2000
+do_catchsql_test 1.2 {
+ SELECT * FROM t1
+} {0 {1 2 3 4 5 6 7 8 9 10 11 12}}
+
+vwait ::done
+
+#-------------------------------------------------------------------------
+# Check that the SQLITE_SETLK_BLOCK_ON_CONNECT does not cause connections
+# to block when taking a SHARED lock on a rollback mode database.
+#
+reset_db
+do_execsql_test 2.1 {
+ CREATE TABLE x1(a);
+ INSERT INTO x1 VALUES(1), (2), (3);
+}
+
+proc sql_block_on_write {sql} {
+ testfixture_nb done [string map [list %SQL% $sql] {
+ sqlite3 db test.db
+ db eval "BEGIN EXCLUSIVE"
+ db eval {%SQL%}
+ after 3000
+ db eval COMMIT
+ db close
+ }]
+}
+
+db close
+sql_block_on_write {
+ INSERT INTO x1 VALUES(4);
+}
+
+after 500 {set ok 1}
+vwait ok
+
+sqlite3 db test.db
+sqlite3_setlk_timeout -block db 2000
+
+do_catchsql_test 2.2 {
+ SELECT * FROM x1
+} {1 {database is locked}}
+
+vwait ::done
+after 500 {set ok 1}
+vwait ok
+
+do_catchsql_test 2.3 {
+ SELECT * FROM x1
+} {0 {1 2 3 4}}
+
+finish_test
+
diff --git a/test/win32longpath.test b/test/win32longpath.test
index 9ffea775e7..b948de79fa 100644
--- a/test/win32longpath.test
+++ b/test/win32longpath.test
@@ -115,7 +115,12 @@ do_test 1.6 {
db3 close
-foreach tn {1a 1b 1c 1d 1e 1f} {
+# winrt platforms do not handle paths with unix-style '/' directory separators.
+#
+set lUri [list 1a 1b 1c 1d 1e 1f]
+ifcapable winrt { set lUri [list 1a 1c 1e] }
+
+foreach tn $lUri {
sqlite3 db3 $uri($tn) -vfs win32-longpath -uri 1 -translatefilename 0
do_test 1.7.$tn {
diff --git a/test/without_rowid1.test b/test/without_rowid1.test
index 3c33f733a1..5d0bc81105 100644
--- a/test/without_rowid1.test
+++ b/test/without_rowid1.test
@@ -487,4 +487,33 @@ ifcapable altertable {
SELECT name FROM sqlite_sequence ORDER BY +name;
} {a c0 c2}
}
+
+# Ensure that the number of columns in an index on a WITHOUT ROWID
+# table does not exceed SQLITE_LIMIT_COLUMN.
+#
+reset_db
+sqlite3_limit db SQLITE_LIMIT_COLUMN 8
+do_execsql_test 16.1 {
+ CREATE TABLE t1(
+ c1,c2,c3,c4,c5,c6,c7,c8,
+ PRIMARY KEY(c1,c2,c1 COLLATE NOCASE)
+ ) WITHOUT ROWID;
+} {}
+do_execsql_test 16.2 {
+ CREATE TABLE t2(
+ c1,c2,c3,c4,c5,c6,c7,c8,
+ PRIMARY KEY(c1 COLLATE nocase,c1 COLLATE rtrim,
+ c2 COLLATE nocase,c2 COLLATE rtrim,
+ c3 COLLATE nocase,c3 COLLATE rtrim,
+ c4 COLLATE nocase,c4 COLLATE rtrim)
+ ) WITHOUT ROWID;
+} {}
+do_execsql_test 16.3 {
+ CREATE TABLE t3(
+ c1,c2,c3,c4,c5,c6,c7,c8,
+ PRIMARY KEY(c1,c2),
+ UNIQUE(c3,c4,c5,c6,c7,c8,c3 COLLATE nocase)
+ ) WITHOUT ROWID;
+} {}
+
finish_test
diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat
index 8f9a1b7b09..83d660deb0 100755
--- a/tool/build-all-msvc.bat
+++ b/tool/build-all-msvc.bat
@@ -198,7 +198,7 @@ IF NOT DEFINED ComSpec (
REM
REM NOTE: This batch file requires the VcInstallDir environment variable to be
-REM set. Tyipcally, this means this batch file needs to be run from an
+REM set. Typically, this means this batch file needs to be run from an
REM MSVC command prompt.
REM
IF NOT DEFINED VCINSTALLDIR (
diff --git a/tool/genfkey.README b/tool/genfkey.README
index 57cdff87f8..5609945042 100644
--- a/tool/genfkey.README
+++ b/tool/genfkey.README
@@ -63,7 +63,7 @@ CAPABILITIES
LIMITATIONS
- Apart from those limitiations described above:
+ Apart from those limitations described above:
* Implicit mapping to composite primary keys is not supported. If
a parent table has a composite primary key, then any child table
@@ -108,7 +108,7 @@ USAGE
If errors are found and the --ignore-errors option is passed, then
no error messages are printed. No "CREATE TRIGGER" statements are generated
- for foriegn-key definitions that contained errors, they are silently
+ for foreign-key definitions that contained errors, they are silently
ignored by subsequent processing.
All triggers generated by this command have names that match the pattern
@@ -129,7 +129,7 @@ USAGE
they will be printed to stdout, but this can be configured using other
dot-commands (i.e. ".output").
- The simplest way to activate the foriegn key definitions in a database
+ The simplest way to activate the foreign key definitions in a database
is simply to open it using the shell tool and enter the command
".genfkey --exec":
diff --git a/tool/lemon.c b/tool/lemon.c
index 5747520b6e..f0f2c8d726 100644
--- a/tool/lemon.c
+++ b/tool/lemon.c
@@ -3695,7 +3695,7 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
switch( ap->type ){
case SHIFT: act = ap->x.stp->statenum; break;
case SHIFTREDUCE: {
- /* Since a SHIFT is inherient after a prior REDUCE, convert any
+ /* Since a SHIFT is inherent after a prior REDUCE, convert any
** SHIFTREDUCE action with a nonterminal on the LHS into a simple
** REDUCE action: */
if( ap->sp->index>=lemp->nterminal
diff --git a/tool/lempar.c b/tool/lempar.c
index 851a0e2e54..74314efeaa 100644
--- a/tool/lempar.c
+++ b/tool/lempar.c
@@ -13,7 +13,7 @@
**
** The "lemon" program processes an LALR(1) input grammar file, then uses
** this template to construct a parser. The "lemon" program inserts text
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
+** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
** interstitial "-" characters) contained in this template is changed into
** the value of the %name directive from the grammar. Otherwise, the content
** of this template is copied straight through into the generate parser
diff --git a/tool/mkctimec.tcl b/tool/mkctimec.tcl
index 0577437c99..20d0afe8a9 100755
--- a/tool/mkctimec.tcl
+++ b/tool/mkctimec.tcl
@@ -167,6 +167,7 @@ set boolean_defnil_options {
SQLITE_ENABLE_RBU
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_SESSION
+ SQLITE_ENABLE_SETLK_TIMEOUT
SQLITE_ENABLE_SNAPSHOT
SQLITE_ENABLE_SORTER_REFERENCES
SQLITE_ENABLE_SQLLOG
@@ -319,6 +320,7 @@ set value_options {
SQLITE_ENABLE_LOCKING_STYLE
SQLITE_EXTRA_AUTOEXT
SQLITE_EXTRA_INIT
+ SQLITE_EXTRA_INIT_MUTEXED
SQLITE_EXTRA_SHUTDOWN
SQLITE_FTS3_MAX_EXPR_DEPTH
SQLITE_INTEGRITY_CHECK_ERROR_MAX
diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl
index d38572f359..ff18de5638 100644
--- a/tool/mkpragmatab.tcl
+++ b/tool/mkpragmatab.tcl
@@ -534,10 +534,13 @@ foreach f [lsort [array names allflags]] {
set fv [expr {$fv*2}]
}
-# Sort the column lists so that longer column lists occur first
+# Sort the column lists so that longer column lists occur first.
+# In the event of a tie, sort column lists lexicographically.
#
proc colscmp {a b} {
- return [expr {[llength $b] - [llength $a]}]
+ set rc [expr {[llength $b] - [llength $a]}]
+ if {$rc} {return $rc}
+ return [string compare $a $b]
}
set cols_list [lsort -command colscmp $cols_list]
diff --git a/tool/mksqlite3h.tcl b/tool/mksqlite3h.tcl
index b1d5ecdcd3..6bbfa8c8bc 100644
--- a/tool/mksqlite3h.tcl
+++ b/tool/mksqlite3h.tcl
@@ -82,7 +82,13 @@ set nVersion [eval format "%d%03d%03d" [split $zVersion .]]
set PWD [pwd]
cd $TOP
set tmpfile $PWD/tmp-[clock millisec]-[expr {int(rand()*100000000000)}].txt
-exec $PWD/mksourceid manifest > $tmpfile
+set mksourceid $PWD/mksourceid
+if {![file exists $mksourceid] && [file exists ${mksourceid}.exe]} {
+ # Workaround for Windows-based Unix-like environments
+ # https://sqlite.org/forum/forumpost/41ba710dd9943453
+ set mksourceid ${mksourceid}.exe
+}
+exec $mksourceid manifest > $tmpfile
set fd [open $tmpfile rb]
set zSourceId [string trim [read $fd]]
close $fd
diff --git a/tool/mksqlite3internalh.tcl b/tool/mksqlite3internalh.tcl
index 8db593fe75..e1a42ee776 100644
--- a/tool/mksqlite3internalh.tcl
+++ b/tool/mksqlite3internalh.tcl
@@ -92,7 +92,7 @@ proc section_comment {text} {
# Read the source file named $filename and write it into the
# sqlite3.c output file. If any #include statements are seen,
-# process them approprately.
+# process them appropriately.
#
proc copy_file {filename} {
global seen_hdr available_hdr out
diff --git a/tool/run-speed-test.sh b/tool/run-speed-test.sh
index 0e970ea0f6..9c76465a26 100644
--- a/tool/run-speed-test.sh
+++ b/tool/run-speed-test.sh
@@ -5,7 +5,7 @@
#
# sh run-speed-test.sh trunk # Baseline measurement of trunk
# sh run-speed-test.sh x1 # Measure some experimental change
-# fossil test-diff --tk cout-trunk.txt cout-x1.txt # View chanages
+# fossil test-diff --tk cout-trunk.txt cout-x1.txt # View changes
#
# There are multiple output files, all with a base name given by
# the first argument:
diff --git a/tool/soak1.tcl b/tool/soak1.tcl
index 846f905935..e09c566b86 100644
--- a/tool/soak1.tcl
+++ b/tool/soak1.tcl
@@ -4,7 +4,7 @@
#
# tclsh soak1.tcl local-makefile.mk ?target? ?scenario?
#
-# This generates many variations on local-makefile.mk (by modifing
+# This generates many variations on local-makefile.mk (by modifying
# the OPT = lines) and runs them will fulltest, one by one. The
# constructed makefiles are named "soak1.mk".
#
diff --git a/tool/speed-check.sh b/tool/speed-check.sh
index 8a9e67a38b..fd122a12db 100644
--- a/tool/speed-check.sh
+++ b/tool/speed-check.sh
@@ -5,7 +5,7 @@
#
# sh speed-check.sh trunk # Baseline measurement of trunk
# sh speed-check.sh x1 # Measure some experimental change
-# fossil xdiff --tk cout-trunk.txt cout-x1.txt # View chanages
+# fossil xdiff --tk cout-trunk.txt cout-x1.txt # View changes
#
# There are multiple output files, all with a base name given by
# the first argument:
diff --git a/tool/sqldiff.c b/tool/sqldiff.c
index bb26daf139..44bf488f86 100644
--- a/tool/sqldiff.c
+++ b/tool/sqldiff.c
@@ -205,7 +205,7 @@ static char **columnNames(
int naz = 0; /* Number of entries in az[] */
sqlite3_stmt *pStmt; /* SQL statement being run */
char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */
- int truePk = 0; /* PRAGMA table_info indentifies the PK to use */
+ int truePk = 0; /* PRAGMA table_info identifies the PK to use */
int nPK = 0; /* Number of PRIMARY KEY columns */
int i, j; /* Loop counters */
diff --git a/tool/stripccomments.c b/tool/stripccomments.c
index 1bdb5c6b82..1d85252784 100644
--- a/tool/stripccomments.c
+++ b/tool/stripccomments.c
@@ -117,7 +117,7 @@ void do_it_all(void){
https://github.com/emscripten-core/emscripten/issues/23412
- Such regexes will always necessarily be preceeded by a
+ Such regexes will always necessarily be preceded by a
backslash, though.
It is hypothetically possible for a legitimate comment