diff options
author | drh <> | 2025-01-31 00:54:59 +0000 |
---|---|---|
committer | drh <> | 2025-01-31 00:54:59 +0000 |
commit | 0911f86abf39bfaf0f3b144f07860238baf6a483 (patch) | |
tree | 468e924cf458bcffd8948677078a460b66c688ea | |
parent | c850c2be757ffbf11423b47f8ef94bd0ce20f048 (diff) | |
parent | 49906e8e4bfbac201532e111b5f972129ce7bafe (diff) | |
download | sqlite-0911f86abf39bfaf0f3b144f07860238baf6a483.tar.gz sqlite-0911f86abf39bfaf0f3b144f07860238baf6a483.zip |
Merge all the latest trunk changes into the extra-security branch.
FossilOrigin-Name: 86ba57561a8d8c14e401c06b2345a9417053aa3a5f0c84e52460f23f5e6aa8d0
50 files changed, 1505 insertions, 1174 deletions
diff --git a/Makefile.in b/Makefile.in index 5fff3d2fc..15e61217f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -323,9 +323,6 @@ distclean-autosetup: clean rm -f $(TOP)/tool/emcc.sh rm -f libsqlite3*$(T.dll) rm -f jimsh0* -# -if [ -f ext/wasm/GNUmakefile ]; then \ -# gmake --no-print-directory --ignore-errors -C ext/wasm distclean; \ -# fi >/dev/null 2>&1; true distclean: distclean-autosetup # @@ -14,6 +14,16 @@ # use sqlite-config +if {[string first " " $autosetup(srcdir)] != -1} { + user-error "The pathname of the source tree\ + may not contain space characters" +} +if {[string first " " $autosetup(builddir)] != -1} { + user-error "The pathname of the build directory\ + may not contain space characters" +} + + ######################################################################## # Regarding flag compatibility with the historical autotool configure # script: @@ -210,22 +220,6 @@ options [subst -nobackslashes -nocommands $flags] unset flags sqlite-post-options-init -if {1} { - # TODO: move this into autosetup/sqlite-config.tcl once we get the - # version info into autoconf/auto.def. - 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" - unset srcdir -} - sqlite-setup-default-cflags proj-if-opt-truthy dev { # --enable-dev needs to come early so that the downstream tests @@ -281,8 +275,6 @@ sqlite-handle-load-extension sqlite-handle-math sqlite-handle-icu sqlite-handle-emsdk -sqlite-handle-common-feature-flags -sqlite-show-feature-flags sqlite-process-dot-in-files sqlite-post-config-validation sqlite-dump-defines diff --git a/autoconf/INSTALL b/autoconf/INSTALL deleted file mode 100644 index a1e89e18a..000000000 --- a/autoconf/INSTALL +++ /dev/null @@ -1,370 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, -Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `<wchar.h>' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am deleted file mode 100644 index 1eaa560ff..000000000 --- a/autoconf/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ - -AM_CFLAGS = @BUILD_CFLAGS@ -lib_LTLIBRARIES = libsqlite3.la -libsqlite3_la_SOURCES = sqlite3.c -libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 - -bin_PROGRAMS = sqlite3 -sqlite3_SOURCES = shell.c sqlite3.h -EXTRA_sqlite3_SOURCES = sqlite3.c -sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@ -sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ -sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_DQS=0 -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS) - -include_HEADERS = sqlite3.h sqlite3ext.h - -EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback -pkgconfigdir = ${libdir}/pkgconfig -pkgconfig_DATA = sqlite3.pc - -man_MANS = sqlite3.1 diff --git a/autoconf/Makefile.in b/autoconf/Makefile.in new file mode 100644 index 000000000..0c97f1632 --- /dev/null +++ b/autoconf/Makefile.in @@ -0,0 +1,221 @@ +######################################################################## +# This is a main makefile for the "autoconf" bundle of SQLite. This is +# a trimmed-down version of the canonical makefile, devoid of most +# documentation. For the full docs, see 'main.mk' in the canonical +# source tree. +all: + +TOP = @abs_top_srcdir@ + +PACKAGE_VERSION = @PACKAGE_VERSION@ + +# +# Filename extensions for binaries and libraries +# +B.exe = @BUILD_EXEEXT@ +T.exe = @TARGET_EXEEXT@ +B.dll = @BUILD_DLLEXT@ +T.dll = @TARGET_DLLEXT@ +B.lib = @BUILD_LIBEXT@ +T.lib = @TARGET_LIBEXT@ + +# +# Autotools-compatibility dirs +# +prefix = @prefix@ +datadir = @datadir@ +mandir = @mandir@ +includedir = @includedir@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ + +# +# Required binaries +# +INSTALL = @BIN_INSTALL@ +AR = @AR@ +AR.flags = cr +CC = @CC@ + + +ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@ +ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@ + +CFLAGS = @CFLAGS@ @CPPFLAGS@ +# +# $(LDFLAGS.configure) represents any LDFLAGS=... the client passes to +# configure. See main.mk. +# +LDFLAGS.configure = @LDFLAGS@ + +CFLAGS.core = @SH_CFLAGS@ +LDFLAGS.shlib = @SH_LDFLAGS@ +LDFLAGS.zlib = @LDFLAGS_ZLIB@ +LDFLAGS.math = @LDFLAGS_MATH@ +LDFLAGS.rpath = @LDFLAGS_RPATH@ +LDFLAGS.pthread = @LDFLAGS_PTHREAD@ +LDFLAGS.dlopen = @LDFLAGS_DLOPEN@ +LDFLAGS.readline = @LDFLAGS_READLINE@ +CFLAGS.readline = @CFLAGS_READLINE@ +LDFLAGS.icu = @LDFLAGS_ICU@ +CFLAGS.icu = @CFLAGS_ICU@ +LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@ + +# When cross-compiling, we need to avoid the -s flag because it only +# works on the build host's platform. +INSTALL.strip.1 = $(INSTALL) +INSTALL.strip.0 = $(INSTALL) -s +INSTALL.strip = $(INSTALL.strip.@IS_CROSS_COMPILING@) +INSTALL.noexec = $(INSTALL) -m 0644 + +install-dir.bin = $(DESTDIR)$(bindir) +install-dir.lib = $(DESTDIR)$(libdir) +install-dir.include = $(DESTDIR)$(includedir) +install-dir.pkgconfig = $(DESTDIR)$(libdir)/pkgconfig +install-dir.man1 = $(DESTDIR)$(mandir)/man1 +install-dir.all = $(install-dir.bin) $(install-dir.include) \ + $(install-dir.lib) $(install-dir.man1) \ + $(install-dir.pkgconfig) +$(install-dir.all): + $(INSTALL) -d "$@" + + +# +# Vars with the AS_ prefix are specifically related to AutoSetup. +# +# AS_AUTO_DEF is the main configure script. +# +AS_AUTO_DEF = $(TOP)/auto.def + +# +# Shell commands to re-run $(TOP)/configure with the same args it was +# invoked with to produce this makefile. +# +AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@ +Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF) + $(AS_AUTORECONFIG) + @touch $@ + +sqlite3.pc: $(TOP)/sqlite3.pc.in $(AS_AUTO_DEF) + $(AS_AUTORECONFIG) + @touch $@ + +sqlite_cfg.h: $(AS_AUTO_DEF) + $(AS_AUTORECONFIG) + @touch $@ + +# +# CFLAGS for sqlite3$(T.exe) +# +SHELL_OPT ?= @OPT_SHELL@ + +# +# Library-level feature flags +# +OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ + +LDFLAGS.libsqlite3 = \ + $(LDFLAGS.rpath) $(LDFLAGS.pthread) \ + $(LDFLAGS.math) $(LDFLAGS.dlopen) \ + $(LDFLAGS.zlib) $(LDFLAGS.icu) \ + $(LDFLAGS.configure) +LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@ +CFLAGS.libsqlite3 = -I. $(CFLAGS.core) $(CFLAGS.icu) $(OPT_FEATURE_FLAGS) + +sqlite3.o: sqlite3.h sqlite3.c + $(CC) -c sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3) + +libsqlite3.LIB = libsqlite3$(T.lib) +libsqlite3.SO = libsqlite3$(T.dll) + +$(libsqlite3.SO): sqlite3.o + $(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \ + $(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.libsqlite3.soname) +all: $(libsqlite3.SO) + +$(libsqlite3.LIB): sqlite3.o + $(AR) $(AR.flags) $@ sqlite3.o +all: $(libsqlite3.LIB) + +install-so-1: $(install-dir.lib) $(libsqlite3.SO) + $(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)" + @echo "Setting up $(libsqlite3.SO) symlinks..."; \ + 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).[03]*; \ + 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-so-0 install-so-: +install-so: install-so-$(ENABLE_LIB_SHARED) +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_LIB_STATIC) +install: install-lib + + +sqlite3$(T.exe): shell.c sqlite3.c + $(CC) -o $@ \ + shell.c sqlite3.c \ + -I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \ + $(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \ + $(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.readline) +all: sqlite3$(T.exe) + +install-shell: sqlite3$(T.exe) $(install-dir.bin) + $(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)" +install: install-shell + +install-headers: sqlite3.h $(install-dir.include) + $(INSTALL.noexec) sqlite3.h sqlite3ext.h "$(install-dir.include)" +install: install-headers + +install-pc: sqlite3.pc $(install-dir.pkgconfig) + $(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)" +install: install-pc + +install-man1: sqlite3.1 $(install-dir.man1) + $(INSTALL.noexec) sqlite3.1 "$(install-dir.man1)" +install: install-man1 + +clean: + rm -f *.o sqlite3$(T.exe) + rm -f $(libsqlite3.LIB) $(libsqlite3.SO) + +distclean: clean + rm -f jimsh0$(T.exe) config.* sqlite3.pc + +DIST_FILES := \ + README.txt VERSION \ + auto.def autosetup configure tea \ + sqlite3.h sqlite3.c shell.c sqlite3ext.h \ + Makefile.in Makefile.msc Makefile.fallback \ + sqlite3.rc sqlite3rc.h Replace.cs \ + sqlite3.pc.in sqlite3.1 + +# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so +# that tool/mkautoconfamal.sh knows how to find it. +dist_name = sqlite-$(PACKAGE_VERSION) +dist_tarball = $(dist_name).tar.gz +dist: + rm -fr $(dist_name) + mkdir -p $(dist_name) + cp -rp $(DIST_FILES) $(dist_name)/. + tar czf $(dist_tarball) $(dist_name) + rm -fr $(dist_name) + ls -l $(dist_tarball) diff --git a/autoconf/README.first b/autoconf/README.first index 5c2ea0a70..75c4a76d6 100644 --- a/autoconf/README.first +++ b/autoconf/README.first @@ -1,11 +1,12 @@ -This directory contains components use to build an autoconf-ready package -of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz +This directory contains components used to build an autoconf-like +package of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz -To build the autoconf amalgamation, run from the top-level: +To build the autoconf amalgamation, run from the top of the canonical +source tree: ./configure make amalgamation-tarball -The amalgamation-tarball target (also available in "main.mk") runs the -script tool/mkautoconfamal.sh which does the work. Refer to that script -for details. +The amalgamation-tarball target (available in "main.mk") runs the +script tool/mkautoconfamal.sh which does the work. Refer to that +script for details. diff --git a/autoconf/README.txt b/autoconf/README.txt index b3d351074..646c0a121 100644 --- a/autoconf/README.txt +++ b/autoconf/README.txt @@ -4,7 +4,7 @@ This package contains: * the sqlite3.h and sqlite3ext.h header files that define the C-language interface to the sqlite3.c library file * the shell.c file used to build the sqlite3 command-line shell program - * autoconf/automake installation infrastucture for building on POSIX + * autoconf-like installation infrastucture for building on POSIX compliant systems * a Makefile.msc, sqlite3.rc, and Replace.cs for building with Microsoft Visual C++ on Windows @@ -19,8 +19,10 @@ using only generic tools and without having to install TCL. The purpose of this package is to provide that capability. This package contains a pre-build SQLite amalgamation file "sqlite3.c" -(and its associated header file "sqlite3.h"). Because the amalgamation -has been pre-built, no TCL is required. +(and its associated header file "sqlite3.h"). Because the +amalgamation has been pre-built, no TCL is required for the code +generate (the configure script itself is written in TCL but it can use +the embedded copy of JimTCL). REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE ================================================================== @@ -47,14 +49,12 @@ SUMMARY OF HOW TO BUILD USING THIS PACKAGE BUILDING ON POSIX ================= -The generic installation instructions for autoconf/automake are found -in the INSTALL file. +The configure script follows common conventions, making it easy +to use for anyone who has configured a software tree before. +It supports a number of build-time flags, the full list of which +can be seen by running: -The following SQLite specific boolean options are supported: - - --enable-readline use readline in shell tool [default=yes] - --enable-threadsafe build a thread-safe library [default=yes] - --enable-dynamic-extensions support loadable extensions [default=yes] + ./configure --help The default value for the CFLAGS variable (options passed to the C compiler) includes debugging symbols in the build, resulting in larger @@ -65,10 +65,11 @@ line like this: to produce a smaller installation footprint. -Other SQLite compilation parameters can also be set using CFLAGS. For +Many SQLite compilation parameters can be defined by passing flags +to the configure script. Others may be passed on in the CFLAGS. For example: - $ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure + $ CFLAGS="-Os -DSQLITE_OMIT_DEPRECATED" ./configure BUILDING WITH MICROSOFT VISUAL C++ diff --git a/autoconf/auto.def b/autoconf/auto.def new file mode 100644 index 000000000..12eb3d75c --- /dev/null +++ b/autoconf/auto.def @@ -0,0 +1,98 @@ +#/do/not/tclsh +# ^^^ help out editors which guess this file's content type. +# +# 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 + +options { + # <build-modes> + static=1 => {Disable build of static library} + shared=1 => {Disable build of shared library} + # </build-modes> + # <lib-feature> + threadsafe=1 => {Disable mutexing} + with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always} + load-extension=1 => {Disable loading of external extensions} + math=1 => {Disable math functions} + json=1 => {Disable JSON functions} + memsys5 => {Enable MEMSYS5} + memsys3 => {Enable MEMSYS3} + fts3 => {Enable the FTS3 extension} + fts4 => {Enable the FTS4 extension} + fts5 => {Enable the FTS5 extension} + update-limit => {Enable the UPDATE/DELETE LIMIT clause} + geopoly => {Enable the GEOPOLY extension} + rtree => {Enable the RTREE extension} + session => {Enable the SESSION extension} + all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions} + # </lib-feature> + # <line-editing> + readline=1 => {Disable readline support} + # --with-readline-lib is a backwards-compatible alias for + # --with-readline-ldflags + with-readline-lib: + with-readline-ldflags:=auto + => {Readline LDFLAGS, e.g. -lreadline -lncurses} + # --with-readline-inc is a backwards-compatible alias for + # --with-readline-cflags. + with-readline-inc: + with-readline-cflags:=auto + => {Readline CFLAGS, e.g. -I/path/to/includes} + with-readline-header:PATH + => {Full path to readline.h, from which --with-readline-cflags will be derived} + with-linenoise:DIR => {Source directory for linenoise.c and linenoise.h} + editline=0 => {Enable BSD editline support} + # </line-editing> + # <icu> + with-icu-ldflags:LDFLAGS + => {Enable SQLITE_ENABLE_ICU and add the given linker flags for the ICU libraries} + with-icu-cflags:CFLAGS + => {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. e.g. -I/usr/local/include} + with-icu-config:=auto => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, /path/to/icu-config} + icu-collations=0 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... or --with-icu-config} + # </icu> + # <developer> + # Note that using the --debug/--enable-debug flag here requires patching + # autosetup/autosetup to rename the --debug to --autosetup-debug. + with-debug=0 + debug=0 => + {Enable debug build flags. This option will impact performance by + as much as 4x, as it includes large numbers of assert()s in + performance-critical loops. Never use --debug for production + builds.} + # </developer> + soname:=legacy => + # --soname has a long story behind it: https://sqlite.org/src/forumpost/5a3b44f510df8ded + {SONAME for libsqlite3.so. "none", or not using this flag, sets no + soname. "legacy" sets it to its historical value of + libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets + 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". + } +} + +sqlite-post-options-init +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_LIB_SHARED [opt-bool shared] +define ENABLE_LIB_STATIC [opt-bool static] + +sqlite-process-dot-in-files +sqlite-post-config-validation diff --git a/autoconf/configure.ac b/autoconf/configure.ac deleted file mode 100644 index 0c7a32db1..000000000 --- a/autoconf/configure.ac +++ /dev/null @@ -1,270 +0,0 @@ - -#----------------------------------------------------------------------- -# Supports the following non-standard switches. -# -# --enable-threadsafe -# --enable-readline -# --enable-editline -# --enable-static-shell -# --enable-dynamic-extensions -# - -AC_PREREQ(2.61) -AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org) -AC_CONFIG_SRCDIR([sqlite3.c]) -AC_CONFIG_AUX_DIR([.]) - -# Use automake. -AM_INIT_AUTOMAKE([foreign]) - -AC_SYS_LARGEFILE - -# Check for required programs. -AC_PROG_CC -AC_PROG_LIBTOOL -AC_PROG_MKDIR_P - -# Check for library functions that SQLite can optionally use. -AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r]) -AC_FUNC_STRERROR_R - -AC_CONFIG_FILES([Makefile sqlite3.pc]) -BUILD_CFLAGS= -AC_SUBST(BUILD_CFLAGS) - -#------------------------------------------------------------------------- -# Two options to enable readline compatible libraries: -# -# --enable-editline -# --enable-readline -# -# Both are enabled by default. If, after command line processing both are -# still enabled, the script searches for editline first and automatically -# disables readline if it is found. So, to use readline explicitly, the -# user must pass "--disable-editline". To disable command line editing -# support altogether, "--disable-editline --disable-readline". -# -# When searching for either library, check for headers before libraries -# as some distros supply packages that contain libraries but not header -# files, which come as a separate development package. -# -AC_ARG_ENABLE(editline, [AS_HELP_STRING([--enable-editline],[use BSD libedit])]) -AC_ARG_ENABLE(readline, [AS_HELP_STRING([--enable-readline],[use readline])]) - -AS_IF([ test x"$enable_editline" != xno ],[ - AC_CHECK_HEADERS([editline/readline.h],[ - sLIBS=$LIBS - LIBS="" - AC_SEARCH_LIBS([readline],[edit],[ - AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline) - READLINE_LIBS="$LIBS -ltinfo" - enable_readline=no - ],[],[-ltinfo]) - AS_UNSET(ac_cv_search_readline) - LIBS=$sLIBS - ]) -]) - -AS_IF([ test x"$enable_readline" != xno ],[ - AC_CHECK_HEADERS([readline/readline.h],[ - sLIBS=$LIBS - LIBS="" - AC_SEARCH_LIBS(tgetent, termcap curses ncurses ncursesw, [], []) - AC_SEARCH_LIBS(readline,[readline edit], [ - AC_DEFINE([HAVE_READLINE],1,Define to use readline or wrapper) - READLINE_LIBS=$LIBS - ]) - LIBS=$sLIBS - ]) -]) - -AC_SUBST(READLINE_LIBS) -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-threadsafe -# -AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING( - [--enable-threadsafe], [build a thread-safe library [default=yes]])], - [], [enable_threadsafe=yes]) -if test x"$enable_threadsafe" == "xno"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0" -else - BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1" - AC_SEARCH_LIBS(pthread_create, pthread) - AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-dynamic-extensions -# -AC_ARG_ENABLE(dynamic-extensions, [AS_HELP_STRING( - [--enable-dynamic-extensions], [support loadable extensions [default=yes]])], - [], [enable_dynamic_extensions=yes]) -if test x"$enable_dynamic_extensions" != "xno"; then - AC_SEARCH_LIBS(dlopen, dl) -else - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1" -fi -AC_MSG_CHECKING([for whether to support dynamic extensions]) -AC_MSG_RESULT($enable_dynamic_extensions) -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-math -# -AC_ARG_ENABLE(math, [AS_HELP_STRING( - [--enable-math], [SQL math functions [default=yes]])], - [], [enable_math=yes]) -AC_MSG_CHECKING([SQL math functions]) -if test x"$enable_math" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS" - AC_MSG_RESULT([enabled]) - AC_SEARCH_LIBS(ceil, m) -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-fts4 -# -AC_ARG_ENABLE(fts4, [AS_HELP_STRING( - [--enable-fts4], [include fts4 support [default=yes]])], - [], [enable_fts4=yes]) -AC_MSG_CHECKING([FTS4 extension]) -if test x"$enable_fts4" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4" - AC_MSG_RESULT([enabled]) -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-fts3 -# -AC_ARG_ENABLE(fts3, [AS_HELP_STRING( - [--enable-fts3], [include fts3 support [default=no]])], - [], []) -AC_MSG_CHECKING([FTS3 extension]) -if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3" - AC_MSG_RESULT([enabled]) -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-fts5 -# -AC_ARG_ENABLE(fts5, [AS_HELP_STRING( - [--enable-fts5], [include fts5 support [default=yes]])], - [], [enable_fts5=yes]) -AC_MSG_CHECKING([FTS5 extension]) -if test x"$enable_fts5" = "xyes"; then - AC_MSG_RESULT([enabled]) - AC_SEARCH_LIBS(log, m) - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5" -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-rtree -# -AC_ARG_ENABLE(rtree, [AS_HELP_STRING( - [--enable-rtree], [include rtree support [default=yes]])], - [], [enable_rtree=yes]) -AC_MSG_CHECKING([RTREE extension]) -if test x"$enable_rtree" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY" - AC_MSG_RESULT([enabled]) -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-session -# -AC_ARG_ENABLE(session, [AS_HELP_STRING( - [--enable-session], [enable the session extension [default=no]])], - [], []) -AC_MSG_CHECKING([Session extension]) -if test x"$enable_session" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" - AC_MSG_RESULT([enabled]) -else - AC_MSG_RESULT([disabled]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-debug -# -AC_ARG_ENABLE(debug, [AS_HELP_STRING( - [--enable-debug], [build with debugging features enabled [default=no]])], - [], []) -AC_MSG_CHECKING([Build type]) -if test x"$enable_debug" = "xyes"; then - BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" - CFLAGS="-g -O0" - AC_MSG_RESULT([debug]) -else - AC_MSG_RESULT([release]) -fi -#----------------------------------------------------------------------- - -#----------------------------------------------------------------------- -# --enable-static-shell -# -AC_ARG_ENABLE(static-shell, [AS_HELP_STRING( - [--enable-static-shell], - [statically link libsqlite3 into shell tool [default=yes]])], - [], [enable_static_shell=yes]) -if test x"$enable_static_shell" = "xyes"; then - EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT -else - EXTRA_SHELL_OBJ=libsqlite3.la -fi -AC_SUBST(EXTRA_SHELL_OBJ) -#----------------------------------------------------------------------- - -AC_CHECK_FUNCS(posix_fallocate) -AC_CHECK_HEADERS(zlib.h,[ - AC_SEARCH_LIBS(deflate,z,[BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB"]) -]) - -AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"]) -AC_SUBST(SHELL_CFLAGS) - -#----------------------------------------------------------------------- -# UPDATE: Maybe it's better if users just set CFLAGS before invoking -# configure. This option doesn't really add much... -# -# --enable-tempstore -# -# AC_ARG_ENABLE(tempstore, [AS_HELP_STRING( -# [--enable-tempstore], -# [in-memory temporary tables (never, no, yes, always) [default=no]])], -# [], [enable_tempstore=no]) -# AC_MSG_CHECKING([for whether or not to store temp tables in-memory]) -# case "$enable_tempstore" in -# never ) TEMP_STORE=0 ;; -# no ) TEMP_STORE=1 ;; -# always ) TEMP_STORE=3 ;; -# yes ) TEMP_STORE=3 ;; -# * ) -# TEMP_STORE=1 -# enable_tempstore=yes -# ;; -# esac -# AC_MSG_RESULT($enable_tempstore) -# AC_SUBST(TEMP_STORE) -#----------------------------------------------------------------------- - -AC_OUTPUT diff --git a/autosetup/README.md b/autosetup/README.md index fd426d56d..19a16c943 100644 --- a/autosetup/README.md +++ b/autosetup/README.md @@ -33,12 +33,26 @@ $ ./configure --reference | less That will include any docs from any TCL files in the `./autosetup` dir which contain certain (simple) markup defined by autosetup. -This project's own autosetup-related APIs are in [proj.tcl][] or -[auto.def][]. The former contains helper APIs which are, more or -less, portable across projects (that file is re-used as-is in other -projects) and all have a `proj-` name prefix. The latter is the main -configure script driver and contains related functions which are -specific to this tree. +This project's own configuration-related TCL code is spread across the +following files: + +- [proj.tcl][]: project-agnostic utility code for autosetup-driven + projects. This file is designed to be shared between this project, + other projects managed under the SQLite/Hwaci umbrella + (e.g. Fossil), and personal projects of SQLite's developers. It is + essentially an amalgamation of a decade's worth of autosetup-related + utility code. +- [auto.def][]: the primary driver for the `./configure` process. + When we talk about "the configure script," we're referring to + this file. +- [sqlite-config.tcl][]: utility code which is too project-specific + for `proj.tcl`. We split this out of `auto.def` so that it can be + used by both `auto.def` and... +- [autoconf/auto.def][]: the main driver script for the "autoconf" + bundle's configure script. It is essentially a slightly trimmed-down + version of the main `auto.def` file. The `autoconf` dir was ported + from the Autotools to Autosetup in the 3.49.0 dev cycle but retains + the "autoconf" name to minimize downstream disruption. <a name="apitips"></a> @@ -47,9 +61,11 @@ Autosetup API Tips This section briefly covers only APIs which are frequently useful in day-to-day maintenance and might not be immediately recognized as such -obvious from a casual perusal of [auto.def][]. The complete docs of -those with `proj-` prefix can be found in [proj.tcl][]. The others are -scattered around [the TCL files in ./autosetup](/dir/autosetup). +obvious from a casual perusal of the relevant TCL files. The complete +docs of those with `proj-` prefix can be found in [proj.tcl][] and +those with an `sqlite-` prefix are in [sqlite-config.tcl][]. The +others are scattered around [the TCL files in +./autosetup](/dir/autosetup). In (mostly) alphabetical order: @@ -331,8 +347,10 @@ If autosetup is upgraded and this patch is _not_ applied the invoking [Autosetup]: https://msteveb.github.io/autosetup/ [auto.def]: /file/auto.def +[autoconf/auto.def]: /file/autoconf/auto.def [autosetup-git]: https://github.com/msteveb/autosetup [proj.tcl]: /file/autosetup/proj.tcl +[sqlite-config.tcl]: /file/autosetup/sqlite-config.tcl [Makefile.in]: /file/Makefile.in [main.mk]: /file/main.mk [JimTCL]: https://jim.tcl.tk diff --git a/autosetup/proj.tcl b/autosetup/proj.tcl index 915a6b134..88da2112c 100644 --- a/autosetup/proj.tcl +++ b/autosetup/proj.tcl @@ -276,9 +276,9 @@ proc proj-find-executable-path {args} { # a binary, sets a define (see below) to the result, and returns the # result (an empty string if not found). # -# The define'd name is: if defName is empty then "BIN_X" is used, -# where X is the upper-case form of $binName with any '-' characters -# replaced with '_'. +# The define'd name is: If $defName is not empty, it is used as-is. If +# $defName is empty then "BIN_X" is used, where X is the upper-case +# form of $binName with any '-' characters replaced with '_'. proc proj-bin-define {binName {defName {}}} { set check [proj-find-executable-path -v $binName] if {"" eq $defName} { @@ -850,16 +850,16 @@ proc proj-affirm-files-exist {args} { # If the given directory is found, it expects to find emsdk_env.sh in # that directory, as well as the emcc compiler somewhere under there. # -# If the --with-emsdk flag is explicitly provided and the SDK is not -# found then a fatal error is generated, otherwise failure to find the -# SDK is not fatal. +# If the --with-emsdk[=DIR] flag is explicitly provided and the SDK is +# not found then a fatal error is generated, otherwise failure to find +# the SDK is not fatal. # # Defines the following: # -# - EMSDK_HOME = top dir of the emsdk or "". -# - EMSDK_ENV_SH = path to EMSDK_HOME/emsdk_env.sh or "" -# - BIN_EMCC = $EMSDK_HOME/upstream/emscripten/emcc or "" # - HAVE_EMSDK = 0 or 1 (this function's return value) +# - EMSDK_HOME = "" or top dir of the emsdk +# - EMSDK_ENV_SH = "" or $EMSDK_HOME/emsdk_env.sh +# - BIN_EMCC = "" or $EMSDK_HOME/upstream/emscripten/emcc # # Returns 1 if EMSDK_ENV_SH is found, else 0. If EMSDK_HOME is not empty # but BIN_EMCC is then emcc was not found in the EMSDK_HOME, in which diff --git a/autosetup/sqlite-config.tcl b/autosetup/sqlite-config.tcl index 7f4292286..9f300e317 100644 --- a/autosetup/sqlite-config.tcl +++ b/autosetup/sqlite-config.tcl @@ -64,11 +64,29 @@ proc sqlite-post-options-init {} { define SQLITE_OS_UNIX 1 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" } +######################################################################## +# Internal config-time debugging output routine. It generates no +# output unless msg-debug=1 is passed to the configure script. proc msg-debug {msg} { if {$::sqliteConfig(msg-debug-enabled)} { puts stderr [proj-bold "** DEBUG: $msg"] @@ -208,6 +226,24 @@ proc sqlite-setup-default-cflags {} { 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 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). + # https://sqlite.org/forum/forumpost/9801e54665afd728 + # + # If any configure flags for features are in conflict with + # CFLAGS-specified feature flags, all bets are off. There are no + # guarantees about which one will take precedence. + foreach cf [get-define CFLAGS ""] { + switch -glob -- $cf { + -DSQLITE_OMIT* - + -DSQLITE_ENABLE* { + sqlite-add-feature-flag $cf + } + } + } } ######################################################################## @@ -240,6 +276,11 @@ proc sqlite-handle-common-feature-flags {} { } scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {} } { + if {$boolFlag ni $::autosetup(options)} { + # Skip flags which are in the canonical build but not + # the autoconf bundle. + continue + } proj-if-opt-truthy $boolFlag { sqlite-add-feature-flag $featureFlag if {0 != [eval $ifSetEvalThis] && "all" ne $boolFlag} { @@ -270,8 +311,9 @@ proc sqlite-handle-common-feature-flags {} { } ######################################################################### -# Show the final feature flag sets. -proc sqlite-show-feature-flags {} { +# Remove duplicates from the final feature flag sets and show them to +# the user. +proc sqlite-finalize-feature-flags {} { set oFF [get-define OPT_FEATURE_FLAGS] if {"" ne $oFF} { define OPT_FEATURE_FLAGS [lsort -unique $oFF] @@ -282,7 +324,6 @@ proc sqlite-show-feature-flags {} { define OPT_SHELL [lsort -unique $oFF] msg-result "Shell options: [get-define OPT_SHELL]" } - #parray ::sqliteConfig } ######################################################################## @@ -395,26 +436,58 @@ proc sqlite-handle-tempstore {} { ######################################################################## # Check for the Emscripten SDK for building the web-based wasm # components. The core lib and tools do not require this but ext/wasm -# does. +# does. Most of the work is done via [proj-check-emsdk], then this +# function adds the following defines: +# +# - EMCC_WRAPPER = "" or top-srcdir/tool/emcc.sh +# - BIN_WASM_OPT = "" or path to wasm-opt +# - BIN_WASM_STRIP = "" or path to wasm-strip +# +# Noting that: +# +# 1) Not finding the SDK is not fatal at this level, nor is failure to +# find one of the related binaries. +# +# 2) wasm-strip is part of the wabt package: +# +# https://github.com/WebAssembly/wabt +# +# and this project requires it for production-mode builds but not dev +# builds. +# proc sqlite-handle-emsdk {} { + define EMCC_WRAPPER "" + define BIN_WASM_STRIP "" + define BIN_WASM_OPT "" set srcdir $::autosetup(srcdir) if {$srcdir ne $::autosetup(builddir)} { # The EMSDK pieces require writing to the original source tree # even when doing an out-of-tree build. The ext/wasm pieces do not - # support an out-of-tree build so we catch that case and treat it - # as if EMSDK were not found. + # support an out-of-tree build so we treat that case as if EMSDK + # were not found. msg-result "Out-of tree build: not checking for EMSDK." - define EMCC_WRAPPER "" return } - set emccsh $srcdir/tool/emcc.sh + set emccSh $srcdir/tool/emcc.sh + set extWasmConfig $srcdir/ext/wasm/config.make if {![get-define HAVE_WASI_SDK] && [proj-check-emsdk]} { - define EMCC_WRAPPER $emccsh - proj-make-from-dot-in $emccsh - catch {exec chmod u+x $emccsh} + define EMCC_WRAPPER $emccSh + set emsdkHome [get-define EMSDK_HOME ""] + proj-assert {"" ne $emsdkHome} + #define EMCC_WRAPPER ""; # just for testing + proj-bin-define wasm-strip + proj-bin-define bash; # ext/wasm/GNUmakefile requires bash + if {[file-isexec $emsdkHome/upstream/bin/wasm-opt]} { + define BIN_WASM_OPT $emsdkHome/upstream/bin/wasm-opt + } else { + # Maybe there's a copy in the path? + proj-bin-define wasm-opt BIN_WASM_OPT + } + proj-make-from-dot-in $emccSh $extWasmConfig + catch {exec chmod u+x $emccSh} } else { define EMCC_WRAPPER "" - file delete -force $emccsh + file delete -force -- $emccSh $extWasmConfig } } @@ -789,13 +862,21 @@ proc sqlite-handle-math {} { } ######################################################################## -# Generate the configure-process output file(s). +# Perform some late-stage work and generate the configure-process +# output file(s). proc sqlite-process-dot-in-files {} { ######################################################################## # When cross-compiling, we have to avoid using the -s flag to - # /usr/bin/install: https://sqlite.org/forum/forumpost/9a67df63eda9925c + # /usr/bin/install: + # https://sqlite.org/forum/forumpost/9a67df63eda9925c define IS_CROSS_COMPILING $::sqliteConfig(is-cross-compiling) + # Finish up handling of the various feature flags here because it's + # convenient for both the canonical build and autoconf bundles that + # it be done here. + sqlite-handle-common-feature-flags + sqlite-finalize-feature-flags + ######################################################################## # "Re-export" the autoconf-conventional --XYZdir flags into something # which is more easily overridable from a make invocation. See the docs @@ -828,11 +909,14 @@ proc sqlite-post-config-validation {} { # Check #1: ensure that files which get filtered for @VAR@ do not # contain any unresolved @VAR@ refs. That may indicate an # unexported/unused var or a typo. - foreach f "Makefile sqlite3.pc $::autosetup(srcdir)/tool/emcc.sh" { + set srcdir $::autosetup(srcdir) + foreach f [list Makefile sqlite3.pc \ + $srcdir/tool/emcc.sh \ + $srcdir/ext/wasm/config.make] { if {![file exists $f]} continue set lnno 1 foreach line [proj-file-content-list $f] { - if {[regexp {(@[A-Za-z_]+@)} $line match]} { + if {[regexp {(@[A-Za-z0-9_]+@)} $line match]} { error "Unresolved reference to $match at line $lnno of $f" } incr lnno @@ -1054,7 +1138,9 @@ proc sqlite-check-tcl {} { # Export a subset of tclConfig.sh to the current TCL-space. If $cfg # is an empty string, this emits empty-string entries for the # various options we're interested in. - eval [exec "$srcdir/tool/tclConfigShToAutoDef.sh" "$cfg"] + eval [exec sh "$srcdir/tool/tclConfigShToAutoDef.sh" "$cfg"] + # ---------^^ a Windows/msys workaround, without which it cannot + # exec a .sh file: https://sqlite.org/forum/forumpost/befb352a42a7cd6d if {"" eq $with_tclsh && $cfg ne ""} { # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh diff --git a/doc/compile-for-windows.md b/doc/compile-for-windows.md index 717569dd7..2e6228633 100644 --- a/doc/compile-for-windows.md +++ b/doc/compile-for-windows.md @@ -43,8 +43,13 @@ systems, including MacOS. or <https://sqlite.org/tmp/tcl9.0.0.tar.gz>. <li>Untar or unzip the source archive. CD into the "win/" subfolder of the source tree. - <li>Run: `nmake /f makefile.vc release` - <li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install` + <li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl release` + <li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install` <br> + Notes: + <ol type="i"> + <li> The previous two `nmake` commands must be run separately. + <li> Also, the INSTALLDIR=... argument is required on both. + </ol> <li><i>Optional:</i> CD to `c:\Tcl\bin` and make a copy of `tclsh90.exe` over into just `tclsh.exe`. <li><i>Optional:</i> diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index c98844e73..c53bad824 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -778,7 +778,7 @@ static int fts5LeafFirstTermOff(Fts5Data *pLeaf){ /* ** Close the read-only blob handle, if it is open. */ -void fts5IndexCloseReader(Fts5Index *p){ +static void fts5IndexCloseReader(Fts5Index *p){ if( p->pReader ){ int rc; sqlite3_blob *pReader = p->pReader; @@ -6955,7 +6955,7 @@ static void fts5SegIterSetEOF(Fts5SegIter *pSeg){ pSeg->pLeaf = 0; } -void fts5IterClose(Fts5IndexIter *pIndexIter){ +static void fts5IterClose(Fts5IndexIter *pIndexIter){ if( pIndexIter ){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; Fts5Index *pIndex = pIter->pIndex; diff --git a/ext/misc/sqlite3_stdio.c b/ext/misc/sqlite3_stdio.c index be3acc665..c9bceb194 100644 --- a/ext/misc/sqlite3_stdio.c +++ b/ext/misc/sqlite3_stdio.c @@ -46,6 +46,11 @@ ** use O_U8TEXT when writing to the Windows console (or anything ** else for which _isatty() returns true) and to use O_BINARY or O_TEXT ** for all other output channels. +** +** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available. If +** defined, it forces the use of Win32 APIs for all console I/O, both +** input and output. This is necessary for some non-Microsoft run-times +** that implement stdio differently from Microsoft/Visual-Studio. */ #if defined(SQLITE_U8TEXT_ONLY) # define UseWtextForOutput(fd) 1 @@ -148,7 +153,7 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){ */ wchar_t *b1 = sqlite3_malloc( sz*sizeof(wchar_t) ); if( b1==0 ) return 0; -#ifndef SQLITE_USE_STDIO_FOR_CONSOLE +#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO DWORD nRead = 0; if( IsConsole(in) && ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0) @@ -226,7 +231,7 @@ int sqlite3_fputs(const char *z, FILE *out){ sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz); b1[sz] = 0; -#ifndef SQLITE_STDIO_FOR_CONSOLE +#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO DWORD nWr = 0; if( IsConsole(out) && WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0) @@ -236,8 +241,9 @@ int sqlite3_fputs(const char *z, FILE *out){ }else #endif { - /* For non-console I/O, or if SQLITE_USE_STDIO_FOR_CONSOLE is defined - ** then write using the standard library. */ + /* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for + ** non-console I/O even if that macro is defined, write using the + ** standard library. */ _setmode(_fileno(out), _O_U8TEXT); if( UseBinaryWText(out) ){ piecemealOutput(b1, sz, out); diff --git a/ext/misc/vfstrace.c b/ext/misc/vfstrace.c index fed87e88f..c274558d1 100644 --- a/ext/misc/vfstrace.c +++ b/ext/misc/vfstrace.c @@ -1033,7 +1033,7 @@ static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){ vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; sqlite3_vfs *pRoot = pInfo->pRootVfs; vfstraceOnOff(pInfo, VTR_DLCLOSE); - vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName); + vfstrace_printf(pInfo, "%s.xDlClose()\n", pInfo->zVfsName); pRoot->xDlClose(pRoot, pHandle); } diff --git a/ext/session/session1.test b/ext/session/session1.test index dfc1aa895..6da905179 100644 --- a/ext/session/session1.test +++ b/ext/session/session1.test @@ -285,7 +285,7 @@ do_conflict_test $tn.3.2.3 -tables t2 -sql { {FOREIGN_KEY 1} } do_execsql_test $tn.3.2.4 "SELECT * FROM t2" {} -do_db2_test $tn.3.2.5 "SELECT * FROM t2" {1 one 2 two 4 five} +do_db2_test $tn.3.2.5 "SELECT * FROM t2" {4 five} # Test UPDATE changesets. # diff --git a/ext/session/session9.test b/ext/session/session9.test index 6b7d1648b..5c406c344 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -80,7 +80,7 @@ foreach {tn delrow trans conflictargs conflictret} { 8 3 1 {FOREIGN_KEY 1} ABORT } { - set A(OMIT,0) {1 SQLITE_CONSTRAINT} + set A(OMIT,0) {0 {}} set A(OMIT,1) {0 {}} set A(ABORT,0) {1 SQLITE_CONSTRAINT} set A(ABORT,1) {1 SQLITE_CONSTRAINT} @@ -95,7 +95,7 @@ foreach {tn delrow trans conflictargs conflictret} { do_test 1.2.$tn.2 { set ::xConflict } $conflictargs - set A(OMIT,0) {0 0} + set A(OMIT,0) {1 1} set A(OMIT,1) {1 1} set A(ABORT,0) {0 0} set A(ABORT,1) {0 0} diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index 3ff84f1c5..7c1273bb1 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -201,12 +201,16 @@ proc compare_db {db1 db2} { foreach tbl $lot1 { set col1 [list] set col2 [list] + set quoted [list] $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name } - $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name } + $db2 eval "PRAGMA table_info = $tbl" { + lappend col2 $name + lappend quoted "\"[string map {\" \"\"} $name]\"" + } if {$col1 != $col2} { error "table $tbl schema mismatch" } - set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" + set sql "SELECT * FROM $tbl ORDER BY [join $quoted ,]" set data1 [$db1 eval $sql] set data2 [$db2 eval $sql] if {$data1 != $data2} { diff --git a/ext/session/session_gen.test b/ext/session/session_gen.test new file mode 100644 index 000000000..8d3c5887f --- /dev/null +++ b/ext/session/session_gen.test @@ -0,0 +1,190 @@ +# 2025 Jan 28 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix session_gen + + +foreach {otn sct} { + 1 VIRTUAL + 2 STORED +} { +eval [string map [list %TYPE% $sct] { + reset_db + set testprefix $testprefix-$otn + +do_execsql_test 1.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + + CREATE TABLE t2(a INTEGER PRIMARY KEY, b AS (c+1) %TYPE%, c); + + CREATE TABLE t3( + a, + b AS (a+10) %TYPE%, + c, + d AS (c+1) %TYPE%, + e, + PRIMARY KEY(c, e) + ) WITHOUT ROWID; + + CREATE TABLE t4(a AS (c*100) %TYPE%, b INTEGER PRIMARY KEY, c); + + CREATE TABLE t5(x, y); +} + +foreach {tn sql changeset} { + + 0.1 { + INSERT INTO t5 VALUES('abc', 'def'); + } { + {INSERT t5 0 X.. {} {i 1 t abc t def}} + } + 0.2 { + UPDATE t5 SET y='xyz' WHERE rowid=1; + } { + {UPDATE t5 0 X.. {i 1 {} {} t def} {{} {} {} {} t xyz}} + } + 0.3 { + DELETE FROM t5; + } { + {DELETE t5 0 X.. {i 1 t abc t xyz} {}} + } + + 1.1 { + INSERT INTO t2 VALUES(1, 2); + INSERT INTO t2 VALUES(2, 123); + } { + {INSERT t2 0 X. {} {i 1 i 2}} + {INSERT t2 0 X. {} {i 2 i 123}} + } + 1.2 { + UPDATE t2 SET c=456 WHERE a=1 + } { + {UPDATE t2 0 X. {i 1 i 2} {{} {} i 456}} + } + + 1.3 { + DELETE FROM t2 WHERE a=2 + } { + {DELETE t2 0 X. {i 2 i 123} {}} + } + + 1.4 { + UPDATE t2 SET a=15 + } { + {INSERT t2 0 X. {} {i 15 i 456}} + {DELETE t2 0 X. {i 1 i 456} {}} + } + + 2.1 { + INSERT INTO t3 VALUES(5, 6, 7); + INSERT INTO t3 VALUES(8, 9, 10); + } { + {INSERT t3 0 .XX {} {i 8 i 9 i 10}} + {INSERT t3 0 .XX {} {i 5 i 6 i 7}} + } + + 2.2 { + UPDATE t3 SET a = 505 WHERE (c, e) = (6, 7); + } { + {UPDATE t3 0 .XX {i 5 i 6 i 7} {i 505 {} {} {} {}}} + } + + 2.3 { + DELETE FROM t3 WHERE (c, e) = (9, 10); + } { + {DELETE t3 0 .XX {i 8 i 9 i 10} {}} + } + + 2.4 { + UPDATE t3 SET c=1000 + } { + {DELETE t3 0 .XX {i 505 i 6 i 7} {}} + {INSERT t3 0 .XX {} {i 505 i 1000 i 7}} + } + + 3.1 { + INSERT INTO t4 VALUES(100, 100); + } { + {INSERT t4 0 X. {} {i 100 i 100}} + } + +} { + do_test 1.$tn.1 { + sqlite3session S db main + S object_config rowid 1 + S attach * + execsql $sql + } {} + + do_changeset_test 1.$tn.2 S $changeset + + S delete +} +#------------------------------------------------------------------------- +reset_db + +forcedelete test.db2 +sqlite3 db2 test.db2 + +do_common_sql { + CREATE TABLE t0(x INTEGER PRIMARY KEY, y); + INSERT INTO t0 VALUES(1, 'one'); + INSERT INTO t0 VALUES(2, 'two'); + + CREATE TABLE t1(a AS (c*10) %TYPE%, b INTEGER PRIMARY KEY, c); + INSERT INTO t1 VALUES(1, 5); + INSERT INTO t1 VALUES(2, 10); + INSERT INTO t1 VALUES(3, 5); + + CREATE TABLE t2( + a, b, c AS (a*b) %TYPE%, + 'k 1', 'k 2', PRIMARY KEY('k 1', 'k 2') + ) WITHOUT ROWID; + INSERT INTO t2 VALUES('a', 'b', 1, 11); + INSERT INTO t2 VALUES('A', 'B', 2, 22); + INSERT INTO t2 VALUES('Aa', 'Bb', 3, 33); +} + +foreach {tn sql} { + 1.1 { INSERT INTO t0 VALUES(4, 15) } + 1.2 { INSERT INTO t1 VALUES(4, 15) } + 1.3 { INSERT INTO t2 VALUES(1, 2, 3, 4) } + + 2.1 { UPDATE t1 SET c=100 WHERE b=2 } + 2.2 { UPDATE t2 SET a=11 } + + 3.1 { DELETE FROM t2 WHERE (t2.'k 1') = 2 } + 3.2 { DELETE FROM t1 } +} { + do_test 2.$tn.1 { + # execsql { PRAGMA vdbe_listing = 1 } db2 + do_then_apply_sql $sql + } {} + do_test 2.$tn.2 { + compare_db db db2 + } {} +} + +}]} + + + + +finish_test diff --git a/ext/session/sessionnoact.test b/ext/session/sessionnoact.test index e447bc8a1..54e9a6215 100644 --- a/ext/session/sessionnoact.test +++ b/ext/session/sessionnoact.test @@ -59,7 +59,7 @@ do_execsql_test 1.2 { set ::nConflict 0 proc conflict {args} { incr ::nConflict - return "OMIT" + return "ABORT" } sqlite3changeset_apply_v2 db $C conflict @@ -111,6 +111,9 @@ do_execsql_test 1.8 { # Check that a changeset that causes an FK violation may not be applied, # even if SQLITE_CHANGESETAPPLY_FKNOACTION is specified. # +# UPDATE: Unless the conflict-handler returns OMIT. In that case it can +# be committed. See test cases 3.* in this file. +# reset_db do_execsql_test 2.0 { CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE); @@ -164,5 +167,66 @@ do_execsql_test 2.8 { SELECT * FROM c1; } {two} +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE); + INSERT INTO p1 VALUES(1, 1, 'one'); + INSERT INTO p1 VALUES(2, 2, 'two'); + + CREATE TABLE c1(x REFERENCES p1(c) ON DELETE CASCADE); + INSERT INTO c1 VALUES('two'); +} + +set ::nConflict 0 +proc conflict {args} { + incr ::nConflict + return "OMIT" +} + +db_save + +set C [changeset_from_sql { + DELETE FROM p1 WHERE a=2; +}] + +db_restore_and_reopen + +do_test 3.1 { + sqlite3changeset_apply_v2 -noaction db $C conflict +} {} +do_execsql_test 3.2 { + SELECT * FROM p1 +} {1 1 one} + +db_restore_and_reopen +db eval { PRAGMA foreign_keys = 1 } + +do_test 3.3 { + list [catch { sqlite3changeset_apply_v2 -noaction db $C conflict } msg] $msg +} {0 {}} +do_execsql_test 3.4 { + SELECT * FROM p1; +} {1 1 one} +do_execsql_test 3.5 { + SELECT * FROM c1; +} {two} + +db_restore_and_reopen +db eval { PRAGMA foreign_keys = 1 } + +do_test 3.6 { + list [catch { + sqlite3changeset_apply_v2 -ignorenoop -noaction db $C conflict + } msg] $msg +} {0 {}} +do_execsql_test 3.7 { + SELECT * FROM p1; +} {1 1 one} +do_execsql_test 3.8 { + SELECT * FROM c1; +} {two} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index a3f132add..66b21d63a 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -139,11 +139,13 @@ struct sqlite3_changeset_iter { struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ - int nCol; /* Number of columns in table zName */ + int nCol; /* Number of non-hidden columns */ + int nTotalCol; /* Number of columns including hidden */ int bStat1; /* True if this is sqlite_stat1 */ int bRowid; /* True if this table uses rowid for PK */ const char **azCol; /* Column names */ const char **azDflt; /* Default value expressions */ + int *aiIdx; /* Index to pass to xNew/xOld */ u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ @@ -546,22 +548,22 @@ static int sessionPreupdateHash( unsigned int h = 0; /* Hash value to return */ int i; /* Used to iterate through columns */ + assert( pTab->nTotalCol==pSession->hook.xCount(pSession->hook.pCtx) ); if( pTab->bRowid ){ - assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) ); h = sessionHashAppendI64(h, iRowid); }else{ assert( *pbNullPK==0 ); - assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) ); for(i=0; i<pTab->nCol; i++){ if( pTab->abPK[i] ){ int rc; int eType; sqlite3_value *pVal; + int iIdx = pTab->aiIdx[i]; if( bNew ){ - rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); + rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal); }else{ - rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); + rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal); } if( rc!=SQLITE_OK ) return rc; @@ -898,6 +900,7 @@ static int sessionPreupdateEqual( sqlite3_value *pVal; /* Value returned by preupdate_new/old */ int rc; /* Error code from preupdate_new/old */ int eType = *a++; /* Type of value from change record */ + int iIdx = pTab->aiIdx[iCol]; /* The following calls to preupdate_new() and preupdate_old() can not ** fail. This is because they cache their return values, and by the @@ -906,10 +909,10 @@ static int sessionPreupdateEqual( ** this (that the method has already been called). */ if( op==SQLITE_INSERT ){ /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */ - rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal); + rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal); }else{ /* assert( db->pPreUpdate->pUnpacked ); */ - rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); + rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal); } assert( rc==SQLITE_OK ); (void)rc; /* Suppress warning about unused variable */ @@ -1034,9 +1037,11 @@ static int sessionTableInfo( const char *zDb, /* Name of attached database (e.g. "main") */ const char *zThis, /* Table name */ int *pnCol, /* OUT: number of columns */ + int *pnTotalCol, /* OUT: number of hidden columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ const char ***pazDflt, /* OUT: Array of default value expressions */ + int **paiIdx, /* OUT: Array of xNew/xOld indexes */ u8 **pabPK, /* OUT: Array of booleans - true for PK col */ int *pbRowid /* OUT: True if only PK is a rowid */ ){ @@ -1051,6 +1056,7 @@ static int sessionTableInfo( char **azCol = 0; char **azDflt = 0; u8 *abPK = 0; + int *aiIdx = 0; int bRowid = 0; /* Set to true to use rowid as PK */ assert( pazCol && pabPK ); @@ -1058,6 +1064,8 @@ static int sessionTableInfo( *pazCol = 0; *pabPK = 0; *pnCol = 0; + if( pnTotalCol ) *pnTotalCol = 0; + if( paiIdx ) *paiIdx = 0; if( pzTab ) *pzTab = 0; if( pazDflt ) *pazDflt = 0; @@ -1067,9 +1075,9 @@ static int sessionTableInfo( if( rc==SQLITE_OK ){ /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */ zPragma = sqlite3_mprintf( - "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL " - "SELECT 1, 'idx', '', 0, '', 2 UNION ALL " - "SELECT 2, 'stat', '', 0, '', 0" + "SELECT 0, 'tbl', '', 0, '', 1, 0 UNION ALL " + "SELECT 1, 'idx', '', 0, '', 2, 0 UNION ALL " + "SELECT 2, 'stat', '', 0, '', 0, 0" ); }else if( rc==SQLITE_ERROR ){ zPragma = sqlite3_mprintf(""); @@ -1077,7 +1085,7 @@ static int sessionTableInfo( return rc; } }else{ - zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_xinfo('%q')", zDb, zThis); } if( !zPragma ){ return SQLITE_NOMEM; @@ -1094,7 +1102,9 @@ static int sessionTableInfo( while( SQLITE_ROW==sqlite3_step(pStmt) ){ nByte += sqlite3_column_bytes(pStmt, 1); /* name */ nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */ - nDbCol++; + if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */ + nDbCol++; + } if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */ } if( nDbCol==0 ) bRowid = 0; @@ -1103,7 +1113,7 @@ static int sessionTableInfo( rc = sqlite3_reset(pStmt); if( rc==SQLITE_OK ){ - nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1); + nByte += nDbCol * (sizeof(const char *)*2 +sizeof(int)+sizeof(u8) + 1 + 1); pAlloc = sessionMalloc64(pSession, nByte); if( pAlloc==0 ){ rc = SQLITE_NOMEM; @@ -1114,8 +1124,8 @@ static int sessionTableInfo( if( rc==SQLITE_OK ){ azCol = (char **)pAlloc; azDflt = (char**)&azCol[nDbCol]; - pAlloc = (u8 *)&azDflt[nDbCol]; - abPK = (u8 *)pAlloc; + aiIdx = (int*)&azDflt[nDbCol]; + abPK = (u8 *)&aiIdx[nDbCol]; pAlloc = &abPK[nDbCol]; if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); @@ -1130,27 +1140,32 @@ static int sessionTableInfo( azCol[i] = (char*)pAlloc; pAlloc += nName+1; abPK[i] = 1; + aiIdx[i] = -1; i++; } while( SQLITE_ROW==sqlite3_step(pStmt) ){ - int nName = sqlite3_column_bytes(pStmt, 1); - int nDflt = sqlite3_column_bytes(pStmt, 4); - const unsigned char *zName = sqlite3_column_text(pStmt, 1); - const unsigned char *zDflt = sqlite3_column_text(pStmt, 4); - - if( zName==0 ) break; - memcpy(pAlloc, zName, nName+1); - azCol[i] = (char *)pAlloc; - pAlloc += nName+1; - if( zDflt ){ - memcpy(pAlloc, zDflt, nDflt+1); - azDflt[i] = (char *)pAlloc; - pAlloc += nDflt+1; - }else{ - azDflt[i] = 0; + if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */ + int nName = sqlite3_column_bytes(pStmt, 1); + int nDflt = sqlite3_column_bytes(pStmt, 4); + const unsigned char *zName = sqlite3_column_text(pStmt, 1); + const unsigned char *zDflt = sqlite3_column_text(pStmt, 4); + + if( zName==0 ) break; + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + if( zDflt ){ + memcpy(pAlloc, zDflt, nDflt+1); + azDflt[i] = (char *)pAlloc; + pAlloc += nDflt+1; + }else{ + azDflt[i] = 0; + } + abPK[i] = sqlite3_column_int(pStmt, 5); + aiIdx[i] = sqlite3_column_int(pStmt, 0); + i++; } - abPK[i] = sqlite3_column_int(pStmt, 5); - i++; + if( pnTotalCol ) (*pnTotalCol)++; } rc = sqlite3_reset(pStmt); } @@ -1163,6 +1178,7 @@ static int sessionTableInfo( if( pazDflt ) *pazDflt = (const char**)azDflt; *pabPK = abPK; *pnCol = nDbCol; + if( paiIdx ) *paiIdx = aiIdx; }else{ sessionFree(pSession, azCol); } @@ -1194,7 +1210,8 @@ static int sessionInitTable( u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); rc = sessionTableInfo(pSession, db, zDb, - pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK, + pTab->zName, &pTab->nCol, &pTab->nTotalCol, 0, &pTab->azCol, + &pTab->azDflt, &pTab->aiIdx, &abPK, ((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0) ); if( rc==SQLITE_OK ){ @@ -1229,15 +1246,17 @@ static int sessionInitTable( */ static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){ int nCol = 0; + int nTotalCol = 0; const char **azCol = 0; const char **azDflt = 0; + int *aiIdx = 0; u8 *abPK = 0; int bRowid = 0; assert( pSession->rc==SQLITE_OK ); pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, - pTab->zName, &nCol, 0, &azCol, &azDflt, &abPK, + pTab->zName, &nCol, &nTotalCol, 0, &azCol, &azDflt, &aiIdx, &abPK, (pSession->bImplicitPK ? &bRowid : 0) ); if( pSession->rc==SQLITE_OK ){ @@ -1260,8 +1279,10 @@ static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){ const char **a = pTab->azCol; pTab->azCol = azCol; pTab->nCol = nCol; + pTab->nTotalCol = nTotalCol; pTab->azDflt = azDflt; pTab->abPK = abPK; + pTab->aiIdx = aiIdx; azCol = a; } if( pSession->bEnableSize ){ @@ -1579,7 +1600,7 @@ static int sessionUpdateMaxSize( int ii; for(ii=0; ii<pTab->nCol; ii++){ sqlite3_value *p = 0; - pSession->hook.xNew(pSession->hook.pCtx, ii, &p); + pSession->hook.xNew(pSession->hook.pCtx, pTab->aiIdx[ii], &p); sessionSerializeValue(0, p, &nNew); } } @@ -1599,8 +1620,9 @@ static int sessionUpdateMaxSize( int bChanged = 1; int nOld = 0; int eType; + int iIdx = pTab->aiIdx[ii]; sqlite3_value *p = 0; - pSession->hook.xNew(pSession->hook.pCtx, ii-pTab->bRowid, &p); + pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p); if( p==0 ){ return SQLITE_NOMEM; } @@ -1697,11 +1719,11 @@ static void sessionPreupdateOneChange( /* Check the number of columns in this xPreUpdate call matches the ** number of columns in the table. */ nExpect = pSession->hook.xCount(pSession->hook.pCtx); - if( (pTab->nCol-pTab->bRowid)<nExpect ){ + if( pTab->nTotalCol<nExpect ){ if( sessionReinitTable(pSession, pTab) ) return; if( sessionUpdateChanges(pSession, pTab) ) return; } - if( (pTab->nCol-pTab->bRowid)!=nExpect ){ + if( pTab->nTotalCol!=nExpect ){ pSession->rc = SQLITE_SCHEMA; return; } @@ -1758,14 +1780,15 @@ static void sessionPreupdateOneChange( /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); - for(i=0; i<(pTab->nCol-pTab->bRowid); i++){ + for(i=pTab->bRowid; i<pTab->nCol; i++){ + int iIdx = pTab->aiIdx[i]; sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ /* This may fail if the column has a non-NULL default and was added ** using ALTER TABLE ADD COLUMN after this record was created. */ - rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p); + rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p); }else if( pTab->abPK[i] ){ - TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); + TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx,iIdx,&p); assert( trc==SQLITE_OK ); } @@ -1800,12 +1823,13 @@ static void sessionPreupdateOneChange( sessionPutI64(&pC->aRecord[1], iRowid); nByte = 9; } - for(i=0; i<(pTab->nCol-pTab->bRowid); i++){ + for(i=pTab->bRowid; i<pTab->nCol; i++){ sqlite3_value *p = 0; + int iIdx = pTab->aiIdx[i]; if( op!=SQLITE_INSERT ){ - pSession->hook.xOld(pSession->hook.pCtx, i, &p); + pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p); }else if( pTab->abPK[i] ){ - pSession->hook.xNew(pSession->hook.pCtx, i, &p); + pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p); } sessionSerializeValue(&pC->aRecord[nByte], p, &nByte); } @@ -2207,7 +2231,8 @@ int sqlite3session_diff( int bRowid = 0; u8 *abPK; const char **azCol = 0; - rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK, + rc = sessionTableInfo(0, db, zFrom, zTbl, + &nCol, 0, 0, &azCol, 0, 0, &abPK, pSession->bImplicitPK ? &bRowid : 0 ); if( rc==SQLITE_OK ){ @@ -2784,10 +2809,10 @@ static int sessionSelectStmt( int rc = SQLITE_OK; char *zSql = 0; const char *zSep = ""; - const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*"; int nSql = -1; int i; + SessionBuffer cols = {0, 0, 0}; SessionBuffer nooptest = {0, 0, 0}; SessionBuffer pkfield = {0, 0, 0}; SessionBuffer pkvar = {0, 0, 0}; @@ -2800,9 +2825,16 @@ static int sessionSelectStmt( sessionAppendStr(&pkvar, "?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc ); - zCols = "tbl, ?2, stat"; + sessionAppendStr(&cols, "tbl, ?2, stat", &rc); }else{ + #if 0 + if( bRowid ){ + sessionAppendStr(&cols, SESSIONS_ROWID, &rc); + } + #endif for(i=0; i<nCol; i++){ + if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc); + sessionAppendIdent(&cols, azCol[i], &rc); if( abPK[i] ){ sessionAppendStr(&pkfield, zSep, &rc); sessionAppendStr(&pkvar, zSep, &rc); @@ -2820,7 +2852,7 @@ static int sessionSelectStmt( if( rc==SQLITE_OK ){ zSql = sqlite3_mprintf( "SELECT %s%s FROM %Q.%Q WHERE (%s) IS (%s)", - zCols, (bIgnoreNoop ? (char*)nooptest.aBuf : ""), + (char*)cols.aBuf, (bIgnoreNoop ? (char*)nooptest.aBuf : ""), zDb, zTab, (char*)pkfield.aBuf, (char*)pkvar.aBuf ); if( zSql==0 ) rc = SQLITE_NOMEM; @@ -2863,6 +2895,7 @@ static int sessionSelectStmt( sqlite3_free(nooptest.aBuf); sqlite3_free(pkfield.aBuf); sqlite3_free(pkvar.aBuf); + sqlite3_free(cols.aBuf); return rc; } @@ -5203,7 +5236,8 @@ static int sessionChangesetApply( sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo(0, db, "main", zNew, - &sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid + &sApply.nCol, 0, &zTab, &sApply.azCol, 0, 0, + &sApply.abPK, &sApply.bRowid ); if( rc!=SQLITE_OK ) break; for(i=0; i<sApply.nCol; i++){ @@ -5284,6 +5318,11 @@ static int sessionChangesetApply( } } + { + int rc2 = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); + if( rc==SQLITE_OK ) rc = rc2; + } + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index ad6fafacc..3e9621c6d 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -32,19 +32,16 @@ # # - Emscripten SDK: https://emscripten.org/docs/getting_started/downloads.html # - The bash shell -# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH) +# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH and without +# a "g" prefix like they have on some non-GNU systems) # - wasm-strip for release builds: https://github.com/WebAssembly/wabt # - InfoZip for 'dist' zip file ######################################################################## default: all #default: quick -SHELL := $(firstword $(shell which bash) $(wildcard /usr/local/bin/bash /usr/bin/bash /bin/bash)) -ifeq (,$(SHELL)) - $(error Cannot find the bash shell) -endif MAKEFILE := $(lastword $(MAKEFILE_LIST)) CLEAN_FILES := -DISTCLEAN_FILES := +DISTCLEAN_FILES := config.make MAKING_CLEAN := $(if $(filter %clean,$(MAKECMDGOALS)),1,0) .PHONY: clean distclean clean: @@ -52,6 +49,67 @@ clean: distclean: clean -rm -f $(DISTCLEAN_FILES) + +######################################################################## +# Special-case builds for which we require certain pre-conditions +# which, if not met, may cause warnings or fatal errors in the build. +# This also affects the default optimization level flags. Note that +# the fiddle targets are in this list because they are used for +# generating sqlite.org/fiddle. +OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug + +ifeq (1,$(MAKING_CLEAN)) + bin.wasm-strip := echo "not stripping" + bin.wasm-opt := irrelevant + bin.emcc := irrelevant + bin.bash := irrelevant + emcc.version := unknown +else + # Include config.make and perform some bootstrapping... + ifeq (,$(wildcard ./config.make)) + $(error Missing config.make (gets generated by the configure script if the EMSDK is found)) + endif + include ./config.make + ifeq (,$(bin.bash)) + $(error Configure script did not find the bash shell) + endif + ifeq (,$(bin.emcc)) + $(error Configure script did not find emcc) + endif + emcc.version := $(shell $(bin.emcc) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;') + $(info using emcc version [$(emcc.version)]) + ifeq (,$(bin.wasm-strip)) + #################################################################### + # We need wasm-strip for release builds (see below for why) but + # not strictly for non-release builds. + $(info WARNING: *******************************************************************) + $(info WARNING: Builds using -Oz will minify WASM-exported names, breaking) + $(info WARNING: _All The Things_. The workaround for that is to build) + $(info WARNING: with -g3 (which explodes the file size) and then strip the debug) + $(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.) + $(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.) + $(info WARNING: If this build uses any optimization level higher than -O1 then) + $(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.) + $(info WARNING: wasm-strip is part of the wabt package:) + $(info WARNING: https://github.com/WebAssembly/wabt) + $(info WARNING: on Ubuntu-like systems it can be installed with:) + $(info WARNING: sudo apt install wabt) + $(info WARNING: *******************************************************************) + ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS))) + $(error Cannot make release-quality binary because wasm-strip is not available.) + endif + bin.wasm-strip := echo "not wasm-stripping" + endif + ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS))) + $(info ==============================================================) + $(info == Development build. Make one of (dist, snapshot) for a) + $(info == smaller release build.) + $(info ==============================================================) + endif +endif +# ^^^ end of are-we-MAKING_CLEAN +maybe-wasm-strip := $(bin.wasm-strip) + ######################################################################## # JS_BUILD_NAMES exists for documentation purposes only. It enumerates # the core build styles: @@ -133,13 +191,15 @@ sqlite3.canonical.c := $(dir.top)/sqlite3.c sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c)) sqlite3.h := $(dir.top)/sqlite3.h -ifneq (1,$(MAKING_CLEAN)) -ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c))) +ifeq (1,$(MAKING_CLEAN)) SQLITE_C_IS_SEE := 0 else - SQLITE_C_IS_SEE := 1 - $(info This is an SEE build) -endif + ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c))) + SQLITE_C_IS_SEE := 0 + else + SQLITE_C_IS_SEE := 1 + $(info This is an SEE build) + endif endif ########################################################################@ @@ -152,65 +212,6 @@ $(sqlite3.h): $(sqlite3.c): $(sqlite3.h) ######################################################################## -# Special-case builds for which we require certain pre-conditions -# which, if not met, may cause warnings or fatal errors in the build. -# This also affects the default optimization level flags. Note that -# the fiddle targets are in this list because they are used for -# generating sqlite.org/fiddle. -OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug - -ifneq (1,$(MAKING_CLEAN)) - ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS))) - $(info ==============================================================) - $(info == Development build. Make one of (dist, snapshot) for a) - $(info == smaller release build.) - $(info ==============================================================) - endif -endif - -######################################################################## -# Find emcc (Emscripten compiler)... -ifeq (1,$(MAKING_CLEAN)) - emcc.bin := echo - emcc.version := unknown -else - emcc.bin := $(dir.tool)/emcc.sh - ifeq (,$(wildcard $(emcc.bin))) - $(error Configure script did not find emcc.) - endif - emcc.version := $(shell $(emcc.bin) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;') - $(info using emcc version [$(emcc.version)]) -endif -######################################################################### -# Find wasm-strip, which we need for release builds (see below for -# why) but not strictly for non-release builds. -ifeq (1,$(MAKING_CLEAN)) - wasm-strip.bin := irrelevant -else - wasm-strip.bin ?= $(shell which wasm-strip 2>/dev/null) - ifeq (,$(wasm-strip.bin)) - $(info WARNING: *******************************************************************) - $(info WARNING: Builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,) - $(info WARNING: breaking _All The Things_. The workaround for that is to build) - $(info WARNING: with -g3 (which explodes the file size) and then strip the debug) - $(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.) - $(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.) - $(info WARNING: If this build uses any optimization level higher than -O1 then) - $(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.) - $(info WARNING: wasm-strip is part of the wabt package:) - $(info WARNING: https://github.com/WebAssembly/wabt) - $(info WARNING: on Ubuntu-like systems it can be installed with:) - $(info WARNING: sudo apt install wabt) - $(info WARNING: *******************************************************************) - ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS))) - $(error Cannot make release-quality binary because wasm-strip is not available.) - endif - wasm-strip.bin := echo "not wasm-stripping" - endif -endif -maybe-wasm-strip := $(wasm-strip.bin) - -######################################################################## # barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the # goal being to create a WASM file with only the core APIs. ifeq (1,$(barebones)) @@ -376,20 +377,7 @@ $(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE) DISTCLEAN_FILES += $(bin.stripccomments) ######################################################################## -# bin.mkwb is used for generating some of the makefile code for the -# various wasm builds. It used to be generated in this makefile via a -# difficult-to-read/maintain block of $(eval)'d code. Attempts were -# made to generate it from tcl and bash (shell) but having to escape -# the $ references in those languages made it just as illegible as the -# native makefile code. Somewhat surprisingly, moving that code generation -# to C makes it slightly less illegible than the previous 3 options. -bin.mkwb := ./mkwasmbuilds -$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE) - $(CC) -o $@ $< -DISTCLEAN_FILES += $(bin.mkwb) - -######################################################################## -# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via: +# SQLITE.CALL.C-PP.FILTER: a $(call)able to transform $(1) to $(2) via: # # ./c-pp -f $(1) -o $(2) $(3) # @@ -419,7 +407,7 @@ DISTCLEAN_FILES += $(bin.mkwb) # JS/WASM build. They are solely for use with $(bin.c-pp) itself. # # -D... flags which should be included in all invocations should be -# appended to $(C-PP.FILTER.global). +# appended to $(SQLITE.CALL.C-PP.FILTER.global). bin.c-pp := ./c-pp $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE) $(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \ @@ -427,20 +415,20 @@ $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE) -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=3 DISTCLEAN_FILES += $(bin.c-pp) -C-PP.FILTER.global ?= +SQLITE.CALL.C-PP.FILTER.global ?= ifeq (1,$(SQLITE_C_IS_SEE)) - C-PP.FILTER.global += -Denable-see + SQLITE.CALL.C-PP.FILTER.global += -Denable-see endif -define C-PP.FILTER +define SQLITE.CALL.C-PP.FILTER # Create $2 from $1 using $(bin.c-pp) # $1 = Input file: c-pp -f $(1).js # $2 = Output file: c-pp -o $(2).js # $3 = optional c-pp -D... flags $(2): $(1) $$(MAKEFILE) $$(bin.c-pp) - $$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global) + $$(bin.c-pp) -f $(1) -o $$@ $(3) $(SQLITE.CALL.C-PP.FILTER.global) #CLEAN_FILES += $(2) endef -# /end C-PP.FILTER +# /end SQLITE.CALL.C-PP.FILTER ######################################################################## # cflags.common = C compiler flags for all builds @@ -618,7 +606,6 @@ emcc.cflags += -I. -I$(dir.top) ######################################################################## # emcc flags specific to building .js/.wasm files... emcc.jsflags := -fPIC -emcc.jsflags += --minify 0 emcc.jsflags += --no-entry emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT) emcc.jsflags += -sMODULARIZE @@ -826,7 +813,7 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles) ######################################################################## ######################################################################## -# SQLITE3.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the +# SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the # wasmfs build. $1 is 1 if the build mode needs this workaround # (modes: esm, bundler-friendly, node) and 0 if not (vanilla). $2 must # be 0 for all builds except sqlite3-wasmfs.mjs, in which case it must @@ -847,9 +834,9 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles) # # Maintenance reminder: Mac sed works differently than GNU sed, so we # use awk instead of sed for this. -define SQLITE3.xJS.ESM-EXPORT-DEFAULT +define SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT if [ x1 = x$(1) ]; then \ - echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.ESM-EXPORT-DEFAULT."; \ + echo "Fragile workaround for emscripten/issues/18237. See SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT."; \ {\ awk '/^export default/ && !f{f=1; next} 1' $@ > $@.tmp && mv $@.tmp $@; \ } || exit $$?; \ @@ -873,14 +860,6 @@ sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs sqlite3-api-wasmfs.mjs := $(dir.tmp)/sqlite3-api-wasmfs.mjs sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle -ifneq (1,$(MAKING_CLEAN)) -.wasmbuilds.make: $(bin.mkwb) - @rm -f $@ - $(bin.mkwb) > $@ - @chmod -w $@ --include .wasmbuilds.make -endif -DISTCLEAN_FILES += .wasmbuilds.make # The various -D... values used by *.c-pp.js include: # @@ -930,22 +909,22 @@ sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js sqlite3-worker1-promiser.mjs := $(dir.dout)/sqlite3-worker1-promiser.mjs sqlite3-worker1-bundler-friendly.mjs := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js -$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js))) -$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\ +$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js))) +$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\ $(c-pp.D.sqlite3-bundler-friendly))) -$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js))) -$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\ +$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js))) +$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\ $(sqlite3-worker1-promiser-bundler-friendly.js),\ $(c-pp.D.sqlite3-bundler-friendly))) -$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\ +$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\ -Dtarget=es6-module -Dtarget=es6-bundler-friendly)) $(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.mjs) \ $(sqlite3-worker1-promiser-bundler-friendly.js) -$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js)) -$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\ +$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js)) +$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\ -Dtarget=es6-module)) -$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html)) -$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\ +$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html)) +$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\ -Dtarget=es6-module)) all: $(sqlite3-worker1.js) \ $(sqlite3-worker1-promiser.js) $(sqlite3-worker1-promiser.mjs) @@ -961,6 +940,27 @@ sqlite3-api.ext.jses += \ all quick: $(sqlite3-api.ext.jses) q: quick +ifneq (1,$(MAKING_CLEAN)) +######################################################################## +# bin.mkwb is used for generating some of the makefile code for the +# various wasm builds. It used to be generated in this makefile via a +# difficult-to-read/maintain block of $(eval)'d code. Attempts were +# made to generate it from tcl and bash (shell) but having to escape +# the $ references in those languages made it just as illegible as the +# native makefile code. Somewhat surprisingly, moving that code generation +# to C makes it slightly less illegible than the previous 3 options. +bin.mkwb := ./mkwasmbuilds +$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE) + $(CC) -o $@ $< +DISTCLEAN_FILES += $(bin.mkwb) +.wasmbuilds.make: $(bin.mkwb) + @rm -f $@ + $(bin.mkwb) > $@ + @chmod -w $@ +-include .wasmbuilds.make +endif +DISTCLEAN_FILES += .wasmbuilds.make + ######################################################################## # batch-runner.js is part of one of the test apps which reads in SQL # dumps generated by $(speedtest1) and executes them. @@ -1042,7 +1042,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \ $(pre-post-speedtest1-vanilla.deps) \ $(EXPORTED_FUNCTIONS.speedtest1) @echo "Building $@ ..." - $(emcc.bin) \ + $(bin.emcc) \ $(emcc.speedtest1) \ $(emcc.speedtest1.common) \ $(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \ @@ -1078,10 +1078,10 @@ all: speedtest1 # tester1.mjs: cases 3 and 4 # # To create those, we filter tester1.c-pp.js with $(bin.c-pp)... -$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.js)) -$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm))) -$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html)) -$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm))) +$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.js)) +$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm))) +$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1.html)) +$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm))) tester1: tester1.js tester1.mjs tester1.html tester1-esm.html # Note that we do not include $(sqlite3-bundler-friendly.mjs) in this # because bundlers are client-specific. diff --git a/ext/wasm/README.md b/ext/wasm/README.md index 0c328310d..21330f0eb 100644 --- a/ext/wasm/README.md +++ b/ext/wasm/README.md @@ -29,8 +29,16 @@ $ ./emsdk install latest $ ./emsdk activate latest ``` -The following needs to be run for each shell instance which needs the -`emcc` compiler: +(Sidebar: Emscripten updates can and do _change things_, i.e. _break +things_, so it's considered _required practice_ to test thoroughly +after upgrading it! Our build process makes no guarantees about which +Emscripten version(s) will or won't work, but it's important that +production builds are built using a compatible version. During active +development, the EMSDK is frequently updated, the goal being to keep +sqlite3.wasm working with "the latest" EMSDK.) + +The SQLite configure script will search for the EMSDK. One way +to ensure that it finds it is: ``` # Activate PATH and other environment variables in the current terminal: @@ -38,15 +46,27 @@ $ source ./emsdk_env.sh $ which emcc /path/to/emsdk/upstream/emscripten/emcc + +$ ./configure ... +``` + +Optionally, add that `source` part to your login shell's resource file +(`~/.bashrc` or equivalent). + +Another way is to pass the EMSDK dir to configure: + +``` +$ ./configure --with-emsdk=/path/to/emsdk ``` -Optionally, add that to your login shell's resource file (`~/.bashrc` -or equivalent). +The build tree uses a small wrapper for invoking the `emcc` (the +Emscripten compiler): `tool/emcc.sh` is generated from +`tool/emcc.sh.in` using the EMSDK path found by the configure process. -That `env` script needs to be sourced for building this application -from the top of the sqlite3 build tree: +With that in place, the most common build approaches are: ``` +# From the top of the tree: $ make fiddle ``` @@ -57,7 +77,7 @@ $ cd ext/wasm $ make ``` -That will generate the a number of files required for a handful of +Those will generate the a number of files required for a handful of test and demo applications which can be accessed via `index.html`. WASM content cannot, due to XMLHttpRequest security limitations, be loaded if the containing HTML file is opened directly @@ -68,10 +88,15 @@ needs to be served via an HTTP server. For example, using ``` $ cd ext/wasm $ althttpd --enable-sab --max-age 1 --page index.html +# Or, more simply, from the ext/wasm dir: +$ make httpd ``` -That will open the system's browser and run the index page, from which -all of the test and demo applications can be accessed. +That will open the system's browser and visit the index page, from +which (almost) all of the test and demo applications can be accessed. +(`ext/wasm/SQLTester` is not listed in that page because it's only of +real utility when it's used in conjunction with the proprietary test +suite, which most users don't have access to.) Note that when serving this app via [althttpd][], it must be a version from 2022-09-26 or newer so that it recognizes the `--enable-sab` diff --git a/ext/wasm/config.make.in b/ext/wasm/config.make.in new file mode 100644 index 000000000..f30baac3f --- /dev/null +++ b/ext/wasm/config.make.in @@ -0,0 +1,15 @@ +# Gets filtered by the configure script +bin.bash = @BIN_BASH@ +bin.emcc = @EMCC_WRAPPER@ +bin.wasm-strip = @BIN_WASM_STRIP@ +bin.wasm-opt = @BIN_WASM_OPT@ + +SHELL := $(bin.bash) + +# The following overrides can be uncommented to test various +# validation and if/else branches the makefile code: +# +#bin.bash := +#bin.emcc := +#bin.wasm-strip := +#bin.wasm-opt := diff --git a/ext/wasm/index-dist.html b/ext/wasm/index-dist.html index 7b778b020..47bae3f7a 100644 --- a/ext/wasm/index-dist.html +++ b/ext/wasm/index-dist.html @@ -97,8 +97,8 @@ wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> - <li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>: - same as the previous demo except loads the promiser from an ESM module.</li> + <!--li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>: + same as the previous demo except loads the promiser from an ESM module.</li--> </ul> </li> </ul> diff --git a/ext/wasm/index.html b/ext/wasm/index.html index a3d41f1a9..5d53b62d4 100644 --- a/ext/wasm/index.html +++ b/ext/wasm/index.html @@ -84,8 +84,8 @@ wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> - <li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>: - same as the previous demo except loads the promiser from an ESM module.</li> + <!--li><a href='demo-worker1-promiser-esm.html'>demo-worker1-promiser-esm</a>: + same as the previous demo except loads the promiser from an ESM module.</li--> </ul> </li> <li>speedtest1 ports (sqlite3's primary benchmarking tool)... diff --git a/ext/wasm/mkwasmbuilds.c b/ext/wasm/mkwasmbuilds.c index d7a9a3e71..1e09f83c0 100644 --- a/ext/wasm/mkwasmbuilds.c +++ b/ext/wasm/mkwasmbuilds.c @@ -64,6 +64,75 @@ static void mk_prologue(void){ ps("# pre-post-jses.deps.* = a list of dependencies for the"); ps("# --[extern-][pre/post]-js files."); ps("pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)"); + + { + /* SQLITE.CALL.WASM-OPT = shell code to run $(1) (source wasm file + ** name) through $(bin.wasm-opt) */ + const char * zOptFlags = + /* + ** Flags for wasm-opt. It has many, many, MANY "passes" options + ** and the ones which appear here were selected solely on the + ** basis of trial and error. + ** + ** All wasm file size savings/costs mentioned below are based on + ** the vanilla build of sqlite3.wasm with -Oz (our shipping + ** configuration). Comments like "saves nothing" may not be + ** technically correct: "nothing" means "some neglible amount." + ** + ** Note that performance gains/losses are _not_ taken into + ** account here: only wasm file size. + */ + "--enable-bulk-memory-opt " /* required */ + "--all-features " /* required */ + "--post-emscripten " /* Saves roughly 12kb */ + "--strip-debug " /* We already wasm-strip, but in + ** case this environment has no + ** wasm-strip... */ + /* + ** The rest are trial-and-error. See wasm-opt --help and search + ** for "Optimization passes" to find the full list. + ** + ** With many flags this gets unusuably slow. + */ + /*"--converge " saves nothing for the options we're using */ + /*"--dce " saves nothing */ + /*"--directize " saves nothing */ + /*"--gsi " no: requires --closed-world flag, which does not + ** sound like something we want. */ + /*"--gufa --gufa-cast-all --gufa-optimizing " costs roughly 2kb */ + /*"--heap-store-optimization " saves nothing */ + /*"--heap2local " saves nothing */ + //"--inlining --inlining-optimizing " costs roughly 3kb */ + "--local-cse " /* saves roughly 1kb */ + /*"--once-reduction " saves nothing */ + /*"--remove-memory-init " presumably a performance tweak */ + /*"--remove-unused-names " saves nothing */ + /*"--safe-heap "*/ + /*"--vacuum " saves nothing */ + ; + ps("ifeq (,$(bin.wasm-opt))"); + ps("define SQLITE.CALL.WASM-OPT"); + ps("echo 'wasm-opt not available for $(1)'"); + ps("endef"); + ps("else"); + ps("define SQLITE.CALL.WASM-OPT"); + pf("echo -n 'Before wasm-opt:'; ls -l $(1);\\\n" + "\trm -f wasm-opt-tmp.wasm;\\\n" + /* It's very likely that the set of wasm-opt flags varies from + ** version to version, so we'll ignore any errors here. */ + "\tif $(bin.wasm-opt) $(1) -o wasm-opt-tmp.wasm \\\n" + "\t\t%s; then \\\n" + "\t\tmv wasm-opt-tmp.wasm $(1); \\\n" + "\t\techo -n 'After wasm-opt: '; \\\n" + "\t\tls -l $(1); \\\n" + "\telse \\\n" + "\t\techo 'WARNING: ignoring wasm-opt failure'; \\\n" + "\tfi\n", + zOptFlags + ); + ps("endef"); + ps("endif"); + } } /* @@ -84,14 +153,14 @@ static void mk_pre_post(const char *zName /* build name */, zNM, zNM); pf("$(pre-js.js.%s-%s): $(MAKEFILE)\n", zNM); #if 1 - pf("$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s)," + pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s)," "$(c-pp.D.%s-%s)))\n", zNM, zNM); #else /* This part is needed if/when we re-enable the custom ** Module.instantiateModule() impl in api/pre-js.c-pp.js. */ pf("pre-js.js.%s-%s.intermediary := $(dir.tmp)/pre-js.%s-%s.intermediary.js\n", zNM, zNM); - pf("$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s.intermediary)," + pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s.intermediary)," "$(c-pp.D.%s-%s) -Dcustom-Module.instantiateModule))\n", zNM, zNM); pf("$(pre-js.js.%s-%s): $(pre-js.js.%s-%s.intermediary)\n", zNM, zNM); pf("\tcp $(pre-js.js.%s-%s.intermediary) $@\n", zNM); @@ -107,12 +176,12 @@ static void mk_pre_post(const char *zName /* build name */, /* --post-js=... */ pf("post-js.js.%s-%s := $(dir.tmp)/post-js.%s-%s.js\n", zNM, zNM); - pf("$(eval $(call C-PP.FILTER,$(post-js.js.in)," + pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(post-js.js.in)," "$(post-js.js.%s-%s),$(c-pp.D.%s-%s)))\n", zNM, zNM); /* --extern-post-js=... */ pf("extern-post-js.js.%s-%s := $(dir.tmp)/extern-post-js.%s-%s.js\n", zNM, zNM); - pf("$(eval $(call C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.%s-%s)," + pf("$(eval $(call SQLITE.CALL.C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.%s-%s)," "$(c-pp.D.%s-%s)))\n", zNM, zNM); /* Combine flags for use with emcc... */ @@ -155,23 +224,23 @@ static void mk_fiddle(){ "$(SOAP.js)\n", zTail, (i ? " $(fiddle-module.js)" : "")); if( 1==i ){/*fiddle.debug*/ - pf(" @test -d \"$(dir $@)\" || mkdir -p \"$(dir $@)\"\n"); + pf("\t@test -d \"$(dir $@)\" || mkdir -p \"$(dir $@)\"\n"); } - pf(" $(emcc.bin) -o $@ $(fiddle.emcc-flags%s) " + pf("\t$(bin.emcc) -o $@ $(fiddle.emcc-flags%s) " "$(pre-post-fiddle-module-vanilla.flags) $(fiddle.cses)\n", zTail); - pf(" $(maybe-wasm-strip) $(fiddle-module.wasm%s)\n", zTail); - pf(" @cp -p $(SOAP.js) $(dir $@)\n"); + pf("\t$(maybe-wasm-strip) $(fiddle-module.wasm%s)\n", zTail); + pf("\t@cp -p $(SOAP.js) $(dir $@)\n"); if( 1==i ){/*fiddle.debug*/ - pf(" cp -p $(dir.fiddle)/index.html " + pf("\tcp -p $(dir.fiddle)/index.html " "$(dir.fiddle)/fiddle.js " "$(dir.fiddle)/fiddle-worker.js " "$(dir $@)\n"); } - pf(" @for i in %s/*.*js %s/*.html %s/*.wasm; do \\\n" - " test -f $${i} || continue; \\\n" - " gzip < $${i} > $${i}.gz; \\\n" - " done\n", zDir, zDir, zDir); + pf("\t@for i in %s/*.*js %s/*.html %s/*.wasm; do \\\n" + "\t\ttest -f $${i} || continue; \\\n" + "\t\tgzip < $${i} > $${i}.gz; \\\n" + "\tdone\n", zDir, zDir, zDir); if( 0==i ){ ps("fiddle: $(fiddle-module.js)"); }else{ @@ -193,6 +262,10 @@ static void mk_lib_mode(const char *zName /* build name */, const char *zJsOut /* name of generated sqlite3.js/.mjs */, const char *zCmppD /* extra -D flags for c-pp */, const char *zEmcc /* extra flags for emcc */){ + const char * zWasmOut = "$(basename $@).wasm" + /* The various targets named X.js or X.mjs (zJsOut) also generate + ** X.wasm, and we need that part of the name to perform some + ** post-processing after Emscripten generates X.wasm. */; assert( zName ); assert( zMode ); assert( zApiJsOut ); @@ -201,22 +274,28 @@ static void mk_lib_mode(const char *zName /* build name */, if( !zEmcc ) zEmcc = ""; pf("%s# Begin build [%s-%s]\n", zBanner, zNM); - pf("ifneq (1,$(MAKING_CLEAN))\n"); pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut); mk_pre_post(zNM, zCmppD); pf("\nemcc.flags.%s.%s ?=\n", zNM); if( zEmcc[0] ){ pf("emcc.flags.%s.%s += %s\n", zNM, zEmcc); } - pf("$(eval $(call C-PP.FILTER, $(sqlite3-api.js.in), %s, %s))\n", + pf("$(eval $(call SQLITE.CALL.C-PP.FILTER, $(sqlite3-api.js.in), %s, %s))\n", zApiJsOut, zCmppD); /* target zJsOut */ pf("%s: %s $(MAKEFILE) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) " - "$(pre-post-%s-%s.deps)\n", + "$(pre-post-%s-%s.deps) " + "$(sqlite3-api.ext.jses)" + /* ^^^ maintenance reminder: we set these as deps so that they + get copied into place early. That allows the developer to + reload the base-most test pages while the later-stage builds + are still compiling, which is especially helpful when running + builds with long build times (like -Oz). */ + "\n", zJsOut, zApiJsOut, zNM); pf("\t@echo \"Building $@ ...\"\n"); - pf("\t$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n"); + pf("\t$(bin.emcc) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n"); pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode); pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM); pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM); @@ -227,40 +306,45 @@ static void mk_lib_mode(const char *zName /* build name */, /* TODO? Replace this CALL with the corresponding makefile code. ** OTOH, we also use this $(call) in the speedtest1-wasmfs build, ** which is not part of the rules emitted by this program. */ - pf("\t@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,%d)\n", + pf("\t@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,%d)\n", 0==strcmp("sqlite3-wasmfs", zName) ? 1 : 0); } - pf("\t@dotwasm=$(basename $@).wasm; \\\n" - "\tchmod -x $$dotwasm; \\\n" - "\t$(maybe-wasm-strip) $$dotwasm; \\\n"); - pf("\tsed -i -e '/^var _sqlite3.*createExportWrapper/d' %s; \\\n" - "\techo 'Stripped out createExportWrapper() parts.'; \\\n", + pf("\t@chmod -x %s; \\\n" + "\t\t$(maybe-wasm-strip) %s;\n", + zWasmOut, zWasmOut); + pf("\t@$(call SQLITE.CALL.WASM-OPT,%s)\n", zWasmOut); + pf("\t@sed -i -e '/^var _sqlite3.*createExportWrapper/d' %s || exit; \\\n" + /* ^^^^^^ reminder: Mac/BSD sed has no -i flag */ + "\t\techo 'Stripped out createExportWrapper() parts.'\n", zJsOut) /* Our JS code installs bindings of each WASM export. The generated Emscripten JS file does the same using its own framework, but we don't use those results and can speed up lib init, and reduce memory cost considerably, by stripping them out. */; /* - ** The above $(emcc.bin) call will write zJsOut and will create a - ** like-named .wasm file. That .wasm file name gets hard-coded into - ** zJsOut so we need to, for some cases, patch zJsOut to use the - ** name sqlite3.wasm instead. Note that the resulting .wasm file is - ** identical for all builds for which zEmcc is empty. + ** The above $(bin.emcc) call will write zJsOut and will create a + ** like-named .wasm file (zWasmOut). That .wasm file name gets + ** hard-coded into zJsOut so we need to, for some cases, patch + ** zJsOut to use the name sqlite3.wasm instead. Note that the + ** resulting .wasm file is identical for all builds for which zEmcc + ** is empty. */ if( 0==strcmp("bundler-friendly", zMode) - || 0==strcmp("node", zMode) ) { - pf("\techo 'Patching $@ for %s.wasm...' \\\n", zName); - pf("\trm -f $$dotwasm; dotwasm=; \\\n" - "\tsed -i -e 's/%s-%s.wasm/%s.wasm/g' $@ || exit $$?; \\\n", + || 0==strcmp("node", zMode) ){ + 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"); + }else{ + pf("\t@ls -la %s $@\n", zWasmOut); } - pf("\tls -la $$dotwasm $@\n"); if( 0!=strcmp("sqlite3-wasmfs", zName) ){ /* The sqlite3-wasmfs build is optional and needs to be invoked ** conditionally using info we don't have here. */ pf("all: %s\n", zJsOut); } - ps("endif\n# ^^^ !$(MAKING_CLEAN)"); pf("# End build [%s-%s]%s", zNM, zBanner); } diff --git a/ext/wasm/wasmfs.make b/ext/wasm/wasmfs.make index 9de5574f2..2c6fa35bd 100644 --- a/ext/wasm/wasmfs.make +++ b/ext/wasm/wasmfs.make @@ -101,7 +101,7 @@ $(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \ $(emcc.flags.sqlite3-wasmfs) \ $(emcc.flags.speedtest1-wasmfs) \ -o $@ $(speedtest1.cfiles) -lm - @$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,1) + @$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,1) $(maybe-wasm-strip) $(speedtest1-wasmfs.wasm) chmod -x $(speedtest1-wasmfs.wasm) ls -la $@ $(speedtest1-wasmfs.wasm) @@ -351,13 +351,6 @@ T.cc += $(OPTS) INSTALL.noexec = $(INSTALL) -m 0644 # ^^^ do not use GNU-specific flags to $(INSTALL), e.g. --mode=... -# When cross-compiling, we need to avoid the -s flag because it only -# works on the build host's platform. -INSTALL.strip.1 = $(INSTALL) -INSTALL.strip.0 = $(INSTALL) -s -INSTALL.strip. = $(INSTALL.strip.0) -INSTALL.strip = $(INSTALL.strip.$(IS_CROSS_COMPILING)) - # # $(T.compile) = generic target platform compiler invocation, # differing only from $(T.cc) in that it appends $(T.compile.extras), @@ -1514,7 +1507,7 @@ install: install-headers # libtclsqlite3... # pkgIndex.tcl: - echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@ + echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] Sqlite3]' > $@ pkgIndex.tcl-1: pkgIndex.tcl pkgIndex.tcl-0 pkgIndex.tcl-: tcl: pkgIndex.tcl-$(HAVE_TCL) @@ -2024,7 +2017,7 @@ sqlite3d$(T.exe): shell.c $(LIBOBJS0) $(LDFLAGS.libsqlite3) $(LDFLAGS.readline) install-shell-0: sqlite3$(T.exe) $(install-dir.bin) - $(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)" + $(INSTALL) sqlite3$(T.exe) "$(install-dir.bin)" install-shell-1: install: install-shell-$(HAVE_WASI_SDK) @@ -2038,7 +2031,7 @@ sqldiff$(T.exe): $(sqldiff.$(LINK_TOOLS_DYNAMICALLY).deps) $(sqldiff.$(LINK_TOOLS_DYNAMICALLY).rules) install-diff: sqldiff$(T.exe) $(install-dir.bin) - $(INSTALL.strip) sqldiff$(T.exe) "$(install-dir.bin)" + $(INSTALL) sqldiff$(T.exe) "$(install-dir.bin)" #install: install-diff dbhash$(T.exe): $(TOP)/tool/dbhash.c sqlite3.o sqlite3.h @@ -1,9 +1,9 @@ -C Add\stwo\snew\ssqlite3_db_config()\soptions\sthat\senable\sthe\sATTACH\scommand\nto\screate\snew\sdatabase\sfiles\sand\sto\sopen\sdatabases\sread/write.\s\sBoth\ndefault\sto\son\sfor\sbackwards\scompatibility. -D 2025-01-22T19:37:47.938 +C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\sextra-security\sbranch. +D 2025-01-31T00:54:59.552 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d -F Makefile.in 572271a39d7ac1ae228ed911c63fdf374300a6a880ceb851b1f3d357e9a9534e +F Makefile.in 38485d15d9190cdad0d7bee25af7b442028865964025dcc61f40fd8d6e369cfc F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0 F Makefile.msc 39785ec45f9ae0311e49094eff2ee079562246fed6be3b9f632a99d4df20056a F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159 @@ -14,14 +14,13 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531 -F auto.def 056352c70a74a82929bdb5aaef65b38d44e4b912a8c7ebcb0a7d87fa1fd7c185 -F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am adedc1324b6a87fdd1265ddd336d2fb7d4f36a0e77b86ea553ae7cc4ea239347 +F auto.def e7e92090c98aeb0174d29988c259834eb1b71ae1ea927015c3ef300f6f9b68ae F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac +F autoconf/Makefile.in 56697ad25ecf23afa317148b06bdc14f85960b42e5ec434ac1ba87f63a3cb789 w autoconf/Makefile.am F autoconf/Makefile.msc ffff61fe851443015ddb6600ab69a9df503cfec25459b336be7ba8c9a9e473f8 -F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 -F autoconf/README.txt 5e946ffb6fbdbb114c81e1bdc862df27fce8beab557d7b0421820b0fe8fc048f -F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277 +F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136 +F autoconf/README.txt 7f01dc3915e2d68f329011073662369e62a0938a2c69398807823c57591cb288 +F autoconf/auto.def 23bc095a3890c0ca334abf7ef67d1c8af4c22c12832bcc738015e868d54fe9d7 F autoconf/tea/Makefile.in ba0556fee8da09c066bad85a4457904e46ee2c2eabaa309c0e83a78f2f151a8e F autoconf/tea/README.txt 61e62e519579e4a112791354d6d440f8b51ea6db3b0bab58d59f29df42d2dfe3 F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43 @@ -38,7 +37,7 @@ F autoconf/tea/win/rules.vc 94a18c3e453535459b4a643983acca52fb8756e79055bd2ad4b0 F autoconf/tea/win/targets.vc 96a25a1fa6e9e9cfb348fd3760a5395b4ce8acafc8ed10f0412937ec200d5dbd F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4 F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e -F autosetup/README.md 1a02f5a94fd460eb7ffc8dea5d6f1657e38ddf8ffa2d6c5dce9a630b97021a69 +F autosetup/README.md 2737c4eb44b022a694b1f93fb01c3b6c3a45b4f663e18490c2106643a77b39da F autosetup/autosetup df8b53928b1fe3c67db5bc77c8e1eb8160c1b6a26c370e9a06c68748f803b7e4 x F autosetup/autosetup-config.guess dfa101c5e8220e864d5e9c72a85e87110df60260d36cb951ad0a85d6d9eaa463 x F autosetup/autosetup-config.sub a38fb074d0dece01cf919e9fb534a26011608aa8fa606490864295328526cd73 x @@ -50,14 +49,14 @@ F autosetup/cc-shared.tcl 4f024e94a47f427ba61de1739f6381ef0080210f9fae89112d5c1d F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f F autosetup/jimsh0.c d40e381ea4526a067590e7b91bd4b2efa6d4980d286f908054c647b3df4aee14 F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba -F autosetup/proj.tcl 50b060ea6760b02ef5cb16650fbe9c1840e16351a0be0ccfc3727c565f74a257 -F autosetup/sqlite-config.tcl 96d07366aaaf717a2a1ff9b0ef89c4d669d6a38f18e7e7ae48a2498d076b39ac +F autosetup/proj.tcl 9adf1539673cef15bff862d9360b479e6920cc2c0d85de707b0ba31c04ce4531 +F autosetup/sqlite-config.tcl 00af5b9d94d580367bf01984b86397e8d35b74090427def9591a54ded0e1a287 F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9 F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8af4a0f4adbc -F doc/compile-for-windows.md 31cddda1d5f34027f1f2b7484d580e7558f22a9875884805b6fdc84d56cab848 +F doc/compile-for-windows.md 5141661e783c9ca9e3fd30e813345898712f5c311d71316f183db87038fa28a6 F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706 @@ -113,7 +112,7 @@ F ext/fts5/fts5_buffer.c 0eec58bff585f1a44ea9147eae5da2447292080ea435957f7488c70 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 1ce1e2b43fdd86a2047619c2ea3aafa5c7b909d0cef75185d0fda31e82f0e9c6 +F ext/fts5/fts5_index.c a59ccd06af157da2471f356198af14bc37d86e46231e4e1858b2af2f94c2c6e4 F ext/fts5/fts5_main.c 9a1daef7247f9b8a50b4159323e340efa6b0e4bea4fcd83580480f94d4f2c888 F ext/fts5/fts5_storage.c 1ad05dab4830a4e2eaf2900bb143477f93bc17437093582f36f4b818809e88d8 F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329 @@ -443,7 +442,7 @@ F ext/misc/shathree.c f3a778f27bf3e71b666a77f28e463a3b931c4dbe4219447e61bb678b4b F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c bcc42ef3fd29429bc01a83e751332b8d4690e65d45008449bdffe7656371487f F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634 -F ext/misc/sqlite3_stdio.c 18160504b9348d0ebb9f5620fd61e64cd2d55fffde05ab3f7db03396add4840a +F ext/misc/sqlite3_stdio.c 0fe5a45bd332b30aef2b68c64edbe69e31e9c42365b0fa79ce95a034bca6fbb0 F ext/misc/sqlite3_stdio.h f05eaf5e0258f0573910324a789a9586fc360a57678c57a6d63cfaa2245b6176 F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321 F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc @@ -455,7 +454,7 @@ F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917 F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20 F ext/misc/vfsstat.c a85df08654743922a19410d7b1e3111de41bb7cd07d20dd16eda4e2b808d269d -F ext/misc/vfstrace.c 9c4abd2f67ae2760e7a241eca2e8517c64480ac2c3e66a499326e688a9bbee22 +F ext/misc/vfstrace.c a73386403c350b210dc788a2d23a0f5cc89c49b176109a66af11b5078c116331 F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5 F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668 @@ -577,14 +576,14 @@ F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1 F ext/session/changeset.c 7a1e6a14c7e92d36ca177e92e88b5281acd709f3b726298dc34ec0fb58869cb5 F ext/session/changesetfuzz.c 227076ab0ae4447d742c01ee88a564da6478bbf26b65108bf8fac9cd8b0b24aa F ext/session/changesetfuzz1.test 15b629004e58d5ffcc852e6842a603775bb64b1ce51254831f3d12b113b616cd -F ext/session/session1.test 8d0509cd3fcfdee6a33422d5fe5c95a9770d62a0b8588adb0177ecdf79b2c345 +F ext/session/session1.test cc7e58976c2cc6263fb7ef0c5125a98eafc2f213c75929f986768d2dbc224725 F ext/session/session2.test ee83bb973b9ce17ccce4db931cdcdae65eb40bbb22089b2fe6aa4f6be3b9303f F ext/session/session3.test 2cc1629cfb880243aec1a7251145e07b78411d851b39b2aa1390704550db8e6a F ext/session/session4.test 823f6f018fcbb8dacf61e2960f8b3b848d492b094f8b495eae1d9407d9ab7219 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926 F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904 -F ext/session/session9.test be090b1420f3824a573da9e56ff542b1e1c2a4f772118e9ab2f75774e66d25d0 +F ext/session/session9.test 4e3aff62d6b4294498ddbe309076de06f4fddffad4fe5f5a6c033358b01df083 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57e1f59fce2fdf @@ -593,7 +592,8 @@ F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401 F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859 -F ext/session/session_common.tcl e5598096425486b363718e2cda48ee85d660c96b4f8ea9d9d7a4c3ef514769da +F ext/session/session_common.tcl a31f537a929a695a852d241c9434f2847cadf329856401921139fbb03a5a7697 +F ext/session/session_gen.test 3f2ff2bd71694b82bd17c5ab2002635c54affb909fca2ee749b2daf95ff86648 F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3 F ext/session/sessionalter.test e852acb3d2357aac7d0b920a2109da758c4331bfdf85b41d39aa3a8c18914f65 F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee @@ -607,7 +607,7 @@ F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576d F ext/session/sessionfault3.test ce0b5d182133935c224d72507dbf1c5be1a1febf7e85d0b0fbd6d2f724b32b96 F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25 F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09 -F ext/session/sessionnoact.test 0f552bd318b764bbc5b2cd6f3518435254a1c830fdaa5aab9c688f507ebc301e +F ext/session/sessionnoact.test 4c7ae5c7d351cb5323bca62b6b095592ad24bd90a6713c178b62ab0063d23e19 F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7 F ext/session/sessionnoop2.test de4672dce88464396ec9f30ed08c6c01643a69c53ae540fadbbf6d30642d64e8 F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2 @@ -615,13 +615,13 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795 F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc -F ext/session/sqlite3session.c d6f5e3e83b9b0bbc4a8db4837284f0ecc6af5321d4c8e7136380b456b278c46a +F ext/session/sqlite3session.c 01e321269fe21982b79336c8b7a4b83ef0779f5c1644a04c8bb7c1174c8c71ae F ext/session/sqlite3session.h 683ccbf16e2c2521661fc4c1cf918ce57002039efbcabcd8097fa4bca569104b F ext/session/test_session.c 12e0a2c15fd60f92da4bb29c697c9177ff0c0dbcdc5129a54c47e999f147937a F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c -F ext/wasm/GNUmakefile 78f49e47146d58fa44f9ac624627a718fba4b2b2baeaea641bcf6fed300c0f0d +F ext/wasm/GNUmakefile 47f121d057c08ba49443c06c1c51ba2572e3d5d28a06c968cf0b2ccd5878c3d3 F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576 -F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193 +F ext/wasm/README.md 6c1dd9e4448c672f4a072c56d3ce9164b3c7dc818ea8f18b49c6834bfd5efe24 F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff F ext/wasm/SQLTester/SQLTester.mjs 66e1adc3d79467b68e3e40614fd42c1a577c7e219ec0985db966eded52a941e5 F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0 @@ -660,6 +660,7 @@ F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b5318317 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f F ext/wasm/common/whwasmutil.js d76c69617e95d85ffc9996f7d9d7481df6976dcbd860ecd82bd8c075e3a101ae +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 @@ -675,11 +676,11 @@ F ext/wasm/fiddle.make d4969f0322a582c57a22ce3541f10a5b09a609d14eab32891f613f43b 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/index-dist.html 564b5ec5669676482c5a25dea9e721d8eafed426ecb155f93d29aeff8507511f -F ext/wasm/index.html e4bbffdb3d40eff12b3f9c7abedef91787e2935620b7f8d40f2c774b80ad8fa9 +F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730 +F ext/wasm/index.html 10ff3ad190aadccb713109fa55a38e5c1f3c2a8cf05cd31783745bab3f184079 F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54 F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8 -F ext/wasm/mkwasmbuilds.c af06fd14fcb7803c0adacab276047bb696c07f5b683a6f70adc5b3f146cf61f3 +F ext/wasm/mkwasmbuilds.c d5885bacf2253bed913cdc7eb16b44f9c9e782133e10600652d1a78841c337af F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337 F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 @@ -699,9 +700,9 @@ F ext/wasm/tester1.c-pp.js 228101c290003423f0bfb66a6ebbfc6904fa7b1b69466e700c135 F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 -F ext/wasm/wasmfs.make bc8bb227f35d5bd3863a7bd2233437c37472a0d81585979f058f9b9b503bef35 +F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0 -F main.mk a187ada134ccb55b5d59ea3eb8f71cc6b19bfc244689e24a729f7a64aa500dc3 +F main.mk 043987843e8365dbaf74dce60c11683b62e2bcfcb3122574c14a0324d37a72f3 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421 @@ -721,7 +722,7 @@ F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522 F src/btree.c 63ca6b647342e8cef643863cd0962a542f133e1069460725ba4461dcda92b03c F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50 F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6 -F src/build.c c6b09342d870a509529244ed8e19b4175a261f2e3163c199241d69e1d8a57607 +F src/build.c 357f98cdd9fe93f86e93ad3324fd224492480e48506c0c7db8ae3a94f3b5c5ee F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c d35723024b963edce9c0fad5b3303e8bb9266083784844baed10a6dedfe26f3b @@ -729,16 +730,16 @@ F src/date.c 842c08ac143a56a627b05ac51d68624f2b7b03e3b4cba596205e735eed64ee57 F src/dbpage.c e90410e5d4c0217dfddc4184a81e38ec4903c25d4ec0f201060a0e54e7c2099f F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42 -F src/expr.c 30a407765d4e4b592f9f958085fb4e8336e54fa46a70ade7f5a67111bc191563 +F src/expr.c 8705be31ee713aaa43c97d91399db09f16ee41b88250406eb99de6b47f550a98 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f -F src/func.c 30051410d0379059e1e3642ffc0caae6963a2b01b3b6d9dd44c5e09b1a66d066 +F src/func.c f5b31c805679930cc5afcdfb1e657f9dd273053f52ff51133df5a448c519e5d9 F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c f8d1a0f8ee258411009c6b7f2d93170e351bd19f5ad89d57e1180644297cbe70 +F src/insert.c db8bfff30fd7f71812651df3ddf5d1624b9e19104b31e349cd9055bbc9d622c4 F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 @@ -781,14 +782,14 @@ F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 83e88fbb36f89b6703b348777491619554f0fd6f917c9fdf51e4c2e9cda6c04e F src/shell.c.in 9915487b27e3169d59a4018c88d14246059c392c662d98fc516264267396b65e -F src/sqlite.h.in 666fa171bf5a9fa532b637571303a596c80723e89f3e10962c0d81378b2b789d +F src/sqlite.h.in 584579ac930f5e0c55f40cf5f2c7e4caa93e0a3aa14c4dc078a18cec66f6fde3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h dd2385d05fbc892d865296fa3f493ba132044a2bbbd15bfad67984bb4afba1d3 +F src/sqliteInt.h 64b3af946f779e1c7b58a1cdd2ec747797fe9f76f6e23d5f7c7c5896b5ea3ada F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 -F src/tclsqlite.c 6a7538560adc856faea295c0f09c33a57a1cfa5c59f85ab4e12aa50dba7ff2de +F src/tclsqlite.c 5c1e367e26711044730c93d4b81312170918a8d1fe811f45be740ab48f7de8c1 F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395 F src/test1.c 9d2da51b4c33633e7370e4068af6d16d2c52b22a5810ec012ac32e77f8397b64 F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3 @@ -841,7 +842,7 @@ F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c fe17e03175cae35b6694d0f879e7bc3d1ddea2fd4ab148cba9bbd025b7a7bb12 -F src/treeview.c d1f3003cb21846828f314a304cf9117f5e80ce0be259315a681d25147004d26d +F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc62279 F src/trigger.c 247e2d712d5edc6021d52a169f6ac9a9c10d7144bc4ac7ea06c1ed2aa414659f F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508 F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1 @@ -849,9 +850,9 @@ F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba F src/util.c e5f6a5eeaa26b69054a43bbd0048cfe3d2851f6961052b35aed8f695df922850 F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40 F src/vdbe.c b428a751953c0c2ff85e3e152ec16e29d488895cd541c8c20876ff9f3bf6978a -F src/vdbe.h 9676348d342bd04e21e384c63b57224171ce84fac77853357334ef94c4d33cf4 +F src/vdbe.h 3d26d5c7660c5c7bd33ffb0d8784615072d8b23c81f8110870efe2631136bc89 F src/vdbeInt.h 895b1ab7536f018d3d70d690f6c0adbd1062b6dddce1c2cad912927856d4033c -F src/vdbeapi.c 76fa76b21f46afc70e71ecd69954f601e9b80b5fb0c1eb7ace06d30802255768 +F src/vdbeapi.c 08d0445b6066b04e5014d5d322b75736a61fe847ed88eb6e1a186c79dd9ed117 F src/vdbeaux.c 885e16100597507fbbe09d82cbb963bff3fd8a9c1e358dc4f463fc95feb18e8b F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797 F src/vdbemem.c 977438546df236c6a3e7d8b4fe86c0643c13b89b00235db1f11c3a91a4796d30 @@ -863,8 +864,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 4e6181d8780ab0af2e1388d0754cbe6f2f04593d2b1ab6c41699a89942fd8997 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 -F src/where.c 5e74d76b264abcd7e6682e02853756b5d32f543c59fb47bb55a02575b73693ae -F src/whereInt.h 2b0804f300c7f65de4046a1d81c65f01b208d6c08950ccd1fa6b8c16162a8af7 +F src/where.c 09dc313e7223ca1217c39c7026b00f16ff449a8323511a762fcba7863a00f4cd +F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1 F src/wherecode.c 0c3d3199a2b769a5e2bb70feb5003dc85b3d86842ecaf903a47f2b4205ca5dab F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f F src/window.c 2bf01f9941a64fbcead61a0e3cb5db3fca5094b30d2ff0d23274c2a81d2e2385 @@ -989,7 +990,7 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9 F test/capi2.test 4ee545824adc3eb33bf57ef89f77440b28188ec3da72e5425ff0fcdba32e8d5a -F test/capi3.test 4892b5e53d2a6941edc9d204a0ab174dd66e8689282d9a15e4384561c3965945 +F test/capi3.test ab90c548969613315605c555a8623f6b56e00e28d451c46a17ef73683c422c70 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a490f7 F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde @@ -1306,7 +1307,7 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test bb767ec1cfd1730256f0a83219f0acda36bc251b63f8b8bb7d8c7cff17875a4f F test/in5.test 4fd79c70dfa0681313e8cdca07f5ff0400bdc0e20f808a5c59eaef1e4b48082a F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b -F test/in7.test 5050b648510d88bd27ff6b40991a45e1cc277c20e258162e81650e01069a56bb +F test/in7.test d9efdee00b074a60c6343993b2eda78bc369ab080dad864513c73f8aca89d566 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f F test/incrblob3.test 67621a04b3084113bf38ce03797d70eca012d9d8f948193b8f655df577b0da6f @@ -1678,7 +1679,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c -F test/speedtest.md e4f467683acfdb2834ca1d6ce209c3d883dfecf73c41f77234b2368be9579de2 +F test/speedtest.md ee958457ae1b729d9715ae33c0320600000bf1d9ddea1a88dcf79f56729d6fad F test/speedtest.tcl 8a9362c1e429318e741b91d26888e7edcc326f98c3aea505ffd618cc5b9e7f0a x F test/speedtest1.c 323ce0956430a5aae56ea20f502da7bea3fb62b8ed02e9b0f12ab078b2b258f5 F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e @@ -1688,7 +1689,7 @@ F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb F test/sqllimits1.test 408131e4975d61868711c83f101a56d4602313cc5cae88d3eee81c1da364fd89 F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a -F test/starschema1.test a84205f97fe278a015ac39546c86b97228d22043af28f3a2ef809e8d5637ce1d +F test/starschema1.test f5388cd32527ab18d3f98f9e3402ec780f6a186e04e0d9c8531d7568ee734e11 F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805 F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408 F test/statfault.test 064f43379e4992b5221b7d9ac887c313b3191f85cce605d78e416fc4045da64e @@ -2113,7 +2114,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/build-all-msvc.bat c817b716e0edeecaf265a6775b63e5f45c34a6544f1d4114a222701ed5ac79ab x F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f -F tool/buildtclext.tcl e82120d672b34b507e1d9cb220ce18c5c36c3ee0ff0328e35f1806ce74ed2266 +F tool/buildtclext.tcl 20726b6b73c7911baa8519a9467b4062104339a5ce57947819884525c56d79e3 F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca @@ -2143,7 +2144,7 @@ F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669 F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkamalzip.tcl 8aa5ebe7973c8b8774062d34e15fea9815c4cc2ceea3a9b184695f005910876a -F tool/mkautoconfamal.sh 4fbfd523330c8cf12ead8f0e0acdb3c5c9c08a1bcb293119267aeaa3e0bbe3e1 +F tool/mkautoconfamal.sh 14d2144043c6455958012f92324f4ce7c90a261b5daa2f2c7509498468475f8d F tool/mkccode.tcl 210159febe0ef0ecbc53c79833500663ceaba0115b2b374405818dc835b5f84b x F tool/mkctimec.tcl ef6a67ec82e5b6fc19152a4c79f237227b18bf67ff16d155bac7adb94355d9cf x F tool/mkkeywordhash.c 6b0be901c47f9ad42215fc995eb2f4384ac49213b1fba395102ec3e999acf559 @@ -2208,11 +2209,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 c20d21b473d8a45267262c5df1d7b102eccce8e4cfbe1e467ea66c474aea0af5 -R 1e3a803f41f6c1dff31eede2c9428a7d -T *branch * enable-attach -T *sym-enable-attach * -T -sym-trunk * +P fe0c58d00b491d1af7c0894f5c32542954aeea2e6510853b3bcbf13ac0bf5ce0 0cc4ed8c6e53aca1f5e94c132bedbc7f561c04a77f1a30b965ffe7560634bfeb +R 21110132d98b76250ca6d2606f60e660 U drh -Z 45431d003e2c2a4fccdcefe1b482f2e1 +Z a99c7811057635504d507854afc123c4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4aa4c3121..6b29b0712 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe0c58d00b491d1af7c0894f5c32542954aeea2e6510853b3bcbf13ac0bf5ce0 +86ba57561a8d8c14e401c06b2345a9417053aa3a5f0c84e52460f23f5e6aa8d0 diff --git a/src/build.c b/src/build.c index a5deb54fc..cc29610e0 100644 --- a/src/build.c +++ b/src/build.c @@ -4691,7 +4691,6 @@ void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ int i; assert( db!=0 ); if( pList==0 ) return; - assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */ for(i=0; i<pList->nId; i++){ sqlite3DbFree(db, pList->a[i].zName); } diff --git a/src/expr.c b/src/expr.c index ca5b9092e..8f898a1e3 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1932,16 +1932,13 @@ IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ int i; assert( db!=0 ); if( p==0 ) return 0; - assert( p->eU4!=EU4_EXPR ); pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) ); if( pNew==0 ) return 0; pNew->nId = p->nId; - pNew->eU4 = p->eU4; for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; const struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->u4 = pOldItem->u4; } return pNew; } @@ -3465,6 +3462,7 @@ static int findCompatibleInRhsSubrtn( assert( pOp->opcode==OP_BeginSubrtn ); pSig = pOp->p4.pSubrtnSig; assert( pSig!=0 ); + if( !pSig->bComplete ) continue; if( pNewSig->selId!=pSig->selId ) continue; if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue; pExpr->y.sub.iAddr = pSig->iAddr; @@ -3511,6 +3509,7 @@ void sqlite3CodeRhsOfIN( KeyInfo *pKeyInfo = 0; /* Key information */ int nVal; /* Size of vector pLeft */ Vdbe *v; /* The prepared statement under construction */ + SubrtnSig *pSig = 0; /* Signature for this subroutine */ v = pParse->pVdbe; assert( v!=0 ); @@ -3531,7 +3530,6 @@ void sqlite3CodeRhsOfIN( ** Compute a signature for the RHS of the IN operator to facility ** finding and reusing prior instances of the same IN operator. */ - SubrtnSig *pSig = 0; assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 ); if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){ pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0])); @@ -3574,6 +3572,7 @@ void sqlite3CodeRhsOfIN( pExpr->y.sub.iAddr = sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; if( pSig ){ + pSig->bComplete = 0; pSig->iAddr = pExpr->y.sub.iAddr; pSig->regReturn = pExpr->y.sub.regReturn; pSig->iTable = iTab; @@ -3709,6 +3708,7 @@ void sqlite3CodeRhsOfIN( sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } + if( pSig ) pSig->bComplete = 1; if( pKeyInfo ){ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); } diff --git a/src/func.c b/src/func.c index 2bd4be31c..bd25a44d4 100644 --- a/src/func.c +++ b/src/func.c @@ -2808,10 +2808,8 @@ void sqlite3RegisterBuiltinFunctions(void){ #endif /* SQLITE_ENABLE_MATH_FUNCTIONS */ FUNCTION(sign, 1, 0, 0, signFunc ), INLINE_FUNC(coalesce, -4, INLINEFUNC_coalesce, 0 ), - INLINE_FUNC(iif, 2, INLINEFUNC_iif, 0 ), - INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ), - INLINE_FUNC(if, 2, INLINEFUNC_iif, 0 ), - INLINE_FUNC(if, 3, INLINEFUNC_iif, 0 ), + INLINE_FUNC(iif, -4, INLINEFUNC_iif, 0 ), + INLINE_FUNC(if, -4, INLINEFUNC_iif, 0 ), }; #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(); diff --git a/src/insert.c b/src/insert.c index d380281be..83baeece6 100644 --- a/src/insert.c +++ b/src/insert.c @@ -927,6 +927,7 @@ void sqlite3Insert( int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int *aRegIdx = 0; /* One register allocated to each index */ + int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ @@ -1071,15 +1072,15 @@ void sqlite3Insert( */ bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; if( pColumn ){ - assert( pColumn->eU4!=EU4_EXPR ); - pColumn->eU4 = EU4_IDX; - for(i=0; i<pColumn->nId; i++){ - pColumn->a[i].u4.idx = -1; - } + aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int)); + if( aTabColMap==0 ) goto insert_cleanup; for(i=0; i<pColumn->nId; i++){ + const char *zCName = pColumn->a[i].zName; + u8 hName = sqlite3StrIHash(zCName); for(j=0; j<pTab->nCol; j++){ - if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){ - pColumn->a[i].u4.idx = j; + if( pTab->aCol[j].hName!=hName ) continue; + if( sqlite3StrICmp(zCName, pTab->aCol[j].zCnName)==0 ){ + if( aTabColMap[j]==0 ) aTabColMap[j] = i+1; if( i!=j ) bIdListInOrder = 0; if( j==pTab->iPKey ){ ipkColumn = i; assert( !withoutRowid ); @@ -1401,9 +1402,9 @@ void sqlite3Insert( } } if( pColumn ){ - assert( pColumn->eU4==EU4_IDX ); - for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){} - if( j>=pColumn->nId ){ + j = aTabColMap[i]; + assert( j>=0 && j<=pColumn->nId ); + if( j==0 ){ /* A column not named in the insert column list gets its ** default value */ sqlite3ExprCodeFactorable(pParse, @@ -1411,7 +1412,7 @@ void sqlite3Insert( iRegStore); continue; } - k = j; + k = j - 1; }else if( nColumn==0 ){ /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */ sqlite3ExprCodeFactorable(pParse, @@ -1656,7 +1657,10 @@ insert_cleanup: sqlite3ExprListDelete(db, pList); sqlite3UpsertDelete(db, pUpsert); sqlite3SelectDelete(db, pSelect); - sqlite3IdListDelete(db, pColumn); + if( pColumn ){ + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aTabColMap); + } if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 46336bf3e..b8f4ba3cb 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -10785,8 +10785,9 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Serialize a database ** -** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory -** that is a serialization of the S database on [database connection] D. +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to +** memory that is a serialization of the S database on +** [database connection] D. If S is a NULL pointer, the main database is used. ** If P is not a NULL pointer, then the size of the database in bytes ** is written into *P. ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index aa7e297e7..8c1be72c1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -881,6 +881,8 @@ typedef u64 tRowcnt; ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 */ typedef INT16_TYPE LogEst; +#define LOGEST_MIN (-32768) +#define LOGEST_MAX (32767) /* ** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer @@ -1151,7 +1153,7 @@ extern u32 sqlite3WhereTrace; ** 0xFFFF---- Low-level debug messages ** ** 0x00000001 Code generation -** 0x00000002 Solver +** 0x00000002 Solver (Use 0x40000 for less detail) ** 0x00000004 Solver costs ** 0x00000008 WhereLoop inserts ** @@ -1170,6 +1172,8 @@ extern u32 sqlite3WhereTrace; ** ** 0x00010000 Show more detail when printing WHERE terms ** 0x00020000 Show WHERE terms returned from whereScanNext() +** 0x00040000 Solver overview messages +** 0x00080000 Star-query heuristic */ @@ -3221,13 +3225,8 @@ struct ExprList { */ struct IdList { int nId; /* Number of identifiers on the list */ - u8 eU4; /* Which element of a.u4 is valid */ struct IdList_item { char *zName; /* Name of the identifier */ - union { - int idx; /* Index in some Table.aCol[] of a column named zName */ - Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */ - } u4; } a[1]; }; diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 76c9ef75c..824e8c4d3 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -510,7 +510,7 @@ static int createIncrblobChannel( ** or {...} or ; to be seen anywhere. Most callback scripts consist ** of just a single procedure name and they meet this requirement. */ -static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){ +static int safeToUseEvalObjv(Tcl_Obj *pCmd){ /* We could try to do something with Tcl_Parse(). But we will instead ** just do a search for forbidden characters. If any of the forbidden ** characters appear in pCmd, we will report the string as unsafe. @@ -2993,7 +2993,7 @@ deserialize_error: } pFunc->pScript = pScript; Tcl_IncrRefCount(pScript); - pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); + pFunc->useEvalObjv = safeToUseEvalObjv(pScript); pFunc->eType = eType; rc = sqlite3_create_function(pDb->db, zName, nArg, flags, pFunc, tclSqlFunc, 0, 0); @@ -4021,7 +4021,9 @@ EXTERN int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; } EXTERN int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;} -/* Also variants with a lowercase "s" */ +/* Also variants with a lowercase "s". I'm told that these are +** deprecated in Tcl9, but they continue to be included for backwards +** compatibility. */ EXTERN int sqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);} EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);} diff --git a/src/treeview.c b/src/treeview.c index 2cfcfb69b..832965924 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -978,21 +978,7 @@ void sqlite3TreeViewBareIdList( if( zName==0 ) zName = "(null)"; sqlite3TreeViewPush(&pView, moreToFollow); sqlite3TreeViewLine(pView, 0); - if( pList->eU4==EU4_NONE ){ - fprintf(stdout, "%s\n", zName); - }else if( pList->eU4==EU4_IDX ){ - fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx); - }else{ - assert( pList->eU4==EU4_EXPR ); - if( pList->a[i].u4.pExpr==0 ){ - fprintf(stdout, "%s (pExpr=NULL)\n", zName); - }else{ - fprintf(stdout, "%s\n", zName); - sqlite3TreeViewPush(&pView, i<pList->nId-1); - sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0); - sqlite3TreeViewPop(&pView); - } - } + fprintf(stdout, "%s\n", zName); sqlite3TreeViewPop(&pView); } } diff --git a/src/vdbe.h b/src/vdbe.h index 71aae29a0..476f1b4ea 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -40,6 +40,7 @@ typedef struct SubrtnSig SubrtnSig; */ struct SubrtnSig { int selId; /* SELECT-id for the SELECT statement on the RHS */ + u8 bComplete; /* True if fully coded and available for reusable */ char *zAff; /* Affinity of the overall IN expression */ int iTable; /* Ephemeral table generated by the subroutine */ int iAddr; /* Subroutine entry address */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 113b8a9c0..aab7ac8a3 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -2177,6 +2177,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p; Mem *pMem; int rc = SQLITE_OK; + int iStore = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( db==0 || ppValue==0 ){ @@ -2191,9 +2192,11 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_old_out; } if( p->pPk ){ - iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx); + iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); + }else{ + iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } - if( iIdx>=p->pCsr->nField || iIdx<0 ){ + if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_old_out; } @@ -2224,8 +2227,8 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ p->aRecord = aRec; } - pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; - if( iIdx>=p->pUnpacked->nField ){ + pMem = *ppValue = &p->pUnpacked->aMem[iStore]; + if( iStore>=p->pUnpacked->nField ){ /* This occurs when the table has been extended using ALTER TABLE ** ADD COLUMN. The value to return is the default value of the column. */ Column *pCol = &p->pTab->aCol[iIdx]; @@ -2329,6 +2332,7 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p; int rc = SQLITE_OK; Mem *pMem; + int iStore = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( db==0 || ppValue==0 ){ @@ -2341,9 +2345,12 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_new_out; } if( p->pPk && p->op!=SQLITE_UPDATE ){ - iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx); + iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); + }else{ + iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } - if( iIdx>=p->pCsr->nField || iIdx<0 ){ + + if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_new_out; } @@ -2363,14 +2370,14 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ } p->pNewUnpacked = pUnpack; } - pMem = &pUnpack->aMem[iIdx]; + pMem = &pUnpack->aMem[iStore]; if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); - }else if( iIdx>=pUnpack->nField ){ + }else if( iStore>=pUnpack->nField ){ pMem = (sqlite3_value *)columnNullValue(); } }else{ - /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required + /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required ** value. Make a copy of the cell contents and return a pointer to it. ** It is not safe to return a pointer to the memory cell itself as the ** caller may modify the value text encoding. @@ -2383,13 +2390,13 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ goto preupdate_new_out; } } - assert( iIdx>=0 && iIdx<p->pCsr->nField ); - pMem = &p->aNew[iIdx]; + assert( iStore>=0 && iStore<p->pCsr->nField ); + pMem = &p->aNew[iStore]; if( pMem->flags==0 ){ if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); }else{ - rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]); if( rc!=SQLITE_OK ) goto preupdate_new_out; } } diff --git a/src/where.c b/src/where.c index 0b8e5acea..5cb52b8ad 100644 --- a/src/where.c +++ b/src/where.c @@ -2431,8 +2431,9 @@ void sqlite3WhereClausePrint(WhereClause *pWC){ ** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31 */ void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ + WhereInfo *pWInfo; if( pWC ){ - WhereInfo *pWInfo = pWC->pWInfo; + pWInfo = pWC->pWInfo; int nb = 1+(pWInfo->pTabList->nSrc+3)/4; SrcItem *pItem = pWInfo->pTabList->a + p->iTab; Table *pTab = pItem->pSTab; @@ -2442,6 +2443,7 @@ void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); }else{ + pWInfo = 0; sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d", p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab); } @@ -2473,7 +2475,12 @@ void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ }else{ sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm); } - sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); + if( pWInfo && pWInfo->bStarUsed && p->rStarDelta!=0 ){ + sqlite3DebugPrintf(" cost %d,%d,%d delta=%d\n", + p->rSetup, p->rRun, p->nOut, p->rStarDelta); + }else{ + sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); + } if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){ int i; for(i=0; i<p->nLTerm; i++){ @@ -5441,77 +5448,179 @@ static LogEst whereSortingCost( ** 18 for star queries ** 12 otherwise ** -** For the purposes of SQLite, a star-query is defined as a query -** with a large central table that is joined (using an INNER JOIN, -** not a LEFT JOIN) against four or more smaller tables. The central -** table is called the "fact" table. The smaller tables that get -** joined are "dimension tables". +** For the purposes of this heuristic, a star-query is defined as a query +** with a large central table that is joined using an INNER JOIN, +** not CROSS or OUTER JOINs, against four or more smaller tables. +** The central table is called the "fact" table. The smaller tables +** that get joined are "dimension tables". Also, any table that is +** self-joined cannot be a dimension table; we assume that dimension +** tables may only be joined against fact tables. ** ** SIDE EFFECT: (and really the whole point of this subroutine) ** -** If pWInfo describes a star-query, then the cost on WhereLoops for the -** fact table is reduced. This heuristic helps keep fact tables in -** outer loops. Without this heuristic, paths with fact tables in outer -** loops tend to get pruned by the mxChoice limit on the number of paths, -** resulting in poor query plans. The total amount of heuristic cost -** adjustment is stored in pWInfo->nOutStarDelta and the cost adjustment -** for each WhereLoop is stored in its rStarDelta field. +** If pWInfo describes a star-query, then the cost for SCANs of dimension +** WhereLoops is increased to be slightly larger than the cost of a SCAN +** in the fact table. Only SCAN costs are increased. SEARCH costs are +** unchanged. This heuristic helps keep fact tables in outer loops. Without +** this heuristic, paths with fact tables in outer loops tend to get pruned +** by the mxChoice limit on the number of paths, resulting in poor query +** plans. See the starschema1.test test module for examples of queries +** that need this heuristic to find good query plans. +** +** This heuristic can be completely disabled, so that no query is +** considered a star-query, using SQLITE_TESTCTRL_OPTIMIZATION to +** disable the SQLITE_StarQuery optimization. In the CLI, the command +** to do that is: ".testctrl opt -starquery". +** +** HISTORICAL NOTES: +** +** This optimization was first added on 2024-05-09 by check-in 38db9b5c83d. +** The original optimization reduced the cost and output size estimate for +** fact tables to help them move to outer loops. But months later (as people +** started upgrading) performance regression reports started caming in, +** including: +** +** forum post b18ef983e68d06d1 (2024-12-21) +** forum post 0025389d0860af82 (2025-01-14) +** forum post d87570a145599033 (2025-01-17) +** +** To address these, the criteria for a star-query was tightened to exclude +** cases where the fact and dimensions are separated by an outer join, and +** the affect of star-schema detection was changed to increase the rRun cost +** on just full table scans of dimension tables, rather than reducing costs +** in the all access methods of the fact table. */ -static int computeMxChoice(WhereInfo *pWInfo, LogEst nRowEst){ +static int computeMxChoice(WhereInfo *pWInfo){ int nLoop = pWInfo->nLevel; /* Number of terms in the join */ - if( nRowEst==0 - && nLoop>=5 + WhereLoop *pWLoop; /* For looping over WhereLoops */ + +#ifdef SQLITE_DEBUG + /* The star-query detection code below makes use of the following + ** properties of the WhereLoop list, so verify them before + ** continuing: + ** (1) .maskSelf is the bitmask corresponding to .iTab + ** (2) The WhereLoop list is in ascending .iTab order + */ + for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ + assert( pWLoop->maskSelf==MASKBIT(pWLoop->iTab) ); + assert( pWLoop->pNextLoop==0 || pWLoop->iTab<=pWLoop->pNextLoop->iTab ); + } +#endif /* SQLITE_DEBUG */ + + if( nLoop>=5 + && !pWInfo->bStarDone && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery) ){ - /* Check to see if we are dealing with a star schema and if so, reduce - ** the cost of fact tables relative to dimension tables, as a heuristic - ** to help keep the fact tables in outer loops. + SrcItem *aFromTabs; /* All terms of the FROM clause */ + int iFromIdx; /* Term of FROM clause is the candidate fact-table */ + Bitmask m; /* Bitmask for candidate fact-table */ + Bitmask mSelfJoin = 0; /* Tables that cannot be dimension tables */ + WhereLoop *pStart; /* Where to start searching for dimension-tables */ + + pWInfo->bStarDone = 1; /* Only do this computation once */ + + /* Look for fact tables with four or more dimensions where the + ** dimension tables are not separately from the fact tables by an outer + ** or cross join. Adjust cost weights if found. */ - int iLoop; /* Counter over join terms */ - Bitmask m; /* Bitmask for current loop */ - assert( pWInfo->nOutStarDelta==0 ); - for(iLoop=0, m=1; iLoop<nLoop; iLoop++, m<<=1){ - WhereLoop *pWLoop; /* For looping over WhereLoops */ + assert( !pWInfo->bStarUsed ); + aFromTabs = pWInfo->pTabList->a; + pStart = pWInfo->pLoops; + for(iFromIdx=0, m=1; iFromIdx<nLoop; iFromIdx++, m<<=1){ int nDep = 0; /* Number of dimension tables */ - LogEst rDelta; /* Heuristic cost adjustment */ + LogEst mxRun; /* Maximum SCAN cost of a fact table */ Bitmask mSeen = 0; /* Mask of dimension tables */ - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iLoop */ + SrcItem *pFactTab; /* The candidate fact table */ + + pFactTab = aFromTabs + iFromIdx; + if( (pFactTab->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ + /* If the candidate fact-table is the right table of an outer join + ** restrict the search for dimension-tables to be tables to the right + ** of the fact-table. */ + if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */ + while( pStart && pStart->iTab<=iFromIdx ){ + pStart = pStart->pNextLoop; + } + } + for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ + if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ + /* Fact-tables and dimension-tables cannot be separated by an + ** outer join (at least for the definition of fact- and dimension- + ** used by this heuristic). */ + break; + } + if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */ && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */ - && (pWInfo->pTabList->a[pWLoop->iTab].fg.jointype & JT_LEFT)==0 - /* ^- pWInfo isn't a LEFT JOIN */ + && (pWLoop->maskSelf & mSelfJoin)==0 /* Not a self-join */ ){ - nDep++; - mSeen |= pWLoop->maskSelf; + if( aFromTabs[pWLoop->iTab].pSTab==pFactTab->pSTab ){ + mSelfJoin |= m; + }else{ + nDep++; + mSeen |= pWLoop->maskSelf; + } } } if( nDep<=3 ) continue; - rDelta = 15*(nDep-3); -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - SrcItem *pItem = pWInfo->pTabList->a + iLoop; - sqlite3DebugPrintf( - "Fact-table %s(%d): %d dimensions, cost reduced %d\n", - pItem->zAlias ? pItem->zAlias : pItem->pSTab->zName, iLoop, - nDep, rDelta); - } -#endif - if( pWInfo->nOutStarDelta==0 ){ + + /* If we reach this point, it means that pFactTab is a fact table + ** with four or more dimensions connected by inner joins. Proceed + ** to make cost adjustments. */ + +#ifdef WHERETRACE_ENABLED + /* Make sure rStarDelta values are initialized */ + if( !pWInfo->bStarUsed ){ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ pWLoop->rStarDelta = 0; } } - pWInfo->nOutStarDelta += rDelta; +#endif + pWInfo->bStarUsed = 1; + + /* Compute the maximum cost of any WhereLoop for the + ** fact table plus one epsilon */ + mxRun = LOGEST_MIN; + for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ + if( pWLoop->iTab<iFromIdx ) continue; + if( pWLoop->iTab>iFromIdx ) break; + if( pWLoop->rRun>mxRun ) mxRun = pWLoop->rRun; + } + if( ALWAYS(mxRun<LOGEST_MAX) ) mxRun++; + + /* Increase the cost of table scans for dimension tables to be + ** slightly more than the maximum cost of the fact table */ + for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ + if( (pWLoop->maskSelf & mSeen)==0 ) continue; + if( pWLoop->nLTerm ) continue; + if( pWLoop->rRun<mxRun ){ +#ifdef WHERETRACE_ENABLED /* 0x80000 */ + if( sqlite3WhereTrace & 0x80000 ){ + SrcItem *pDim = aFromTabs + pWLoop->iTab; + sqlite3DebugPrintf( + "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n", + pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab, + pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, + iFromIdx, mxRun + ); + } + pWLoop->rStarDelta = mxRun - pWLoop->rRun; +#endif /* WHERETRACE_ENABLED */ + pWLoop->rRun = mxRun; + } + } + } +#ifdef WHERETRACE_ENABLED /* 0x80000 */ + if( (sqlite3WhereTrace & 0x80000)!=0 && pWInfo->bStarUsed ){ + sqlite3DebugPrintf("WhereLoops changed by star-query heuristic:\n"); for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( pWLoop->maskSelf==m ){ - pWLoop->rRun -= rDelta; - pWLoop->nOut -= rDelta; - pWLoop->rStarDelta = rDelta; + if( pWLoop->rStarDelta ){ + sqlite3WhereLoopPrint(pWLoop, &pWInfo->sWC); } } - } + } +#endif } - return pWInfo->nOutStarDelta>0 ? 18 : 12; + return pWInfo->bStarUsed ? 18 : 12; } /* @@ -5586,8 +5695,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ mxChoice = 1; }else if( nLoop==2 ){ mxChoice = 5; + }else if( pParse->nErr ){ + mxChoice = 1; }else{ - mxChoice = computeMxChoice(pWInfo, nRowEst); + mxChoice = computeMxChoice(pWInfo); } assert( nLoop<=pWInfo->pTabList->nSrc ); @@ -5838,8 +5949,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( sqlite3WhereTrace & 0x02 ){ LogEst rMin, rFloor = 0; int nDone = 0; + int nProgress; sqlite3DebugPrintf("---- after round %d ----\n", iLoop); - while( nDone<nTo ){ + do{ + nProgress = 0; rMin = 0x7fff; for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){ if( pTo->rCost>rFloor && pTo->rCost<rMin ) rMin = pTo->rCost; @@ -5855,10 +5968,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ sqlite3DebugPrintf("\n"); } nDone++; + nProgress++; } } rFloor = rMin; - } + }while( nDone<nTo && nProgress>0 ); } #endif @@ -5952,7 +6066,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } } - pWInfo->nRowOut = pFrom->nRow + pWInfo->nOutStarDelta; + pWInfo->nRowOut = pFrom->nRow; +#ifdef WHERETRACE_ENABLED + pWInfo->rTotalCost = pFrom->rCost; +#endif /* Free temporary memory and return success */ sqlite3StackFreeNN(pParse->db, pSpace); @@ -6350,7 +6467,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( } } nSearch += pLoop->nOut; - if( pWInfo->nOutStarDelta ) nSearch += pLoop->rStarDelta; } } @@ -6833,7 +6949,8 @@ WhereInfo *sqlite3WhereBegin( assert( db->mallocFailed==0 ); #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace ){ - sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); + sqlite3DebugPrintf("---- Solution cost=%d, nRow=%d", + pWInfo->rTotalCost, pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); } diff --git a/src/whereInt.h b/src/whereInt.h index f44c04041..8ba8a7072 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -162,8 +162,10 @@ struct WhereLoop { /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) u16 nLSlot; /* Number of slots allocated for aLTerm[] */ +#ifdef WHERETRACE_ENABLED LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not - ** initialized unless pWInfo->nOutStarDelta>0 */ + ** initialized unless pWInfo->bStarUsed */ +#endif WhereTerm **aLTerm; /* WhereTerms used */ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */ @@ -485,9 +487,13 @@ struct WhereInfo { unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */ unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */ unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */ - unsigned sorted :1; /* True if really sorted (not just grouped) */ - LogEst nOutStarDelta; /* Artifical nOut reduction for star-query */ + unsigned sorted :1; /* True if really sorted (not just grouped) */ + unsigned bStarDone :1; /* True if check for star-query is complete */ + unsigned bStarUsed :1; /* True if star-query heuristic is used */ LogEst nRowOut; /* Estimated number of output rows */ +#ifdef WHERETRACE_ENABLED + LogEst rTotalCost; /* Total cost of the solution */ +#endif int iTop; /* The very beginning of the WHERE loop */ int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ diff --git a/test/capi3.test b/test/capi3.test index e65f90e3a..6319d8284 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -689,7 +689,9 @@ do_test capi3-6.3 { sqlite3_finalize $STMT } {SQLITE_OK} -if {[clang_sanitize_address]==0} { +if {0 && [clang_sanitize_address]==0} { + # This use-after-free occasionally causes segfaults during ordinary + # builds. Let's just disable it completely. do_test capi3-6.4-misuse { db cache flush sqlite3_close $DB diff --git a/test/in7.test b/test/in7.test index 4dc0821d1..763396140 100644 --- a/test/in7.test +++ b/test/in7.test @@ -219,4 +219,33 @@ do_execsql_test 3.8 { SELECT t1.a, t2.b FROM t1, t2 WHERE (t1.a, t2.b) IN ((1, 2)); } {1 2} +# 2025-01-30 Inifinite loop in byte-code discovered by dbsqlfuzz +# having to do with SubrtnSig logic. The code was using a Subroutine +# from within itself resulting in infinite recursion. +# +# This test will spin forever if the bug has not been fixed, or if +# it reappears. +# +reset_db +do_execsql_test 4.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + INSERT INTO t1 VALUES(1,x'1111'); + CREATE TABLE t2(c); + CREATE TABLE t3(d); + CREATE TRIGGER t1tr UPDATE ON t1 BEGIN + UPDATE t1 SET b=x'2222' FROM t2; + UPDATE t1 + SET b = (SELECT a IN (SELECT a + FROM t1 + WHERE (b,a) IN (SELECT rowid, d + FROM t3 + ) + ) + FROM t1 NATURAL RIGHT JOIN t1 + ); + END; + UPDATE t1 SET b=x'3333'; + SELECT quote(b) FROM t1; +} {X'3333'} + finish_test diff --git a/test/speedtest.md b/test/speedtest.md index 645742d75..135e562ae 100644 --- a/test/speedtest.md +++ b/test/speedtest.md @@ -9,7 +9,7 @@ You will need: * tclsh * A script or program named "open" that brings up *.txt files in an editor for viewing. (Macs provide this by default. You'll need to - come up with your own on Linxu and Windows.) + come up with your own on Linux and Windows.) * An SQLite source tree The procedure described in this document is not the only way to make diff --git a/test/starschema1.test b/test/starschema1.test index af8168b51..bb7d8aa79 100644 --- a/test/starschema1.test +++ b/test/starschema1.test @@ -10,7 +10,7 @@ #*********************************************************************** # # Test cases for the ability of the query planner to cope with -# star-schema queries on databases with goofy indexes. +# star-schema queries. # set testdir [file dirname $argv0] diff --git a/tool/buildtclext.tcl b/tool/buildtclext.tcl index 26f9b6dcc..905087d1d 100644 --- a/tool/buildtclext.tcl +++ b/tool/buildtclext.tcl @@ -289,7 +289,7 @@ if {$build} { # Tcl package index file, version ??? # package ifneeded sqlite3 $VERSION \\ - [list load [file join \$dir $OUT] sqlite3] + [list load [file join \$dir $OUT] Sqlite3] }] close $fd diff --git a/tool/mkautoconfamal.sh b/tool/mkautoconfamal.sh index f3ce9dd5b..c26ca47bf 100644 --- a/tool/mkautoconfamal.sh +++ b/tool/mkautoconfamal.sh @@ -13,7 +13,7 @@ # -# Bail out of the script if any command returns a non-zero exit +# Bail out of the script if any command returns a non-zero exit # status. Or if the script tries to use an unset variable. These # may fail for old /bin/sh interpreters. # @@ -22,8 +22,8 @@ set -u TMPSPACE=./mkpkg_tmp_dir VERSION=`cat $TOP/VERSION` -HASH=`sed 's/^\(..........\).*/\1/' $TOP/manifest.uuid` -DATETIME=`grep '^D' $TOP/manifest | sed -e 's/[^0-9]//g' -e 's/\(............\).*/\1/'` +HASH=`cut -c1-10 $TOP/manifest.uuid` +DATETIME=`grep '^D' $TOP/manifest | tr -c -d '[0-9]' | cut -c1-12` # Verify that the version number in the TEA autoconf file is correct. # Fail with an error if not. @@ -34,12 +34,12 @@ else echo "TEA version number mismatch. Should be $VERSION"; exit 1 fi # If this script is given an argument of --snapshot, then generate a -# snapshot tarball named for the current checkout SHA1 hash, rather than +# snapshot tarball named for the current checkout SHA hash, rather than # the version number. # if test "$#" -ge 1 -a x$1 != x--snapshot then - # Set global variable $ARTIFACT to the "3xxyyzz" string incorporated + # Set global variable $ARTIFACT to the "3xxyyzz" string incorporated # into artifact filenames. And $VERSION2 to the "3.x.y[.z]" form. xx=`echo $VERSION|sed 's/3\.\([0-9]*\)\..*/\1/'` yy=`echo $VERSION|sed 's/3\.[^.]*\.\([0-9]*\).*/\1/'` @@ -54,6 +54,8 @@ fi rm -rf $TMPSPACE cp -R $TOP/autoconf $TMPSPACE +cp -R $TOP/autosetup $TMPSPACE +cp -p $TOP/configure $TMPSPACE cp sqlite3.c $TMPSPACE cp sqlite3.h $TMPSPACE cp sqlite3ext.h $TMPSPACE @@ -63,32 +65,33 @@ cp $TOP/sqlite3.pc.in $TMPSPACE cp shell.c $TMPSPACE cp $TOP/src/sqlite3.rc $TMPSPACE cp $TOP/tool/Replace.cs $TMPSPACE +cp $TOP/VERSION $TMPSPACE +cp $TOP/main.mk $TMPSPACE -cat $TMPSPACE/configure.ac | -sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp -mv $TMPSPACE/tmp $TMPSPACE/configure.ac +cd $TMPSPACE -cat $TMPSPACE/sqlite3.pc.in | -sed "s/^Libs.private:.*/Libs.private: @LIBS@/" > $TMPSPACE/tmp -mv $TMPSPACE/tmp $TMPSPACE/sqlite3.pc.in +# Clean up emacs-generated backup files from the target +rm -f ./autosetup/*~ +rm -f ./*~ -cd $TMPSPACE -autoreconf -i -#libtoolize -#aclocal -#autoconf -#automake --add-missing +#if true; then + # Clean up *~ files (emacs-generated backups). + # This bit is only for use during development of + # the autoconf bundle. +# find . -name '*~' -exec rm \{} \; +#fi mkdir -p tea/generic -echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c -echo "# include <sqlite3.h>" >> tea/generic/tclsqlite3.c -echo "#else" >> tea/generic/tclsqlite3.c -echo "#include \"sqlite3.c\"" >> tea/generic/tclsqlite3.c -echo "#endif" >> tea/generic/tclsqlite3.c +cat <<EOF > tea/generic/tclsqlite3.c +#ifdef USE_SYSTEM_SQLITE +# include <sqlite3.h> +#else +# include "sqlite3.c" +#endif +EOF cat $TOP/src/tclsqlite.c >> tea/generic/tclsqlite3.c -cat tea/configure.ac | - sed "s/AC_INIT(\[sqlite\], .*)/AC_INIT([sqlite], [$VERSION])/" > tmp +sed "s/AC_INIT(\[sqlite\], .*)/AC_INIT([sqlite], [$VERSION])/" tea/configure.ac > tmp mv tmp tea/configure.ac cd tea @@ -97,9 +100,9 @@ rm -rf autom4te.cache cd ../ ./configure && make dist -tar -xzf sqlite-$VERSION.tar.gz +tar xzf sqlite-$VERSION.tar.gz mv sqlite-$VERSION $TARBALLNAME -tar -czf $TARBALLNAME.tar.gz $TARBALLNAME +tar czf $TARBALLNAME.tar.gz $TARBALLNAME mv $TARBALLNAME.tar.gz .. cd .. ls -l $TARBALLNAME.tar.gz |