Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8f850e7bd | |||
| 0a4af54a7e | |||
| 6cc36dfb16 | |||
| b2972b8c6f | |||
| 8f79342f6a | |||
| dadd0b4085 | |||
| 9dfc2c61ec | |||
| 3ea05b5b4f | |||
| a0d35d44e4 | |||
| 93df8109fc | |||
| 3efac4aa78 | |||
| 3bdebaeabb | |||
| b85b7f257d | |||
| 79d0aa6f56 | |||
| 63f4926524 | |||
| e108f97256 | |||
| 00bc96c05c | |||
| f858182689 | |||
| 3e06f2d79b | |||
| 5b0b8653b6 | |||
| 66172ceb89 | |||
| 9d90a3af2f | |||
| 03c65171b8 | |||
| 297a95bad5 | |||
| f62d053b49 | |||
| 7df570421c | |||
| 84b0f221f4 | |||
| 7fd936e5ed | |||
| 189a4a0bbb | |||
| ede1690cce | |||
| 7a7002143c | |||
| d8452a9517 | |||
| 4192a95d23 | |||
| 6b3010a134 | |||
| 038424727b | |||
| 65552a7ae1 | |||
| 01bfe2a531 | |||
| 3c013479c3 |
@@ -121,6 +121,10 @@ LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
|
||||
@@ -2846,4 +2846,5 @@ clean:
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
del /Q lsm.h lsm1.c 2>NUL
|
||||
del /q src-verify.exe 2>NUL
|
||||
del /q jimsh.exe jimsh0.exe 2>NUL
|
||||
# <</mark>>
|
||||
|
||||
@@ -230,7 +230,7 @@ proj-if-opt-truthy dev {
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env].
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
}
|
||||
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
@@ -275,6 +275,5 @@ sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
sqlite-handle-emsdk
|
||||
sqlite-process-dot-in-files
|
||||
sqlite-post-config-validation
|
||||
sqlite-common-late-stage-config
|
||||
sqlite-dump-defines
|
||||
|
||||
+43
-17
@@ -1,8 +1,17 @@
|
||||
########################################################################
|
||||
# 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
|
||||
# documentation. For the full docs, see /main.mk in the canonical
|
||||
# source tree.
|
||||
#
|
||||
# Maintenance reminders:
|
||||
#
|
||||
# - To keep this working with an out-of-tree build, be sure to prefix
|
||||
# input file names with $(TOP)/ where appropriate (which is most
|
||||
# places).
|
||||
#
|
||||
# - The original/canonical recipes can be found in /main.mk in the
|
||||
# canonical source tree.
|
||||
all:
|
||||
|
||||
TOP = @abs_top_srcdir@
|
||||
@@ -60,7 +69,6 @@ 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.
|
||||
@@ -78,7 +86,8 @@ install-dir.all = $(install-dir.bin) $(install-dir.include) \
|
||||
$(install-dir.lib) $(install-dir.man1) \
|
||||
$(install-dir.pkgconfig)
|
||||
$(install-dir.all):
|
||||
$(INSTALL) -d "$@"
|
||||
if [ ! -d "$@" ]; then $(INSTALL) -d "$@"; fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
|
||||
|
||||
#
|
||||
@@ -115,23 +124,30 @@ SHELL_OPT ?= @OPT_SHELL@
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
|
||||
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)
|
||||
sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
|
||||
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
|
||||
|
||||
libsqlite3.LIB = libsqlite3$(T.lib)
|
||||
libsqlite3.SO = libsqlite3$(T.dll)
|
||||
|
||||
$(libsqlite3.SO): sqlite3.o
|
||||
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.libsqlite3.soname)
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
all: $(libsqlite3.SO)
|
||||
|
||||
$(libsqlite3.LIB): sqlite3.o
|
||||
@@ -140,8 +156,16 @@ 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 $$?; \
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
if [ x.dylib = x$(T.dll) ]; then \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
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 $$?; \
|
||||
@@ -157,7 +181,9 @@ install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
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
|
||||
fi; \
|
||||
fi
|
||||
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_LIB_SHARED)
|
||||
install: install-so
|
||||
@@ -169,9 +195,9 @@ install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
|
||||
sqlite3$(T.exe): shell.c sqlite3.c
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(TOP)/sqlite3.c
|
||||
$(CC) -o $@ \
|
||||
shell.c sqlite3.c \
|
||||
$(TOP)/shell.c $(TOP)/sqlite3.c \
|
||||
-I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \
|
||||
$(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.readline)
|
||||
@@ -181,21 +207,21 @@ 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-headers: $(TOP)/sqlite3.h $(install-dir.include)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.h $(TOP)/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-man1: $(TOP)/sqlite3.1 $(install-dir.man1)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.1 "$(install-dir.man1)"
|
||||
install: install-man1
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(T.exe)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
|
||||
|
||||
distclean: clean
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc
|
||||
|
||||
+1
-2
@@ -94,5 +94,4 @@ 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
|
||||
sqlite-common-late-stage-config
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.49.0])
|
||||
AC_INIT([sqlite],[3.50.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
+15
-17
@@ -75,9 +75,6 @@ extern "C" {
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
#define HAVE_DLOPEN
|
||||
void *dlopen(const char *path, int mode);
|
||||
int dlclose(void *handle);
|
||||
@@ -1201,6 +1198,11 @@ int Jim_OpenForRead(const char *filename);
|
||||
#define Jim_FileStat _fstat64
|
||||
#define Jim_Lseek _lseeki64
|
||||
#define O_TEXT _O_TEXT
|
||||
#define O_BINARY _O_BINARY
|
||||
#define Jim_SetMode _setmode
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if defined(HAVE_STAT64)
|
||||
@@ -2941,22 +2943,22 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
|
||||
static int aio_cmd_translation(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
enum {OPT_BINARY, OPT_TEXT};
|
||||
enum {OPT_BINARY, OPT_TEXT};
|
||||
static const char * const options[] = {
|
||||
"binary",
|
||||
"text",
|
||||
NULL
|
||||
};
|
||||
int opt;
|
||||
int opt;
|
||||
|
||||
if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
#if defined(_setmode) && defined(O_BINARY)
|
||||
else {
|
||||
AioFile *af = Jim_CmdPrivData(interp);
|
||||
_setmode(af->fh, opt == OPT_BINARY ? O_BINARY : O_TEXT);
|
||||
}
|
||||
if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
#if defined(Jim_SetMode)
|
||||
else {
|
||||
AioFile *af = Jim_CmdPrivData(interp);
|
||||
Jim_SetMode(af->fd, opt == OPT_BINARY ? O_BINARY : O_TEXT);
|
||||
}
|
||||
#endif
|
||||
return JIM_OK;
|
||||
}
|
||||
@@ -24374,10 +24376,6 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern int Jim_initjimshInit(Jim_Interp *interp);
|
||||
|
||||
|
||||
+19
-14
@@ -114,11 +114,13 @@ proc proj-bold {str} {
|
||||
#
|
||||
# If the -notice flag it used then it emits using [user-notice], which
|
||||
# means its rendering will (A) go to stderr and (B) be delayed until
|
||||
# the next time autosetup goes to output a message. If -notice
|
||||
# is not used, it will send the message to stdout without delay.
|
||||
# the next time autosetup goes to output a message.
|
||||
#
|
||||
# If the -error flag is provided then it renders the message
|
||||
# immediately to stderr and then exits.
|
||||
#
|
||||
# If neither -notice nor -error are used, the message will be sent to
|
||||
# stdout without delay.
|
||||
proc proj-indented-notice {args} {
|
||||
set fErr ""
|
||||
set outFunc "puts"
|
||||
@@ -126,6 +128,7 @@ proc proj-indented-notice {args} {
|
||||
switch -exact -- [lindex $args 0] {
|
||||
-error {
|
||||
set args [lassign $args fErr]
|
||||
set outFunc "user-notice"
|
||||
}
|
||||
-notice {
|
||||
set args [lassign $args -]
|
||||
@@ -181,8 +184,8 @@ proc proj-lshift_ {listVar {count 1}} {
|
||||
|
||||
########################################################################
|
||||
# Expects to receive string input, which it splits on newlines, strips
|
||||
# out any lines which begin with an number of whitespace followed by a
|
||||
# '#', and returns a value containing the [append]ed results of each
|
||||
# out any lines which begin with any number of whitespace followed by
|
||||
# a '#', and returns a value containing the [append]ed results of each
|
||||
# remaining line with a \n between each.
|
||||
proc proj-strip-hash-comments {val} {
|
||||
set x {}
|
||||
@@ -200,7 +203,7 @@ proc proj-strip-hash-comments {val} {
|
||||
# A proxy for cc-check-function-in-lib which does not make any global
|
||||
# changes to the LIBS define. Returns the result of
|
||||
# cc-check-function-in-lib (i.e. true or false). The resulting linker
|
||||
# flags are stored in ${lib_${function}}.
|
||||
# flags are stored in the [define] named lib_${function}.
|
||||
proc proj-check-function-in-lib {function libs {otherlibs {}}} {
|
||||
set found 0
|
||||
define-push {LIBS} {
|
||||
@@ -760,7 +763,7 @@ proc proj-exe-extension {} {
|
||||
# Trivia: for .dylib files, the linker needs the -dynamiclib flag
|
||||
# instead of -shared.
|
||||
proc proj-dll-extension {} {
|
||||
proc inner {key} {
|
||||
set inner {{key} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*apple* {
|
||||
return ".dylib"
|
||||
@@ -772,9 +775,9 @@ proc proj-dll-extension {} {
|
||||
return ".so"
|
||||
}
|
||||
}
|
||||
}
|
||||
define BUILD_DLLEXT [inner build]
|
||||
define TARGET_DLLEXT [inner host]
|
||||
}}
|
||||
define BUILD_DLLEXT [apply $inner build]
|
||||
define TARGET_DLLEXT [apply $inner host]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
@@ -784,18 +787,20 @@ proc proj-dll-extension {} {
|
||||
# BUILD_LIBEXT and TARGET_LIBEXT to the conventional static library
|
||||
# extension for the being-built-on resp. the target platform.
|
||||
proc proj-lib-extension {} {
|
||||
proc inner {key} {
|
||||
set inner {{key} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
return ".lib"
|
||||
return ".a"
|
||||
# ^^^ this was ".lib" until 2025-02-07. See
|
||||
# https://sqlite.org/forum/forumpost/02db2d4240
|
||||
}
|
||||
default {
|
||||
return ".a"
|
||||
}
|
||||
}
|
||||
}
|
||||
define BUILD_LIBEXT [inner build]
|
||||
define TARGET_LIBEXT [inner host]
|
||||
}}
|
||||
define BUILD_LIBEXT [apply $inner build]
|
||||
define TARGET_LIBEXT [apply $inner host]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
|
||||
+137
-14
@@ -43,7 +43,10 @@ set sqliteConfig(is-cross-compiling) [proj-is-cross-compiling]
|
||||
|
||||
########################################################################
|
||||
# Runs some common initialization which must happen immediately after
|
||||
# autosetup's [options] function is called.
|
||||
# autosetup's [options] function is called. This is also a convenient
|
||||
# place to put some generic pieces common to both the canonical
|
||||
# top-level build and the "autoconf" build, but it's not intended to
|
||||
# be a catch-all dumping ground for such.
|
||||
proc sqlite-post-options-init {} {
|
||||
#
|
||||
# Carry values from hidden --flag aliases over to their canonical
|
||||
@@ -227,23 +230,47 @@ proc sqlite-setup-default-cflags {} {
|
||||
# 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
|
||||
# Copy all CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
|
||||
# -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
|
||||
# from the legacy build and was missing the 3.48.0 release (the
|
||||
# initial Autosetup port).
|
||||
# https://sqlite.org/forum/forumpost/9801e54665afd728
|
||||
#
|
||||
# Handling of CPPFLAGS, as well as removing ENABLE/OMIT from
|
||||
# CFLAGS/CPPFLAGS, was missing in the 3.49.0 release as well.
|
||||
#
|
||||
# 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 ""] {
|
||||
# CFLAGS/CPPFLAGS-specified feature flags, all bets are off. There
|
||||
# are no guarantees about which one will take precedence.
|
||||
foreach flagDef {CFLAGS CPPFLAGS} {
|
||||
set tmp ""
|
||||
foreach cf [get-define $flagDef ""] {
|
||||
switch -glob -- $cf {
|
||||
-DSQLITE_OMIT* -
|
||||
-DSQLITE_ENABLE* {
|
||||
sqlite-add-feature-flag $cf
|
||||
}
|
||||
default {
|
||||
lappend tmp $cf
|
||||
}
|
||||
}
|
||||
}
|
||||
define $flagDef $tmp
|
||||
}
|
||||
|
||||
# Strip all SQLITE_ENABLE/OMIT flags from BUILD_CFLAGS,
|
||||
# for compatibility with the legacy build.
|
||||
set tmp ""
|
||||
foreach cf [get-define BUILD_CFLAGS ""] {
|
||||
switch -glob -- $cf {
|
||||
-DSQLITE_OMIT* -
|
||||
-DSQLITE_ENABLE* {
|
||||
sqlite-add-feature-flag $cf
|
||||
-DSQLITE_ENABLE* {}
|
||||
default {
|
||||
lappend tmp $cf
|
||||
}
|
||||
}
|
||||
}
|
||||
define BUILD_CFLAGS $tmp
|
||||
}
|
||||
|
||||
########################################################################
|
||||
@@ -828,20 +855,53 @@ proc sqlite-handle-icu {} {
|
||||
|
||||
|
||||
########################################################################
|
||||
# Handles the --enable-load-extension flag.
|
||||
# Handles the --enable-load-extension flag. Returns 1 if the support
|
||||
# is enabled, else 0. If support for that feature is not found, a
|
||||
# fatal error is triggered if --enable-load-extension is explicitly
|
||||
# provided, else a loud warning is instead emited. If
|
||||
# --disable-load-extension is used, no check is performed.
|
||||
#
|
||||
# Makes the following environment changes:
|
||||
#
|
||||
# - defines LDFLAGS_DLOPEN to any linker flags needed for this
|
||||
# feature. It may legally be empty on some systems where dlopen()
|
||||
# is in libc.
|
||||
#
|
||||
# - If the feature is not available, adds
|
||||
# -DSQLITE_OMIT_LOAD_EXTENSION=1 to the feature flags list.
|
||||
proc sqlite-handle-load-extension {} {
|
||||
define LDFLAGS_DLOPEN ""
|
||||
set found 0
|
||||
proj-if-opt-truthy load-extension {
|
||||
if {[proj-check-function-in-lib dlopen dl]} {
|
||||
set found [proj-check-function-in-lib dlopen dl]
|
||||
if {$found} {
|
||||
define LDFLAGS_DLOPEN [get-define lib_dlopen]
|
||||
undefine lib_dlopen
|
||||
} else {
|
||||
user-error "dlopen() not found. Use --disable-load-extension to bypass this check."
|
||||
if {[proj-opt-was-provided load-extension]} {
|
||||
# Explicit --enable-load-extension: fail if not found
|
||||
proj-indented-notice -error {
|
||||
--enable-load-extension was provided but dlopen()
|
||||
not found. Use --disable-load-extension to bypass this
|
||||
check.
|
||||
}
|
||||
} else {
|
||||
# It was implicitly enabled: warn if not found
|
||||
proj-indented-notice {
|
||||
WARNING: dlopen() not found, so loadable module support will
|
||||
be disabled. Use --disable-load-extension to bypass this
|
||||
check.
|
||||
}
|
||||
}
|
||||
}
|
||||
} {
|
||||
define LDFLAGS_DLOPEN ""
|
||||
sqlite-add-feature-flag {-DSQLITE_OMIT_LOAD_EXTENSION=1}
|
||||
msg-result "Disabling loadable extensions."
|
||||
}
|
||||
if {$found} {
|
||||
msg-result "Loadable extension support enabled."
|
||||
} else {
|
||||
msg-result "Disabling loadable extension support. Use --enable-load-extensions to enable them."
|
||||
sqlite-add-feature-flag {-DSQLITE_OMIT_LOAD_EXTENSION=1}
|
||||
}
|
||||
return $found
|
||||
}
|
||||
|
||||
########################################################################
|
||||
@@ -861,6 +921,69 @@ proc sqlite-handle-math {} {
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# If this OS looks like a Mac, checks for the Mac-specific
|
||||
# -current_version and -compatibility_version linker flags. Defines
|
||||
# LDFLAGS_MAC_CVERSION to an empty string and returns 0 if they're not
|
||||
# supported, else defines that to the linker flags and returns 1.
|
||||
#
|
||||
# We don't check this on non-Macs because this whole thing is a
|
||||
# libtool compatibility kludge to account for a version stamp which
|
||||
# libtool applied only on Mac platforms.
|
||||
#
|
||||
# Based on https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7.
|
||||
proc sqlite-check-mac-cversion {} {
|
||||
define LDFLAGS_MAC_CVERSION ""
|
||||
set rc 0
|
||||
if {[proj-looks-like-mac]} {
|
||||
cc-with {} {
|
||||
# These version numbers are historical libtool-defined values, not
|
||||
# library-defined ones
|
||||
if {[cc-check-flags "-Wl,-current_version,9.6.0"]
|
||||
&& [cc-check-flags "-Wl,-compatibility_version,9.0.0"]} {
|
||||
define LDFLAGS_MAC_CVERSION "-Wl,-compatibility_version,9.0.0 -Wl,-current_version,9.6.0"
|
||||
set rc 1
|
||||
} elseif {[cc-check-flags "-compatibility_version 9.0.0"]
|
||||
&& [cc-check-flags "-current_version 9.6.0"]} {
|
||||
define LDFLAGS_MAC_CVERSION "-compatibility_version 9.0.0 -current_version 9.6.0"
|
||||
set rc 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Define LDFLAGS_OUT_IMPLIB to either an empty string or to a
|
||||
# -Wl,... flag for the platform-specific --out-implib flag, which is
|
||||
# used for building an "import library .dll.a" file on some platforms
|
||||
# (e.g. mingw). Returns 1 if supported, else 0.
|
||||
#
|
||||
# Added in response to: https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
proc sqlite-check-out-implib {} {
|
||||
define LDFLAGS_OUT_IMPLIB ""
|
||||
set rc 0
|
||||
cc-with {} {
|
||||
set dll "libsqlite3[get-define TARGET_DLLEXT]"
|
||||
set flags "-Wl,--out-implib,${dll}.a"
|
||||
if {[cc-check-flags $flags]} {
|
||||
define LDFLAGS_OUT_IMPLIB $flags
|
||||
set rc 1
|
||||
}
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Performs late-stage config steps common to both the canonical and
|
||||
# autoconf bundle builds.
|
||||
proc sqlite-common-late-stage-config {} {
|
||||
sqlite-check-mac-cversion
|
||||
sqlite-check-out-implib
|
||||
sqlite-process-dot-in-files
|
||||
sqlite-post-config-validation
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Perform some late-stage work and generate the configure-process
|
||||
# output file(s).
|
||||
|
||||
+34
-23
@@ -165,7 +165,7 @@ dir.wasmfs := $(dir.dout)
|
||||
|
||||
MKDIR.bld := $(dir.tmp)
|
||||
$(MKDIR.bld):
|
||||
-mkdir -p $@ $(dir.dout)
|
||||
@mkdir -p $@ $(dir.dout)
|
||||
|
||||
CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
|
||||
$(dir.fiddle-debug)/* $(dir.dout)/* $(dir.tmp)/*
|
||||
@@ -424,7 +424,8 @@ define SQLITE.CALL.C-PP.FILTER
|
||||
# $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)
|
||||
$(2): $(1) $$(MAKEFILE_LIST) $$(bin.c-pp)
|
||||
@mkdir -p $$(dir $$@)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(SQLITE.CALL.C-PP.FILTER.global)
|
||||
#CLEAN_FILES += $(2)
|
||||
endef
|
||||
@@ -618,6 +619,12 @@ emcc.exportedRuntimeMethods := \
|
||||
emcc.jsflags += $(emcc.exportedRuntimeMethods)
|
||||
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
|
||||
emcc.jsflags += -sIMPORTED_MEMORY
|
||||
ifeq (,$(filter -O0,$(emcc_opt)))
|
||||
emcc.assert ?= 0
|
||||
else
|
||||
emcc.assert ?= 2
|
||||
endif
|
||||
emcc.jsflags += -sASSERTIONS=$(emcc.assert)
|
||||
emcc.jsflags += -sSTRICT_JS=0
|
||||
# STRICT_JS disabled due to:
|
||||
# https://github.com/emscripten-core/emscripten/issues/18610
|
||||
@@ -909,6 +916,31 @@ 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
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
# This block MUST come between the above definitions of
|
||||
# sqlite3-...js/mjs and the $(eval) calls below this block which use
|
||||
# SQLITE.CALL.C-PP.FILTER.
|
||||
########################################################################
|
||||
# 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
|
||||
|
||||
$(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)))
|
||||
@@ -940,27 +972,6 @@ 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.
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
point the sqlite3 JS API bits will get set up.
|
||||
*/
|
||||
Module.runSQLite3PostLoadInit = function(EmscriptenModule/*the Emscripten-style module object*/){
|
||||
/** ^^^ As don't use Module.postRun, as that runs a different time
|
||||
/** ^^^ Don't use Module.postRun, as that runs a different time
|
||||
depending on whether this file is built with emcc 3.1.x or
|
||||
4.0.x. This function name is intentionally obnoxiously verbose to
|
||||
ensure that we don't collide with current and future Emscripten
|
||||
symbol names. */
|
||||
'use strict';
|
||||
//console.warn("This is the start of the Module.postRun handler.");
|
||||
//console.warn("This is the start of Module.runSQLite3PostLoadInit()");
|
||||
/* This function will contain at least the following:
|
||||
|
||||
- post-js-header.js (this file)
|
||||
- post-js-header.js => this file
|
||||
- sqlite3-api-prologue.js => Bootstrapping bits to attach the rest to
|
||||
- common/whwasmutil.js => Replacements for much of Emscripten's glue
|
||||
- jaccwabyt/jaccwabyt.js => Jaccwabyt (C/JS struct binding)
|
||||
@@ -26,8 +26,8 @@ Module.runSQLite3PostLoadInit = function(EmscriptenModule/*the Emscripten-style
|
||||
- sqlite3-api-worker1.js => Worker-based API
|
||||
- sqlite3-vfs-helper.c-pp.js => Utilities for VFS impls
|
||||
- sqlite3-vtab-helper.c-pp.js => Utilities for virtual table impls
|
||||
- sqlite3-vfs-opfs.c-pp.js => OPFS VFS
|
||||
- sqlite3-vfs-opfs.c-pp.js => OPFS VFS
|
||||
- sqlite3-vfs-opfs-sahpool.c-pp.js => OPFS SAHPool VFS
|
||||
- sqlite3-api-cleanup.js => final API cleanup
|
||||
- post-js-footer.js => closes this postRun() function
|
||||
- post-js-footer.js => closes this function
|
||||
*/
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
This file is intended to be combined at build-time with other
|
||||
related code, most notably a header and footer which wraps this
|
||||
whole file into an Emscripten Module.postRun()-style handler. The
|
||||
sqlite3 JS API has no hard requirements on Emscripten and does not
|
||||
expose any Emscripten APIs to clients. It is structured such that
|
||||
its build can be tweaked to include it in arbitrary WASM
|
||||
environments which can supply the necessary underlying features
|
||||
(e.g. a POSIX file I/O layer).
|
||||
whole file into a single callback which can be run after Emscripten
|
||||
loads the corresponding WASM module. The sqlite3 JS API has no hard
|
||||
requirements on Emscripten and does not expose any Emscripten APIs
|
||||
to clients. It is structured such that its build can be tweaked to
|
||||
include it in arbitrary WASM environments which can supply the
|
||||
necessary underlying features (e.g. a POSIX file I/O layer).
|
||||
|
||||
Main project home page: https://sqlite.org
|
||||
|
||||
|
||||
@@ -279,11 +279,11 @@
|
||||
The arguments are in the same form accepted by oo1.DB.exec(), with
|
||||
the exceptions noted below.
|
||||
|
||||
If the `countChanges` arguments property (added in version 3.43) is
|
||||
truthy then the `result` property contained by the returned object
|
||||
will have a `changeCount` property which holds the number of changes
|
||||
made by the provided SQL. Because the SQL may contain an arbitrary
|
||||
number of statements, the `changeCount` is calculated by calling
|
||||
If `args.countChanges` (added in version 3.43) is truthy then the
|
||||
`result` property contained by the returned object will have a
|
||||
`changeCount` property which holds the number of changes made by the
|
||||
provided SQL. Because the SQL may contain an arbitrary number of
|
||||
statements, the `changeCount` is calculated by calling
|
||||
`sqlite3_total_changes()` before and after the SQL is evaluated. If
|
||||
the value of `countChanges` is 64 then the `changeCount` property
|
||||
will be returned as a 64-bit integer in the form of a BigInt (noting
|
||||
@@ -292,6 +292,15 @@
|
||||
calling `sqlite3_total_changes64()` before and after the SQL is
|
||||
evaluated.
|
||||
|
||||
If the `args.lastInsertRowId` (added in version 3.50.0) is truthy
|
||||
then the `result` property contained by the returned object will
|
||||
have a `lastInsertRowId` will hold a BigInt-type value corresponding
|
||||
to the result of sqlite3_last_insert_rowid(). This value is only
|
||||
fetched once, after the SQL is run, regardless of how many
|
||||
statements the SQL contains. This API has no idea whether the SQL
|
||||
contains any INSERTs, so it is up to the client to apply/rely on
|
||||
this property only when it makes sense to do so.
|
||||
|
||||
A function-type args.callback property cannot cross
|
||||
the window/Worker boundary, so is not useful here. If
|
||||
args.callback is a string then it is assumed to be a
|
||||
@@ -542,6 +551,12 @@ sqlite3.initWorker1API = function(){
|
||||
if(undefined !== changeCount){
|
||||
rc.changeCount = db.changes(true,64===rc.countChanges) - changeCount;
|
||||
}
|
||||
const lastInsertRowId = !!rc.lastInsertRowId
|
||||
? sqlite3.capi.sqlite3_last_insert_rowid(db)
|
||||
: undefined;
|
||||
if( undefined!==lastInsertRowId ){
|
||||
rc.lastInsertRowId = lastInsertRowId;
|
||||
}
|
||||
if(rc.callback instanceof Function){
|
||||
rc.callback = theCallback;
|
||||
/* Post a sentinel message to tell the client that the end
|
||||
|
||||
@@ -115,6 +115,7 @@ delete globalThis.sqlite3Worker1Promiser;
|
||||
"insert into t(a,b) values(1,2),(3,4),(5,6)"
|
||||
].join(';'),
|
||||
resultRows: [], columnNames: [],
|
||||
lastInsertRowId: true,
|
||||
countChanges: sqConfig.bigIntEnabled ? 64 : true
|
||||
}, function(ev){
|
||||
ev = ev.result;
|
||||
@@ -122,7 +123,9 @@ delete globalThis.sqlite3Worker1Promiser;
|
||||
.assert(0===ev.columnNames.length)
|
||||
.assert(sqConfig.bigIntEnabled
|
||||
? (3n===ev.changeCount)
|
||||
: (3===ev.changeCount));
|
||||
: (3===ev.changeCount))
|
||||
.assert('bigint'===typeof ev.lastInsertRowId)
|
||||
.assert(ev.lastInsertRowId>=3);
|
||||
});
|
||||
|
||||
await wtest('exec',{
|
||||
|
||||
@@ -156,11 +156,14 @@
|
||||
sql: ["create table t(a,b);",
|
||||
"insert into t(a,b) values(1,2),(3,4),(5,6)"
|
||||
],
|
||||
lastInsertRowId: true,
|
||||
resultRows: [], columnNames: []
|
||||
}, function(ev){
|
||||
ev = ev.result;
|
||||
T.assert(0===ev.resultRows.length)
|
||||
.assert(0===ev.columnNames.length);
|
||||
.assert(0===ev.columnNames.length)
|
||||
.assert('bigint'===typeof ev.lastInsertRowId)
|
||||
.assert(ev.lastInsertRowId>=3);
|
||||
});
|
||||
runOneTest('exec',{
|
||||
sql: 'select a a, b b from t order by a',
|
||||
|
||||
+2
-2
@@ -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)...
|
||||
|
||||
+18
-6
@@ -151,7 +151,7 @@ static void mk_pre_post(const char *zName /* build name */,
|
||||
/* --pre-js=... */
|
||||
pf("pre-js.js.%s-%s := $(dir.tmp)/pre-js.%s-%s.js\n",
|
||||
zNM, zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(MAKEFILE)\n", zNM);
|
||||
pf("$(pre-js.js.%s-%s): $(MAKEFILE_LIST)\n", zNM);
|
||||
#if 1
|
||||
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);
|
||||
@@ -218,7 +218,7 @@ static void mk_fiddle(){
|
||||
pf("fiddle-module.js%s := %s/fiddle-module.js\n", zTail, zDir);
|
||||
pf("fiddle-module.wasm%s := "
|
||||
"$(subst .js,.wasm,$(fiddle-module.js%s))\n", zTail, zTail);
|
||||
pf("$(fiddle-module.js%s):%s $(MAKEFILE) $(MAKEFILE.fiddle) "
|
||||
pf("$(fiddle-module.js%s):%s $(MAKEFILE_LIST) $(MAKEFILE.fiddle) "
|
||||
"$(EXPORTED_FUNCTIONS.fiddle) "
|
||||
"$(fiddle.cses) $(pre-post-fiddle-module-vanilla.deps) "
|
||||
"$(SOAP.js)\n",
|
||||
@@ -274,6 +274,7 @@ static void mk_lib_mode(const char *zName /* build name */,
|
||||
if( !zEmcc ) zEmcc = "";
|
||||
|
||||
pf("%s# Begin build [%s-%s]\n", zBanner, zNM);
|
||||
pf("# zApiJsOut=%s\n# zJsOut=%s\n# zCmppD=%s\n", zApiJsOut, zJsOut, zCmppD);
|
||||
pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut);
|
||||
mk_pre_post(zNM, zCmppD);
|
||||
pf("\nemcc.flags.%s.%s ?=\n", zNM);
|
||||
@@ -284,7 +285,7 @@ static void mk_lib_mode(const char *zName /* build name */,
|
||||
zApiJsOut, zCmppD);
|
||||
|
||||
/* target zJsOut */
|
||||
pf("%s: %s $(MAKEFILE) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) "
|
||||
pf("%s: %s $(MAKEFILE_LIST) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) "
|
||||
"$(pre-post-%s-%s.deps) "
|
||||
"$(sqlite3-api.ext.jses)"
|
||||
/* ^^^ maintenance reminder: we set these as deps so that they
|
||||
@@ -303,9 +304,10 @@ static void mk_lib_mode(const char *zName /* build name */,
|
||||
"\t\t$(cflags.%s) $(cflags.%s.%s) \\\n"
|
||||
"\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM);
|
||||
if( bIsEsm ){
|
||||
/* TODO? Replace this CALL with the corresponding makefile code.
|
||||
** OTOH, we also use this $(call) in the speedtest1-wasmfs build,
|
||||
** which is not part of the rules emitted by this program. */
|
||||
/* TODO? Replace this $(call) with the corresponding makefile
|
||||
** code. OTOH, we also use this $(call) in the speedtest1-wasmfs
|
||||
** build, which is not part of the rules emitted by this
|
||||
** program. */
|
||||
pf("\t@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,%d)\n",
|
||||
0==strcmp("sqlite3-wasmfs", zName) ? 1 : 0);
|
||||
}
|
||||
@@ -337,6 +339,16 @@ static void mk_lib_mode(const char *zName /* build name */,
|
||||
/* ^^^^^^ reminder: Mac/BSD sed has no -i flag */
|
||||
zNM, zName);
|
||||
pf("\t@ls -la $@\n");
|
||||
if( 0==strcmp("bundler-friendly", zMode) ){
|
||||
/* Avoid a 3rd occurance of the bug fixed by 65798c09a00662a3,
|
||||
** which was (in two cases) caused by makefile refactoring and
|
||||
** not recognized until after a release was made with the broken
|
||||
** sqlite3-bundler-friendly.mjs: */
|
||||
pf("\t@if grep -e '^ *importScripts(' $@; "
|
||||
"then echo 'ERROR: bug fixed in 65798c09a00662a3 has re-appeared'; "
|
||||
"exit 1; fi;\n");
|
||||
}
|
||||
|
||||
}else{
|
||||
pf("\t@ls -la %s $@\n", zWasmOut);
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ LDFLAGS.shlib ?= -shared
|
||||
LDFLAGS.icu ?= # -licui18n -licuuc -licudata
|
||||
CFLAGS.icu ?=
|
||||
LDFLAGS.libsqlite3.soname ?= # see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific ?= # see https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# libreadline (or a workalike):
|
||||
# To activate readline in the shell: SHELL_OPT = -DHAVE_READLINE=1
|
||||
LDFLAGS.readline ?= -lreadline # these vary across platforms
|
||||
@@ -434,7 +435,8 @@ install-dir.all = $(install-dir.bin) $(install-dir.include) \
|
||||
$(install-dir.lib) $(install-dir.man1) \
|
||||
$(install-dir.pkgconfig)
|
||||
$(install-dir.all):
|
||||
$(INSTALL) -d "$@"
|
||||
if [ ! -d "$@" ]; then $(INSTALL) -d "$@"; fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
|
||||
#
|
||||
# After jimsh is compiled, we run some sanity checks to ensure that
|
||||
@@ -1411,7 +1413,7 @@ all: lib
|
||||
#
|
||||
$(libsqlite3.SO): $(LIBOBJ)
|
||||
$(T.link.shared) -o $@ $(LIBOBJ) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.soname)
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
$(libsqlite3.SO)-1: $(libsqlite3.SO)
|
||||
$(libsqlite3.SO)-0 $(libsqlite3.SO)-:
|
||||
so: $(libsqlite3.SO)-$(ENABLE_SHARED)
|
||||
@@ -1429,6 +1431,9 @@ all: so
|
||||
# unnecessary unless we want to set SONAME to libsqlite3.so.3, which
|
||||
# is also unnecessary.
|
||||
#
|
||||
# N.B. different transformations are applied on systems where $(T.dll)
|
||||
# is ".dylib" and none of the following docs apply on such systems.
|
||||
#
|
||||
# The link named libsqlite3.so.0 is provided in an attempt to reduce
|
||||
# downstream disruption when performing upgrades from pre-3.48 to a
|
||||
# version 3.48 or higher. That name is considered a legacy remnant
|
||||
@@ -1465,8 +1470,16 @@ all: so
|
||||
#
|
||||
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 $$?; \
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
if [ x.dylib = x$(T.dll) ]; then \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
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 $$?; \
|
||||
@@ -1482,7 +1495,8 @@ install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
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
|
||||
fi; \
|
||||
fi
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_SHARED)
|
||||
install: install-so
|
||||
@@ -2318,7 +2332,7 @@ tidy: tidy-.
|
||||
rm -f lemon$(B.exe) sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(B.exe) mksourceid$(B.exe)
|
||||
rm -f parse.* fts5parse.*
|
||||
rm -f $(libsqlite3.SO) $(libsqlite3.LIB) $(libtclsqlite3.SO)
|
||||
rm -f $(libsqlite3.SO) $(libsqlite3.LIB) $(libtclsqlite3.SO) libsqlite3$(T.dll).a
|
||||
rm -f tclsqlite3$(T.exe) $(TESTPROGS)
|
||||
rm -f LogEst$(T.exe) fts3view$(T.exe) rollback-test$(T.exe) showdb$(T.exe)
|
||||
rm -f showjournal$(T.exe) showstat4$(T.exe) showwal$(T.exe) speedtest1$(T.exe)
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
C Version\s3.49.0
|
||||
D 2025-02-06T11:55:18.769
|
||||
C Attempt\sto\simprovement\sperformance\sof\smultiple\sOP_Columns\sthat\soccur\sin\sa\srow.\nMinimal\simprovement\sfor\sa\slot\sof\scomplexity\sand\srisk.
|
||||
D 2025-02-11T16:00:52.467
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
|
||||
F Makefile.in 38485d15d9190cdad0d7bee25af7b442028865964025dcc61f40fd8d6e369cfc
|
||||
F Makefile.in 63c4d6e535dac4b7f6a6ffa566c96e3d68fa7f244799c38ee1e3d59305c5b55b
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc a9b95ae9807e17f9b0734ebe97d68032141c3f95286bb64593cb73b206f043cf
|
||||
F Makefile.msc 990e4ea94a417135d1b2fd35550997c3f40fc1758bd7546bd17c0f4312f0babc
|
||||
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
|
||||
F VERSION 01f7606130e48fd58a74d1e45e565f2674819d6eadbc219d328d94bb3362b818
|
||||
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
|
||||
F auto.def e7e92090c98aeb0174d29988c259834eb1b71ae1ea927015c3ef300f6f9b68ae
|
||||
F auto.def fdd6965e06bce02a8b9f9ed57a52d05bcbec4b56e4bef2174866bb5713c65fda
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.in 56697ad25ecf23afa317148b06bdc14f85960b42e5ec434ac1ba87f63a3cb789
|
||||
F autoconf/Makefile.in f706b48abb13553ecc5034d5fc296d424fd36d73c222285b7590004dec508925
|
||||
F autoconf/Makefile.msc 0a071367537dc395285a5d624ac4f99f3a387b27cc5e89752423c0499e15aec4
|
||||
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
|
||||
F autoconf/README.txt 7f01dc3915e2d68f329011073662369e62a0938a2c69398807823c57591cb288
|
||||
F autoconf/auto.def 23bc095a3890c0ca334abf7ef67d1c8af4c22c12832bcc738015e868d54fe9d7
|
||||
F autoconf/auto.def 71dde17158afcd6fb097b66853371991bb6ca5517b034e2efa9f0c47a2e730f2
|
||||
F autoconf/tea/Makefile.in ba0556fee8da09c066bad85a4457904e46ee2c2eabaa309c0e83a78f2f151a8e
|
||||
F autoconf/tea/README.txt 61e62e519579e4a112791354d6d440f8b51ea6db3b0bab58d59f29df42d2dfe3
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
F autoconf/tea/configure.ac d22326594f005a493a7857cb4ad2496b91480101be731d7f0541bb8d7eba22a2
|
||||
F autoconf/tea/configure.ac 830cb2af5a3888312d0fd88402c2509d551d60e4c03f0481006a07c78313ef12
|
||||
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in 55aec3c6d7e9a1de9b8d2fdc9c27fd055da3ac3a51b572195e2ae7300bcfd3a2
|
||||
@@ -47,10 +47,10 @@ F autosetup/cc-db.tcl 6e0ed90146197a5a05b245e649975c07c548e30926b218ca3e1d4dc034
|
||||
F autosetup/cc-lib.tcl 493c5935b5dd3bf9bd4eca89b07c8b1b1a9356d61783035144e21795facf7360
|
||||
F autosetup/cc-shared.tcl 4f024e94a47f427ba61de1739f6381ef0080210f9fae89112d5c1de1e5460d78
|
||||
F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f
|
||||
F autosetup/jimsh0.c 5a74bdbf43c52289e3f482f3b9578db4bd657e88e8fe04b16c564d9fb710540a
|
||||
F autosetup/jimsh0.c 6573f6bc6ff204de0139692648d7037ca0b6c067bac83a7b4e087f20a86866a4
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl 9adf1539673cef15bff862d9360b479e6920cc2c0d85de707b0ba31c04ce4531
|
||||
F autosetup/sqlite-config.tcl 00af5b9d94d580367bf01984b86397e8d35b74090427def9591a54ded0e1a287
|
||||
F autosetup/proj.tcl cef1e0aa0f2dee2042af66f28c97a9445f84d55d858ba9db4f6116846a1a325f
|
||||
F autosetup/sqlite-config.tcl 341c2751f42c6c8eeeae50bec13d2bb28db73ca2c8b9b97598332aed02e0a71b
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
@@ -619,7 +619,7 @@ F ext/session/sqlite3session.c 52a680dbb03c4734748b215d95987fb4d95ab23baaf053a01
|
||||
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 47f121d057c08ba49443c06c1c51ba2572e3d5d28a06c968cf0b2ccd5878c3d3
|
||||
F ext/wasm/GNUmakefile 06e0556e9840fd3d8870997025c2507ace9ba7bf11195f770295fc7947dfc1b5
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -635,13 +635,13 @@ F ext/wasm/api/README.md c64ec8e84449c069e0217706d9d7d31b3bd53627228b2ba0c3cddbd
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 3fcd904f1204685dea84e5ae90d8b7e65a1dcebab1e838386d8328b74cce46c9
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90ae151e37fa9f75bf41
|
||||
F ext/wasm/api/post-js-header.js 54b2b4294501b3866245cc94315a16f5424c0e87729d0fb610fba151593c6d26
|
||||
F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
|
||||
F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 5c0209e6a28164b4c2c1a34b0bb4aee3b7b1a264988d7e71fac08b8ede5b7ae3
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 5ff913355b3144f1c9719d0406667fa6e13eb813c71ed7ce29440e2e65363e82
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 5cc22a3c0d52828cb32aad8691488719f47d27567e63e8bc8b832d74371c352d
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 9e7d89a2c0d02b8b2052a62757a89f1e7e4dbcc0d9cd3f2dafa896786954dad2
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 3774befd97cd1a5e2895c8225a894aad946848c6d9b4028acc988b5d123475af
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
@@ -667,9 +667,9 @@ F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32
|
||||
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
|
||||
F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a9ef7c42ff04d7a125ddca7e5db8
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js af168699d3cab1c27ad2364ebe06cd49db300bdbf404e23b00d5742ed52816ba
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
|
||||
F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535da776950314
|
||||
F ext/wasm/dist.make 92ef4ffe33022a50f92d602acabad10bd8dd91759f3eb7df27fc6d7d37072b96
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make d4969f0322a582c57a22ce3541f10a5b09a609d14eab32891f613f43b3c14d8b
|
||||
@@ -677,10 +677,10 @@ F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea
|
||||
F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
|
||||
F ext/wasm/fiddle/index.html c79b1741cbeba78f88af0a84cf5ec7de87a909a6a8d10a369b1f4824c66c2088
|
||||
F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730
|
||||
F ext/wasm/index.html 10ff3ad190aadccb713109fa55a38e5c1f3c2a8cf05cd31783745bab3f184079
|
||||
F ext/wasm/index.html e4bbffdb3d40eff12b3f9c7abedef91787e2935620b7f8d40f2c774b80ad8fa9
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 59a20df389abcc3606eb4eaea7fb7ba14504beb3e345dbea9b99a0618ba3bec8
|
||||
F ext/wasm/mkwasmbuilds.c d5885bacf2253bed913cdc7eb16b44f9c9e782133e10600652d1a78841c337af
|
||||
F ext/wasm/mkwasmbuilds.c baf6636e139e2c1e3b56e8dc26073ec80f6d14ae1876b023985315f43ccf312b
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -702,7 +702,7 @@ F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65a
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 8cfe182232ac7bbc87530792db6f31c09f2a2f35e9887d0412978746efe42ea9
|
||||
F main.mk 7c9df07a41c406a5fbe4e7e4021f29fa4f18821d61354721fd0435fc24f95321
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -712,8 +712,8 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
|
||||
F src/alter.c aa93e37e4a36a0525bbb2a2aeda20d2018f0aa995542c7dc658e031375e3f532
|
||||
F src/analyze.c 9a8b67239d899ac12289db5db3f5bfe7f7a0ad1277f80f87ead1d048085876eb
|
||||
F src/alter.c 1751e231d8385067fa0d0145f0d461a092db6bd3d7edbfc3172db625aceccd9a
|
||||
F src/analyze.c 0823d2edb3ce564157e9d62714cc729027933209b712e95fbabb23e47fff0aec
|
||||
F src/attach.c 3a5cb9ee4aad6c5b22268287340a4f2f7b07959b7a522201be30fee23cd802e9
|
||||
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
@@ -722,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 357f98cdd9fe93f86e93ad3324fd224492480e48506c0c7db8ae3a94f3b5c5ee
|
||||
F src/build.c 602fc45ea6301a3dc03ec20a9f9b294c492b7e1766ae96651f2ba8044dc445a6
|
||||
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c d35723024b963edce9c0fad5b3303e8bb9266083784844baed10a6dedfe26f3b
|
||||
@@ -730,20 +730,20 @@ F src/date.c 842c08ac143a56a627b05ac51d68624f2b7b03e3b4cba596205e735eed64ee57
|
||||
F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
|
||||
F src/expr.c 8705be31ee713aaa43c97d91399db09f16ee41b88250406eb99de6b47f550a98
|
||||
F src/expr.c ca943270395374afc65256ce86cdb152a22fa6ff146895175833b89ba870e117
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
|
||||
F src/func.c 0712a5b03fdfc8af0cda6d076bfe231b66388d3d5a28b46dc1a94b90d41cac6a
|
||||
F src/func.c b2fb33139972d7d65640b27ea962a49f1616265428001090cab39fcf270228e1
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c db8bfff30fd7f71812651df3ddf5d1624b9e19104b31e349cd9055bbc9d622c4
|
||||
F src/json.c 68a98c020c22127f2d65f08855f7fc7460ff352a6ce0b543d8931dde83319c22
|
||||
F src/insert.c 05e04ef637cbc0dccb9a5c5d188a5a2608891e554c8ec17c7a71afe2cf896a06
|
||||
F src/json.c 2663a0c7e574cb928de944720dcdcc11c931877d877549b8f1258a4002efd6f7
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 59bdd8d9bbdb3a746eaef14d611ddd5638aa18acef7c5e3271e815dbd215a1af
|
||||
F src/main.c b99d15d843f7a86adbec855de77b1656dde07359722ef63a9d9393678dbb58d1
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -769,7 +769,7 @@ F src/os_win.c 49c7725b500f5867e8360e75eeb30f9d70b62fa1f05c8a101da627210578df32
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 3a1c4e7f69af482e33c8cba8a75afe0dda0ea6391240adac22b040ce1bdeef44
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 5dce477d23c6cd41da97ff9bc4ef93fba0e0a0aaa72a15ddb8a3f71618d76cac
|
||||
F src/parse.y f84673f1454e2bcf517623d4346e67fb2d73e57826ea103681ad5848238f6029
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
|
||||
@@ -778,14 +778,14 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
|
||||
F src/printf.c 96f7f8baeedc7639da94e4e7a4a2c200e2537c4eec9e5e1c2ffc821f40eb3105
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68
|
||||
F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 83e88fbb36f89b6703b348777491619554f0fd6f917c9fdf51e4c2e9cda6c04e
|
||||
F src/select.c 57893cc8b099f231f7ed5b84faff14841f2aabb4776e32e17fae00aeae0a8993
|
||||
F src/shell.c.in b377a59822f207106424f08aead37e78b609222e98f86f04cc8a03563ccf3237
|
||||
F src/sqlite.h.in d2902f13ace94d3d3609646bd6d12a2d7a4f6cbdf6a5a4097580ac305f54c3f0
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 9d7052c71f46ca3a1a4880ba4a62590da334651139a38327d488894d9c883f3b
|
||||
F src/sqliteInt.h 8cbfef6c26efd539eb93011905f4d3ce7fdb77475d1280764d86f9e7954c464b
|
||||
F src/sqliteLimit.h 1bbdbf72bd0411d003267ffebc59a262f061df5653027a75627d03f48ca30523
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -843,30 +843,30 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 375a772e2342274f4bf73605a70633237da09deed00a9bf4c4816a56777ea7c9
|
||||
F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc62279
|
||||
F src/trigger.c 247e2d712d5edc6021d52a169f6ac9a9c10d7144bc4ac7ea06c1ed2aa414659f
|
||||
F src/update.c 0e01aa6a3edf9ec112b33eb714b9016a81241497b1fb7c3e74332f4f71756508
|
||||
F src/trigger.c da3c25786870d8bf97cd46b493374c2375d1abaf20a9b0f5f8629a3f2f2ce383
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 8b29d9a5956569ea2700f869669b8ef67a9662ee5e724ff77ab3c387e27094ba
|
||||
F src/util.c e5f6a5eeaa26b69054a43bbd0048cfe3d2851f6961052b35aed8f695df922850
|
||||
F src/util.c 9ff6470dabcf943fd796d2da766c98bd328c8f6fe036a31e5b338e628603f989
|
||||
F src/vacuum.c b763b6457bd058d2072ef9364832351fd8d11e8abf70cbb349657360f7d55c40
|
||||
F src/vdbe.c b428a751953c0c2ff85e3e152ec16e29d488895cd541c8c20876ff9f3bf6978a
|
||||
F src/vdbe.c eeb0882a45918150d9576f5bbcaa255689082e70cc9abf82287439bc39440edf
|
||||
F src/vdbe.h 3d26d5c7660c5c7bd33ffb0d8784615072d8b23c81f8110870efe2631136bc89
|
||||
F src/vdbeInt.h 895b1ab7536f018d3d70d690f6c0adbd1062b6dddce1c2cad912927856d4033c
|
||||
F src/vdbeInt.h 078b1c15b26587b54c1c1879d0d2f4dec812b9de4c337fed9faf73fbcc3bf091
|
||||
F src/vdbeapi.c 82fe278a7c71b653235c6f9fb5de0b5de589908dfcb011ba2a782e8becf06f86
|
||||
F src/vdbeaux.c 885e16100597507fbbe09d82cbb963bff3fd8a9c1e358dc4f463fc95feb18e8b
|
||||
F src/vdbeblob.c 255be187436da38b01f276c02e6a08103489bbe2a7c6c21537b7aecbe0e1f797
|
||||
F src/vdbemem.c 977438546df236c6a3e7d8b4fe86c0643c13b89b00235db1f11c3a91a4796d30
|
||||
F src/vdbeaux.c 541d3d232714455960eab4ed10b34cb48b4bcd565d7539ef31092f5e73648e6b
|
||||
F src/vdbeblob.c 9166b6eb7054e5da82e35255892fb1ed551355a4716452539e8e3ac14f25fbe3
|
||||
F src/vdbemem.c 4af21a948820259ced96e3d46d70f9af347afa2deb7cb60a8b3981d5748e4279
|
||||
F src/vdbesort.c d0a3c7056c081703c8b6d91ad60f17da5e062a5c64bf568ed0fa1b5f4cae311f
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c bd4ab699ac4d1ee6da7339d3fbbb5edf23d9737c1fd322ccd75984329d070472
|
||||
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 4e6181d8780ab0af2e1388d0754cbe6f2f04593d2b1ab6c41699a89942fd8997
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 09dc313e7223ca1217c39c7026b00f16ff449a8323511a762fcba7863a00f4cd
|
||||
F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1
|
||||
F src/wherecode.c 0c3d3199a2b769a5e2bb70feb5003dc85b3d86842ecaf903a47f2b4205ca5dab
|
||||
F src/wherecode.c 5baa06f0daae7d38aca1d4814030b82ad4f127fe6bad18f0644776a474f6088b
|
||||
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
|
||||
F src/window.c 2bf01f9941a64fbcead61a0e3cb5db3fca5094b30d2ff0d23274c2a81d2e2385
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
@@ -1680,8 +1680,8 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest.md ee958457ae1b729d9715ae33c0320600000bf1d9ddea1a88dcf79f56729d6fad
|
||||
F test/speedtest.tcl 8a9362c1e429318e741b91d26888e7edcc326f98c3aea505ffd618cc5b9e7f0a x
|
||||
F test/speedtest1.c 204acd8af326bbca2c28f68166635d4574381f4cabbac1bc243663f5dcc5051d
|
||||
F test/speedtest.tcl 926d1e168f4a14e6fb68c5dc174de743536b547f365264bd5bac533b3621a4a0 x
|
||||
F test/speedtest1.c 132cd5ba064f48910bb4b68337442b0ef419218c8de9e9855f66d98015286ddb
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -2209,11 +2209,12 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 9f28f6694f97d5ee0345b45f9bf81e3fdce0990ce32fb9bdbbaac079126a67c9
|
||||
R 84a73aa92675a2727074c491235ee053
|
||||
T +sym-major-release *
|
||||
T +sym-release *
|
||||
T +sym-version-3.49.0 *
|
||||
P 57b2b812c8c5524f315e20cee0e6a12a3b1635aeb42925bf891532a7029d0eb0
|
||||
R 5b40ead92f50e29d43d44519f8927a47
|
||||
T *branch * column-optimization
|
||||
T *sym-column-optimization *
|
||||
T +closed *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 345e0ae7aa6443f7f8d274ba6f526736
|
||||
Z 359be1e71666f10555b25682f42340bf
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4a7dd425dc2a0e5082a9049c9b4a9d4f199a71583d014c24b4cfe276c5a77cde
|
||||
53478f29347c7f17d46ec2a1e7c390c9be9e9fc32f31da77a4ba7a9d67440a8e
|
||||
|
||||
+2
-4
@@ -632,10 +632,8 @@ void sqlite3AlterRenameColumn(
|
||||
** altered. Set iCol to be the index of the column being renamed */
|
||||
zOld = sqlite3NameFromToken(db, pOld);
|
||||
if( !zOld ) goto exit_rename_column;
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
|
||||
}
|
||||
if( iCol==pTab->nCol ){
|
||||
iCol = sqlite3ColumnIndex(pTab, zOld);
|
||||
if( iCol<0 ){
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
|
||||
goto exit_rename_column;
|
||||
}
|
||||
|
||||
+2
-1
@@ -215,7 +215,8 @@ static void openStatTable(
|
||||
sqlite3NestedParse(pParse,
|
||||
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
|
||||
);
|
||||
aRoot[i] = (u32)pParse->regRoot;
|
||||
assert( pParse->isCreate || pParse->nErr );
|
||||
aRoot[i] = (u32)pParse->u1.cr.regRoot;
|
||||
aCreateTbl[i] = OPFLAG_P2ISREG;
|
||||
}
|
||||
}else{
|
||||
|
||||
+41
-34
@@ -168,10 +168,12 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
|
||||
if( v ){
|
||||
if( pParse->bReturning ){
|
||||
Returning *pReturning = pParse->u1.pReturning;
|
||||
Returning *pReturning;
|
||||
int addrRewind;
|
||||
int reg;
|
||||
|
||||
assert( !pParse->isCreate );
|
||||
pReturning = pParse->u1.d.pReturning;
|
||||
if( pReturning->nRetCol ){
|
||||
sqlite3VdbeAddOp0(v, OP_FkCheck);
|
||||
addrRewind =
|
||||
@@ -247,7 +249,9 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
}
|
||||
|
||||
if( pParse->bReturning ){
|
||||
Returning *pRet = pParse->u1.pReturning;
|
||||
Returning *pRet;
|
||||
assert( !pParse->isCreate );
|
||||
pRet = pParse->u1.d.pReturning;
|
||||
if( pRet->nRetCol ){
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
|
||||
}
|
||||
@@ -1319,8 +1323,9 @@ void sqlite3StartTable(
|
||||
/* If the file format and encoding in the database have not been set,
|
||||
** set them now.
|
||||
*/
|
||||
reg1 = pParse->regRowid = ++pParse->nMem;
|
||||
reg2 = pParse->regRoot = ++pParse->nMem;
|
||||
assert( pParse->isCreate );
|
||||
reg1 = pParse->u1.cr.regRowid = ++pParse->nMem;
|
||||
reg2 = pParse->u1.cr.regRoot = ++pParse->nMem;
|
||||
reg3 = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
@@ -1335,8 +1340,8 @@ void sqlite3StartTable(
|
||||
** The record created does not contain anything yet. It will be replaced
|
||||
** by the real entry in code generated at sqlite3EndTable().
|
||||
**
|
||||
** The rowid for the new entry is left in register pParse->regRowid.
|
||||
** The root page number of the new table is left in reg pParse->regRoot.
|
||||
** The rowid for the new entry is left in register pParse->u1.cr.regRowid.
|
||||
** The root page of the new table is left in reg pParse->u1.cr.regRoot.
|
||||
** The rowid and root page number values are needed by the code that
|
||||
** sqlite3EndTable will generate.
|
||||
*/
|
||||
@@ -1347,7 +1352,7 @@ void sqlite3StartTable(
|
||||
#endif
|
||||
{
|
||||
assert( !pParse->bReturning );
|
||||
pParse->u1.addrCrTab =
|
||||
pParse->u1.cr.addrCrTab =
|
||||
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
|
||||
}
|
||||
sqlite3OpenSchemaTable(pParse, iDb);
|
||||
@@ -1425,7 +1430,8 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
|
||||
sqlite3ExprListDelete(db, pList);
|
||||
return;
|
||||
}
|
||||
pParse->u1.pReturning = pRet;
|
||||
assert( !pParse->isCreate );
|
||||
pParse->u1.d.pReturning = pRet;
|
||||
pRet->pParse = pParse;
|
||||
pRet->pReturnEL = pList;
|
||||
sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet);
|
||||
@@ -1467,7 +1473,6 @@ void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
|
||||
char *zType;
|
||||
Column *pCol;
|
||||
sqlite3 *db = pParse->db;
|
||||
u8 hName;
|
||||
Column *aNew;
|
||||
u8 eType = COLTYPE_CUSTOM;
|
||||
u8 szEst = 1;
|
||||
@@ -1521,13 +1526,10 @@ void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
|
||||
memcpy(z, sName.z, sName.n);
|
||||
z[sName.n] = 0;
|
||||
sqlite3Dequote(z);
|
||||
hName = sqlite3StrIHash(z);
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
|
||||
sqlite3DbFree(db, z);
|
||||
return;
|
||||
}
|
||||
if( p->nCol && sqlite3ColumnIndex(p, z)>=0 ){
|
||||
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
|
||||
sqlite3DbFree(db, z);
|
||||
return;
|
||||
}
|
||||
aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
|
||||
if( aNew==0 ){
|
||||
@@ -1538,7 +1540,7 @@ void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
|
||||
pCol = &p->aCol[p->nCol];
|
||||
memset(pCol, 0, sizeof(p->aCol[0]));
|
||||
pCol->zCnName = z;
|
||||
pCol->hName = hName;
|
||||
pCol->hName = sqlite3StrIHash(z);
|
||||
sqlite3ColumnPropertiesFromName(p, pCol);
|
||||
|
||||
if( sType.n==0 ){
|
||||
@@ -1562,9 +1564,14 @@ void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
|
||||
pCol->affinity = sqlite3AffinityType(zType, pCol);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
}
|
||||
if( p->nCol<=0xff ){
|
||||
u8 h = pCol->hName % sizeof(p->aHx);
|
||||
p->aHx[h] = p->nCol;
|
||||
}
|
||||
p->nCol++;
|
||||
p->nNVCol++;
|
||||
pParse->constraintName.n = 0;
|
||||
assert( pParse->isCreate );
|
||||
pParse->u1.cr.constraintName.n = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1828,15 +1835,11 @@ void sqlite3AddPrimaryKey(
|
||||
assert( pCExpr!=0 );
|
||||
sqlite3StringToId(pCExpr);
|
||||
if( pCExpr->op==TK_ID ){
|
||||
const char *zCName;
|
||||
assert( !ExprHasProperty(pCExpr, EP_IntValue) );
|
||||
zCName = pCExpr->u.zToken;
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
|
||||
pCol = &pTab->aCol[iCol];
|
||||
makeColumnPartOfPrimaryKey(pParse, pCol);
|
||||
break;
|
||||
}
|
||||
iCol = sqlite3ColumnIndex(pTab, pCExpr->u.zToken);
|
||||
if( iCol>=0 ){
|
||||
pCol = &pTab->aCol[iCol];
|
||||
makeColumnPartOfPrimaryKey(pParse, pCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1888,8 +1891,10 @@ void sqlite3AddCheckConstraint(
|
||||
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
|
||||
){
|
||||
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
|
||||
if( pParse->constraintName.n ){
|
||||
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
|
||||
assert( pParse->isCreate );
|
||||
if( pParse->u1.cr.constraintName.n ){
|
||||
sqlite3ExprListSetName(pParse, pTab->pCheck,
|
||||
&pParse->u1.cr.constraintName, 1);
|
||||
}else{
|
||||
Token t;
|
||||
for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
|
||||
@@ -2339,9 +2344,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
** into BTREE_BLOBKEY.
|
||||
*/
|
||||
assert( !pParse->bReturning );
|
||||
if( pParse->u1.addrCrTab ){
|
||||
if( pParse->u1.cr.addrCrTab ){
|
||||
assert( v );
|
||||
sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
|
||||
sqlite3VdbeChangeP3(v, pParse->u1.cr.addrCrTab, BTREE_BLOBKEY);
|
||||
}
|
||||
|
||||
/* Locate the PRIMARY KEY index. Or, if this table was originally
|
||||
@@ -2781,7 +2786,7 @@ void sqlite3EndTable(
|
||||
|
||||
/* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
|
||||
** statement to populate the new table. The root-page number for the
|
||||
** new table is in register pParse->regRoot.
|
||||
** new table is in register pParse->u1.cr.regRoot.
|
||||
**
|
||||
** Once the SELECT has been coded by sqlite3Select(), it is in a
|
||||
** suitable state to query for the column names and types to be used
|
||||
@@ -2812,7 +2817,8 @@ void sqlite3EndTable(
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
sqlite3MayAbort(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
|
||||
assert( pParse->isCreate );
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
@@ -2857,6 +2863,7 @@ void sqlite3EndTable(
|
||||
** schema table. We just need to update that slot with all
|
||||
** the information we've collected.
|
||||
*/
|
||||
assert( pParse->isCreate );
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q." LEGACY_SCHEMA_TABLE
|
||||
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
|
||||
@@ -2865,9 +2872,9 @@ void sqlite3EndTable(
|
||||
zType,
|
||||
p->zName,
|
||||
p->zName,
|
||||
pParse->regRoot,
|
||||
pParse->u1.cr.regRoot,
|
||||
zStmt,
|
||||
pParse->regRowid
|
||||
pParse->u1.cr.regRowid
|
||||
);
|
||||
sqlite3DbFree(db, zStmt);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
|
||||
+1
-8
@@ -1849,7 +1849,6 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
|
||||
}
|
||||
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
|
||||
pItem->fg = pOldItem->fg;
|
||||
pItem->fg.done = 0;
|
||||
pItem->u = pOldItem->u;
|
||||
}
|
||||
return pNew;
|
||||
@@ -2966,13 +2965,7 @@ const char *sqlite3RowidAlias(Table *pTab){
|
||||
int ii;
|
||||
assert( VisibleRowid(pTab) );
|
||||
for(ii=0; ii<ArraySize(azOpt); ii++){
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break;
|
||||
}
|
||||
if( iCol==pTab->nCol ){
|
||||
return azOpt[ii];
|
||||
}
|
||||
if( sqlite3ColumnIndex(pTab, azOpt[ii])<0 ) return azOpt[ii];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+12
-13
@@ -356,11 +356,6 @@ static void substrFunc(
|
||||
i64 p1, p2;
|
||||
|
||||
assert( argc==3 || argc==2 );
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_NULL
|
||||
|| (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
|
||||
){
|
||||
return;
|
||||
}
|
||||
p0type = sqlite3_value_type(argv[0]);
|
||||
p1 = sqlite3_value_int64(argv[1]);
|
||||
if( p0type==SQLITE_BLOB ){
|
||||
@@ -378,19 +373,23 @@ static void substrFunc(
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_SUBSTR_COMPATIBILITY
|
||||
/* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
|
||||
** as substr(X,1,N) - it returns the first N characters of X. This
|
||||
** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
|
||||
** from 2009-02-02 for compatibility of applications that exploited the
|
||||
** old buggy behavior. */
|
||||
if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
|
||||
#endif
|
||||
if( argc==3 ){
|
||||
p2 = sqlite3_value_int64(argv[2]);
|
||||
if( p2==0 && sqlite3_value_type(argv[2])==SQLITE_NULL ) return;
|
||||
}else{
|
||||
p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
|
||||
}
|
||||
if( p1==0 ){
|
||||
#ifdef SQLITE_SUBSTR_COMPATIBILITY
|
||||
/* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
|
||||
** as substr(X,1,N) - it returns the first N characters of X. This
|
||||
** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
|
||||
** from 2009-02-02 for compatibility of applications that exploited the
|
||||
** old buggy behavior. */
|
||||
p1 = 1; /* <rdar://problem/6778339> */
|
||||
#endif
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
|
||||
}
|
||||
if( p1<0 ){
|
||||
p1 += len;
|
||||
if( p1<0 ){
|
||||
|
||||
+24
-22
@@ -54,12 +54,19 @@ void sqlite3HashClear(Hash *pH){
|
||||
*/
|
||||
static unsigned int strHash(const char *z){
|
||||
unsigned int h = 0;
|
||||
unsigned char c;
|
||||
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
|
||||
** 0x9e3779b1 is 2654435761 which is the closest prime number to
|
||||
** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
|
||||
h += sqlite3UpperToLower[c];
|
||||
** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2.
|
||||
**
|
||||
** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are
|
||||
** hashed since the omitted bits determine the upper/lower case difference.
|
||||
*/
|
||||
#ifdef SQLITE_EBCDIC
|
||||
h += 0xbf & (unsigned char)*(z++);
|
||||
#else
|
||||
h += 0xdf & (unsigned char)*(z++);
|
||||
#endif
|
||||
h *= 0x9e3779b1;
|
||||
}
|
||||
return h;
|
||||
@@ -132,9 +139,8 @@ static int rehash(Hash *pH, unsigned int new_size){
|
||||
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
|
||||
memset(new_ht, 0, new_size*sizeof(struct _ht));
|
||||
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
|
||||
unsigned int h = strHash(elem->pKey) % new_size;
|
||||
next_elem = elem->next;
|
||||
insertElement(pH, &new_ht[h], elem);
|
||||
insertElement(pH, &new_ht[elem->h % new_size], elem);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -152,23 +158,22 @@ static HashElem *findElementWithHash(
|
||||
HashElem *elem; /* Used to loop thru the element list */
|
||||
unsigned int count; /* Number of elements left to test */
|
||||
unsigned int h; /* The computed hash */
|
||||
static HashElem nullElement = { 0, 0, 0, 0 };
|
||||
static HashElem nullElement = { 0, 0, 0, 0, 0 };
|
||||
|
||||
h = strHash(pKey);
|
||||
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
struct _ht *pEntry;
|
||||
h = strHash(pKey) % pH->htsize;
|
||||
pEntry = &pH->ht[h];
|
||||
pEntry = &pH->ht[h % pH->htsize];
|
||||
elem = pEntry->chain;
|
||||
count = pEntry->count;
|
||||
}else{
|
||||
h = 0;
|
||||
elem = pH->first;
|
||||
count = pH->count;
|
||||
}
|
||||
if( pHash ) *pHash = h;
|
||||
while( count ){
|
||||
assert( elem!=0 );
|
||||
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
|
||||
if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){
|
||||
return elem;
|
||||
}
|
||||
elem = elem->next;
|
||||
@@ -180,10 +185,9 @@ static HashElem *findElementWithHash(
|
||||
/* Remove a single entry from the hash table given a pointer to that
|
||||
** element and a hash on the element's key.
|
||||
*/
|
||||
static void removeElementGivenHash(
|
||||
static void removeElement(
|
||||
Hash *pH, /* The pH containing "elem" */
|
||||
HashElem* elem, /* The element to be removed from the pH */
|
||||
unsigned int h /* Hash value for the element */
|
||||
HashElem *elem /* The element to be removed from the pH */
|
||||
){
|
||||
struct _ht *pEntry;
|
||||
if( elem->prev ){
|
||||
@@ -195,7 +199,7 @@ static void removeElementGivenHash(
|
||||
elem->next->prev = elem->prev;
|
||||
}
|
||||
if( pH->ht ){
|
||||
pEntry = &pH->ht[h];
|
||||
pEntry = &pH->ht[elem->h % pH->htsize];
|
||||
if( pEntry->chain==elem ){
|
||||
pEntry->chain = elem->next;
|
||||
}
|
||||
@@ -246,7 +250,7 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
|
||||
if( elem->data ){
|
||||
void *old_data = elem->data;
|
||||
if( data==0 ){
|
||||
removeElementGivenHash(pH,elem,h);
|
||||
removeElement(pH,elem);
|
||||
}else{
|
||||
elem->data = data;
|
||||
elem->pKey = pKey;
|
||||
@@ -257,14 +261,12 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
|
||||
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
|
||||
if( new_elem==0 ) return data;
|
||||
new_elem->pKey = pKey;
|
||||
new_elem->h = h;
|
||||
new_elem->data = data;
|
||||
pH->count++;
|
||||
if( pH->count>=10 && pH->count > 2*pH->htsize ){
|
||||
if( rehash(pH, pH->count*2) ){
|
||||
assert( pH->htsize>0 );
|
||||
h = strHash(pKey) % pH->htsize;
|
||||
}
|
||||
if( pH->count>=5 && pH->count > 2*pH->htsize ){
|
||||
rehash(pH, pH->count*3);
|
||||
}
|
||||
insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
|
||||
insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ struct HashElem {
|
||||
HashElem *next, *prev; /* Next and previous elements in the table */
|
||||
void *data; /* Data associated with this element */
|
||||
const char *pKey; /* Key associated with this element */
|
||||
unsigned int h; /* hash for pKey */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+16
-22
@@ -1075,28 +1075,22 @@ void sqlite3Insert(
|
||||
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( 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 );
|
||||
}
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot INSERT into generated column \"%s\"",
|
||||
pTab->aCol[j].zCnName);
|
||||
goto insert_cleanup;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
j = sqlite3ColumnIndex(pTab, pColumn->a[i].zName);
|
||||
if( j>=0 ){
|
||||
if( aTabColMap[j]==0 ) aTabColMap[j] = i+1;
|
||||
if( i!=j ) bIdListInOrder = 0;
|
||||
if( j==pTab->iPKey ){
|
||||
ipkColumn = i; assert( !withoutRowid );
|
||||
}
|
||||
}
|
||||
if( j>=pTab->nCol ){
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot INSERT into generated column \"%s\"",
|
||||
pTab->aCol[j].zCnName);
|
||||
goto insert_cleanup;
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
|
||||
ipkColumn = i;
|
||||
bIdListInOrder = 0;
|
||||
@@ -1394,7 +1388,7 @@ void sqlite3Insert(
|
||||
continue;
|
||||
}else if( pColumn==0 ){
|
||||
/* Hidden columns that are not explicitly named in the INSERT
|
||||
** get there default value */
|
||||
** get their default value */
|
||||
sqlite3ExprCodeFactorable(pParse,
|
||||
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
|
||||
iRegStore);
|
||||
|
||||
+9
-9
@@ -2054,10 +2054,7 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
||||
u8 x;
|
||||
u32 sz;
|
||||
u32 n;
|
||||
if( NEVER(i>pParse->nBlob) ){
|
||||
*pSz = 0;
|
||||
return 0;
|
||||
}
|
||||
assert( i<=pParse->nBlob );
|
||||
x = pParse->aBlob[i]>>4;
|
||||
if( x<=11 ){
|
||||
sz = x;
|
||||
@@ -2101,8 +2098,8 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
||||
if( (i64)i+sz+n > pParse->nBlob
|
||||
&& (i64)i+sz+n > pParse->nBlob-pParse->delta
|
||||
){
|
||||
sz = 0;
|
||||
n = 0;
|
||||
*pSz = 0;
|
||||
return 0;
|
||||
}
|
||||
*pSz = sz;
|
||||
return n;
|
||||
@@ -2199,9 +2196,12 @@ static u32 jsonTranslateBlobToText(
|
||||
}
|
||||
case JSONB_TEXT:
|
||||
case JSONB_TEXTJ: {
|
||||
jsonAppendChar(pOut, '"');
|
||||
jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
|
||||
jsonAppendChar(pOut, '"');
|
||||
if( pOut->nUsed+sz+2<=pOut->nAlloc || jsonStringGrow(pOut, sz+2)==0 ){
|
||||
pOut->zBuf[pOut->nUsed] = '"';
|
||||
memcpy(pOut->zBuf+pOut->nUsed+1,(const char*)&pParse->aBlob[i+n],sz);
|
||||
pOut->zBuf[pOut->nUsed+sz+1] = '"';
|
||||
pOut->nUsed += sz+2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSONB_TEXT5: {
|
||||
|
||||
+3
-6
@@ -3943,13 +3943,10 @@ int sqlite3_table_column_metadata(
|
||||
if( zColumnName==0 ){
|
||||
/* Query for existence of table only */
|
||||
}else{
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
iCol = sqlite3ColumnIndex(pTab, zColumnName);
|
||||
if( iCol>=0 ){
|
||||
pCol = &pTab->aCol[iCol];
|
||||
if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( iCol==pTab->nCol ){
|
||||
}else{
|
||||
if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
|
||||
iCol = pTab->iPKey;
|
||||
pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
|
||||
|
||||
+19
-4
@@ -62,6 +62,11 @@
|
||||
%include {
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Verify that the pParse->isCreate field is set
|
||||
*/
|
||||
#define ASSERT_IS_CREATE assert(pParse->isCreate)
|
||||
|
||||
/*
|
||||
** Disable all error recovery processing in the parser push-down
|
||||
** automaton.
|
||||
@@ -125,6 +130,10 @@ static void parserSyntaxError(Parse *pParse, Token *p){
|
||||
static void disableLookaside(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
pParse->disableLookaside++;
|
||||
#ifdef SQLITE_DEBUG
|
||||
pParse->isCreate = 1;
|
||||
#endif
|
||||
memset(&pParse->u1.cr, 0, sizeof(pParse->u1.cr));
|
||||
DisableLookaside;
|
||||
}
|
||||
|
||||
@@ -197,7 +206,9 @@ cmd ::= create_table create_table_args.
|
||||
create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
|
||||
sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
|
||||
}
|
||||
createkw(A) ::= CREATE(A). {disableLookaside(pParse);}
|
||||
createkw(A) ::= CREATE(A). {
|
||||
disableLookaside(pParse);
|
||||
}
|
||||
|
||||
%type ifnotexists {int}
|
||||
ifnotexists(A) ::= . {A = 0;}
|
||||
@@ -373,7 +384,7 @@ scantok(A) ::= . {
|
||||
//
|
||||
carglist ::= carglist ccons.
|
||||
carglist ::= .
|
||||
ccons ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
|
||||
ccons ::= CONSTRAINT nm(X). {ASSERT_IS_CREATE; pParse->u1.cr.constraintName = X;}
|
||||
ccons ::= DEFAULT scantok(A) term(X).
|
||||
{sqlite3AddDefaultValue(pParse,X,A.z,&A.z[A.n]);}
|
||||
ccons ::= DEFAULT LP(A) expr(X) RP(Z).
|
||||
@@ -448,9 +459,9 @@ conslist_opt(A) ::= . {A.n = 0; A.z = 0;}
|
||||
conslist_opt(A) ::= COMMA(A) conslist.
|
||||
conslist ::= conslist tconscomma tcons.
|
||||
conslist ::= tcons.
|
||||
tconscomma ::= COMMA. {pParse->constraintName.n = 0;}
|
||||
tconscomma ::= COMMA. {ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;}
|
||||
tconscomma ::= .
|
||||
tcons ::= CONSTRAINT nm(X). {pParse->constraintName = X;}
|
||||
tcons ::= CONSTRAINT nm(X). {ASSERT_IS_CREATE; pParse->u1.cr.constraintName = X;}
|
||||
tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
|
||||
{sqlite3AddPrimaryKey(pParse,X,R,I,0);}
|
||||
tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
|
||||
@@ -1659,6 +1670,10 @@ trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z)
|
||||
ON fullname(E) foreach_clause when_clause(G). {
|
||||
sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
|
||||
A = (Z.n==0?B:Z); /*A-overwrites-T*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( pParse->isCreate ); /* Set by createkw reduce action */
|
||||
pParse->isCreate = 0; /* But, should not be set for CREATE TRIGGER */
|
||||
#endif
|
||||
}
|
||||
|
||||
%type trigger_time {int}
|
||||
|
||||
+39
-51
@@ -294,7 +294,6 @@ static int lookupName(
|
||||
Schema *pSchema = 0; /* Schema of the expression */
|
||||
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
|
||||
Table *pTab = 0; /* Table holding the row */
|
||||
Column *pCol; /* A column of pTab */
|
||||
ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
|
||||
const char *zCol = pRight->u.zToken;
|
||||
|
||||
@@ -345,7 +344,6 @@ static int lookupName(
|
||||
|
||||
if( pSrcList ){
|
||||
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
|
||||
u8 hCol;
|
||||
pTab = pItem->pSTab;
|
||||
assert( pTab!=0 && pTab->zName!=0 );
|
||||
assert( pTab->nCol>0 || pParse->nErr );
|
||||
@@ -433,43 +431,38 @@ static int lookupName(
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
|
||||
}
|
||||
}
|
||||
hCol = sqlite3StrIHash(zCol);
|
||||
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
|
||||
if( pCol->hName==hCol
|
||||
&& sqlite3StrICmp(pCol->zCnName, zCol)==0
|
||||
){
|
||||
if( cnt>0 ){
|
||||
if( pItem->fg.isUsing==0
|
||||
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
|
||||
){
|
||||
/* Two or more tables have the same column name which is
|
||||
** not joined by USING. This is an error. Signal as much
|
||||
** by clearing pFJMatch and letting cnt go above 1. */
|
||||
sqlite3ExprListDelete(db, pFJMatch);
|
||||
pFJMatch = 0;
|
||||
}else
|
||||
if( (pItem->fg.jointype & JT_RIGHT)==0 ){
|
||||
/* An INNER or LEFT JOIN. Use the left-most table */
|
||||
continue;
|
||||
}else
|
||||
if( (pItem->fg.jointype & JT_LEFT)==0 ){
|
||||
/* A RIGHT JOIN. Use the right-most table */
|
||||
cnt = 0;
|
||||
sqlite3ExprListDelete(db, pFJMatch);
|
||||
pFJMatch = 0;
|
||||
}else{
|
||||
/* For a FULL JOIN, we must construct a coalesce() func */
|
||||
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
|
||||
}
|
||||
j = sqlite3ColumnIndex(pTab, zCol);
|
||||
if( j>=0 ){
|
||||
if( cnt>0 ){
|
||||
if( pItem->fg.isUsing==0
|
||||
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
|
||||
){
|
||||
/* Two or more tables have the same column name which is
|
||||
** not joined by USING. This is an error. Signal as much
|
||||
** by clearing pFJMatch and letting cnt go above 1. */
|
||||
sqlite3ExprListDelete(db, pFJMatch);
|
||||
pFJMatch = 0;
|
||||
}else
|
||||
if( (pItem->fg.jointype & JT_RIGHT)==0 ){
|
||||
/* An INNER or LEFT JOIN. Use the left-most table */
|
||||
continue;
|
||||
}else
|
||||
if( (pItem->fg.jointype & JT_LEFT)==0 ){
|
||||
/* A RIGHT JOIN. Use the right-most table */
|
||||
cnt = 0;
|
||||
sqlite3ExprListDelete(db, pFJMatch);
|
||||
pFJMatch = 0;
|
||||
}else{
|
||||
/* For a FULL JOIN, we must construct a coalesce() func */
|
||||
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
|
||||
}
|
||||
cnt++;
|
||||
pMatch = pItem;
|
||||
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
|
||||
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
|
||||
if( pItem->fg.isNestedFrom ){
|
||||
sqlite3SrcItemColumnUsed(pItem, j);
|
||||
}
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
pMatch = pItem;
|
||||
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
|
||||
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
|
||||
if( pItem->fg.isNestedFrom ){
|
||||
sqlite3SrcItemColumnUsed(pItem, j);
|
||||
}
|
||||
}
|
||||
if( 0==cnt && VisibleRowid(pTab) ){
|
||||
@@ -559,23 +552,18 @@ static int lookupName(
|
||||
|
||||
if( pTab ){
|
||||
int iCol;
|
||||
u8 hCol = sqlite3StrIHash(zCol);
|
||||
pSchema = pTab->pSchema;
|
||||
cntTab++;
|
||||
for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
|
||||
if( pCol->hName==hCol
|
||||
&& sqlite3StrICmp(pCol->zCnName, zCol)==0
|
||||
){
|
||||
if( iCol==pTab->iPKey ){
|
||||
iCol = -1;
|
||||
}
|
||||
break;
|
||||
iCol = sqlite3ColumnIndex(pTab, zCol);
|
||||
if( iCol>=0 ){
|
||||
if( pTab->iPKey==iCol ) iCol = -1;
|
||||
}else{
|
||||
if( sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
|
||||
iCol = -1;
|
||||
}else{
|
||||
iCol = pTab->nCol;
|
||||
}
|
||||
}
|
||||
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
|
||||
/* IMP: R-51414-32910 */
|
||||
iCol = -1;
|
||||
}
|
||||
if( iCol<pTab->nCol ){
|
||||
cnt++;
|
||||
pMatch = 0;
|
||||
|
||||
+27
-4
@@ -319,10 +319,33 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
|
||||
*/
|
||||
int sqlite3ColumnIndex(Table *pTab, const char *zCol){
|
||||
int i;
|
||||
u8 h = sqlite3StrIHash(zCol);
|
||||
Column *pCol;
|
||||
for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
|
||||
if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
|
||||
u8 h;
|
||||
const Column *aCol;
|
||||
int nCol;
|
||||
|
||||
h = sqlite3StrIHash(zCol);
|
||||
aCol = pTab->aCol;
|
||||
nCol = pTab->nCol;
|
||||
|
||||
/* See if the aHx gives us a lucky match */
|
||||
i = pTab->aHx[h % sizeof(pTab->aHx)];
|
||||
assert( i<nCol );
|
||||
if( aCol[i].hName==h
|
||||
&& sqlite3StrICmp(aCol[i].zCnName, zCol)==0
|
||||
){
|
||||
return i;
|
||||
}
|
||||
|
||||
/* No lucky match from the hash table. Do a full search. */
|
||||
i = 0;
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
if( aCol[i].hName==h
|
||||
&& sqlite3StrICmp(aCol[i].zCnName, zCol)==0
|
||||
){
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
if( i>=nCol ) break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+31
-19
@@ -843,6 +843,11 @@ typedef INT16_TYPE i16; /* 2-byte signed integer */
|
||||
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
|
||||
typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
|
||||
/* A bitfield type for use inside of structures. Always follow with :N where
|
||||
** N is the number of bits.
|
||||
*/
|
||||
typedef unsigned bft; /* Bit Field Type */
|
||||
|
||||
/*
|
||||
** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
|
||||
** that can be stored in a u32 without loss of data. The value
|
||||
@@ -2426,6 +2431,7 @@ struct Table {
|
||||
} u;
|
||||
Trigger *pTrigger; /* List of triggers on this object */
|
||||
Schema *pSchema; /* Schema that contains this table */
|
||||
u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3823,25 +3829,32 @@ struct Parse {
|
||||
char *zErrMsg; /* An error message */
|
||||
Vdbe *pVdbe; /* An engine for executing database bytecode */
|
||||
int rc; /* Return code from execution */
|
||||
u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
|
||||
u8 checkSchema; /* Causes schema cookie check after an error */
|
||||
LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
|
||||
u8 nested; /* Number of nested calls to the parser/code generator */
|
||||
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
|
||||
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
|
||||
u8 mayAbort; /* True if statement may throw an ABORT exception */
|
||||
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
|
||||
u8 okConstFactor; /* OK to factor out constants */
|
||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
||||
u8 bHasWith; /* True if statement contains WITH */
|
||||
u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
|
||||
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
|
||||
u8 bReturning; /* Coding a RETURNING trigger */
|
||||
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
||||
u8 disableTriggers; /* True to disable triggers */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
|
||||
u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
|
||||
** and ALTER TABLE ADD COLUMN. */
|
||||
#endif
|
||||
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
|
||||
bft bHasWith :1; /* True if statement contains WITH */
|
||||
bft okConstFactor :1; /* OK to factor out constants */
|
||||
bft checkSchema :1; /* Causes schema cookie check after an error */
|
||||
int nRangeReg; /* Size of the temporary register block */
|
||||
int iRangeReg; /* First register in temporary register block */
|
||||
int nErr; /* Number of errors seen */
|
||||
@@ -3856,12 +3869,9 @@ struct Parse {
|
||||
ExprList *pConstExpr;/* Constant expressions */
|
||||
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
|
||||
IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
|
||||
Token constraintName;/* Name of the constraint currently being parsed */
|
||||
yDbMask writeMask; /* Start a write transaction on these databases */
|
||||
yDbMask cookieMask; /* Bitmask of schema verified databases */
|
||||
int regRowid; /* Register holding rowid of CREATE TABLE entry */
|
||||
int regRoot; /* Register holding root page number for new objects */
|
||||
int nMaxArg; /* Max args passed to user function by sub-program */
|
||||
int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */
|
||||
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
|
||||
@@ -3875,17 +3885,6 @@ struct Parse {
|
||||
Table *pTriggerTab; /* Table triggers are being coded for */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
|
||||
union {
|
||||
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
|
||||
Returning *pReturning; /* The RETURNING clause */
|
||||
} u1;
|
||||
u32 oldmask; /* Mask of old.* columns referenced */
|
||||
u32 newmask; /* Mask of new.* columns referenced */
|
||||
LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
|
||||
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
|
||||
u8 bReturning; /* Coding a RETURNING trigger */
|
||||
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
||||
u8 disableTriggers; /* True to disable triggers */
|
||||
|
||||
/**************************************************************************
|
||||
** Fields above must be initialized to zero. The fields that follow,
|
||||
@@ -3897,6 +3896,19 @@ struct Parse {
|
||||
int aTempReg[8]; /* Holding area for temporary registers */
|
||||
Parse *pOuterParse; /* Outer Parse object when nested */
|
||||
Token sNameToken; /* Token with unqualified schema object name */
|
||||
u32 oldmask; /* Mask of old.* columns referenced */
|
||||
u32 newmask; /* Mask of new.* columns referenced */
|
||||
union {
|
||||
struct { /* These fields available when isCreate is true */
|
||||
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
|
||||
int regRowid; /* Register holding rowid of CREATE TABLE entry */
|
||||
int regRoot; /* Register holding root page for new objects */
|
||||
Token constraintName; /* Name of the constraint currently being parsed */
|
||||
} cr;
|
||||
struct { /* These fields available to all other statements */
|
||||
Returning *pReturning; /* The RETURNING clause */
|
||||
} d;
|
||||
} u1;
|
||||
|
||||
/************************************************************************
|
||||
** Above is constant between recursions. Below is reset before and after
|
||||
|
||||
+6
-2
@@ -70,7 +70,8 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
||||
assert( pParse->db->pVtabCtx==0 );
|
||||
#endif
|
||||
assert( pParse->bReturning );
|
||||
assert( &(pParse->u1.pReturning->retTrig) == pTrig );
|
||||
assert( !pParse->isCreate );
|
||||
assert( &(pParse->u1.d.pReturning->retTrig) == pTrig );
|
||||
pTrig->table = pTab->zName;
|
||||
pTrig->pTabSchema = pTab->pSchema;
|
||||
pTrig->pNext = pList;
|
||||
@@ -1047,7 +1048,8 @@ static void codeReturningTrigger(
|
||||
return;
|
||||
}
|
||||
assert( db->pParse==pParse );
|
||||
pReturning = pParse->u1.pReturning;
|
||||
assert( !pParse->isCreate );
|
||||
pReturning = pParse->u1.d.pReturning;
|
||||
if( pTrigger != &(pReturning->retTrig) ){
|
||||
/* This RETURNING trigger is for a different statement */
|
||||
return;
|
||||
@@ -1277,6 +1279,8 @@ static TriggerPrg *codeRowTrigger(
|
||||
sSubParse.eTriggerOp = pTrigger->op;
|
||||
sSubParse.nQueryLoop = pParse->nQueryLoop;
|
||||
sSubParse.prepFlags = pParse->prepFlags;
|
||||
sSubParse.oldmask = 0;
|
||||
sSubParse.newmask = 0;
|
||||
|
||||
v = sqlite3GetVdbe(&sSubParse);
|
||||
if( v ){
|
||||
|
||||
+20
-26
@@ -465,38 +465,32 @@ void sqlite3Update(
|
||||
*/
|
||||
chngRowid = chngPk = 0;
|
||||
for(i=0; i<pChanges->nExpr; i++){
|
||||
u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
|
||||
/* If this is an UPDATE with a FROM clause, do not resolve expressions
|
||||
** here. The call to sqlite3Select() below will do that. */
|
||||
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
if( pTab->aCol[j].hName==hCol
|
||||
&& sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
|
||||
){
|
||||
if( j==pTab->iPKey ){
|
||||
chngRowid = 1;
|
||||
pRowidExpr = pChanges->a[i].pExpr;
|
||||
iRowidExpr = i;
|
||||
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
|
||||
chngPk = 1;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
|
||||
testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
|
||||
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot UPDATE generated column \"%s\"",
|
||||
pTab->aCol[j].zCnName);
|
||||
goto update_cleanup;
|
||||
}
|
||||
#endif
|
||||
aXRef[j] = i;
|
||||
break;
|
||||
j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName);
|
||||
if( j>=0 ){
|
||||
if( j==pTab->iPKey ){
|
||||
chngRowid = 1;
|
||||
pRowidExpr = pChanges->a[i].pExpr;
|
||||
iRowidExpr = i;
|
||||
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
|
||||
chngPk = 1;
|
||||
}
|
||||
}
|
||||
if( j>=pTab->nCol ){
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
|
||||
testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
|
||||
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"cannot UPDATE generated column \"%s\"",
|
||||
pTab->aCol[j].zCnName);
|
||||
goto update_cleanup;
|
||||
}
|
||||
#endif
|
||||
aXRef[j] = i;
|
||||
}else{
|
||||
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
|
||||
j = -1;
|
||||
chngRowid = 1;
|
||||
|
||||
+5
-1
@@ -1130,7 +1130,11 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
}
|
||||
p->z = &p->zBuf[i+1];
|
||||
assert( i+p->n < sizeof(p->zBuf) );
|
||||
while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
|
||||
assert( p->n>0 );
|
||||
while( p->z[p->n-1]=='0' ){
|
||||
p->n--;
|
||||
assert( p->n>0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+27
@@ -3055,6 +3055,7 @@ op_column_restart:
|
||||
goto op_column_restart;
|
||||
}
|
||||
|
||||
op_column_again:
|
||||
/* Make sure at least the first p2+1 entries of the header have been
|
||||
** parsed and valid information is in aOffset[] and pC->aType[].
|
||||
*/
|
||||
@@ -3210,6 +3211,30 @@ op_column_restart:
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to save work if two or more OP_Columns against the same
|
||||
** cursor occur one right after another.
|
||||
**
|
||||
** This optimization saves CPU cycles when it applies. But it is
|
||||
** not applicable very often. So we often burn more CPU cycles
|
||||
** determining whether or not the optimization does apply than the
|
||||
** optimization actually saves, depending on the workload. Even
|
||||
** when there is a net gain, it is not that much.
|
||||
**
|
||||
** This change (and this comment) are saved for future reference.
|
||||
** But unless some further improvement is found, it does not seem
|
||||
** worth the added complexity.
|
||||
*/
|
||||
if( pOp[1].opcode==OP_Column
|
||||
&& pC==p->apCsr[pOp[1].p1]
|
||||
){
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
pOp++;
|
||||
nVmStep++;
|
||||
p2 = (u32)pOp->p2;
|
||||
goto op_column_again;
|
||||
}
|
||||
|
||||
op_column_out:
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
@@ -8363,6 +8388,7 @@ case OP_VFilter: { /* jump, ncycle */
|
||||
|
||||
/* Invoke the xFilter method */
|
||||
apArg = p->apArg;
|
||||
assert( nArg<=p->napArg );
|
||||
for(i = 0; i<nArg; i++){
|
||||
apArg[i] = &pArgc[i+1];
|
||||
}
|
||||
@@ -8573,6 +8599,7 @@ case OP_VUpdate: {
|
||||
u8 vtabOnConflict = db->vtabOnConflict;
|
||||
apArg = p->apArg;
|
||||
pX = &aMem[pOp->p3];
|
||||
assert( nArg<=p->napArg );
|
||||
for(i=0; i<nArg; i++){
|
||||
assert( memIsValid(pX) );
|
||||
memAboutToChange(p, pX);
|
||||
|
||||
+2
-5
@@ -398,10 +398,6 @@ struct sqlite3_context {
|
||||
sqlite3_value *argv[1]; /* Argument set */
|
||||
};
|
||||
|
||||
/* A bitfield type for use inside of structures. Always follow with :N where
|
||||
** N is the number of bits.
|
||||
*/
|
||||
typedef unsigned bft; /* Bit Field Type */
|
||||
|
||||
/* The ScanStatus object holds a single value for the
|
||||
** sqlite3_stmt_scanstatus() interface.
|
||||
@@ -462,7 +458,7 @@ struct Vdbe {
|
||||
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
|
||||
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
||||
Mem *aMem; /* The memory locations */
|
||||
Mem **apArg; /* Arguments to currently executing user function */
|
||||
Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */
|
||||
VdbeCursor **apCsr; /* One element of this array for each open cursor */
|
||||
Mem *aVar; /* Values for the OP_Variable opcode. */
|
||||
|
||||
@@ -482,6 +478,7 @@ struct Vdbe {
|
||||
#ifdef SQLITE_DEBUG
|
||||
int rcApp; /* errcode set by sqlite3_result_error_code() */
|
||||
u32 nWrite; /* Number of write operations that have occurred */
|
||||
int napArg; /* Size of the apArg[] array */
|
||||
#endif
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
u16 nResAlloc; /* Column slots allocated to aColName[] */
|
||||
|
||||
+15
-8
@@ -856,8 +856,8 @@ void sqlite3VdbeAssertAbortable(Vdbe *p){
|
||||
** (1) For each jump instruction with a negative P2 value (a label)
|
||||
** resolve the P2 value to an actual address.
|
||||
**
|
||||
** (2) Compute the maximum number of arguments used by any SQL function
|
||||
** and store that value in *pMaxFuncArgs.
|
||||
** (2) Compute the maximum number of arguments used by the xUpdate/xFilter
|
||||
** methods of any virtual table and store that value in *pMaxVtabArgs.
|
||||
**
|
||||
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
|
||||
** indicate what the prepared statement actually does.
|
||||
@@ -870,8 +870,8 @@ void sqlite3VdbeAssertAbortable(Vdbe *p){
|
||||
** script numbers the opcodes correctly. Changes to this routine must be
|
||||
** coordinated with changes to mkopcodeh.tcl.
|
||||
*/
|
||||
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
int nMaxArgs = *pMaxFuncArgs;
|
||||
static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){
|
||||
int nMaxVtabArgs = *pMaxVtabArgs;
|
||||
Op *pOp;
|
||||
Parse *pParse = p->pParse;
|
||||
int *aLabel = pParse->aLabel;
|
||||
@@ -916,15 +916,19 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
case OP_VUpdate: {
|
||||
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
|
||||
if( pOp->p2>nMaxVtabArgs ) nMaxVtabArgs = pOp->p2;
|
||||
break;
|
||||
}
|
||||
case OP_VFilter: {
|
||||
int n;
|
||||
/* The instruction immediately prior to VFilter will be an
|
||||
** OP_Integer that sets the "argc" value for the VFilter. See
|
||||
** the code where OP_VFilter is generated at tag-20250207a. */
|
||||
assert( (pOp - p->aOp) >= 3 );
|
||||
assert( pOp[-1].opcode==OP_Integer );
|
||||
assert( pOp[-1].p2==pOp->p3+1 );
|
||||
n = pOp[-1].p1;
|
||||
if( n>nMaxArgs ) nMaxArgs = n;
|
||||
if( n>nMaxVtabArgs ) nMaxVtabArgs = n;
|
||||
/* Fall through into the default case */
|
||||
/* no break */ deliberate_fall_through
|
||||
}
|
||||
@@ -965,7 +969,7 @@ resolve_p2_values_loop_exit:
|
||||
pParse->aLabel = 0;
|
||||
}
|
||||
pParse->nLabel = 0;
|
||||
*pMaxFuncArgs = nMaxArgs;
|
||||
*pMaxVtabArgs = nMaxVtabArgs;
|
||||
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
|
||||
}
|
||||
|
||||
@@ -2643,7 +2647,7 @@ void sqlite3VdbeMakeReady(
|
||||
int nVar; /* Number of parameters */
|
||||
int nMem; /* Number of VM memory registers */
|
||||
int nCursor; /* Number of cursors required */
|
||||
int nArg; /* Number of arguments in subprograms */
|
||||
int nArg; /* Max number args to xFilter or xUpdate */
|
||||
int n; /* Loop counter */
|
||||
struct ReusableSpace x; /* Reusable bulk memory */
|
||||
|
||||
@@ -2715,6 +2719,9 @@ void sqlite3VdbeMakeReady(
|
||||
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->napArg = nArg;
|
||||
#endif
|
||||
|
||||
if( db->mallocFailed ){
|
||||
p->nVar = 0;
|
||||
|
||||
+2
-6
@@ -192,12 +192,8 @@ int sqlite3_blob_open(
|
||||
pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
|
||||
|
||||
/* Now search pTab for the exact column. */
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++) {
|
||||
if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( iCol==pTab->nCol ){
|
||||
iCol = sqlite3ColumnIndex(pTab, zColumn);
|
||||
if( iCol<0 ){
|
||||
sqlite3DbFree(db, zErr);
|
||||
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
|
||||
rc = SQLITE_ERROR;
|
||||
|
||||
+1
-1
@@ -327,7 +327,7 @@ void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
|
||||
return;
|
||||
}
|
||||
if( pMem->enc!=SQLITE_UTF8 ) return;
|
||||
if( NEVER(pMem->z==0) ) return;
|
||||
assert( pMem->z!=0 );
|
||||
if( pMem->flags & MEM_Dyn ){
|
||||
if( pMem->xDel==sqlite3_free
|
||||
&& sqlite3_msize(pMem->z) >= (u64)(pMem->n+1)
|
||||
|
||||
+3
-2
@@ -479,11 +479,12 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
||||
** schema table. We just need to update that slot with all
|
||||
** the information we've collected.
|
||||
**
|
||||
** The VM register number pParse->regRowid holds the rowid of an
|
||||
** The VM register number pParse->u1.cr.regRowid holds the rowid of an
|
||||
** entry in the sqlite_schema table that was created for this vtab
|
||||
** by sqlite3StartTable().
|
||||
*/
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( pParse->isCreate );
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q." LEGACY_SCHEMA_TABLE " "
|
||||
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
|
||||
@@ -492,7 +493,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
||||
pTab->zName,
|
||||
pTab->zName,
|
||||
zStmt,
|
||||
pParse->regRowid
|
||||
pParse->u1.cr.regRowid
|
||||
);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
|
||||
@@ -1608,6 +1608,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
|
||||
/* The instruction immediately prior to OP_VFilter must be an OP_Integer
|
||||
** that sets the "argc" value for xVFilter. This is necessary for
|
||||
** resolveP2() to work correctly. See tag-20250207a. */
|
||||
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
|
||||
pLoop->u.vtab.idxStr,
|
||||
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
|
||||
|
||||
@@ -27,6 +27,7 @@ Other options include:
|
||||
--lookaside N SZ Lookahead uses N slots of SZ bytes each.
|
||||
--pagesize N Use N as the page size.
|
||||
--quiet | -q "Quite". Put results in file but don't pop up editor
|
||||
--size N Change the test size. 100 means 100%. Default: 5.
|
||||
--testset TEST Specify the specific testset to use. The default
|
||||
is "mix1". Other options include: "main", "json",
|
||||
"cte", "orm", "fp", "rtree".
|
||||
@@ -78,6 +79,14 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
incr i
|
||||
set testset [lindex $argv $i]
|
||||
}
|
||||
-size -
|
||||
--size {
|
||||
incr i
|
||||
set newsize [lindex $argv $i]
|
||||
if {$newsize<1} {set newsize 1}
|
||||
set speedtestflags \
|
||||
[regsub {.-size \d+} $speedtestflags "-size $newsize"]
|
||||
}
|
||||
-n -
|
||||
-dryrun -
|
||||
--dryrun {
|
||||
@@ -174,9 +183,14 @@ if {!$dryrun} {
|
||||
}
|
||||
lappend speedtestflags --testset $testset
|
||||
set stcmd [list valgrind --tool=cachegrind ./speedtest1 {*}$speedtestflags]
|
||||
lappend stcmd speedtest1.db
|
||||
lappend stcmd >valgrind-out.txt 2>valgrind-err.txt
|
||||
puts $stcmd
|
||||
if {!$dryrun} {
|
||||
foreach file {speedtest1.db speedtest1.db-journal speedtest1.db-wal
|
||||
speedtest1.db-shm} {
|
||||
if {[file exists $file]} {file delete $file}
|
||||
}
|
||||
exec {*}$stcmd
|
||||
}
|
||||
|
||||
|
||||
+582
-19
@@ -64,10 +64,9 @@ static const char zHelp[] =
|
||||
" --stats Show statistics at the end\n"
|
||||
" --stmtscanstatus Activate SQLITE_DBCONFIG_STMT_SCANSTATUS\n"
|
||||
" --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n"
|
||||
" --testset T Run test-set T (main, cte, rtree, orm, fp, json,"
|
||||
" debug)\n"
|
||||
" Can be a comma-separated list of values, with /SCALE\n"
|
||||
" suffixes or macro \"mix1\"\n"
|
||||
" --testset T Run test-set T (main, cte, rtree, orm, fp, json,\n"
|
||||
" star, app, debug). Can be a comma-separated list\n"
|
||||
" of values, with /SCALE suffixes or macro \"mix1\"\n"
|
||||
" --trace Turn on SQL tracing\n"
|
||||
" --threads N Use up to N threads for sorting\n"
|
||||
" --utf16be Set text encoding to UTF-16BE\n"
|
||||
@@ -113,6 +112,8 @@ struct HashContext {
|
||||
/* All global state is held in this structure */
|
||||
static struct Global {
|
||||
sqlite3 *db; /* The open database connection */
|
||||
const char *zDbName; /* Name of the database file */
|
||||
const char *zVfs; /* --vfs NAME */
|
||||
sqlite3_stmt *pStmt; /* Current SQL statement */
|
||||
sqlite3_int64 iStart; /* Start-time for the current test */
|
||||
sqlite3_int64 iTotal; /* Total time */
|
||||
@@ -1458,6 +1459,561 @@ void testset_fp(void){
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
/*
|
||||
** A testset for star-schema queries.
|
||||
*/
|
||||
void testset_star(void){
|
||||
int n;
|
||||
int i;
|
||||
n = g.szTest*50;
|
||||
speedtest1_begin_test(100, "Create a fact table with %d entries", n);
|
||||
speedtest1_exec(
|
||||
"CREATE TABLE facttab("
|
||||
" attr01 INT,"
|
||||
" attr02 INT,"
|
||||
" attr03 INT,"
|
||||
" data01 TEXT,"
|
||||
" attr04 INT,"
|
||||
" attr05 INT,"
|
||||
" attr06 INT,"
|
||||
" attr07 INT,"
|
||||
" attr08 INT,"
|
||||
" factid INTEGER PRIMARY KEY,"
|
||||
" data02 TEXT"
|
||||
");"
|
||||
);
|
||||
speedtest1_exec(
|
||||
"WITH RECURSIVE counter(nnn) AS"
|
||||
"(VALUES(1) UNION ALL SELECT nnn+1 FROM counter WHERE nnn<%d)"
|
||||
"INSERT INTO facttab(attr01,attr02,attr03,attr04,attr05,"
|
||||
"attr06,attr07,attr08,data01,data02)"
|
||||
"SELECT random()%%12, random()%%13, random()%%14, random()%%15,"
|
||||
"random()%%16, random()%%17, random()%%18, random()%%19,"
|
||||
"concat('data-',nnn), format('%%x',random()) FROM counter;",
|
||||
n
|
||||
);
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(110, "Create indexes on all attributes columns");
|
||||
for(i=1; i<=8; i++){
|
||||
speedtest1_exec(
|
||||
"CREATE INDEX fact_attr%02d ON facttab(attr%02d)", i, i
|
||||
);
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(120, "Create dimension tables");
|
||||
for(i=1; i<=8; i++){
|
||||
speedtest1_exec(
|
||||
"CREATE TABLE dimension%02d("
|
||||
"beta%02d INT, "
|
||||
"content%02d TEXT, "
|
||||
"rate%02d REAL)",
|
||||
i, i, i, i
|
||||
);
|
||||
speedtest1_exec(
|
||||
"WITH RECURSIVE ctr(nn) AS"
|
||||
" (VALUES(1) UNION ALL SELECT nn+1 FROM ctr WHERE nn<%d)"
|
||||
" INSERT INTO dimension%02d"
|
||||
" SELECT nn%%(%d), concat('content-%02d-',nn),"
|
||||
" (random()%%10000)*0.125 FROM ctr;",
|
||||
4*(i+1), i, 2*(i+1), i
|
||||
);
|
||||
if( i&2 ){
|
||||
speedtest1_exec(
|
||||
"CREATE INDEX dim%02d ON dimension%02d(beta%02d);",
|
||||
i, i, i
|
||||
);
|
||||
}else{
|
||||
speedtest1_exec(
|
||||
"CREATE INDEX dim%02d ON dimension%02d(beta%02d,content%02d);",
|
||||
i, i, i, i
|
||||
);
|
||||
}
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(130, "Star query over the entire fact table");
|
||||
speedtest1_exec(
|
||||
"SELECT count(*), max(content04), min(content03), sum(rate04), avg(rate05)"
|
||||
" FROM facttab, dimension01, dimension02, dimension03, dimension04,"
|
||||
" dimension05, dimension06, dimension07, dimension08"
|
||||
" WHERE attr01=beta01"
|
||||
" AND attr02=beta02"
|
||||
" AND attr03=beta03"
|
||||
" AND attr04=beta04"
|
||||
" AND attr05=beta05"
|
||||
" AND attr06=beta06"
|
||||
" AND attr07=beta07"
|
||||
" AND attr08=beta08"
|
||||
";"
|
||||
);
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(130, "Star query with LEFT JOINs");
|
||||
speedtest1_exec(
|
||||
"SELECT count(*), max(content04), min(content03), sum(rate04), avg(rate05)"
|
||||
" FROM facttab LEFT JOIN dimension01 ON attr01=beta01"
|
||||
" LEFT JOIN dimension02 ON attr02=beta02"
|
||||
" JOIN dimension03 ON attr03=beta03"
|
||||
" JOIN dimension04 ON attr04=beta04"
|
||||
" JOIN dimension05 ON attr05=beta05"
|
||||
" LEFT JOIN dimension06 ON attr06=beta06"
|
||||
" JOIN dimension07 ON attr07=beta07"
|
||||
" JOIN dimension08 ON attr08=beta08"
|
||||
" WHERE facttab.data01 LIKE 'data-9%%'"
|
||||
";"
|
||||
);
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
/*
|
||||
** Tests that simulate an application opening and closing an SQLite database
|
||||
** frequently. Fossil is used as the model. The focus here is on rapidly
|
||||
** parsing the database schema and rapidly generating prepared statements,
|
||||
** in other words, rapid start-up of Fossil-like applications.
|
||||
**
|
||||
** The same database has no data, so the performance of sqlite3_step() is
|
||||
** not significant to this testset.
|
||||
*/
|
||||
static void testset_app(void){
|
||||
int i, n;
|
||||
speedtest1_begin_test(100, "Generate a Fossil-like database schema");
|
||||
speedtest1_exec(
|
||||
"BEGIN;"
|
||||
"CREATE TABLE blob(\n"
|
||||
" rid INTEGER PRIMARY KEY,\n"
|
||||
" rcvid INTEGER,\n"
|
||||
" size INTEGER,\n"
|
||||
" uuid TEXT UNIQUE NOT NULL,\n"
|
||||
" content BLOB,\n"
|
||||
" CHECK( length(uuid)>=40 AND rid>0 )\n"
|
||||
");\n"
|
||||
"CREATE TABLE delta(\n"
|
||||
" rid INTEGER PRIMARY KEY,\n"
|
||||
" srcid INTEGER NOT NULL REFERENCES blob\n"
|
||||
");\n"
|
||||
"CREATE TABLE rcvfrom(\n"
|
||||
" rcvid INTEGER PRIMARY KEY,\n"
|
||||
" uid INTEGER REFERENCES user,\n"
|
||||
" mtime DATETIME,\n"
|
||||
" nonce TEXT UNIQUE,\n"
|
||||
" ipaddr TEXT\n"
|
||||
");\n"
|
||||
"CREATE TABLE private(rid INTEGER PRIMARY KEY);\n"
|
||||
"CREATE TABLE accesslog(\n"
|
||||
" uname TEXT,\n"
|
||||
" ipaddr TEXT,\n"
|
||||
" success BOOLEAN,\n"
|
||||
" mtime TIMESTAMP\n"
|
||||
");\n"
|
||||
"CREATE TABLE user(\n"
|
||||
" uid INTEGER PRIMARY KEY,\n"
|
||||
" login TEXT UNIQUE,\n"
|
||||
" pw TEXT,\n"
|
||||
" cap TEXT,\n"
|
||||
" cookie TEXT,\n"
|
||||
" ipaddr TEXT,\n"
|
||||
" cexpire DATETIME,\n"
|
||||
" info TEXT,\n"
|
||||
" mtime DATE,\n"
|
||||
" photo BLOB\n"
|
||||
", jx TEXT DEFAULT '{}');\n"
|
||||
"CREATE TABLE reportfmt(\n"
|
||||
" rn INTEGER PRIMARY KEY,\n"
|
||||
" owner TEXT,\n"
|
||||
" title TEXT UNIQUE,\n"
|
||||
" mtime INTEGER,\n"
|
||||
" cols TEXT,\n"
|
||||
" sqlcode TEXT\n"
|
||||
", jx TEXT DEFAULT '{}');\n"
|
||||
"CREATE TABLE config(\n"
|
||||
" name TEXT PRIMARY KEY NOT NULL,\n"
|
||||
" value CLOB, mtime INTEGER,\n"
|
||||
" CHECK( typeof(name)='text' AND length(name)>=1 )\n"
|
||||
") WITHOUT ROWID;\n"
|
||||
"CREATE TABLE shun(uuid PRIMARY KEY, mtime INTEGER, scom TEXT)\n"
|
||||
" WITHOUT ROWID;\n"
|
||||
"CREATE TABLE concealed(\n"
|
||||
" hash TEXT PRIMARY KEY,\n"
|
||||
" content TEXT\n"
|
||||
", mtime INTEGER) WITHOUT ROWID;\n"
|
||||
"CREATE TABLE admin_log(\n"
|
||||
" id INTEGER PRIMARY KEY,\n"
|
||||
" time INTEGER, -- Seconds since 1970\n"
|
||||
" page TEXT, -- path of page\n"
|
||||
" who TEXT, -- User who made the change\n"
|
||||
" what TEXT -- What changed\n"
|
||||
");\n"
|
||||
"CREATE TABLE unversioned(\n"
|
||||
" name TEXT PRIMARY KEY,\n"
|
||||
" rcvid INTEGER,\n"
|
||||
" mtime DATETIME,\n"
|
||||
" hash TEXT,\n"
|
||||
" sz INTEGER,\n"
|
||||
" encoding INT,\n"
|
||||
" content BLOB\n"
|
||||
") WITHOUT ROWID;\n"
|
||||
"CREATE TABLE subscriber(\n"
|
||||
" subscriberId INTEGER PRIMARY KEY,\n"
|
||||
" subscriberCode BLOB DEFAULT (randomblob(32)) UNIQUE,\n"
|
||||
" semail TEXT UNIQUE COLLATE nocase,\n"
|
||||
" suname TEXT,\n"
|
||||
" sverified BOOLEAN DEFAULT true,\n"
|
||||
" sdonotcall BOOLEAN,\n"
|
||||
" sdigest BOOLEAN,\n"
|
||||
" ssub TEXT,\n"
|
||||
" sctime INTDATE,\n"
|
||||
" mtime INTDATE,\n"
|
||||
" smip TEXT\n"
|
||||
", lastContact INT);\n"
|
||||
"CREATE TABLE pending_alert(\n"
|
||||
" eventid TEXT PRIMARY KEY,\n"
|
||||
" sentSep BOOLEAN DEFAULT false,\n"
|
||||
" sentDigest BOOLEAN DEFAULT false\n"
|
||||
", sentMod BOOLEAN DEFAULT false) WITHOUT ROWID;\n"
|
||||
"CREATE TABLE filename(\n"
|
||||
" fnid INTEGER PRIMARY KEY,\n"
|
||||
" name TEXT UNIQUE\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE mlink(\n"
|
||||
" mid INTEGER,\n"
|
||||
" fid INTEGER,\n"
|
||||
" pmid INTEGER,\n"
|
||||
" pid INTEGER,\n"
|
||||
" fnid INTEGER REFERENCES filename,\n"
|
||||
" pfnid INTEGER,\n"
|
||||
" mperm INTEGER,\n"
|
||||
" isaux INT DEFAULT 0\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE plink(\n"
|
||||
" pid INTEGER REFERENCES blob,\n"
|
||||
" cid INTEGER REFERENCES blob,\n"
|
||||
" isprim INT,\n"
|
||||
" mtime REAL,\n"
|
||||
" baseid INTEGER REFERENCES blob,\n"
|
||||
" UNIQUE(pid, cid)\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE leaf(rid INTEGER PRIMARY KEY);\n"
|
||||
"CREATE TABLE event(\n"
|
||||
" type TEXT,\n"
|
||||
" mtime REAL,\n"
|
||||
" objid INTEGER PRIMARY KEY,\n"
|
||||
" tagid INTEGER,\n"
|
||||
" uid INTEGER REFERENCES user,\n"
|
||||
" bgcolor TEXT,\n"
|
||||
" euser TEXT,\n"
|
||||
" user TEXT,\n"
|
||||
" ecomment TEXT,\n"
|
||||
" comment TEXT,\n"
|
||||
" brief TEXT,\n"
|
||||
" omtime REAL\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE phantom(\n"
|
||||
" rid INTEGER PRIMARY KEY\n"
|
||||
");\n"
|
||||
"CREATE TABLE orphan(\n"
|
||||
" rid INTEGER PRIMARY KEY,\n"
|
||||
" baseline INTEGER\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE unclustered(\n"
|
||||
" rid INTEGER PRIMARY KEY\n"
|
||||
");\n"
|
||||
"CREATE TABLE unsent(\n"
|
||||
" rid INTEGER PRIMARY KEY\n"
|
||||
");\n"
|
||||
"CREATE TABLE tag(\n"
|
||||
" tagid INTEGER PRIMARY KEY,\n"
|
||||
" tagname TEXT UNIQUE\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE tagxref(\n"
|
||||
" tagid INTEGER REFERENCES tag,\n"
|
||||
" tagtype INTEGER,\n"
|
||||
" srcid INTEGER REFERENCES blob,\n"
|
||||
" origid INTEGER REFERENCES blob,\n"
|
||||
" value TEXT,\n"
|
||||
" mtime REAL,\n"
|
||||
" rid INTEGER REFERENCES blob,\n"
|
||||
" UNIQUE(rid, tagid)\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE backlink(\n"
|
||||
" target TEXT,\n"
|
||||
" srctype INT,\n"
|
||||
" srcid INT,\n"
|
||||
" mtime REAL,\n"
|
||||
" UNIQUE(target, srctype, srcid)\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE attachment(\n"
|
||||
" attachid INTEGER PRIMARY KEY,\n"
|
||||
" isLatest INT DEFAULT 0,\n"
|
||||
" mtime REAL,\n"
|
||||
" src TEXT,\n"
|
||||
" target TEXT,\n"
|
||||
" filename TEXT,\n"
|
||||
" comment TEXT,\n"
|
||||
" user TEXT\n"
|
||||
") STRICT;\n"
|
||||
"CREATE TABLE cherrypick(\n"
|
||||
" parentid INT,\n"
|
||||
" childid INT,\n"
|
||||
" isExclude INT DEFAULT false,\n"
|
||||
" PRIMARY KEY(parentid, childid)\n"
|
||||
") WITHOUT ROWID, STRICT;\n"
|
||||
"CREATE TABLE vcache(\n"
|
||||
" vid INTEGER, -- check-in ID\n"
|
||||
" fname TEXT, -- filename\n"
|
||||
" rid INTEGER, -- artifact ID\n"
|
||||
" PRIMARY KEY(vid,fname)\n"
|
||||
") WITHOUT ROWID;\n"
|
||||
"CREATE TABLE synclog(\n"
|
||||
" sfrom TEXT,\n"
|
||||
" sto TEXT,\n"
|
||||
" stime INT NOT NULL,\n"
|
||||
" stype TEXT,\n"
|
||||
" PRIMARY KEY(sfrom,sto)\n"
|
||||
") WITHOUT ROWID;\n"
|
||||
"CREATE TABLE chat(\n"
|
||||
" msgid INTEGER PRIMARY KEY AUTOINCREMENT,\n"
|
||||
" mtime JULIANDAY,\n"
|
||||
" lmtime TEXT,\n"
|
||||
" xfrom TEXT,\n"
|
||||
" xmsg TEXT,\n"
|
||||
" fname TEXT,\n"
|
||||
" fmime TEXT,\n"
|
||||
" mdel INT,\n"
|
||||
" file BLOB\n"
|
||||
");\n"
|
||||
"CREATE TABLE ftsdocs(\n"
|
||||
" rowid INTEGER PRIMARY KEY,\n"
|
||||
" type CHAR(1),\n"
|
||||
" rid INTEGER,\n"
|
||||
" name TEXT,\n"
|
||||
" idxed BOOLEAN,\n"
|
||||
" label TEXT,\n"
|
||||
" url TEXT,\n"
|
||||
" mtime DATE,\n"
|
||||
" bx TEXT,\n"
|
||||
" UNIQUE(type,rid)\n"
|
||||
");\n"
|
||||
"CREATE TABLE ticket(\n"
|
||||
" -- Do not change any column that begins with tkt_\n"
|
||||
" tkt_id INTEGER PRIMARY KEY,\n"
|
||||
" tkt_uuid TEXT UNIQUE,\n"
|
||||
" tkt_mtime DATE,\n"
|
||||
" tkt_ctime DATE,\n"
|
||||
" -- Add as many fields as required below this line\n"
|
||||
" type TEXT,\n"
|
||||
" status TEXT,\n"
|
||||
" subsystem TEXT,\n"
|
||||
" priority TEXT,\n"
|
||||
" severity TEXT,\n"
|
||||
" foundin TEXT,\n"
|
||||
" private_contact TEXT,\n"
|
||||
" resolution TEXT,\n"
|
||||
" title TEXT,\n"
|
||||
" comment TEXT\n"
|
||||
");\n"
|
||||
"CREATE TABLE ticketchng(\n"
|
||||
" -- Do not change any column that begins with tkt_\n"
|
||||
" tkt_id INTEGER REFERENCES ticket,\n"
|
||||
" tkt_rid INTEGER REFERENCES blob,\n"
|
||||
" tkt_mtime DATE,\n"
|
||||
" tkt_user TEXT,\n"
|
||||
" -- Add as many fields as required below this line\n"
|
||||
" login TEXT,\n"
|
||||
" username TEXT,\n"
|
||||
" mimetype TEXT,\n"
|
||||
" icomment TEXT\n"
|
||||
");\n"
|
||||
"CREATE TABLE forumpost(\n"
|
||||
" fpid INTEGER PRIMARY KEY,\n"
|
||||
" froot INT,\n"
|
||||
" fprev INT,\n"
|
||||
" firt INT,\n"
|
||||
" fmtime REAL\n"
|
||||
");\n"
|
||||
"CREATE INDEX delta_i1 ON delta(srcid);\n"
|
||||
"CREATE INDEX blob_rcvid ON blob(rcvid);\n"
|
||||
"CREATE INDEX subscriberUname\n"
|
||||
" ON subscriber(suname) WHERE suname IS NOT NULL;\n"
|
||||
"CREATE INDEX mlink_i1 ON mlink(mid);\n"
|
||||
"CREATE INDEX mlink_i2 ON mlink(fnid);\n"
|
||||
"CREATE INDEX mlink_i3 ON mlink(fid);\n"
|
||||
"CREATE INDEX mlink_i4 ON mlink(pid);\n"
|
||||
"CREATE INDEX plink_i2 ON plink(cid,pid);\n"
|
||||
"CREATE INDEX event_i1 ON event(mtime);\n"
|
||||
"CREATE INDEX orphan_baseline ON orphan(baseline);\n"
|
||||
"CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);\n"
|
||||
"CREATE INDEX backlink_src ON backlink(srcid, srctype);\n"
|
||||
"CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime);\n"
|
||||
"CREATE INDEX attachment_idx2 ON attachment(src);\n"
|
||||
"CREATE INDEX cherrypick_cid ON cherrypick(childid);\n"
|
||||
"CREATE INDEX ftsdocIdxed ON ftsdocs(type,rid,name) WHERE idxed==0;\n"
|
||||
"CREATE INDEX ftsdocName ON ftsdocs(name) WHERE type='w';\n"
|
||||
"CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime);\n"
|
||||
"CREATE INDEX forumthread ON forumpost(froot,fmtime);\n"
|
||||
"CREATE VIEW artifact(rid,rcvid,size,atype,srcid,hash,content) AS\n"
|
||||
" SELECT blob.rid,rcvid,size,1,srcid,uuid,content\n"
|
||||
" FROM blob LEFT JOIN delta ON (blob.rid=delta.rid);\n"
|
||||
"CREATE VIEW ftscontent AS\n"
|
||||
" SELECT rowid, type, rid, name, idxed, label, url, mtime,\n"
|
||||
" title(type,rid,name) AS 'title', body(type,rid,name) AS 'body'\n"
|
||||
" FROM ftsdocs;\n"
|
||||
);
|
||||
if( sqlite3_compileoption_used("ENABLE_FTS5") ){
|
||||
speedtest1_exec(
|
||||
"CREATE VIRTUAL TABLE ftsidx\n"
|
||||
" USING fts5(content=\"ftscontent\", title, body);\n"
|
||||
"CREATE VIRTUAL TABLE chatfts1 USING fts5(\n"
|
||||
" xmsg, content=chat, content_rowid=msgid,tokenize=porter);\n"
|
||||
);
|
||||
}else{
|
||||
speedtest1_exec(
|
||||
"CREATE TABLE ftsidx_data(id INTEGER PRIMARY KEY, block BLOB);\n"
|
||||
"CREATE TABLE ftsidx_idx(segid, term, pgno, PRIMARY KEY(segid, term))\n"
|
||||
" WITHOUT ROWID;\n"
|
||||
"CREATE TABLE ftsidx_docsize(id INTEGER PRIMARY KEY, sz BLOB);\n"
|
||||
"CREATE TABLE ftsidx_config(k PRIMARY KEY, v) WITHOUT ROWID;\n"
|
||||
"CREATE TABLE chatfts1_data(id INTEGER PRIMARY KEY, block BLOB);\n"
|
||||
"CREATE TABLE chatfts1_idx(segid, term, pgno, PRIMARY KEY(segid, term))\n"
|
||||
" WITHOUT ROWID;\n"
|
||||
"CREATE TABLE chatfts1_docsize(id INTEGER PRIMARY KEY, sz BLOB);\n"
|
||||
"CREATE TABLE chatfts1_config(k PRIMARY KEY, v) WITHOUT ROWID;\n"
|
||||
);
|
||||
}
|
||||
speedtest1_exec(
|
||||
"ANALYZE sqlite_schema;\n"
|
||||
"INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES\n"
|
||||
" ('ftsidx_config','ftsidx_config','1 1'),\n"
|
||||
" ('ftsidx_idx','ftsidx_idx','4215 401 1'),\n"
|
||||
" ('user','sqlite_autoindex_user_1','25 1'),\n"
|
||||
" ('phantom',NULL,'26'),\n"
|
||||
" ('reportfmt','sqlite_autoindex_reportfmt_1','9 1'),\n"
|
||||
" ('rcvfrom','sqlite_autoindex_rcvfrom_1','18445 401'),\n"
|
||||
" ('private',NULL,'99'),\n"
|
||||
" ('mlink','mlink_i4','116678 401'),\n"
|
||||
" ('mlink','mlink_i3','121212 2'),\n"
|
||||
" ('mlink','mlink_i2','106372 401'),\n"
|
||||
" ('mlink','mlink_i1','99298 5'),\n"
|
||||
" ('ftsidx_data',NULL,'3795'),\n"
|
||||
" ('leaf',NULL,'1559'),\n"
|
||||
" ('delta','delta_i1','66340 1'),\n"
|
||||
" ('unversioned','unversioned','3 1'),\n"
|
||||
" ('pending_alert','pending_alert','3 1'),\n"
|
||||
" ('cherrypick','cherrypick_cid','680 2'),\n"
|
||||
" ('cherrypick','cherrypick','628 1 1'),\n"
|
||||
" ('config','config','128 1'),\n"
|
||||
" ('ftsidx_docsize',NULL,'33848'),\n"
|
||||
" ('event','event_i1','36096 1'),\n"
|
||||
" ('plink','plink_i2','38236 1 1'),\n"
|
||||
" ('plink','sqlite_autoindex_plink_1','38357 1 1'),\n"
|
||||
" ('shun','shun','10 1'),\n"
|
||||
" ('concealed','concealed','110 1'),\n"
|
||||
" ('vcache','vcache','1888 401 1'),\n"
|
||||
" ('ftsdocs','ftsdocName','19 1'),\n"
|
||||
" ('ftsdocs','ftsdocIdxed','168 84 1 1'),\n"
|
||||
" ('ftsdocs','sqlite_autoindex_ftsdocs_1','37312 401 1'),\n"
|
||||
" ('subscriber','subscriberUname','5 1'),\n"
|
||||
" ('subscriber','sqlite_autoindex_subscriber_2','37 1'),\n"
|
||||
" ('subscriber','sqlite_autoindex_subscriber_1','37 1'),\n"
|
||||
" ('tag','sqlite_autoindex_tag_1','2990 1'),\n"
|
||||
" ('filename','sqlite_autoindex_filename_1','3168 1'),\n"
|
||||
" ('chat',NULL,'56124'),\n"
|
||||
" ('tagxref','tagxref_i1','40992 401 2'),\n"
|
||||
" ('tagxref','sqlite_autoindex_tagxref_1','79233 3 1'),\n"
|
||||
" ('attachment','attachment_idx2','11 1'),\n"
|
||||
" ('attachment','attachment_idx1','11 2 2 1'),\n"
|
||||
" ('blob','blob_rcvid','128240 201'),\n"
|
||||
" ('blob','sqlite_autoindex_blob_1','126480 1'),\n"
|
||||
" ('synclog','synclog','12 3 1'),\n"
|
||||
" ('backlink','backlink_src','2160 2 2'),\n"
|
||||
" ('backlink','sqlite_autoindex_backlink_1','2340 2 2 1'),\n"
|
||||
" ('accesslog',NULL,'38'),\n"
|
||||
" ('chatfts1_config','chatfts1_config','1 1'),\n"
|
||||
" ('chatfts1_idx','chatfts1_idx','688 230 1'),\n"
|
||||
" ('ticket','sqlite_autoindex_ticket_1','794 1'),\n"
|
||||
" ('ticketchng','ticketchng_idx1','2089 3 1'),\n"
|
||||
" ('forumpost','forumthread','4 4 1'),\n"
|
||||
" ('unclustered',NULL,'12');\n"
|
||||
"COMMIT;"
|
||||
);
|
||||
speedtest1_end_test();
|
||||
|
||||
n = g.szTest*3;
|
||||
speedtest1_begin_test(110, "Open and use the database %d times", n);
|
||||
for(i=0; i<n; i++){
|
||||
sqlite3 *dbMain = g.db;
|
||||
sqlite3 *dbAux = 0;
|
||||
if( g.zDbName && g.zDbName[0] ){
|
||||
if( sqlite3_open_v2(g.zDbName, &dbAux, SQLITE_OPEN_READWRITE, g.zVfs) ){
|
||||
fatal_error("Cannot open database file: %s\n", g.zDbName);
|
||||
}
|
||||
g.db = dbAux;
|
||||
}
|
||||
speedtest1_exec(
|
||||
"SELECT name FROM pragma_table_list /*scan*/"
|
||||
" WHERE schema='repository' AND type IN ('table','virtual')"
|
||||
" AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
|
||||
"'config','shun','private','reportfmt',"
|
||||
"'concealed','accesslog','modreq',"
|
||||
"'purgeevent','purgeitem','unversioned',"
|
||||
"'subscriber','pending_alert','chat')"
|
||||
" AND name NOT GLOB 'sqlite_*'"
|
||||
" AND name NOT GLOB 'fx_*';"
|
||||
"SELECT 1 FROM pragma_table_xinfo('ticket') WHERE name = 'mimetype';"
|
||||
);
|
||||
speedtest1_exec(
|
||||
"SELECT"
|
||||
" name,"
|
||||
" value,"
|
||||
" unixepoch()/86400-value,"
|
||||
" date(value*86400,'unixepoch')"
|
||||
" FROM config"
|
||||
" WHERE name in ('email-renew-warning','email-renew-cutoff');"
|
||||
"SELECT count(*) FROM pending_alert WHERE NOT sentDigest;"
|
||||
);
|
||||
speedtest1_exec(
|
||||
"WITH priors(rid,who) AS ("
|
||||
" SELECT firt, coalesce(euser,user)"
|
||||
" FROM forumpost LEFT JOIN event ON fpid=objid"
|
||||
" WHERE fpid=12345"
|
||||
" UNION ALL"
|
||||
" SELECT firt, coalesce(euser,user)"
|
||||
" FROM priors, forumpost LEFT JOIN event ON fpid=objid"
|
||||
" WHERE fpid=rid"
|
||||
")"
|
||||
"SELECT ','||group_concat(DISTINCT 'u'||who)||"
|
||||
"','||group_concat(rid) FROM priors;"
|
||||
);
|
||||
speedtest1_exec(
|
||||
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);\n"
|
||||
);
|
||||
speedtest1_exec(
|
||||
"WITH RECURSIVE\n"
|
||||
" parent(pid,cid,isCP) AS (\n"
|
||||
" SELECT plink.pid, plink.cid, 0 AS xisCP FROM plink\n"
|
||||
" UNION ALL\n"
|
||||
" SELECT parentid, childid, 1 FROM cherrypick WHERE NOT isExclude\n"
|
||||
" ),\n"
|
||||
" ancestor(rid, mtime, isCP) AS (\n"
|
||||
" SELECT 123, mtime, 0 FROM event WHERE objid=$object\n"
|
||||
" UNION\n"
|
||||
" SELECT parent.pid, event.mtime, parent.isCP\n"
|
||||
" FROM ancestor, parent, event\n"
|
||||
" WHERE parent.cid=ancestor.rid\n"
|
||||
" AND event.objid=parent.pid\n"
|
||||
" AND NOT ancestor.isCP\n"
|
||||
" AND (event.mtime>=$date OR parent.pid=$pid)\n"
|
||||
" ORDER BY mtime DESC LIMIT 10\n"
|
||||
" )\n"
|
||||
" INSERT OR IGNORE INTO ok SELECT rid FROM ancestor;"
|
||||
);
|
||||
sqlite3_close(dbAux);
|
||||
g.db = dbMain;
|
||||
}
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
/* Generate two numbers between 1 and mx. The first number is less than
|
||||
** the second. Usually the numbers are near each other but can sometimes
|
||||
@@ -2404,11 +2960,9 @@ int main(int argc, char **argv){
|
||||
int memDb = 0; /* --memdb. Use an in-memory database */
|
||||
int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
||||
; /* SQLITE_OPEN_xxx flags. */
|
||||
char *zTSet = "main"; /* Which --testset torun */
|
||||
const char * zVfs = 0; /* --vfs NAME */
|
||||
char *zTSet = "mix1"; /* Which --testset torun */
|
||||
int doTrace = 0; /* True for --trace */
|
||||
const char *zEncoding = 0; /* --utf16be or --utf16le */
|
||||
const char *zDbName = 0; /* Name of the test database */
|
||||
|
||||
void *pHeap = 0; /* Allocated heap space */
|
||||
void *pLook = 0; /* Allocated lookaside space */
|
||||
@@ -2417,6 +2971,10 @@ int main(int argc, char **argv){
|
||||
int i; /* Loop counter */
|
||||
int rc; /* API return code */
|
||||
|
||||
/* "mix1" is a macro testset: */
|
||||
static char zMix1Tests[] =
|
||||
"main,orm/25,cte/20,json,fp/3,parsenumber/25,rtree/10,star,app";
|
||||
|
||||
#ifdef SQLITE_SPEEDTEST1_WASM
|
||||
/* Resetting all state is important for the WASM build, which may
|
||||
** call main() multiple times. */
|
||||
@@ -2435,6 +2993,8 @@ int main(int argc, char **argv){
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
|
||||
/* Process command-line arguments */
|
||||
g.zDbName = 0;
|
||||
g.zVfs = 0;
|
||||
g.zWR = "";
|
||||
g.zNN = "";
|
||||
g.zPK = "UNIQUE";
|
||||
@@ -2560,10 +3120,8 @@ int main(int argc, char **argv){
|
||||
}
|
||||
g.eTemp = argv[i][0] - '0';
|
||||
}else if( strcmp(z,"testset")==0 ){
|
||||
static char zMix1Tests[] = "main,orm/25,cte/20,json,fp/3,parsenumber/25,rtree/10";
|
||||
ARGC_VALUE_CHECK(1);
|
||||
zTSet = argv[++i];
|
||||
if( strcmp(zTSet,"mix1")==0 ) zTSet = zMix1Tests;
|
||||
}else if( strcmp(z,"trace")==0 ){
|
||||
doTrace = 1;
|
||||
}else if( strcmp(z,"threads")==0 ){
|
||||
@@ -2580,7 +3138,7 @@ int main(int argc, char **argv){
|
||||
#endif
|
||||
}else if( strcmp(z,"vfs")==0 ){
|
||||
ARGC_VALUE_CHECK(1);
|
||||
zVfs = argv[++i];
|
||||
g.zVfs = argv[++i];
|
||||
}else if( strcmp(z,"reserve")==0 ){
|
||||
ARGC_VALUE_CHECK(1);
|
||||
g.nReserve = atoi(argv[++i]);
|
||||
@@ -2610,8 +3168,8 @@ int main(int argc, char **argv){
|
||||
fatal_error("unknown option: %s\nUse \"%s -?\" for help\n",
|
||||
argv[i], argv[0]);
|
||||
}
|
||||
}else if( zDbName==0 ){
|
||||
zDbName = argv[i];
|
||||
}else if( g.zDbName==0 ){
|
||||
g.zDbName = argv[i];
|
||||
}else{
|
||||
fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n",
|
||||
argv[i], argv[0]);
|
||||
@@ -2640,8 +3198,8 @@ int main(int argc, char **argv){
|
||||
#endif
|
||||
sqlite3_initialize();
|
||||
|
||||
if( zDbName!=0 ){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
|
||||
if( g.zDbName!=0 ){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfs);
|
||||
/* For some VFSes, e.g. opfs, unlink() is not sufficient. Use the
|
||||
** selected (or default) VFS's xDelete method to delete the
|
||||
** database. This is specifically important for the "opfs" VFS
|
||||
@@ -2649,15 +3207,15 @@ int main(int argc, char **argv){
|
||||
** can be cleaned up properly. For historical compatibility, we'll
|
||||
** also simply unlink(). */
|
||||
if( pVfs!=0 ){
|
||||
pVfs->xDelete(pVfs, zDbName, 1);
|
||||
pVfs->xDelete(pVfs, g.zDbName, 1);
|
||||
}
|
||||
unlink(zDbName);
|
||||
unlink(g.zDbName);
|
||||
}
|
||||
|
||||
/* Open the database and the input file */
|
||||
if( sqlite3_open_v2(memDb ? ":memory:" : zDbName, &g.db,
|
||||
openFlags, zVfs) ){
|
||||
fatal_error("Cannot open database file: %s\n", zDbName);
|
||||
if( sqlite3_open_v2(memDb ? ":memory:" : g.zDbName, &g.db,
|
||||
openFlags, g.zVfs) ){
|
||||
fatal_error("Cannot open database file: %s\n", g.zDbName);
|
||||
}
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( nLook>0 && szLook>0 ){
|
||||
@@ -2715,6 +3273,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
|
||||
if( g.bExplain ) printf(".explain\n.echo on\n");
|
||||
if( strcmp(zTSet,"mix1")==0 ) zTSet = zMix1Tests;
|
||||
do{
|
||||
char *zThisTest = zTSet;
|
||||
char *zSep;
|
||||
@@ -2749,6 +3308,10 @@ int main(int argc, char **argv){
|
||||
testset_orm();
|
||||
}else if( strcmp(zThisTest,"cte")==0 ){
|
||||
testset_cte();
|
||||
}else if( strcmp(zThisTest,"star")==0 ){
|
||||
testset_star();
|
||||
}else if( strcmp(zThisTest,"app")==0 ){
|
||||
testset_app();
|
||||
}else if( strcmp(zThisTest,"fp")==0 ){
|
||||
testset_fp();
|
||||
}else if( strcmp(zThisTest,"json")==0 ){
|
||||
|
||||
Reference in New Issue
Block a user