Merge sqlite-release(3.38.2) into prerelease-integration
This commit is contained in:
commit
3a1baaba94
17
Makefile.in
17
Makefile.in
@ -201,7 +201,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
fts5.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
|
||||
icu.lo insert.lo json.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
@ -256,6 +256,7 @@ SRC = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/json.c \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
@ -388,7 +389,6 @@ SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
# Generated source code files
|
||||
@ -482,6 +482,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/prefixes.c \
|
||||
$(TOP)/ext/misc/qpvtab.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
@ -630,7 +631,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
|
||||
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
|
||||
SHELL_OPT = -DSQLITE_ENABLE_FTS4
|
||||
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_RTREE
|
||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
@ -640,8 +641,8 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZERSHELL_OPT =
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
@ -910,6 +911,9 @@ hash.lo: $(TOP)/src/hash.c $(HDR)
|
||||
insert.lo: $(TOP)/src/insert.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c
|
||||
|
||||
json.lo: $(TOP)/src/json.c
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c
|
||||
|
||||
legacy.lo: $(TOP)/src/legacy.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c
|
||||
|
||||
@ -1213,9 +1217,6 @@ userauth.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
stmt.lo: $(TOP)/ext/misc/stmt.c
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
|
||||
31
Makefile.msc
31
Makefile.msc
@ -363,7 +363,6 @@ SQLITE_TCL_DEP =
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
@ -580,17 +579,17 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
@ -1248,7 +1247,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
fts5.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
|
||||
icu.lo insert.lo json.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
memdb.lo memjournal.lo \
|
||||
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
|
||||
@ -1323,6 +1322,7 @@ SRC00 = \
|
||||
$(TOP)\src\global.c \
|
||||
$(TOP)\src\hash.c \
|
||||
$(TOP)\src\insert.c \
|
||||
$(TOP)\src\json.c \
|
||||
$(TOP)\src\legacy.c \
|
||||
$(TOP)\src\loadext.c \
|
||||
$(TOP)\src\main.c \
|
||||
@ -1453,7 +1453,6 @@ SRC07 = \
|
||||
$(TOP)\ext\rtree\rtree.c \
|
||||
$(TOP)\ext\session\sqlite3session.c \
|
||||
$(TOP)\ext\rbu\sqlite3rbu.c \
|
||||
$(TOP)\ext\misc\json1.c \
|
||||
$(TOP)\ext\misc\stmt.c
|
||||
|
||||
# Extension header files, part 1.
|
||||
@ -1587,6 +1586,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\normalize.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\prefixes.c \
|
||||
$(TOP)\ext\misc\qpvtab.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
@ -1703,9 +1703,9 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
# <<mark>>
|
||||
# Extra compiler options for various test tools.
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS =
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS5
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
@ -1998,6 +1998,9 @@ hash.lo: $(TOP)\src\hash.c $(HDR)
|
||||
insert.lo: $(TOP)\src\insert.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c
|
||||
|
||||
json.lo: $(TOP)\src\json.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\json.c
|
||||
|
||||
legacy.lo: $(TOP)\src\legacy.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c
|
||||
|
||||
@ -2306,9 +2309,6 @@ fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
|
||||
|
||||
json1.lo: $(TOP)\ext\misc\json1.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\json1.c
|
||||
|
||||
stmt.lo: $(TOP)\ext\misc\stmt.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\stmt.c
|
||||
|
||||
@ -2400,7 +2400,6 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
|
||||
@ -471,9 +471,11 @@ describes its purpose and role within the larger system.
|
||||
The `manifest` file at the root directory of the source tree
|
||||
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
|
||||
older files) for every source file in the repository.
|
||||
The SHA3-256 hash of the `manifest`
|
||||
file itself is the official name of the version of the source tree that you
|
||||
have. The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
The name of the version of the entire source tree is just the
|
||||
SHA3-256 hash of the `manifest` file itself, possibly with the
|
||||
last line of that file omitted if the last line begins with
|
||||
"`# Remove this line`".
|
||||
The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
`manifest` file. If all of the above hash comparisons are correct, then
|
||||
you can be confident that your source tree is authentic and unadulterated.
|
||||
|
||||
|
||||
@ -285,7 +285,6 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
@ -502,12 +501,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
|
||||
@ -105,7 +105,7 @@ may be specified in this manner as some require the amalgamation to be built
|
||||
with them enabled (see http://www.sqlite.org/compile.html). For example, the
|
||||
following will work:
|
||||
|
||||
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1"
|
||||
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"
|
||||
|
||||
However, the following will not compile unless the amalgamation was built
|
||||
with it enabled:
|
||||
|
||||
@ -173,21 +173,6 @@ else
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-json1
|
||||
#
|
||||
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
|
||||
[--enable-json1], [include json1 support [default=yes]])],
|
||||
[],[enable_json1=yes])
|
||||
AC_MSG_CHECKING([JSON functions])
|
||||
if test x"$enable_json1" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-rtree
|
||||
#
|
||||
|
||||
60
configure
vendored
60
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlcipher 3.37.2.
|
||||
# Generated by GNU Autoconf 2.69 for sqlcipher 3.38.2.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@ -587,8 +587,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlcipher'
|
||||
PACKAGE_TARNAME='sqlcipher'
|
||||
PACKAGE_VERSION='3.37.2'
|
||||
PACKAGE_STRING='sqlcipher 3.37.2'
|
||||
PACKAGE_VERSION='3.38.2'
|
||||
PACKAGE_STRING='sqlcipher 3.38.2'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@ -777,13 +777,13 @@ enable_debug
|
||||
enable_amalgamation
|
||||
enable_load_extension
|
||||
enable_math
|
||||
enable_json
|
||||
enable_all
|
||||
enable_memsys5
|
||||
enable_memsys3
|
||||
enable_fts3
|
||||
enable_fts4
|
||||
enable_fts5
|
||||
enable_json1
|
||||
enable_update_limit
|
||||
enable_geopoly
|
||||
enable_rtree
|
||||
@ -1352,7 +1352,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlcipher 3.37.2 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlcipher 3.38.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1418,7 +1418,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlcipher 3.37.2:";;
|
||||
short | recursive ) echo "Configuration of sqlcipher 3.38.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1447,13 +1447,13 @@ Optional Features:
|
||||
--disable-load-extension
|
||||
Disable loading of external extensions
|
||||
--disable-math Disable math functions
|
||||
--enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
|
||||
--disable-json Disable JSON functions
|
||||
--enable-all Enable FTS4, FTS5, Geopoly, RTree, Sessions
|
||||
--enable-memsys5 Enable MEMSYS5
|
||||
--enable-memsys3 Enable MEMSYS3
|
||||
--enable-fts3 Enable the FTS3 extension
|
||||
--enable-fts4 Enable the FTS4 extension
|
||||
--enable-fts5 Enable the FTS5 extension
|
||||
--enable-json1 Enable the JSON1 extension
|
||||
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
|
||||
--enable-geopoly Enable the GEOPOLY extension
|
||||
--enable-rtree Enable the RTREE extension
|
||||
@ -1558,7 +1558,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlcipher configure 3.37.2
|
||||
sqlcipher configure 3.38.2
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -1977,7 +1977,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlcipher $as_me 3.37.2, which was
|
||||
It was created by sqlcipher $as_me 3.38.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -13126,6 +13126,24 @@ fi
|
||||
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support JSON functions
|
||||
#
|
||||
# Check whether --enable-json was given.
|
||||
if test "${enable_json+set}" = set; then :
|
||||
enableval=$enable_json;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON functions" >&5
|
||||
$as_echo_n "checking whether to support JSON functions... " >&6; }
|
||||
if test "$enable_json" = "no"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-all argument is short-hand to enable
|
||||
@ -13330,24 +13348,6 @@ else
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
# Check whether --enable-json1 was given.
|
||||
if test "${enable_json1+set}" = set; then :
|
||||
enableval=$enable_json1;
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON" >&5
|
||||
$as_echo_n "checking whether to support JSON... " >&6; }
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
@ -14019,7 +14019,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlcipher $as_me 3.37.2, which was
|
||||
This file was extended by sqlcipher $as_me 3.38.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -14085,7 +14085,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlcipher config.status 3.37.2
|
||||
sqlcipher config.status 3.38.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
25
configure.ac
25
configure.ac
@ -678,12 +678,24 @@ else
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support JSON functions
|
||||
#
|
||||
AC_ARG_ENABLE(json,
|
||||
AC_HELP_STRING([--disable-json],[Disable JSON functions]))
|
||||
AC_MSG_CHECKING([whether to support JSON functions])
|
||||
if test "$enable_json" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-all argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
|
||||
[Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
|
||||
[Enable FTS4, FTS5, Geopoly, RTree, Sessions]))
|
||||
|
||||
##########
|
||||
# Do we want to support memsys3 and/or memsys5
|
||||
@ -739,17 +751,6 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable JSON1
|
||||
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
|
||||
AC_MSG_CHECKING([whether to support JSON])
|
||||
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
|
||||
144
doc/json-enhancements.md
Normal file
144
doc/json-enhancements.md
Normal file
@ -0,0 +1,144 @@
|
||||
# JSON Functions Enhancements (2022)
|
||||
|
||||
This document summaries enhancements to the SQLite JSON support added in
|
||||
early 2022.
|
||||
|
||||
## 1.0 Change summary:
|
||||
|
||||
1. New **->** and **->>** operators that work like MySQL and PostgreSQL (PG).
|
||||
2. JSON functions are built-in rather than being an extension. They
|
||||
are included by default, but can be omitted using the
|
||||
-DSQLITE_OMIT_JSON compile-time option.
|
||||
|
||||
|
||||
## 2.0 New operators **->** and **->>**
|
||||
|
||||
The SQLite language adds two new binary operators **->** and **->>**.
|
||||
Both operators are similar to json_extract(). The left operand is
|
||||
JSON and the right operand is a JSON path expression (possibly abbreviated
|
||||
for compatibility with PG - see below). So they are similar to a
|
||||
two-argument call to json_extract().
|
||||
|
||||
The difference between -> and ->> (and json_extract()) is as follows:
|
||||
|
||||
* The -> operator always returns JSON.
|
||||
|
||||
* The ->> operator converts the answer into a primitive SQL datatype
|
||||
such as TEXT, INTEGER, REAL, or NULL. If a JSON object or array
|
||||
is selected, that object or array is rendered as text. If a JSON
|
||||
value is selected, that value is converted into its corresponding
|
||||
SQL type
|
||||
|
||||
* The json_extract() interface returns JSON when a JSON object or
|
||||
array is selected, or a primitive SQL datatype when a JSON value
|
||||
is selected. This is different from MySQL, in which json_extract()
|
||||
always returns JSON, but the difference is retained because it has
|
||||
worked that way for 6 years and changing it now would likely break
|
||||
a lot of legacy code.
|
||||
|
||||
In MySQL and PG, the ->> operator always returns TEXT (or NULL) and never
|
||||
INTEGER or REAL. This is due to limitations in the type handling capabilities
|
||||
of those systems. In MySQL and PG, the result type a function or operator
|
||||
may only depend on the type of its arguments, never the value of its arguments.
|
||||
But the underlying JSON type depends on the value of the JSON path
|
||||
expression, not the type of the JSON path expression (which is always TEXT).
|
||||
Hence, the result type of ->> in MySQL and PG is unable to vary according
|
||||
to the type of the JSON value being extracted.
|
||||
|
||||
The type system in SQLite is more general. Functions in SQLite are able
|
||||
to return different datatypes depending on the value of their arguments.
|
||||
So the ->> operator in SQLite is able to return TEXT, INTEGER, REAL, or NULL
|
||||
depending on the JSON type of the value being extracted. This means that
|
||||
the behavior of the ->> is slightly different in SQLite versus MySQL and PG
|
||||
in that it will sometimes return INTEGER and REAL values, depending on its
|
||||
inputs. It is possible to implement the ->> operator in SQLite so that it
|
||||
always operates exactly like MySQL and PG and always returns TEXT or NULL,
|
||||
but I have been unable to think of any situations where returning the
|
||||
actual JSON value this would cause problems, so I'm including the enhanced
|
||||
functionality in SQLite.
|
||||
|
||||
The table below attempts to summarize the differences between the
|
||||
-> and ->> operators and the json_extract() function, for SQLite, MySQL,
|
||||
and PG. JSON values are shown using their SQL text representation but
|
||||
in a bold font.
|
||||
|
||||
|
||||
<table border=1 cellpadding=5 cellspacing=0>
|
||||
<tr><th>JSON<th>PATH<th>-> operator<br>(all)<th>->> operator<br>(MySQL/PG)
|
||||
<th>->> operator<br>(SQLite)<th>json_extract()<br>(SQLite)
|
||||
<tr><td> **'{"a":123}'** <td>'$.a'<td> **'123'** <td> '123' <td> 123 <td> 123
|
||||
<tr><td> **'{"a":4.5}'** <td>'$.a'<td> **'4.5'** <td> '4.5' <td> 4.5 <td> 4.5
|
||||
<tr><td> **'{"a":"xyz"}'** <td>'$.a'<td> **'"xyz"'** <td> 'xyz' <td> 'xyz' <td> 'xyz'
|
||||
<tr><td> **'{"a":null}'** <td>'$.a'<td> **'null'** <td> NULL <td> NULL <td> NULL
|
||||
<tr><td> **'{"a":[6,7,8]}'** <td>'$.a'<td> **'[6,7,8]'** <td> '[6,7,8]' <td> '[6,7,8]' <td> **'[6,7,8]'**
|
||||
<tr><td> **'{"a":{"x":9}}'** <td>'$.a'<td> **'{"x":9}'** <td> '{"x":9}' <td> '{"x":9}' <td> **'{"x":9}'**
|
||||
<tr><td> **'{"b":999}'** <td>'$.a'<td> NULL <td> NULL <td> NULL <td> NULL
|
||||
</table>
|
||||
|
||||
Important points about the table above:
|
||||
|
||||
* The -> operator always returns either JSON or NULL.
|
||||
|
||||
* The ->> operator never returns JSON. It always returns TEXT or NULL, or in the
|
||||
case of SQLite, INTEGER or REAL.
|
||||
|
||||
* The MySQL json_extract() function works exactly the same
|
||||
as the MySQL -> operator.
|
||||
|
||||
* The SQLite json_extract() operator works like -> for JSON objects and
|
||||
arrays, and like ->> for JSON values.
|
||||
|
||||
* The -> operator works the same for all systems.
|
||||
|
||||
* The only difference in ->> between SQLite and other systems is that
|
||||
when the JSON value is numeric, SQLite returns a numeric SQL value,
|
||||
whereas the other systems return a text representation of the numeric
|
||||
value.
|
||||
|
||||
### 2.1 Abbreviated JSON path expressions for PG compatibility
|
||||
|
||||
The table above always shows the full JSON path expression: '$.a'. But
|
||||
PG does not accept this syntax. PG only allows a single JSON object label
|
||||
name or a single integer array index. In order to provide compatibility
|
||||
with PG, The -> and ->> operators in SQLite are extended to also support
|
||||
a JSON object label or an integer array index for the right-hand side
|
||||
operand, in addition to a full JSON path expression.
|
||||
|
||||
Thus, a -> or ->> operator that works on MySQL will work in
|
||||
SQLite. And a -> or ->> operator that works in PG will work in SQLite.
|
||||
But because SQLite supports the union of the disjoint capabilities of
|
||||
MySQL and PG, there will always be -> and ->> operators that work in
|
||||
SQLite that do not work in one of MySQL and PG. This is an unavoidable
|
||||
consequence of the different syntax for -> and ->> in MySQL and PG.
|
||||
|
||||
In the following table, assume that "value1" is a JSON object and
|
||||
"value2" is a JSON array.
|
||||
|
||||
<table border=1 cellpadding=5 cellspacing=0>
|
||||
<tr><th>SQL expression <th>Works in MySQL?<th>Works in PG?<th>Works in SQLite
|
||||
<tr><td>value1->'$.a' <td> yes <td> no <td> yes
|
||||
<tr><td>value1->'a' <td> no <td> yes <td> yes
|
||||
<tr><td>value2->'$[2]' <td> yes <td> no <td> yes
|
||||
<tr><td>value2->2 <td> no <td> yes <td> yes
|
||||
</table>
|
||||
|
||||
The abbreviated JSON path expressions only work for the -> and ->> operators
|
||||
in SQLite. The json_extract() function, and all other built-in SQLite
|
||||
JSON functions, continue to require complete JSON path expressions for their
|
||||
PATH arguments.
|
||||
|
||||
## 3.0 JSON moved into the core
|
||||
|
||||
The JSON interface is now moved into the SQLite core.
|
||||
|
||||
When originally written in 2015, the JSON functions were an extension
|
||||
that could be optionally included at compile-time, or loaded at run-time.
|
||||
The implementation was in a source file named ext/misc/json1.c in the
|
||||
source tree. JSON functions were only compiled in if the
|
||||
-DSQLITE_ENABLE_JSON1 compile-time option was used.
|
||||
|
||||
After these enhancements, the JSON functions are now built-ins.
|
||||
The source file that implements the JSON functions is moved to src/json.c.
|
||||
No special compile-time options are needed to load JSON into the build.
|
||||
Instead, there is a new -DSQLITE_OMIT_JSON compile-time option to leave
|
||||
them out.
|
||||
@ -697,17 +697,25 @@ static int idxGetTableInfo(
|
||||
){
|
||||
sqlite3_stmt *p1 = 0;
|
||||
int nCol = 0;
|
||||
int nTab = STRLEN(zTab);
|
||||
int nByte = sizeof(IdxTable) + nTab + 1;
|
||||
int nTab;
|
||||
int nByte;
|
||||
IdxTable *pNew = 0;
|
||||
int rc, rc2;
|
||||
char *pCsr = 0;
|
||||
int nPk = 0;
|
||||
|
||||
*ppOut = 0;
|
||||
if( zTab==0 ) return SQLITE_ERROR;
|
||||
nTab = STRLEN(zTab);
|
||||
nByte = sizeof(IdxTable) + nTab + 1;
|
||||
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
||||
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
||||
const char *zColSeq = 0;
|
||||
if( zCol==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
nByte += 1 + STRLEN(zCol);
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
|
||||
@ -734,7 +742,9 @@ static int idxGetTableInfo(
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
||||
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
||||
const char *zColSeq = 0;
|
||||
int nCopy = STRLEN(zCol) + 1;
|
||||
int nCopy;
|
||||
if( zCol==0 ) continue;
|
||||
nCopy = STRLEN(zCol) + 1;
|
||||
pNew->aCol[nCol].zName = pCsr;
|
||||
pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
|
||||
memcpy(pCsr, zCol, nCopy);
|
||||
@ -886,6 +896,7 @@ static int idxFindCompatible(
|
||||
IdxConstraint *pT = pTail;
|
||||
sqlite3_stmt *pInfo = 0;
|
||||
const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
|
||||
if( zIdx==0 ) continue;
|
||||
|
||||
/* Zero the IdxConstraint.bFlag values in the pEq list */
|
||||
for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
|
||||
@ -1168,7 +1179,7 @@ static void idxWriteFree(IdxWrite *pTab){
|
||||
** runs all the queries to see which indexes they prefer, and populates
|
||||
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
|
||||
*/
|
||||
int idxFindIndexes(
|
||||
static int idxFindIndexes(
|
||||
sqlite3expert *p,
|
||||
char **pzErr /* OUT: Error message (sqlite3_malloc) */
|
||||
){
|
||||
@ -1297,6 +1308,7 @@ static int idxProcessOneTrigger(
|
||||
rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
|
||||
const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
|
||||
if( zCreate==0 ) continue;
|
||||
rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
|
||||
}
|
||||
idxFinalize(&rc, pSelect);
|
||||
@ -1399,8 +1411,9 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
|
||||
|
||||
if( zType==0 || zName==0 ) continue;
|
||||
if( zType[0]=='v' || zType[1]=='r' ){
|
||||
rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
|
||||
if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
|
||||
}else{
|
||||
IdxTable *pTab;
|
||||
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
|
||||
@ -1537,6 +1550,7 @@ static void idxRemFunc(
|
||||
case SQLITE_BLOB:
|
||||
case SQLITE_TEXT: {
|
||||
int nByte = sqlite3_value_bytes(argv[1]);
|
||||
const void *pData = 0;
|
||||
if( nByte>pSlot->nByte ){
|
||||
char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
|
||||
if( zNew==0 ){
|
||||
@ -1548,9 +1562,11 @@ static void idxRemFunc(
|
||||
}
|
||||
pSlot->n = nByte;
|
||||
if( pSlot->eType==SQLITE_BLOB ){
|
||||
memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
|
||||
pData = sqlite3_value_blob(argv[1]);
|
||||
if( pData ) memcpy(pSlot->z, pData, nByte);
|
||||
}else{
|
||||
memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
|
||||
pData = sqlite3_value_text(argv[1]);
|
||||
memcpy(pSlot->z, pData, nByte);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1761,6 +1777,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
|
||||
const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
|
||||
const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
|
||||
if( zTab==0 || zIdx==0 ) continue;
|
||||
if( p->iSample<100 && iPrev!=iRowid ){
|
||||
samplectx.target = (double)p->iSample / 100.0;
|
||||
samplectx.iTarget = p->iSample;
|
||||
@ -1827,14 +1844,14 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
|
||||
/* Copy the entire schema of database [db] into [dbm]. */
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_stmt *pSql;
|
||||
sqlite3_stmt *pSql = 0;
|
||||
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
|
||||
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
|
||||
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
|
||||
);
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
|
||||
rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
|
||||
if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
|
||||
}
|
||||
idxFinalize(&rc, pSql);
|
||||
}
|
||||
|
||||
@ -308,6 +308,12 @@
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
|
||||
typedef struct Fts3HashWrapper Fts3HashWrapper;
|
||||
struct Fts3HashWrapper {
|
||||
Fts3Hash hash; /* Hash table */
|
||||
int nRef; /* Number of pointers to this object */
|
||||
};
|
||||
|
||||
static int fts3EvalNext(Fts3Cursor *pCsr);
|
||||
static int fts3EvalStart(Fts3Cursor *pCsr);
|
||||
static int fts3TermSegReaderCursor(
|
||||
@ -1172,7 +1178,7 @@ static int fts3InitVtab(
|
||||
sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
|
||||
char **pzErr /* Write any error message here */
|
||||
){
|
||||
Fts3Hash *pHash = (Fts3Hash *)pAux;
|
||||
Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash;
|
||||
Fts3Table *p = 0; /* Pointer to allocated vtab */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* Iterator variable */
|
||||
@ -4007,9 +4013,12 @@ static const sqlite3_module fts3Module = {
|
||||
** allocated for the tokenizer hash table.
|
||||
*/
|
||||
static void hashDestroy(void *p){
|
||||
Fts3Hash *pHash = (Fts3Hash *)p;
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3_free(pHash);
|
||||
Fts3HashWrapper *pHash = (Fts3HashWrapper *)p;
|
||||
pHash->nRef--;
|
||||
if( pHash->nRef<=0 ){
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4039,7 +4048,7 @@ void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
||||
*/
|
||||
int sqlite3Fts3Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
Fts3Hash *pHash = 0;
|
||||
Fts3HashWrapper *pHash = 0;
|
||||
const sqlite3_tokenizer_module *pSimple = 0;
|
||||
const sqlite3_tokenizer_module *pPorter = 0;
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
@ -4067,23 +4076,24 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
sqlite3Fts3PorterTokenizerModule(&pPorter);
|
||||
|
||||
/* Allocate and initialize the hash-table used to store tokenizers. */
|
||||
pHash = sqlite3_malloc(sizeof(Fts3Hash));
|
||||
pHash = sqlite3_malloc(sizeof(Fts3HashWrapper));
|
||||
if( !pHash ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
|
||||
sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1);
|
||||
pHash->nRef = 0;
|
||||
}
|
||||
|
||||
/* Load the built-in tokenizers into the hash table */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
|
||||
if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter)
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|| sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
|
||||
|| sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode)
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
|
||||
|| (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_NOMEM;
|
||||
@ -4092,7 +4102,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4101,23 +4111,26 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
** module with sqlite.
|
||||
*/
|
||||
if( SQLITE_OK==rc
|
||||
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
|
||||
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
|
||||
){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pHash->nRef++;
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts4", &fts3Module, (void *)pHash, 0
|
||||
db, "fts4", &fts3Module, (void *)pHash, hashDestroy
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash);
|
||||
pHash->nRef++;
|
||||
rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -4126,7 +4139,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
/* An error has occurred. Delete the hash table and return the error code. */
|
||||
assert( rc!=SQLITE_OK );
|
||||
if( pHash ){
|
||||
sqlite3Fts3HashClear(pHash);
|
||||
sqlite3Fts3HashClear(&pHash->hash);
|
||||
sqlite3_free(pHash);
|
||||
}
|
||||
return rc;
|
||||
|
||||
@ -641,7 +641,7 @@ int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
||||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
|
||||
/* fts3_tokenize_vtab.c */
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
|
||||
|
||||
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
|
||||
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|
||||
|
||||
@ -420,7 +420,7 @@ static int fts3tokRowidMethod(
|
||||
** Register the fts3tok module with database connection db. Return SQLITE_OK
|
||||
** if successful or an error code if sqlite3_create_module() fails.
|
||||
*/
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
||||
int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
|
||||
static const sqlite3_module fts3tok_module = {
|
||||
0, /* iVersion */
|
||||
fts3tokConnectMethod, /* xCreate */
|
||||
@ -449,7 +449,9 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
|
||||
};
|
||||
int rc; /* Return code */
|
||||
|
||||
rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
|
||||
);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# This script builds a single C code file holding all of FTS3 code.
|
||||
# The name of the output file is fts3amal.c. To build this file,
|
||||
# first do:
|
||||
#
|
||||
# make target_source
|
||||
#
|
||||
# The make target above moves all of the source code files into
|
||||
# a subdirectory named "tsrc". (This script expects to find the files
|
||||
# there and will not work if they are not found.)
|
||||
#
|
||||
# After the "tsrc" directory has been created and populated, run
|
||||
# this script:
|
||||
#
|
||||
# tclsh mkfts3amal.tcl
|
||||
#
|
||||
# The amalgamated FTS3 code will be written into fts3amal.c
|
||||
#
|
||||
|
||||
# Open the output file and write a header comment at the beginning
|
||||
# of the file.
|
||||
#
|
||||
set out [open fts3amal.c w]
|
||||
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
|
||||
puts $out [subst \
|
||||
{/******************************************************************************
|
||||
** This file is an amalgamation of separate C source files from the SQLite
|
||||
** Full Text Search extension 2 (fts3). By combining all the individual C
|
||||
** code files into this single large file, the entire code can be compiled
|
||||
** as a one translation unit. This allows many compilers to do optimizations
|
||||
** that would not be possible if the files were compiled separately. It also
|
||||
** makes the code easier to import into other projects.
|
||||
**
|
||||
** This amalgamation was generated on $today.
|
||||
*/}]
|
||||
|
||||
# These are the header files used by FTS3. The first time any of these
|
||||
# files are seen in a #include statement in the C code, include the complete
|
||||
# text of the file in-line. The file only needs to be included once.
|
||||
#
|
||||
foreach hdr {
|
||||
fts3.h
|
||||
fts3_hash.h
|
||||
fts3_tokenizer.h
|
||||
sqlite3.h
|
||||
sqlite3ext.h
|
||||
} {
|
||||
set available_hdr($hdr) 1
|
||||
}
|
||||
|
||||
# 78 stars used for comment formatting.
|
||||
set s78 \
|
||||
{*****************************************************************************}
|
||||
|
||||
# Insert a comment into the code
|
||||
#
|
||||
proc section_comment {text} {
|
||||
global out s78
|
||||
set n [string length $text]
|
||||
set nstar [expr {60 - $n}]
|
||||
set stars [string range $s78 0 $nstar]
|
||||
puts $out "/************** $text $stars/"
|
||||
}
|
||||
|
||||
# Read the source file named $filename and write it into the
|
||||
# sqlite3.c output file. If any #include statements are seen,
|
||||
# process them approprately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr out
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
set in [open $filename r]
|
||||
while {![eof $in]} {
|
||||
set line [gets $in]
|
||||
if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
|
||||
if {[info exists available_hdr($hdr)]} {
|
||||
if {$available_hdr($hdr)} {
|
||||
section_comment "Include $hdr in the middle of $tail"
|
||||
copy_file tsrc/$hdr
|
||||
section_comment "Continuing where we left off in $tail"
|
||||
}
|
||||
} elseif {![info exists seen_hdr($hdr)]} {
|
||||
set seen_hdr($hdr) 1
|
||||
puts $out $line
|
||||
}
|
||||
} elseif {[regexp {^#ifdef __cplusplus} $line]} {
|
||||
puts $out "#if 0"
|
||||
} elseif {[regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} else {
|
||||
puts $out $line
|
||||
}
|
||||
}
|
||||
close $in
|
||||
section_comment "End of $tail"
|
||||
}
|
||||
|
||||
|
||||
# Process the source files. Process files containing commonly
|
||||
# used subroutines first in order to help the compiler find
|
||||
# inlining opportunities.
|
||||
#
|
||||
foreach file {
|
||||
fts3.c
|
||||
fts3_hash.c
|
||||
fts3_porter.c
|
||||
fts3_tokenizer.c
|
||||
fts3_tokenizer1.c
|
||||
} {
|
||||
copy_file tsrc/$file
|
||||
}
|
||||
|
||||
close $out
|
||||
@ -5565,7 +5565,7 @@ int sqlite3Fts5IndexQuery(
|
||||
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
|
||||
int iIdx = 0; /* Index to search */
|
||||
int iPrefixIdx = 0; /* +1 prefix index */
|
||||
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
|
||||
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
|
||||
|
||||
/* Figure out which index to search and set iIdx accordingly. If this
|
||||
** is a prefix query for which there is no prefix index, set iIdx to
|
||||
|
||||
@ -804,7 +804,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
|
||||
rc = sqlite3_step(pSorter->pStmt);
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
|
||||
}else if( rc==SQLITE_ROW ){
|
||||
const u8 *a;
|
||||
const u8 *aBlob;
|
||||
|
||||
@ -15366,6 +15366,160 @@ do_catchsql_test 79.2 {
|
||||
INSERT INTO t1(t1) SELECT 'merge' FROM t2;
|
||||
} {1 {query aborted}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 80.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 40960 pagesize 4096 filename crash-f928a9c1ec68dd.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c ..........n....L
|
||||
| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
|
||||
| 128: 0b f8 0b b3 0b 6e 00 00 00 00 00 00 00 00 00 00 .....n..........
|
||||
| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
|
||||
| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
|
||||
| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
|
||||
| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
|
||||
| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
|
||||
| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
|
||||
| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
|
||||
| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
|
||||
| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
|
||||
| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
|
||||
| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
|
||||
| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
|
||||
| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
|
||||
| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
|
||||
| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
|
||||
| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
|
||||
| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
|
||||
| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
|
||||
| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
|
||||
| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
|
||||
| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
|
||||
| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
|
||||
| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
|
||||
| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
|
||||
| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
|
||||
| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
|
||||
| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
|
||||
| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
|
||||
| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
|
||||
| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
|
||||
| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
|
||||
| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
|
||||
| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
|
||||
| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
|
||||
| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
|
||||
| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
|
||||
| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
|
||||
| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
|
||||
| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
|
||||
| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
|
||||
| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
|
||||
| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
|
||||
| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
|
||||
| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
|
||||
| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
|
||||
| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
|
||||
| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
|
||||
| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
|
||||
| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
|
||||
| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
|
||||
| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
|
||||
| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
|
||||
| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
|
||||
| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
|
||||
| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
|
||||
| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
|
||||
| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
|
||||
| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
|
||||
| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
|
||||
| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
|
||||
| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
|
||||
| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
|
||||
| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
|
||||
| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
|
||||
| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
|
||||
| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
|
||||
| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
|
||||
| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
|
||||
| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
|
||||
| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
|
||||
| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 6e NG fts5(a,b unin
|
||||
| 4064: 64 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 dexed,c,tokenize
|
||||
| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
|
||||
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
|
||||
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
|
||||
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
|
||||
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
|
||||
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
|
||||
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
|
||||
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
|
||||
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
|
||||
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
|
||||
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
|
||||
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 80 01 03 ........7.......
|
||||
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
|
||||
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
|
||||
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
|
||||
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
|
||||
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
|
||||
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
|
||||
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 01 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 7 offset 24576
|
||||
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 00 00 00 00 ................
|
||||
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
|
||||
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
|
||||
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
|
||||
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
|
||||
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
|
||||
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 8 offset 28672
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 12 ................
|
||||
| page 9 offset 32768
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 10 offset 36864
|
||||
| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 00 00 00 00 ........vers....
|
||||
| end crash-f928a9c1ec68dd.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 80.1 {
|
||||
SELECT snippet(rowid, -1, '.', '..', '[', '(]'),snippet(rowid, -1, '.', '.', '', '(]'), highlight(t1, 29, 1 , '') FROM t1('g+ h') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY NOT (SELECT 1 FROM t1('g+ æ') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY rank);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ for {set i 0} {$i < 255} {incr i} {
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
|
||||
INSERT INTO e1 VALUES ("just a few words with a / inside");
|
||||
INSERT INTO e1 VALUES ('just a few words with a / inside');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
|
||||
@ -188,11 +188,11 @@ foreach {tn pgsz} {
|
||||
INSERT INTO hh(hh, rank) VALUES('pgsz', $pgsz);
|
||||
|
||||
WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
|
||||
INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
|
||||
INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
|
||||
FROM s;
|
||||
|
||||
WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999)
|
||||
INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1)
|
||||
INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1)
|
||||
FROM s;
|
||||
|
||||
INSERT INTO hh(hh) VALUES('optimize');
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
**
|
||||
** The virtual table contains read-only hidden columns:
|
||||
**
|
||||
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
|
||||
** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
|
||||
** is BLOB or TEXT then this column is exactly the
|
||||
** same as the key. For the UINT keytype, this column
|
||||
** will be a variable-length integer encoding of the key.
|
||||
|
||||
@ -941,7 +941,7 @@ int sqlite3_csv_init(
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
int rc;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
rc = sqlite3_create_module(db, "csv", &CsvModule, 0);
|
||||
|
||||
@ -368,10 +368,11 @@ static int writeFile(
|
||||
mode_t mode, /* MODE parameter passed to writefile() */
|
||||
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
|
||||
){
|
||||
if( zFile==0 ) return 1;
|
||||
#if !defined(_WIN32) && !defined(WIN32)
|
||||
if( S_ISLNK(mode) ){
|
||||
const char *zTo = (const char*)sqlite3_value_text(pData);
|
||||
if( symlink(zTo, zFile)<0 ) return 1;
|
||||
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
|
||||
@ -284,7 +284,7 @@ int sqlite3_ieee_init(
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
|
||||
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
(void*)&aFunc[i].iAux,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
|
||||
461
ext/misc/qpvtab.c
Normal file
461
ext/misc/qpvtab.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
** 2022-01-19
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file implements a virtual-table that returns information about
|
||||
** how the query planner called the xBestIndex method. This virtual table
|
||||
** is intended for testing and debugging only.
|
||||
**
|
||||
** The schema of the virtual table is this:
|
||||
**
|
||||
** CREATE TABLE qpvtab(
|
||||
** vn TEXT, -- Name of an sqlite3_index_info field
|
||||
** ix INTEGER, -- Array index or value
|
||||
** cn TEXT, -- Column name
|
||||
** op INTEGER, -- operator
|
||||
** ux BOOLEAN, -- "usable" field
|
||||
** rhs TEXT, -- sqlite3_vtab_rhs_value()
|
||||
**
|
||||
** a, b, c, d, e, -- Extra columns to attach constraints to
|
||||
**
|
||||
** flags INTEGER HIDDEN -- control flags
|
||||
** );
|
||||
**
|
||||
** The virtual table returns a description of the sqlite3_index_info object
|
||||
** that was provided to the (successful) xBestIndex method. There is one
|
||||
** row in the result table for each field in the sqlite3_index_info object.
|
||||
**
|
||||
** The values of the "a" through "e" columns are one of:
|
||||
**
|
||||
** 1. TEXT - the same as the column name
|
||||
** 2. INTEGER - 1 for "a", 2 for "b", and so forth
|
||||
**
|
||||
** Option 1 is the default behavior. 2 is use if there is a usable
|
||||
** constraint on "flags" with an integer right-hand side that where the
|
||||
** value of the right-hand side has its 0x001 bit set.
|
||||
**
|
||||
** All constraints on columns "a" through "e" are marked as "omit".
|
||||
**
|
||||
** If there is a usable constraint on "flags" that has a RHS value that
|
||||
** is an integer and that integer has its 0x02 bit set, then the
|
||||
** orderByConsumed flag is set.
|
||||
**
|
||||
** FLAGS SUMMARY:
|
||||
**
|
||||
** 0x001 Columns 'a' through 'e' have INT values
|
||||
** 0x002 orderByConsumed is set
|
||||
** 0x004 OFFSET and LIMIT have omit set
|
||||
**
|
||||
** COMPILE:
|
||||
**
|
||||
** gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
|
||||
**
|
||||
** EXAMPLE USAGE:
|
||||
**
|
||||
** .load ./qpvtab
|
||||
** SELECT rowid, *, flags FROM qpvtab(102)
|
||||
** WHERE a=19
|
||||
** AND b BETWEEN 4.5 and 'hello'
|
||||
** AND c<>x'aabbcc'
|
||||
** ORDER BY d, e DESC;
|
||||
*/
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
|
||||
/* qpvtab_vtab is a subclass of sqlite3_vtab which is
|
||||
** underlying representation of the virtual table
|
||||
*/
|
||||
typedef struct qpvtab_vtab qpvtab_vtab;
|
||||
struct qpvtab_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
};
|
||||
|
||||
/* qpvtab_cursor is a subclass of sqlite3_vtab_cursor which will
|
||||
** serve as the underlying representation of a cursor that scans
|
||||
** over rows of the result
|
||||
*/
|
||||
typedef struct qpvtab_cursor qpvtab_cursor;
|
||||
struct qpvtab_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3_int64 iRowid; /* The rowid */
|
||||
const char *zData; /* Data to return */
|
||||
int nData; /* Number of bytes of data */
|
||||
int flags; /* Flags value */
|
||||
};
|
||||
|
||||
/*
|
||||
** Names of columns
|
||||
*/
|
||||
static const char *azColname[] = {
|
||||
"vn",
|
||||
"ix",
|
||||
"cn",
|
||||
"op",
|
||||
"ux",
|
||||
"rhs",
|
||||
"a", "b", "c", "d", "e",
|
||||
"flags",
|
||||
""
|
||||
};
|
||||
|
||||
/*
|
||||
** The qpvtabConnect() method is invoked to create a new
|
||||
** qpvtab virtual table.
|
||||
*/
|
||||
static int qpvtabConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
qpvtab_vtab *pNew;
|
||||
int rc;
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x("
|
||||
" vn TEXT,"
|
||||
" ix INT,"
|
||||
" cn TEXT,"
|
||||
" op INT,"
|
||||
" ux BOOLEAN,"
|
||||
" rhs TEXT,"
|
||||
" a, b, c, d, e,"
|
||||
" flags INT HIDDEN)"
|
||||
);
|
||||
#define QPVTAB_VN 0
|
||||
#define QPVTAB_IX 1
|
||||
#define QPVTAB_CN 2
|
||||
#define QPVTAB_OP 3
|
||||
#define QPVTAB_UX 4
|
||||
#define QPVTAB_RHS 5
|
||||
#define QPVTAB_A 6
|
||||
#define QPVTAB_B 7
|
||||
#define QPVTAB_C 8
|
||||
#define QPVTAB_D 9
|
||||
#define QPVTAB_E 10
|
||||
#define QPVTAB_FLAGS 11
|
||||
#define QPVTAB_NONE 12
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for qpvtab_vtab objects.
|
||||
*/
|
||||
static int qpvtabDisconnect(sqlite3_vtab *pVtab){
|
||||
qpvtab_vtab *p = (qpvtab_vtab*)pVtab;
|
||||
sqlite3_free(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new qpvtab_cursor object.
|
||||
*/
|
||||
static int qpvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
qpvtab_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a qpvtab_cursor.
|
||||
*/
|
||||
static int qpvtabClose(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance a qpvtab_cursor to its next row of output.
|
||||
*/
|
||||
static int qpvtabNext(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
if( pCur->iRowid<pCur->nData ){
|
||||
const char *z = &pCur->zData[pCur->iRowid];
|
||||
const char *zEnd = strchr(z, '\n');
|
||||
if( zEnd ) zEnd++;
|
||||
pCur->iRowid = (int)(zEnd - pCur->zData);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the qpvtab_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int qpvtabColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int i /* Which column to return */
|
||||
){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
if( i>=QPVTAB_VN && i<=QPVTAB_RHS && pCur->iRowid<pCur->nData ){
|
||||
const char *z = &pCur->zData[pCur->iRowid];
|
||||
const char *zEnd;
|
||||
int j;
|
||||
j = QPVTAB_VN;
|
||||
while(1){
|
||||
zEnd = strchr(z, j==QPVTAB_RHS ? '\n' : ',');
|
||||
if( j==i || zEnd==0 ) break;
|
||||
z = zEnd+1;
|
||||
j++;
|
||||
}
|
||||
if( zEnd==z ){
|
||||
sqlite3_result_null(ctx);
|
||||
}else if( i==QPVTAB_IX || i==QPVTAB_OP || i==QPVTAB_UX ){
|
||||
sqlite3_result_int(ctx, atoi(z));
|
||||
}else{
|
||||
sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
|
||||
}
|
||||
}else if( i>=QPVTAB_A && i<=QPVTAB_E ){
|
||||
if( pCur->flags & 0x001 ){
|
||||
sqlite3_result_int(ctx, i-QPVTAB_A+1);
|
||||
}else{
|
||||
char x = 'a'+i-QPVTAB_A;
|
||||
sqlite3_result_text64(ctx, &x, 1, SQLITE_TRANSIENT, SQLITE_UTF8);
|
||||
}
|
||||
}else if( i==QPVTAB_FLAGS ){
|
||||
sqlite3_result_int(ctx, pCur->flags);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the rowid for the current row. In this implementation, the
|
||||
** rowid is the same as the output value.
|
||||
*/
|
||||
static int qpvtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int qpvtabEof(sqlite3_vtab_cursor *cur){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor*)cur;
|
||||
return pCur->iRowid>=pCur->nData;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the qpvtab_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
** once prior to any call to qpvtabColumn() or qpvtabRowid() or
|
||||
** qpvtabEof().
|
||||
*/
|
||||
static int qpvtabFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
qpvtab_cursor *pCur = (qpvtab_cursor *)pVtabCursor;
|
||||
pCur->iRowid = 0;
|
||||
pCur->zData = idxStr;
|
||||
pCur->nData = (int)strlen(idxStr);
|
||||
pCur->flags = idxNum;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append the text of a value to pStr
|
||||
*/
|
||||
static void qpvtabStrAppendValue(
|
||||
sqlite3_str *pStr,
|
||||
sqlite3_value *pVal
|
||||
){
|
||||
switch( sqlite3_value_type(pVal) ){
|
||||
case SQLITE_NULL:
|
||||
sqlite3_str_appendf(pStr, "NULL");
|
||||
break;
|
||||
case SQLITE_INTEGER:
|
||||
sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pVal));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
sqlite3_str_appendf(pStr, "%!f", sqlite3_value_double(pVal));
|
||||
break;
|
||||
case SQLITE_TEXT: {
|
||||
int i;
|
||||
const char *a = (const char*)sqlite3_value_text(pVal);
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
for(i=0; i<n; i++){
|
||||
char c = a[i];
|
||||
if( c=='\n' ) c = ' ';
|
||||
sqlite3_str_append(pStr, &c, 1);
|
||||
if( c=='\'' ) sqlite3_str_append(pStr, &c, 1);
|
||||
}
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
int i;
|
||||
const unsigned char *a = sqlite3_value_blob(pVal);
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
sqlite3_str_append(pStr, "x'", 2);
|
||||
for(i=0; i<n; i++){
|
||||
sqlite3_str_appendf(pStr, "%02x", a[i]);
|
||||
}
|
||||
sqlite3_str_append(pStr, "'", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the virtual table. This routine needs to create
|
||||
** a query plan for each invocation and compute an estimated cost for that
|
||||
** plan.
|
||||
*/
|
||||
static int qpvtabBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
sqlite3_str *pStr = sqlite3_str_new(0);
|
||||
int i, k = 0;
|
||||
int rc;
|
||||
sqlite3_str_appendf(pStr, "nConstraint,%d,,,,\n", pIdxInfo->nConstraint);
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
sqlite3_value *pVal;
|
||||
int iCol = pIdxInfo->aConstraint[i].iColumn;
|
||||
int op = pIdxInfo->aConstraint[i].op;
|
||||
if( iCol==QPVTAB_FLAGS && pIdxInfo->aConstraint[i].usable ){
|
||||
pVal = 0;
|
||||
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
|
||||
assert( rc==SQLITE_OK || pVal==0 );
|
||||
if( pVal ){
|
||||
pIdxInfo->idxNum = sqlite3_value_int(pVal);
|
||||
if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
}
|
||||
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
iCol = QPVTAB_NONE;
|
||||
}
|
||||
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
|
||||
i,
|
||||
azColname[iCol],
|
||||
op,
|
||||
pIdxInfo->aConstraint[i].usable);
|
||||
pVal = 0;
|
||||
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
|
||||
assert( rc==SQLITE_OK || pVal==0 );
|
||||
if( pVal ){
|
||||
qpvtabStrAppendValue(pStr, pVal);
|
||||
}
|
||||
sqlite3_str_append(pStr, "\n", 1);
|
||||
}
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
int iCol = pIdxInfo->aConstraint[i].iColumn;
|
||||
int op = pIdxInfo->aConstraint[i].op;
|
||||
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|
||||
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
){
|
||||
iCol = QPVTAB_NONE;
|
||||
}
|
||||
if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
|
||||
if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
|
||||
for(i=0; i<pIdxInfo->nOrderBy; i++){
|
||||
int iCol = pIdxInfo->aOrderBy[i].iColumn;
|
||||
sqlite3_str_appendf(pStr, "aOrderBy,%d,%s,%d,,\n",i,
|
||||
iCol>=0 ? azColname[iCol] : "rowid",
|
||||
pIdxInfo->aOrderBy[i].desc
|
||||
);
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "sqlite3_vtab_distinct,%d,,,,\n",
|
||||
sqlite3_vtab_distinct(pIdxInfo));
|
||||
sqlite3_str_appendf(pStr, "idxFlags,%d,,,,\n", pIdxInfo->idxFlags);
|
||||
sqlite3_str_appendf(pStr, "colUsed,%d,,,,\n", (int)pIdxInfo->colUsed);
|
||||
pIdxInfo->estimatedCost = (double)10;
|
||||
pIdxInfo->estimatedRows = 10;
|
||||
sqlite3_str_appendf(pStr, "idxNum,%d,,,,\n", pIdxInfo->idxNum);
|
||||
sqlite3_str_appendf(pStr, "orderByConsumed,%d,,,,\n",
|
||||
pIdxInfo->orderByConsumed);
|
||||
pIdxInfo->idxStr = sqlite3_str_finish(pStr);
|
||||
pIdxInfo->needToFreeIdxStr = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** virtual table.
|
||||
*/
|
||||
static sqlite3_module qpvtabModule = {
|
||||
/* iVersion */ 0,
|
||||
/* xCreate */ 0,
|
||||
/* xConnect */ qpvtabConnect,
|
||||
/* xBestIndex */ qpvtabBestIndex,
|
||||
/* xDisconnect */ qpvtabDisconnect,
|
||||
/* xDestroy */ 0,
|
||||
/* xOpen */ qpvtabOpen,
|
||||
/* xClose */ qpvtabClose,
|
||||
/* xFilter */ qpvtabFilter,
|
||||
/* xNext */ qpvtabNext,
|
||||
/* xEof */ qpvtabEof,
|
||||
/* xColumn */ qpvtabColumn,
|
||||
/* xRowid */ qpvtabRowid,
|
||||
/* xUpdate */ 0,
|
||||
/* xBegin */ 0,
|
||||
/* xSync */ 0,
|
||||
/* xCommit */ 0,
|
||||
/* xRollback */ 0,
|
||||
/* xFindMethod */ 0,
|
||||
/* xRename */ 0,
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
};
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_qpvtab_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3_create_module(db, "qpvtab", &qpvtabModule, 0);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@ -759,13 +759,15 @@ int sqlite3_regexp_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused */
|
||||
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, re_sql_func, 0, 0);
|
||||
rc = sqlite3_create_function(db, "regexp", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
0, re_sql_func, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
|
||||
** of regexp(PATTERN,STRING). */
|
||||
rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
(void*)db, re_sql_func, 0, 0);
|
||||
rc = sqlite3_create_function(db, "regexpi", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
(void*)db, re_sql_func, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -386,7 +386,7 @@ static int seriesBestIndex(
|
||||
** the preferred case */
|
||||
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
|
||||
pIdxInfo->estimatedRows = 1000;
|
||||
if( pIdxInfo->nOrderBy==1 ){
|
||||
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
|
||||
if( pIdxInfo->aOrderBy[0].desc ){
|
||||
idxNum |= 8;
|
||||
}else{
|
||||
|
||||
@ -71,7 +71,7 @@ struct SHA1Context {
|
||||
/*
|
||||
* Hash a single 512-bit block. This is the core of the algorithm.
|
||||
*/
|
||||
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
|
||||
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
|
||||
unsigned int qq[5]; /* a, b, c, d, e; */
|
||||
static int one = 1;
|
||||
unsigned int block[16];
|
||||
|
||||
@ -436,6 +436,7 @@ static void SHA3Update(
|
||||
unsigned int nData
|
||||
){
|
||||
unsigned int i = 0;
|
||||
if( aData==0 ) return;
|
||||
#if SHA3_BYTEORDER==1234
|
||||
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
|
||||
for(; i+7<nData; i+=8){
|
||||
|
||||
@ -1262,9 +1262,14 @@ static int zipfileFilter(
|
||||
zipfileCursorErr(pCsr, "zipfile() function requires an argument");
|
||||
return SQLITE_ERROR;
|
||||
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
|
||||
static const u8 aEmptyBlob = 0;
|
||||
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
assert( pTab->pFirstEntry==0 );
|
||||
if( aBlob==0 ){
|
||||
aBlob = &aEmptyBlob;
|
||||
nBlob = 0;
|
||||
}
|
||||
rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
|
||||
pCsr->pFreeEntry = pTab->pFirstEntry;
|
||||
pTab->pFirstEntry = pTab->pLastEntry = 0;
|
||||
@ -1938,7 +1943,7 @@ static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
|
||||
** SELECT zipfile(name,mode,mtime,data) ...
|
||||
** SELECT zipfile(name,mode,mtime,data,method) ...
|
||||
*/
|
||||
void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
ZipfileCtx *p; /* Aggregate function context */
|
||||
ZipfileEntry e; /* New entry to add to zip archive */
|
||||
|
||||
@ -2113,7 +2118,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
|
||||
/*
|
||||
** xFinalize() callback for zipfile aggregate function.
|
||||
*/
|
||||
void zipfileFinal(sqlite3_context *pCtx){
|
||||
static void zipfileFinal(sqlite3_context *pCtx){
|
||||
ZipfileCtx *p;
|
||||
ZipfileEOCD eocd;
|
||||
sqlite3_int64 nZip;
|
||||
|
||||
@ -1563,7 +1563,7 @@ static char *rbuVacuumTableStart(
|
||||
** the caller has to use an OFFSET clause to extract only the required
|
||||
** rows from the sourct table, just as it does for an RBU update operation.
|
||||
*/
|
||||
char *rbuVacuumIndexStart(
|
||||
static char *rbuVacuumIndexStart(
|
||||
sqlite3rbu *p, /* RBU handle */
|
||||
RbuObjIter *pIter /* RBU iterator object */
|
||||
){
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
*/
|
||||
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
|
||||
#define SQLITE_ENABLE_DBPAGE_VTAB 1
|
||||
#define SQLITE_ENABLE_JSON1 1
|
||||
#undef SQLITE_THREADSAFE
|
||||
#define SQLITE_THREADSAFE 0
|
||||
#undef SQLITE_ENABLE_COLUMN_METADATA
|
||||
|
||||
@ -26,11 +26,7 @@
|
||||
# define GEODEBUG(X)
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Versions of isspace(), isalnum() and isdigit() to which it is safe
|
||||
** to pass signed char values.
|
||||
*/
|
||||
/* Character class routines */
|
||||
#ifdef sqlite3Isdigit
|
||||
/* Use the SQLite core versions if this routine is part of the
|
||||
** SQLite amalgamation */
|
||||
@ -45,6 +41,7 @@
|
||||
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
** the library isspace() function.
|
||||
@ -67,7 +64,7 @@ static const char geopolyIsSpace[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x])
|
||||
#endif /* JSON NULL - back to original code */
|
||||
|
||||
/* Compiler and version */
|
||||
@ -156,7 +153,7 @@ static void geopolySwab32(unsigned char *a){
|
||||
|
||||
/* Skip whitespace. Return the next non-whitespace character. */
|
||||
static char geopolySkipSpace(GeoParse *p){
|
||||
while( safe_isspace(p->z[0]) ) p->z++;
|
||||
while( fast_isspace(p->z[0]) ) p->z++;
|
||||
return p->z[0];
|
||||
}
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ do_corruption_tests rtreeA-3.1 {
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-3.1.0.3 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
} {1}
|
||||
|
||||
do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
|
||||
@ -221,7 +221,7 @@ do_corruption_tests rtreeA-5.1 {
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-5.2 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -238,7 +238,7 @@ do_corruption_tests rtreeA-6.1 {
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-6.2 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
SELECT rtreecheck('main', 't1')!='ok'
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -117,13 +117,13 @@ sqlite3_db_config db DEFENSIVE 0
|
||||
do_execsql_test 3.2 {
|
||||
BEGIN;
|
||||
UPDATE r2_node SET data = X'123456';
|
||||
SELECT rtreecheck('r2')!="ok";
|
||||
SELECT rtreecheck('r2')!='ok';
|
||||
} {1}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
ROLLBACK;
|
||||
UPDATE r2_node SET data = X'00001234';
|
||||
SELECT rtreecheck('r2')!="ok";
|
||||
SELECT rtreecheck('r2')!='ok';
|
||||
} {1}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
|
||||
@ -324,7 +324,7 @@ static int SQLITE_TCLAPI register_box_query(
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx*));
|
||||
pCtx = (BoxQueryCtx*)ckalloc(sizeof(BoxQueryCtx));
|
||||
pCtx->interp = interp;
|
||||
pCtx->pScript = Tcl_DuplicateObj(objv[2]);
|
||||
Tcl_IncrRefCount(pCtx->pScript);
|
||||
|
||||
@ -63,7 +63,7 @@ proc do_then_undo {tn sql} {
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES("abc", "xyz");
|
||||
INSERT INTO t1 VALUES('abc', 'xyz');
|
||||
}
|
||||
do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); }
|
||||
do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; }
|
||||
|
||||
22
main.mk
22
main.mk
@ -64,7 +64,7 @@ LIBOBJ+= vdbe.o parse.o \
|
||||
fts3_tokenize_vtab.o \
|
||||
fts3_unicode.o fts3_unicode2.o \
|
||||
fts3_write.o fts5.o func.o global.o hash.o \
|
||||
icu.o insert.o json1.o legacy.o loadext.o \
|
||||
icu.o insert.o json.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memdb.o memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
|
||||
@ -111,6 +111,7 @@ SRC = \
|
||||
$(TOP)/src/hash.h \
|
||||
$(TOP)/src/hwtime.h \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/json.c \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
@ -244,7 +245,6 @@ SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h
|
||||
SRC += \
|
||||
$(TOP)/ext/misc/json1.c \
|
||||
$(TOP)/ext/misc/stmt.c
|
||||
|
||||
|
||||
@ -377,6 +377,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/normalize.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/prefixes.c \
|
||||
$(TOP)/ext/misc/qpvtab.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
@ -528,7 +529,7 @@ TESTOPTS = --verbose=file --output=test-out.txt
|
||||
|
||||
# Extra compiler options for various shell tools
|
||||
#
|
||||
SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_RTREE
|
||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
@ -537,8 +538,7 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
@ -678,9 +678,6 @@ sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl
|
||||
fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl
|
||||
tclsh $(TOP)/ext/fts2/mkfts2amal.tcl
|
||||
|
||||
fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl
|
||||
tclsh $(TOP)/ext/fts3/mkfts3amal.tcl
|
||||
|
||||
# Rules to build the LEMON compiler generator
|
||||
#
|
||||
lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
||||
@ -831,9 +828,6 @@ fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
fts5.o: fts5.c sqlite3ext.h sqlite3.h
|
||||
$(TCCX) -DSQLITE_CORE -c fts5.c
|
||||
|
||||
json1.o: $(TOP)/ext/misc/json1.c sqlite3ext.h sqlite3.h
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
|
||||
|
||||
stmt.o: $(TOP)/ext/misc/stmt.c sqlite3ext.h sqlite3.h
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
@ -931,12 +925,6 @@ amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c \
|
||||
$(TOP)/ext/session/test_session.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||
|
||||
fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
|
||||
-DSQLITE_ENABLE_FTS3=1 \
|
||||
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
|
||||
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
|
||||
|
||||
coretestprogs: $(TESTPROGS)
|
||||
|
||||
testprogs: coretestprogs srcck1$(EXE) fuzzcheck$(EXE) sessionfuzz$(EXE)
|
||||
|
||||
387
manifest
387
manifest
@ -1,13 +1,13 @@
|
||||
C Version\s3.37.2
|
||||
D 2022-01-06T13:25:41.295
|
||||
C Version\s3.38.2
|
||||
D 2022-03-26T13:51:10.240
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd
|
||||
F Makefile.in b210ad2733317f1a4353085dfb9d385ceec30b0e6a61d20a5accabecac6b1949
|
||||
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
|
||||
F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f
|
||||
F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110
|
||||
F VERSION b8218d35896c0f381cf64a499abbab64eeb86b40116a7d35c5a39c6677e8bb89
|
||||
F Makefile.msc b28a8a7a977e7312f6859f560348e1eb110c21bd6cf9fab0d16537c0a514eef3
|
||||
F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c
|
||||
F VERSION 2c46bf3c621980e333221949b5ea8ce0bf5e6f0c328e6b228501ea3190abe467
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
@ -15,10 +15,10 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc d146a08ebbdf7f881ba600a49cd8dce40c4c807addcdb4b9b6a507e4b40ce837
|
||||
F autoconf/Makefile.msc 8401a514e4e70add3c6448348ae31322d5cb7db427b05a20828f943c3ddb2733
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79
|
||||
F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56
|
||||
F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@ -34,10 +34,11 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
|
||||
F configure f8a03394ccec572e76a570aa858ccd24e0d54fd76c995b7220a4dfda8b899d27 x
|
||||
F configure.ac c8ba54bac7e73e000acdfef5e394fe21a3876aa09d0f5c07131bf5ac5a525299
|
||||
F configure 40cf509efcf3fe6062a5f6a25742a9622cfb6e2df127ba7b5e2400de41994dd8 x
|
||||
F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
@ -51,7 +52,7 @@ F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a4980828
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 3c642a4e7bbb14f21ddab595436fb465a4733f47a0fe5b2855e1d5ff900ef08e
|
||||
F ext/expert/sqlite3expert.c 921a00823a826150cbb9a3341285a8edec7533480b71281e77737f19559b4b14
|
||||
F ext/expert/sqlite3expert.c 6ca30d73b9ed75bd56d6e0d7f2c962d2affaa72c505458619d0ff5d9cdfac204
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
@ -84,9 +85,9 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 6bfdc941372ee431e3d362986674a8708eb0e700b28c3d35d46d953a9351155f
|
||||
F ext/fts3/fts3.c 6634a3854e70afa8710ee5e3a7253cd0f0c89d4cce207fcbfe2ead3bad1db7d5
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h cff59b8b13dafe9d59924a5d710f771ed8b121a55cccbc99b6e2a723fcde14dc
|
||||
F ext/fts3/fts3Int.h dafdc371f9fbab175744b06cfe019d5f040cdfdbd11fea752f5dc28d45b04c05
|
||||
F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f
|
||||
F ext/fts3/fts3_expr.c 903bfb9433109fffb10e910d7066c49cbf8eeae316adc93f0499c4da7dfc932a
|
||||
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
|
||||
@ -96,7 +97,7 @@ F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c f9a8149173553113f3c495a503843e30028b5dc3723d0ca798c5ad6142e130e6
|
||||
F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
|
||||
F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
|
||||
F ext/fts3/fts3_tokenize_vtab.c 8d15b148e7d88a4280389a200b26e8d52abda4c4ec2e9a35e9d7a1fa50e5aa03
|
||||
F ext/fts3/fts3_tokenize_vtab.c a95feda3590f3c3e17672fe35b67ea6112471aeea4c07ef7744a6606b66549aa
|
||||
F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
@ -104,7 +105,6 @@ F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0
|
||||
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
|
||||
F ext/fts3/fts3_write.c 3109c1a232da86474e196cc7db754445a354409f141e08cb11c846cdb17bdf31
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
@ -119,8 +119,8 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
|
||||
F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422f6c2078aa
|
||||
F ext/fts5/fts5_expr.c fcd0770d53028c2b53a15d0f53bf6d0e01b1bf3dd97630b9fedf0801f03aa3ec
|
||||
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
|
||||
F ext/fts5/fts5_index.c b1b2e5d4a9e3b54c740d8354cc47e3fa879f54c2176de55e0b882dab45ab7b07
|
||||
F ext/fts5/fts5_main.c 7c6092a53e6802962fa07b0fad3e61cb077b6c98b74b727d8d44ac2cf63bd914
|
||||
F ext/fts5/fts5_index.c fdfbc8a62827ec1d1b6f207a1e59c1c4986c3ce245592b5128ffe738867cfcd1
|
||||
F ext/fts5/fts5_main.c 6078ae86d3b813753a4f1201054550aff21a3f660e97b30f200d2b1472874151
|
||||
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
|
||||
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
@ -160,7 +160,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
|
||||
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
|
||||
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
|
||||
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
|
||||
F ext/fts5/test/fts5corrupt3.test 0e473620582a53ac61f468f364db8a151c1e18d2a879b16439d172c12c4c9828
|
||||
F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
|
||||
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
|
||||
F ext/fts5/test/fts5corrupt5.test 550d0884c14424f9acad051a741f1dd99ec9342277d938e91ff3daf9123d1209
|
||||
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
|
||||
@ -170,7 +170,7 @@ F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3
|
||||
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
|
||||
F ext/fts5/test/fts5doclist.test faa9e9cc3c0645fa6203667cb5f007c359447c6ee66753f71a58175c2497cacd
|
||||
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
|
||||
F ext/fts5/test/fts5eb.test 239bb2f02571f8cccfc7018d08f502df1cd8cc6a69b65ed1dde5f6a070e3f669
|
||||
F ext/fts5/test/fts5eb.test a973baadac524dbbb4ad9b0e99030e12cabde2c6b28e0ac437298007b642cd12
|
||||
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
|
||||
F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344
|
||||
F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522
|
||||
@ -188,7 +188,7 @@ F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b99
|
||||
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f
|
||||
F ext/fts5/test/fts5integrity.test e387b2bd1c83e50f4a12f58a5fd399111bbab36be2f1c9fd5bb974be08a32de6
|
||||
F ext/fts5/test/fts5integrity.test 62147a1e85405b986691177e0312be5a64ec9e67b17994e83892d9afa6247600
|
||||
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
|
||||
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
@ -280,7 +280,7 @@ F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678
|
||||
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
|
||||
F ext/lsm1/lsm_unix.c 11e0a5c19d754a4e1d93dfad06de8cc201f10f886b8e61a4c599ed34e334fc24
|
||||
F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62
|
||||
F ext/lsm1/lsm_vtab.c 169bfe7ef8e6c9de9c77e17c4c50c9ae55fb0167d80be3d1be82c991184b6f35
|
||||
F ext/lsm1/lsm_vtab.c e57aa3eb456bf2b98064014027e097c9402d6dec7b59564ddbfa1c0ead8f96c5
|
||||
F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
|
||||
F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
|
||||
F ext/lsm1/test/lsm1_simple.test a04d08e8661ae6fc53786c67f0bd102c6692f003e859dde03ed9ac3f12e066e5
|
||||
@ -297,17 +297,16 @@ F ext/misc/cksumvfs.c b42ef52eaaa510d54ec320c87bea149e934a3b06cd232be2093562bf66
|
||||
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
|
||||
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
|
||||
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
|
||||
F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
|
||||
F ext/misc/csv.c d14709096280dc0e20c533f184568952bf4b8022ea80afc4aa9fec5ab3637bb3
|
||||
F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
|
||||
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
|
||||
F ext/misc/decimal.c 09f967dcf4a1ee35a76309829308ec278d3648168733f4a1147820e11ebefd12
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
|
||||
F ext/misc/fileio.c 57fefd0efc535e62bb8b07fa146875171481da81a759bbfbe2fc91bab90058e0
|
||||
F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebfb720
|
||||
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
|
||||
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
|
||||
F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511
|
||||
F ext/misc/json1.c 89a988f06dcb3da0d0af9fdb2b09892452ad12dfd8f432600ee6437a6dcac310
|
||||
F ext/misc/ieee754.c 984d51fe23e956484ec1049df6f5257002e3ab338cabceb39761c2e80ad10bf4
|
||||
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
|
||||
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
|
||||
F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
|
||||
@ -317,13 +316,14 @@ F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1
|
||||
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
|
||||
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
|
||||
F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
|
||||
F ext/misc/regexp.c 8cd0d2d904bf7014ba28beab8c1d502b5154e04a8c738b079d88e4ecca1b3981
|
||||
F ext/misc/qpvtab.c 09738419e25f603a35c0ac8bd0a04daab794f48d08a9bc07a6085b9057b99009
|
||||
F ext/misc/regexp.c b267fd05ff8d38b22f4c2809d7b7a2c61d522e9faf2feb928dbb9662e4a3a386
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c f9896e76b029e3c6553c520552555e803e26e7dfe1890d5866243cf072d938d0
|
||||
F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
|
||||
F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec
|
||||
F ext/misc/series.c 8d79354f2c3d46b95ee21272a07cf0bcabb58d1f2b06d9e7b8a31dca1dacb3e5
|
||||
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
|
||||
F ext/misc/shathree.c 9b6fce315bf8b37bd72786086d1f0974701f651e83022a93244e0e8f56f98a45
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
|
||||
F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
|
||||
@ -339,7 +339,7 @@ F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e
|
||||
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
|
||||
F ext/misc/zipfile.c 5dcbbdae13ba45db5d3843b6f32a8f99df7ab0349a704857a3000618f9ea9ecb
|
||||
F ext/misc/zipfile.c 3e76c6c3f73e05bfc7b2f743c268071c31e9aec0491282506ecb79cdef69d6f2
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
|
||||
@ -382,20 +382,20 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
|
||||
F ext/rbu/rbuvacuum2.test 886add83fd74bcb02e6dd016ae5b585367bd58c5d0694c9d9ca7bdb1d1f578c2
|
||||
F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
|
||||
F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
|
||||
F ext/rbu/sqlite3rbu.c 3658f1c6603955c7426952b74a6896337b1f672d326cd565e5af20e18d5744f0
|
||||
F ext/rbu/sqlite3rbu.c 8737cabdfbee84bb25a7851ecef8b1312be332761238da9be6ddb10c62ad4291
|
||||
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
|
||||
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
|
||||
F ext/repair/checkindex.c 4383e4469c21e5b9ae321d0d63cec53e981af9d7a6564be6374f0eeb93dfc890
|
||||
F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e284c1cf140fc91720f
|
||||
F ext/repair/sqlite3_checker.c.in 445118c5f7fea958b36fba1b2c464283e60ed4842039ddee3265f1698115ebf7
|
||||
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
|
||||
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
|
||||
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
|
||||
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c a7021cb524621573ccda213a35b0339371849dd4acc4909f689786ee1f964b7f
|
||||
F ext/rtree/geopoly.c cc3f89c11abcf114fa60d74709ae8b5bc1eae5a261b30bc1bb7085089c03bfab
|
||||
F ext/rtree/rtree.c d7b4b8b81d8d54376a7f81de5be85ec58b37c11604bcf42984a8418b34158d93
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 35c3bc0def71317b7601ee0d1149e7df2cd8fc4f13ec89a64761ac3f46ca123f
|
||||
@ -407,7 +407,7 @@ F ext/rtree/rtree6.test 9ce3691c1aac43070a9f194f0ebf54372db346c5a82241fd11b525ed
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
|
||||
F ext/rtree/rtree9.test fd3c9384ef8aabbc127b3878764070398f136eebc551cd20484b570f2cc1956a
|
||||
F ext/rtree/rtreeA.test c0d8e91e25052d5f3fbda17632ca843b82ca13c4181fb6000a0d63bd2d7e70ce
|
||||
F ext/rtree/rtreeA.test a7fd235d8194115fa2e14d300337931eb2e960fe8a46cdfb66add2206412ea41
|
||||
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
|
||||
F ext/rtree/rtreeC.test c4bfa9a61c6788c03e4a9ce40ab2cfc6100982559effd9842d1b658e1d47aa5f
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
@ -418,7 +418,7 @@ F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7
|
||||
F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
|
||||
F ext/rtree/rtreecheck.test 1f542257f21c8a22ce3462c852ec1a0847fa8b3133053abfab3972764210e8bc
|
||||
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
|
||||
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
|
||||
F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9
|
||||
@ -426,7 +426,7 @@ F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c
|
||||
F ext/rtree/rtreedoc3.test 555a878c4d79c4e37fa439a1c3b02ee65d3ebaf75d9e8d96a9c55d66db3efbf8
|
||||
F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
|
||||
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
|
||||
F ext/rtree/test_rtreedoc.c 5ad4029d6804eb9efafcac1598a9e0582f6119e48f818854f5b4db1788ca8bd4
|
||||
F ext/rtree/test_rtreedoc.c de76b3472bc74b788d079342fdede22ff598796dd3d97acffe46e09228af83a3
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
@ -440,7 +440,7 @@ F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
|
||||
F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
|
||||
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
|
||||
F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926
|
||||
F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
|
||||
F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904
|
||||
F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
|
||||
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
|
||||
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
|
||||
@ -473,7 +473,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 002e77acdfeb08d1d8f4d360b01e130aa243fb5701728e81fac9085794f27155
|
||||
F main.mk 80ac3d2f82eb21c6fb4423f9c7f8e207abb51be6676845a00e246cfb22f9c77c
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@ -485,45 +485,46 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 23743384e59f9d36df870ce41adfdf7934fd0adb619d7fa6fd1aac77c28a7533
|
||||
F src/alter.c 006325f8844c65d885b3ba469b4c08d9dd0cd3e9ec481d5bcff621f224cb2302
|
||||
F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516
|
||||
F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf
|
||||
F src/attach.c f26d400f3ffe2cdca01406bca70e5f58c5488bf165b4fc37c228136dfcf1b583
|
||||
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
|
||||
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
|
||||
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
|
||||
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 012772a0cbd1c8ee7ac34f5a9ff9861de989725cb26e7a07afbbb2d43deeccd9
|
||||
F src/btree.c 1ebe34ee736e05ead62bcf762a71c5779526356b0616dec67f20478d008e2eb4
|
||||
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
|
||||
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
|
||||
F src/build.c c46bd4f5a69f398410c4472f7c1c4291fb8078d2c9758a2dad5916edd1d30ecc
|
||||
F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc
|
||||
F src/btreeInt.h 8be97d3939d626f734ec1b577efa4e6e186da00daf5b3227af199ca1c24cdd71
|
||||
F src/build.c a0cc68fe8172c0a31b54576f9c6c0fe6f7c82b1b5e1387afdd6a5a13132bc131
|
||||
F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
|
||||
F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e
|
||||
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
|
||||
F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1
|
||||
F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f
|
||||
F src/dbpage.c 30ff075a9a9156bd2cccb5c1ea579f2afbaa64989648e8c9d72cb4a3417f5136
|
||||
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
|
||||
F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7
|
||||
F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846
|
||||
F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d
|
||||
F src/expr.c b90a029105a93a93a0ed5e5f8c5eaed8f19043a3b62e4c4d235a4611d9ada178
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560
|
||||
F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
|
||||
F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8
|
||||
F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c
|
||||
F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761
|
||||
F src/global.c a3daa18a1696aadd94f18d37cbbdebf0bbdb827b8397a534f021cd56c15cd0f9
|
||||
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 04c9b133be6152b4f229aab8e38230b3bf6d2e7e76455a893bff5f70e566237b
|
||||
F src/insert.c 6c0641efc3636732a02f45defe358899d695c065fc26fbba1b2cab415b5b2e57
|
||||
F src/json.c 225b00422112ecd7094a555f3ace16b25d7d5894062b823269ed03899907c2a2
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c
|
||||
F src/main.c 1ea70751e6005ab6a9f784730fa0919efaa6639440a287deb73cb711e5aae57a
|
||||
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
|
||||
F src/loadext.c aa919a6a7884f8b34d7b791841b24d14b1b0ab43f45b3940f4851043b2855c0c
|
||||
F src/main.c 0840cee6984034c7e73cc747a1562c7eaed4673694bf20b00980aaa0672c0405
|
||||
F src/malloc.c fec841aa0a0400a6f7d20706178a5d8e8219a6bf562b6fe712c17f6c26813266
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c c2dc88f97c410eb68a24468344b65526685e18354ddfd15906750c1eaf9dc2dd
|
||||
F src/memjournal.c ff4336a98b05ede2adee7595f22d6f7d1cdc6bf0f0a5c3d77b0acdf017b2e8b2
|
||||
F src/memjournal.c 8bd50ae6d9c6d34b3a96cc3b4f567f9935dc358444d872ab48901a8c11ad82a6
|
||||
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
|
||||
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
@ -535,33 +536,33 @@ F src/os.c b1c4f2d485961e9a5b6b648c36687d25047c252222e9660b7cc25a6e1ea436ab
|
||||
F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e
|
||||
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
|
||||
F src/os_unix.c df6142ed776b5e52c7c3106767283be2d510b63d72beb3b205898462f340a176
|
||||
F src/os_win.c a8ea80037e81127ca01959daa87387cc135f325c88dc745376c4f760de852a10
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 5b79a1c09bc19628a763c822ef96326832090703a6608c64dc5fc166ab8dda79
|
||||
F src/pager.c e4f4c1e07b2cc4fa44fc0bd51957ca6066f6b8c0b0e0388f11a6728b50d8f4e6
|
||||
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
|
||||
F src/parse.y 0bd7971a7489bbf6c3726f1b50da6e508bdff8fa493e9cc3f5a96b12cbb2361e
|
||||
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
|
||||
F src/parse.y 0f02b27cdaa334441463153fff3ceb780fea006ab53ffd6ef566d4468f93e924
|
||||
F src/pcache.c 0aab73936341fad83d107cf62c6a7bc2d2d5fb9aaec8c3ce61e19fc18e4560fc
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
|
||||
F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f
|
||||
F src/pragma.c 7c024d690a3dc93f61830f11f900e4af2357f31d081b0c79099ca5e28919cba7
|
||||
F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
|
||||
F src/prepare.c dab0c2995a33ee2c458354cb7dd13b2b33362425c52301e41d833add7660e7ca
|
||||
F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d
|
||||
F src/prepare.c fd940149c691684e7c1073c3787a7170e44852b02d1275d2e30a5b58e89cfcaf
|
||||
F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32
|
||||
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
|
||||
F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571
|
||||
F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a
|
||||
F src/shell.c.in 1458b700144c8326fda2514aaddeda49d6f01f1d1ccf7b9b696c53a3535a119c
|
||||
F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0
|
||||
F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35
|
||||
F src/shell.c.in 69d1e59da4881f096ab47fbd3e6d99794f3e4a43f41fd9e4d2e845c9b8d20fd5
|
||||
F src/sqlite.h.in b93deee892f1bc4030e5c8712df9e21d786a1bf8e921ab8dc987eaf1e44c676f
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
|
||||
F src/sqliteInt.h 4bf21edf5c330299d1b7399d604da1787001725dbb1c675fe0989ceb1ee8043f
|
||||
F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6
|
||||
F src/sqliteInt.h e7b93bb693cb14259f6c3faadc6d7c824ff509aac673622a76c161a96c5872d0
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6
|
||||
F src/test1.c d6c945a8bb211ed72ea515f0b9743caeaf38c66da6418a7b1dcf3764e1368bbb
|
||||
F src/tclsqlite.c 1f6673991147bc2cecc08a40d22f9803b84c805b24b499fe727f392256f73474
|
||||
F src/test1.c 87fda59eea3ac1eba1baef37c1967565cb1b8d6d264649f2e57f252ca5989914
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
|
||||
@ -573,15 +574,15 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
|
||||
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
|
||||
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
|
||||
F src/test_bestindex.c 8294d8223b7f18a3ddb7f9a0e30815dcca4e61681f78b538c870f7d934f88b81
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 284c29912736f68b0a583a920bf63fd8f9125dffb8a75cb0676e58502b2f7908
|
||||
F src/test_config.c 8264637b06a3c1f0727c88d1ea32dcf7986b9e7e358a970cae87cdac8a5b2708
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
|
||||
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
|
||||
F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480
|
||||
F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276
|
||||
F src/test_func.c 24df3a346c012b1fc9e1001d346db6054deb426db0a7437e92490630e71c9b0a
|
||||
F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd
|
||||
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
|
||||
F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
|
||||
@ -615,34 +616,34 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
|
||||
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 865911afa00fed589cd03b25c140ca88544842aaef7b81f7d41ed769a7a54120
|
||||
F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc
|
||||
F src/trigger.c 043d66ecb25a223c614681c8ab758f1aaf6e507c901d3a4668113afab1cc2dc7
|
||||
F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d
|
||||
F src/tokenize.c 6661a9fa660ecbd3ac0df1acd2ec788b3a8122b4316022bcdaf476ea6754a8de
|
||||
F src/treeview.c a84b57d15e46007d8b1ae249344b3f0b7f3c62def908b98baaa54935a57c8476
|
||||
F src/trigger.c 5fc3cde35cc4de510be68bb2db4dcff0ce0e1625f43e28a0920be9a6f010cd3f
|
||||
F src/update.c f875b0d59da5c3055a0b2ac20560e1650229c6787e78de5e9836267b5cbb8359
|
||||
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167
|
||||
F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
|
||||
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
|
||||
F src/vdbe.c 84cc51edc36f773a97433c0a1388833557806f56562b6a2cb9fefeadc5e236b0
|
||||
F src/vdbe.c 8239c69f3cb6fa27bac30d60c5a1ebac723abc007ff870ffc3af93e5159c7216
|
||||
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
|
||||
F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab
|
||||
F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a
|
||||
F src/vdbeaux.c 9e16b5cb02f9e95df008369880332b6551feea6a3495b44c20da96c381508042
|
||||
F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652
|
||||
F src/vdbemem.c a3d91dc9bb9ef725db77e4e9de7e1acef43192c9f8406c307665d503e3c2837c
|
||||
F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7
|
||||
F src/vdbeInt.h b45599a2b59f1ce042512ab6786b0b82a8cf3002f6b0fa60b4834e2cd3ac61d8
|
||||
F src/vdbeapi.c 8863ffb5a7bac42fe9a68aaa3526ee29fc18fb02a9b27188b756de41e33856e9
|
||||
F src/vdbeaux.c 0d7659fe8cb38ce86092b9bc5131c99a834a04eb78745e54acb77d79d7af2fb5
|
||||
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
|
||||
F src/vdbemem.c 69d3092d47b7a3a466a161961abd92bca7ab148abd8b497438eb17c6afdcbad8
|
||||
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
|
||||
F src/vtab.c 9d5c3f49d3a6959b6eef287bb8fa773563102a80a835c3314c57144412709e78
|
||||
F src/vtab.c 3d72c780d1ea08906a198e4f033921a658a54590e3ed72c544995d84f3f9464a
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028
|
||||
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c de0d4ff409c7b62a8803f9f267cc2c7fedddbc00de9ab7b5382c507383c18665
|
||||
F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d
|
||||
F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33
|
||||
F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825
|
||||
F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e
|
||||
F src/where.c 48d9836b7bdf301783719156fd50d45685a601605334035c559ed2d655df9fb6
|
||||
F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03
|
||||
F src/wherecode.c 84be340684393248b9f3ecbce9b87c8a6f818149b52302702ea0b8d2a9d51faf
|
||||
F src/whereexpr.c 2a71f5491798460c9590317329234d332d9eb1717cba4f3403122189a75c465e
|
||||
F src/window.c 731980c0887f7ec9859f5e0d3c69d5fbeb6e512a9e1d338935f53938eaba431e
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
|
||||
@ -655,19 +656,19 @@ F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807
|
||||
F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680fba3
|
||||
F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d
|
||||
F test/altercol.test b11fa1b131e80ab5b6ecfb3b725fb0419c14ca6efba5adb57aeabfc9baa0c8f3
|
||||
F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc
|
||||
F test/altercol.test 8465ca659c2c55a359cf16cc261df4fcb5c45a5f104a50827c337ae66c09dc15
|
||||
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
|
||||
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
|
||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||
F test/alterfault.test 289067108947bedca27534edd4ff251bcd298cf84402d7b24eaa3749305418c6
|
||||
F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
|
||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||
F test/altermalloc2.test ca3ebc01670d9313953a2b7628d8cc00dc5ea9988f229b3cbbbe1cca506dae45
|
||||
F test/altermalloc3.test 4660ac6240a8c82ba3947b927612dcc7c05a8eec3fe3c9f38e047ca69a789a33
|
||||
F test/alterqf.test 6b2482a957692606b23567ebd2cf80eb773e3c826086f5f151eee9c5a962623d
|
||||
F test/altermalloc2.test 17fb3724c4b004c469c27dc4ef181608aa644555fbd3f3236767584f73747c81
|
||||
F test/altermalloc3.test 55e606edf4b0acfbbd851ddfe93cfdddfae43d103644dcfd6008ae4ab3c44adf
|
||||
F test/alterqf.test ff6c6f881485c29ed699b8ef4774864ca1b0c01a6c08f5cdd624a008e4b40fca
|
||||
F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912
|
||||
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
|
||||
F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
|
||||
F test/altertab3.test 5929f522fd6fd708396ad9f317d4af9ff1a93e460df85bb1d54d4499eeb94960
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
|
||||
@ -689,7 +690,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
|
||||
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test 77e8517df10cb39f2e4e65dbefe1e81c8d8e65f29f68b09265ca6e534c68227e
|
||||
F test/atof1.test 10049623e77006691c4c2978c1dc8a3f75276377a53417811aa85bda7493f963
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
|
||||
@ -698,7 +699,7 @@ F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
|
||||
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
|
||||
F test/auth.test 567d917e0baddb6d0026a251cff977a3ab2c805a3cef906ba8653aafe7ad7240
|
||||
F test/auth.test 0f246deec5cb2f6f893f8fbb76628f182c08fe40f178b254dd72467ca012f657
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
@ -706,7 +707,7 @@ F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728
|
||||
F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex4.test 75cb1191a552b8201351f5a50d160fcb9387a0fbbfb820c77798bfee7da3f8cf
|
||||
F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3
|
||||
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
|
||||
F test/autovacuum2.test 76f7eb4fe6a6bf6d33a196a7141dba98886d2fb53a268d7feca285d5da4759d7
|
||||
@ -714,7 +715,7 @@ F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
|
||||
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
|
||||
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
|
||||
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
|
||||
F test/backup.test fc1ecefce723fad5199b55cec7a5a992ec8c3ad6873419e5e8919066dec457f3
|
||||
F test/backup2.test 8facb54df1388419d34b362ab1f7e233310ff3a3af64e8ad5ec47ba3c2bbe5cf
|
||||
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
@ -723,13 +724,14 @@ F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
|
||||
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
|
||||
F test/bestindex1.test 7cc626f1f4a7483bb6b38487d467db4477083be5cd93958aeda5d5127640dc81
|
||||
F test/bestindex2.test 60266e2854055788459cbfd86cef575601eabe74a2c61faba72601739fea4398
|
||||
F test/bestindex3.test e061a6ed0f519beee037ba7e7a4c37f80c8a7e4a303e2559ed1f760e4b0235eb
|
||||
F test/bestindex4.test 82250e7dcc6d5b15244edc9d6554b1760583af1b8548c2a255a1c4f28e744c0e
|
||||
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
|
||||
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
|
||||
F test/bestindex7.test a11348824aed0de2bb9030f092636929000cd72882bdf919adacc3792f67ccbd
|
||||
F test/bestindex1.test 856a453dff8c68b4568601eed5a8b5e20b4763af9229f3947c215729ed878db0
|
||||
F test/bestindex2.test 394ff8fbf34703391247116d6a44e1c50ee7282236ee77909044573cefc37bc0
|
||||
F test/bestindex3.test 34bea272b0e0f835651b16a3931dbe7ac927039be6b2e1cb617bbe1d584b492b
|
||||
F test/bestindex4.test 3039894f2dad50f3a68443dffad1b44c9b067ac03870102df1ce3d9a46ea602e
|
||||
F test/bestindex5.test a0c90b2dad7836e80a01379e200e5f8ec9476d49b349af02c0dbff2fb75dc98d
|
||||
F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a6f99dd4
|
||||
F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e
|
||||
F test/bestindex8.test abd0016fc04f19dc382976750b06df5463d2757e11e78a8ba7d7dc50671f3337
|
||||
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@ -737,6 +739,7 @@ F test/bigmmap.test b820c234daa56d24bc3bf006e3ac7aa9d9623c8ac656a38f59063b444a2d
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
|
||||
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
|
||||
F test/bind2.test 918bc35135f4141809ead7585909cde57d44db90a7a62aef540127148f91aab7
|
||||
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
|
||||
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
|
||||
F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252
|
||||
@ -760,19 +763,19 @@ F test/capi2.test 4ee545824adc3eb33bf57ef89f77440b28188ec3da72e5425ff0fcdba32e8d
|
||||
F test/capi3.test 3910a73c38ac76d69778dd9eb481ab7cd6ed59117fc047b4f6056a5c72529de1
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b
|
||||
F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bccc4
|
||||
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/carray01.test d55d57bf66b1af1c7ac55fae66ff4910884a8f5d21a90a18797ce386212a2634
|
||||
F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b
|
||||
F test/check.test 4a2a91ed67eee84a6be16057c48d5198b6fb24849cd6da6cd855981de3fbb416
|
||||
F test/check.test 56e4ed457e9f8683b9fc56f5b964f461f6e8a8dd5a13f3d495408215d66419ed
|
||||
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
|
||||
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
|
||||
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
|
||||
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test 532b4992f78e91dd80c2e3c7bd944fada8cbe3d6c0ded0b20f7182b4dfca0006
|
||||
F test/collate1.test 71a6f27fdc93a92f14d8ab80c05e1937656a5a03197e1a10157314554d630ce8
|
||||
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
|
||||
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
|
||||
F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
|
||||
@ -830,18 +833,19 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165
|
||||
F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c
|
||||
F test/csv01.test c9c3af0d58c34e9ac970c5875a77939edb958762c8aafb95409e19a3f088b6cd
|
||||
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
|
||||
F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c4773
|
||||
F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614c7fe201
|
||||
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
|
||||
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
|
||||
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
|
||||
F test/date.test 118e04db8c8b4efeb885542b4918c7b869a34c460a6bebbfe927dfd75706b80d
|
||||
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
|
||||
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
|
||||
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
|
||||
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
|
||||
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
|
||||
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
|
||||
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
|
||||
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
|
||||
F test/dbpage.test fce29035c7566fd7835ec0f19422cb4b9c6944ce0e1b936ff8452443f92e887d
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
|
||||
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
|
||||
@ -863,12 +867,12 @@ F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d54
|
||||
F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50
|
||||
F test/e_blobwrite.test 3075ff539827576d9a34cbb5a2ac75eb65fb49cd5aadc27686b0719fbf99c156
|
||||
F test/e_changes.test 0f8c3e6aab7335cb772d5a3ea34ca4c82f98d0eb896e2eb3add971c16984b405
|
||||
F test/e_createtable.test 04c50b7fe41c12ed9cd88fbbc09b4900bcfc66f98ad198874fc993a2771f3913
|
||||
F test/e_createtable.test e3b9782e80c0cf2898ac0eb1d9cd058412955ff53a8e47307a60c8289d62ff9c
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test e164550b9f8fd9c130283d1eae692dff9e2ba67f4dbd35f7325021f5d4b8851c
|
||||
F test/e_fkey.test ee321dbca3c53204da46cb40b8ec80192e995035f9ea26576ddcd842b1f0877f
|
||||
F test/e_expr.test bc6aa5906ba967587525bc746ea403011557cf6d8e4fc9efb1fab5dae7fb4fd6
|
||||
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
|
||||
@ -890,12 +894,12 @@ F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test bfe979eb1f4b8ab7a3bd7db6d16c2e6c6be0e5a3aada2227716f3fd3a9d76b69
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0
|
||||
F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
|
||||
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
|
||||
F test/expr.test e1afcdb1038e4d3fa67a3df323347c38750946e2e1b4e385bdc75d26284f2dac
|
||||
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
|
||||
F test/exprfault.test 497cc0b8fe6a677f49b55cb485e040f709ec2834b84f25912fe9c2dfeeda33db
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
@ -965,8 +969,8 @@ F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
|
||||
F test/fts3ag.test c003672a215124df7fc6000036d896f498b26b53
|
||||
F test/fts3ah.test dc9f66c32c296f1bc8bcc4535126bddfeca62894
|
||||
F test/fts3ai.test 24058fdc6e9e5102c1fd8459591b114b6a85d285
|
||||
F test/fts3aj.test 0ed71e1dd9b03b843a857dc3eb9b15630e0104fc
|
||||
F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
|
||||
F test/fts3aj.test 1560a7ce5642dc887e8ecfcc4693bcfce1dbb3d1771a735c845f0061e525deb2
|
||||
F test/fts3ak.test 36ea92f609efb390cf018cdb5d389c12e62b650abe31cfc88261b252daf88174
|
||||
F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
|
||||
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
@ -979,7 +983,7 @@ F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd4
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
||||
F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
|
||||
F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6
|
||||
F test/fts3corrupt.test 43c6c89b994e90997590ece4dfa9c9325c9b61cddd7c97e158498da8b1de79f8
|
||||
F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
|
||||
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
|
||||
F test/fts3corrupt4.test 799ff994b964fed7201be6b6b62c7ff2ef7bb3da6c02b9eaf0d96a5a4d9b6ca3
|
||||
@ -991,6 +995,7 @@ F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4
|
||||
F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7
|
||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
|
||||
F test/fts3dropmod.test 7de242ea1c8a713a8b143ea54468f4b1c4953fa068349e23ac178e2c90c59889
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
@ -1036,7 +1041,7 @@ F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4merge5.test 69932d85cda8a1c4dcfb742865900ed8fbda51724b8cf9a45bbe226dfd06c596
|
||||
F test/fts4min.test 1c11e4bde16674a0c795953509cbc3731a7d9cbd1ddc7f35467bf39d632d749f
|
||||
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
|
||||
F test/fts4noti.test d5d933705b1b1516b67a5e3f8e514ecb19c6522fb3357bb744776d48427c2292
|
||||
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
|
||||
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
|
||||
F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb
|
||||
@ -1045,21 +1050,21 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75
|
||||
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
|
||||
F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 3a65ddb6c1998f71aa86492501a6be87904197e62bfb5b70b2493552b558abd1
|
||||
F test/func.test 4be8bed4be235e333f1e0ea31e32f5be3c9f456c30780363e7fcb15e3ff3e6bc
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a
|
||||
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
|
||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
|
||||
F test/func6.test 9cc9b1f43b435af34fe1416eb1e318c8920448ea7a6962f2121972f5215cb9b0
|
||||
F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c
|
||||
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
|
||||
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
|
||||
F test/fuzz.test 4608c1310cff4c3014a84bcced6278139743e080046e5f6784b0de7b069371d8
|
||||
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c bdb852815048a0beebbe5768bca61e75295324a811a8d7216f97b96501befd1e
|
||||
F test/fuzzcheck.c e34696a5db46738118b2efd14fb71f8458ecf0f482df8bbae18fa1d64db9ab7b
|
||||
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@ -1067,7 +1072,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
|
||||
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
|
||||
F test/fuzzdata8.db ef4d280ee69d6da0ebda7f81c0c66839fa577a97b29cc5790a564fde88be7183
|
||||
F test/fuzzdata8.db ca9a97f401b06b0d5376139ec7e1f9e773e13345a9a2d9ccc0032cdbfedea230
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
|
||||
@ -1082,7 +1087,7 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
|
||||
F test/in.test 15de58ee017f43d36390812e9a51217d1b2db7758f97d0df48296ef178ea560b
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test fdd1d8134da8376985c2edba6035a2de1f6c731524d2ffa651419e8fe2cd1c5a
|
||||
@ -1099,7 +1104,7 @@ F test/incrvacuum.test 3fa6145f5e71f603554fd7b8ec3da4290b1341029682313285cb5f9e1
|
||||
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
|
||||
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
F test/index.test a2e948ed949e575487b5c1d521767d4584ac42d352f2dcd8e48004638e7bc7dc
|
||||
F test/index.test d866054c88b394fd42cbf2825628f127ca24dfac525fa019069a936674d92cbe
|
||||
F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
|
||||
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
@ -1116,7 +1121,7 @@ F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
|
||||
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 59cb99521be01a5aefc9be8e8b5a51ee7f3944781d4d7f6201b9f774fcd51662
|
||||
F test/insert4.test 2bf81535a990c969665d66db51fcf76c23499b39893b5109f413d1de4ad34cd3
|
||||
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
|
||||
F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
|
||||
F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4
|
||||
@ -1134,11 +1139,11 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
|
||||
F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238
|
||||
F test/join.test 25cf0ac11c3b81fedfd166f9062166bdb39dea92f5a7c16cacbf6dc1f7f67020
|
||||
F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test f418fccdfefa41f1659663463aa517431ddcf3e30ccbb80e64173b7d615a03f4
|
||||
F test/join5.test 0d63c7e43b3160b9d4b93f196ef83b6efc7751b9edd0d18c53a46fbec7a49cfc
|
||||
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
@ -1146,11 +1151,11 @@ F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ff
|
||||
F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946
|
||||
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b
|
||||
F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144
|
||||
F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173
|
||||
F test/json101.test d7c84854acafaf80f883e183ac4248ea2742615086c94a61a46ad7d7382ce123
|
||||
F test/json102.test 327e77275f338c028faefa2da5164daf6b142a165e3015ff2a6e4251ddc6a0ac
|
||||
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
|
||||
F test/json104.test a502dc01853aada95d721b3b275afbe2dc18fffdac1fea6e96fb20c13586bbb5
|
||||
F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
@ -1207,11 +1212,12 @@ F test/memjournal2.test 89a4e0d1084170a281efa4d54c2677599f986f44227f98f7dfae2828
|
||||
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
|
||||
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
|
||||
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
|
||||
F test/merge1.test 0ade470d77b689c4a64dc7f736527fcd893140bcafa70af8f7b98523cfb83f16
|
||||
F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a71a
|
||||
F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
|
||||
F test/misc1.test e3fa5732080cc9a2b77bd5dd4ebb55bd6785b02565f8806092686b83ac58d600
|
||||
F test/misc1.test 294c97185354030c4ce40e7141b72f7a589585f2a44b666825381eb3df98f07c
|
||||
F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
|
||||
@ -1266,7 +1272,7 @@ F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6a
|
||||
F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test 8cb45ccbdb3ba423fc8158701c8f010a1d104336b8f14ef14bbfbadf14bad700
|
||||
F test/pager1.test ffd885cdc98b986c9f746496508c0c4810ed0eaade3575ddf53c222e85880552
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
@ -1289,7 +1295,7 @@ F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
F test/printf.test 390d0d7fcffc3c4ea3c1bb4cbb267444e32b33b048ae21895f23a291844fe1da
|
||||
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 5e72c51c5e33253ed639ccee1e01ce62d62b6eee5ca893cd82334e4ee7b1d7fc
|
||||
@ -1298,7 +1304,7 @@ F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
|
||||
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
|
||||
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
|
||||
F test/quote.test f33f95990e4032d1227b98c0ef314c0a077d162f3f2e61b3039ed69e6f8adbbf
|
||||
F test/quote.test ffb40f0eb7a25c1d8cfe11ee2fe67f8e85fbf3fed348810834114be1fdada142
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
@ -1307,10 +1313,10 @@ F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79
|
||||
F test/regexp1.test 0c3ff80f66b0eff80e623eb5db7a3dad512095c573d78ac23009785f6d8f51ce
|
||||
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
|
||||
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
|
||||
F test/releasetest_data.tcl 7cea6c852ae6bb3a9ff1a2b910e4dd13c16a05f74443984dfd52159b0b01ea55
|
||||
F test/releasetest_data.tcl 11ba48a21ed1c808147b0e77c6e93d204577f4327ffe6d7c3b34cd3c01eac3a2
|
||||
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test f96c7245f6ac16038e802760cd90b93479369939a8a7a44e2329ee5aed28239c
|
||||
F test/returning1.test c43b8370a351f77aec6d71f4a2cde59b849369ed1933261a2c2c69e23e34ff5e
|
||||
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
@ -1319,11 +1325,11 @@ F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test e29025be95baf6b32f0d5edef59a7633028325896a98f1caa8019559ca910350
|
||||
F test/rowvalue.test 37effea4dd83555ea969a9461dfcffb25e6731a5db7c388e232410999c100853
|
||||
F test/rowvalue.test 228b312f8526ed000ecda559a6a9adf30aa2d79dcb12afa5c04eebaafcf55eae
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
|
||||
F test/rowvalue4.test 441e7e366ac6d939a3a95a574031c56ec2a854077a91d66eee5ff1d86cb5be58
|
||||
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
|
||||
F test/rowvalue5.test 00740304ea6a53a8704640c7405690f0045d5d2a6b4b04dde7bccc14c3068ea7
|
||||
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba
|
||||
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
|
||||
@ -1355,7 +1361,7 @@ F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
|
||||
F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
|
||||
F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae
|
||||
F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
|
||||
F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db766d1f
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
|
||||
@ -1382,11 +1388,11 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test c354008b27c904f0166c2138abd7382013ea070b41114114ecbdfb32c726a807
|
||||
F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c
|
||||
F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566
|
||||
F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
|
||||
F test/shell5.test 6e4aa0e531dcb8dcf74b7920a2a7442c6712d4dff8422bbc81f768f9dee8a0e3
|
||||
F test/shell1.test b224e0793c5f48aa3749e65d8c64b93a30731bd206f2e41e6c5f1bee1bdb16c6
|
||||
F test/shell2.test 89e4b2db062d52baed75022227b462d085cff495809de1699652779d8e0257d6
|
||||
F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c
|
||||
F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759
|
||||
F test/shell5.test 0a9920d81fae28c45cd5dbd1deb809487a23c5f4b422a49f9d31c85f926d4a9c
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
|
||||
@ -1436,16 +1442,16 @@ F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac840
|
||||
F test/statfault.test 55f86055f9cd7b2d962a621b8a04215c1cebd4eaaecde92d279442327fe648a0
|
||||
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
|
||||
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
|
||||
F test/strict1.test a3ec495471f24c1a6e1a1664bd23e24ccdb27ae93b1a763ee1942ec955b68e71
|
||||
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
|
||||
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
|
||||
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
|
||||
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
|
||||
F test/subquery.test 3a1a5b600b8d4f504d2a2c61f33db820983dba94a0ef3e4aedca8f0165eaecb8
|
||||
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
|
||||
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
|
||||
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
|
||||
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
|
||||
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
|
||||
F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
|
||||
F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e1e8e26
|
||||
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
|
||||
F test/swarmvtab3.test 247aa38b6ebd2b99db2075847ae47e789ac34f1c2ab5c720dfcffd990004c544
|
||||
F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95
|
||||
@ -1455,11 +1461,11 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test d6821e7042e5653104dac0c63d75eff24a2415ab1889fc68b5db7fde59464c59
|
||||
F test/tabfunc01.test 241425ce3998687ab24adba09cb95e8012e17499b84a0ed47e128ab45e588bef
|
||||
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 97cda6e4843e9f3e06c56f656d9b77ee0178fe1ee33fb09a6eeae8f125757ac1
|
||||
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
@ -1507,7 +1513,7 @@ F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
|
||||
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
|
||||
F test/tkt-78e04e52ea.test b731f2ab7d1c2482ac5152097da02ef4805a45147ba9498d3cd9da27072f34d1
|
||||
F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
|
||||
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
|
||||
F test/tkt-7bbfb7d442.test e87b59e620700b5a52ecd92f05d56686c1cad9e1aa17456eada55e0bb821b698
|
||||
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
|
||||
F test/tkt-80e031a00f.test 9ee36348b761bf7c14261e002b75a4c0d5a04d4c
|
||||
F test/tkt-8454a207b9.test aff2e76143cfa443ddce6f7d85968a2e9b57a3deb0b881b730120740555f9e2f
|
||||
@ -1590,7 +1596,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
|
||||
F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
|
||||
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
|
||||
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
|
||||
F test/tkt3442.test 6287173de5bb2d43693b1f822426018a209f9df49ce2f454808bac1771852330
|
||||
F test/tkt3442.test c9d95b4c8f4f35a51b523f35d2afd0ce124937812af296545ad551ff763504fd
|
||||
F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
|
||||
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
|
||||
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
|
||||
@ -1614,7 +1620,7 @@ F test/tkt3810.test 3a3be9965d1861bd84019875851ad5ea90fd8d76b638361514a36a48ea53
|
||||
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
|
||||
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
|
||||
F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
|
||||
F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f
|
||||
F test/tkt3841.test c4be3870f777f82aa788a588e40b4fb6627c3874e19f336d0d92894f929ffbfe
|
||||
F test/tkt3871.test d921703d07c68f4fd5312073215a17fa34b0401d
|
||||
F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90
|
||||
F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633
|
||||
@ -1634,7 +1640,7 @@ F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f4
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
|
||||
F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
|
||||
F test/trigger1.test 02cc64dc98278816c1c1ed8e472e18db8edbad88f37018bf46223e9614831963
|
||||
F test/trigger2.test 6e35bd7321c49e63d540aee980eb95dec63e1d1caca175224101045bcc80871f
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
@ -1670,15 +1676,15 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
|
||||
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
|
||||
F test/update.test ef3ebbafeb4be5c96db831f40796e2e77ee846da5ee8b61cfedb1ff1b9e0cc23
|
||||
F test/update.test eb7f4eb172ce270e51bb67d7867521f33a63635bb671e261bbafccaef3bd6db2
|
||||
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
|
||||
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
|
||||
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
|
||||
F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342bbd6b
|
||||
F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af62328a1
|
||||
F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
|
||||
F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
|
||||
F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2
|
||||
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
|
||||
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
|
||||
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe
|
||||
@ -1686,7 +1692,7 @@ F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018d
|
||||
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
|
||||
F test/vacuum-into.test f0b8c091df5305728b6973e9cce4166c861955b650dd3c599cb045d7160d3971
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
|
||||
@ -1704,7 +1710,7 @@ F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c840
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
|
||||
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
|
||||
F test/vtab6.test 8e789f526e6594cf7ae933d1adee0caa87dc9f78
|
||||
F test/vtab6.test 82d5bb8fd3c0643102c1209e9ea353b168b7eb9c8db4406ab2ee2cbbdaead62c
|
||||
F test/vtab7.test 70c6f4a1d6177144a8236e4172d5fba92e683440374664ad1f04851fbb335d3c
|
||||
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
|
||||
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
|
||||
@ -1721,7 +1727,9 @@ F test/vtabK.test 13293177528fada1235c0112db0d187d754af1355c5a39371abd365104e3af
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/vtabdistinct.test 7688f0889358f849fd60bbfde1ded38b014b18066076d4bfbb75395804dfe072
|
||||
F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
|
||||
F test/vtabrhs1.test 9b5ecbc74a689500c33a4b2b36761f9bcc22fcc4e3f9d21066ee0c9c74cf5f6c
|
||||
F test/wal.test b7cc6984709f54afbf8441747ced1f646af120bf0c1b1d847bfa39306fbea089
|
||||
F test/wal2.test 31f6e2c404b9f2cdf9ca19b105a1742fdc19653c2c936da39e3658c617524046
|
||||
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
|
||||
@ -1751,7 +1759,7 @@ F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
|
||||
F test/walprotocol.test 1b3f922125e341703f6e946d77fdc564d38fb3e07a9385cfdc6c99cac1ecf878
|
||||
F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db868eebc131
|
||||
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
|
||||
F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
|
||||
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
@ -1766,7 +1774,7 @@ F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||
F test/where7.test ab41d53ce8f2a6919ea3d5b13cd1153c1375a8e3ddaa129b81781f9033981383
|
||||
F test/where7.test 1c1bf436bf31b913d4764a2b62ac6e98b9681e5c7ae2b562605592a56b7e946b
|
||||
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
|
||||
F test/where9.test 1ffb75edc50a8faa6e7bd77f8221d783febb00b44b0bdb32fb48cec6e38eca95
|
||||
F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
|
||||
@ -1798,7 +1806,7 @@ F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856e
|
||||
F test/window4.tcl 6f85307eb67242b654d051f7da32a996a66aee039a09c5ae358541aa61720742
|
||||
F test/window4.test fbead87f681400ac07ef3555e0488b544a47d35491f8bf09a7474b6f76ce9b4e
|
||||
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
|
||||
F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32
|
||||
F test/window6.test 311de885bd7e453134fa6747680bfb4a1be87c91720bf58703db945891e7d30b
|
||||
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
|
||||
F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
|
||||
F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c
|
||||
@ -1818,7 +1826,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
|
||||
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
|
||||
F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0
|
||||
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
|
||||
F test/without_rowid1.test 78fd9b437f4cdb46f76e6a510d545334e4f58e3e4ce37aaf19384eda5b27de8c
|
||||
F test/without_rowid1.test a5210b8770dc4736bca4e74bc96588f43025ad03ad6a80f885afd36d9890e217
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
@ -1854,16 +1862,16 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 258881835bd5bccd0c74fb110fe54244ff18e8e7ef3d949cbdab7187f02132bb
|
||||
F tool/lemon.c 1c5a14f6044193e42864c36de48359026fa2cdcf205a43cc1a31116101e27258
|
||||
F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 06446d42942a7128ab4963eb438eb3f528e07095d5d1080f9105a6f337238d33
|
||||
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
|
||||
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
|
||||
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl 5ef1891ed3d0e8143ff39bad7c01ed60c2817a2fb2d9a09487f7ccad2df621e4
|
||||
F tool/mkctimec.tcl 3147e9dfc4ad774e94f80084789ebaada9da9b6e66ddab16438cfc07999b6047 x
|
||||
F tool/mkkeywordhash.c 35bfc41adacc4aa6ef6fca7fd0c63e0ec0534b78daf4d0cfdebe398216bbffc3
|
||||
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
@ -1874,12 +1882,12 @@ F tool/mkshellc.tcl df5d249617f9cc94d5c48eb0401673eb3f31f383ecbc54e8a13ca3dd97e8
|
||||
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
|
||||
F tool/mksqlite3c.tcl bf9b40811aba68f73f2a8848fad9b1fb09fd54ab5b77e5227f18eea87ab60d92
|
||||
F tool/mksqlite3c.tcl 6f9e05facb51e906a1a7ef9f95274ef2ec91bf88b96732a9aed40647c605f419
|
||||
F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
|
||||
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
|
||||
F tool/omittest.tcl 3d222272b1d840b4e3d67bff0cb743ce3f633faddadb3702b2056b726775db8f
|
||||
F tool/omittest.tcl 3bc9609aceea871e1ca6ed6749df9ce79b89369d22b492f6ce6078f40647cc3f
|
||||
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/replace.tcl 937c931ad560688e85bdd6258bdc754371bb1e2732e1fb28ef441e44c9228fce
|
||||
@ -1901,7 +1909,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
|
||||
F tool/sqldiff.c 9c639de9fa541a947ea9776435c84adf00f43945e262556e15219ef09f0d912c
|
||||
F tool/sqldiff.c 4f967c199c5f93eec64978e3a625d6c07fb1162212b1d48f65740d9eb4607eee
|
||||
F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
@ -1910,10 +1918,10 @@ F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9b9
|
||||
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe-compress.tcl 1dcb7632e57cf57105248029e6e162fddaf6c0fccb3bb9e6215603752c5a2d4a
|
||||
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 09311479bdc290e20ec8e35a3d1b14b096bbd96222277cfd6274c3a99b3d012f
|
||||
F tool/warnings.sh d58dc38367cc776550f90327e205d7946802d4004fb9f291fd8b81256bc1eedd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
|
||||
F vsixtest/App.xaml.cpp 41158ee43269820136fa3bba00c0bd91b26cc38b650ee392aec2a8d823e54318
|
||||
@ -1936,11 +1944,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P e1871201e73c1d970f0434d3c7190da2c1c49ded3a359640d959ec0c0450b8ed
|
||||
R 6d4acf62ee33d6425f8616c1e2a2b241
|
||||
T +bgcolor * #d0c0ff
|
||||
P 4977d8f453bcd56fb1dfab02cc5b283fb32d402bafdf2b6112e7dd322b7c32ad
|
||||
R da11ed5f90621f5fb7c0aa8d0a45881c
|
||||
T +sym-release *
|
||||
T +sym-version-3.37.2 *
|
||||
T +sym-version-3.38.2 *
|
||||
U drh
|
||||
Z bc8f65914f35757c2569ece42ec5d728
|
||||
Z 1c2a1cc2a9288218f72e9d4db2ebcd7a
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
@ -1 +1 @@
|
||||
872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5d17a0
|
||||
d33c709cc0af66bc5b6dc6216eba9f1f0b40960b9ae83694c986fbf4c1d6f08f
|
||||
|
||||
98
src/alter.c
98
src/alter.c
@ -324,7 +324,9 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
int r1; /* Temporary registers */
|
||||
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ) return;
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ) return;
|
||||
assert( db->mallocFailed==0 );
|
||||
pNew = pParse->pNewTable;
|
||||
assert( pNew );
|
||||
|
||||
@ -450,7 +452,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
" THEN raise(ABORT,'CHECK constraint failed')"
|
||||
" ELSE raise(ABORT,'NOT NULL constraint failed')"
|
||||
" END"
|
||||
" FROM pragma_quick_check(\"%w\",\"%w\")"
|
||||
" FROM pragma_quick_check(%Q,%Q)"
|
||||
" WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'",
|
||||
zTab, zDb
|
||||
);
|
||||
@ -629,7 +631,7 @@ void sqlite3AlterRenameColumn(
|
||||
if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
|
||||
}
|
||||
if( iCol==pTab->nCol ){
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
|
||||
goto exit_rename_column;
|
||||
}
|
||||
|
||||
@ -735,7 +737,9 @@ struct RenameCtx {
|
||||
** following a valid object, it may not be used in comparison operations.
|
||||
*/
|
||||
static void renameTokenCheckAll(Parse *pParse, const void *pPtr){
|
||||
if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
|
||||
assert( pParse==pParse->db->pParse );
|
||||
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
|
||||
if( pParse->nErr==0 ){
|
||||
const RenameToken *p;
|
||||
u8 i = 0;
|
||||
for(p=pParse->pRename; p; p=p->pNext){
|
||||
@ -1057,12 +1061,12 @@ static void renameColumnParseError(
|
||||
const char *zN = (const char*)sqlite3_value_text(pObject);
|
||||
char *zErr;
|
||||
|
||||
zErr = sqlite3_mprintf("error in %s %s%s%s: %s",
|
||||
zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s",
|
||||
zT, zN, (zWhen[0] ? " " : ""), zWhen,
|
||||
pParse->zErrMsg
|
||||
);
|
||||
sqlite3_result_error(pCtx, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
sqlite3DbFree(pParse->db, zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1126,24 +1130,22 @@ static int renameParseSql(
|
||||
int bTemp /* True if SQL is from temp schema */
|
||||
){
|
||||
int rc;
|
||||
char *zErr = 0;
|
||||
|
||||
sqlite3ParseObjectInit(p, db);
|
||||
if( zSql==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
|
||||
|
||||
/* Parse the SQL statement passed as the first argument. If no error
|
||||
** occurs and the parse does not result in a new table, index or
|
||||
** trigger object, the database must be corrupt. */
|
||||
memset(p, 0, sizeof(Parse));
|
||||
p->eParseMode = PARSE_MODE_RENAME;
|
||||
p->db = db;
|
||||
p->nQueryLoop = 1;
|
||||
rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM;
|
||||
assert( p->zErrMsg==0 );
|
||||
assert( rc!=SQLITE_OK || zErr==0 );
|
||||
p->zErrMsg = zErr;
|
||||
rc = sqlite3RunParser(p, zSql);
|
||||
if( db->mallocFailed ) rc = SQLITE_NOMEM;
|
||||
if( rc==SQLITE_OK
|
||||
&& p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0
|
||||
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
|
||||
){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
@ -1421,13 +1423,13 @@ static void renameParseCleanup(Parse *pParse){
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
sqlite3DbFree(db, pParse->zErrMsg);
|
||||
renameTokenFree(db, pParse->pRename);
|
||||
sqlite3ParserReset(pParse);
|
||||
sqlite3ParseObjectReset(pParse);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL function:
|
||||
**
|
||||
** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
|
||||
** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP)
|
||||
**
|
||||
** 0. zSql: SQL statement to rewrite
|
||||
** 1. type: Type of object ("table", "view" etc.)
|
||||
@ -1445,7 +1447,8 @@ static void renameParseCleanup(Parse *pParse){
|
||||
**
|
||||
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
|
||||
** It is only accessible to SQL created using sqlite3NestedParse(). It is
|
||||
** not reachable from ordinary SQL passed into sqlite3_prepare().
|
||||
** not reachable from ordinary SQL passed into sqlite3_prepare() unless the
|
||||
** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled.
|
||||
*/
|
||||
static void renameColumnFunc(
|
||||
sqlite3_context *context,
|
||||
@ -1594,7 +1597,9 @@ static void renameColumnFunc(
|
||||
|
||||
renameColumnFunc_done:
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( sParse.zErrMsg ){
|
||||
if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
}else if( sParse.zErrMsg ){
|
||||
renameColumnParseError(context, "", argv[1], argv[2], &sParse);
|
||||
}else{
|
||||
sqlite3_result_error_code(context, rc);
|
||||
@ -1793,7 +1798,9 @@ static void renameTableFunc(
|
||||
rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( sParse.zErrMsg ){
|
||||
if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){
|
||||
sqlite3_result_value(context, argv[3]);
|
||||
}else if( sParse.zErrMsg ){
|
||||
renameColumnParseError(context, "", argv[1], argv[2], &sParse);
|
||||
}else{
|
||||
sqlite3_result_error_code(context, rc);
|
||||
@ -1818,10 +1825,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** The implementation of an SQL scalar function that rewrites DDL statements
|
||||
** so that any string literals that use double-quotes are modified so that
|
||||
** they use single quotes.
|
||||
/* SQL function: sqlite_rename_quotefix(DB,SQL)
|
||||
**
|
||||
** Rewrite the DDL statement "SQL" so that any string literals that use
|
||||
** double-quotes use single quotes instead.
|
||||
**
|
||||
** Two arguments must be passed:
|
||||
**
|
||||
@ -1840,6 +1847,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
|
||||
** returns the string:
|
||||
**
|
||||
** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
|
||||
**
|
||||
** If there is a error in the input SQL, then raise an error, except
|
||||
** if PRAGMA writable_schema=ON, then just return the input string
|
||||
** unmodified following an error.
|
||||
*/
|
||||
static void renameQuotefixFunc(
|
||||
sqlite3_context *context,
|
||||
@ -1914,7 +1925,11 @@ static void renameQuotefixFunc(
|
||||
renameTokenFree(db, sCtx.pList);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error_code(context, rc);
|
||||
if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){
|
||||
sqlite3_result_value(context, argv[1]);
|
||||
}else{
|
||||
sqlite3_result_error_code(context, rc);
|
||||
}
|
||||
}
|
||||
renameParseCleanup(&sParse);
|
||||
}
|
||||
@ -1926,7 +1941,8 @@ static void renameQuotefixFunc(
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
}
|
||||
|
||||
/*
|
||||
/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS)
|
||||
**
|
||||
** An SQL user function that checks that there are no parse or symbol
|
||||
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
|
||||
** After an ALTER TABLE .. RENAME operation is performed and the schema
|
||||
@ -1941,11 +1957,13 @@ static void renameQuotefixFunc(
|
||||
** 5: "when" part of error message.
|
||||
** 6: True to disable the DQS quirk when parsing SQL.
|
||||
**
|
||||
** Unless it finds an error, this function normally returns NULL. However, it
|
||||
** returns integer value 1 if:
|
||||
** The return value is computed as follows:
|
||||
**
|
||||
** * the SQL argument creates a trigger, and
|
||||
** * the table that the trigger is attached to is in database zDb.
|
||||
** A. If an error is seen and not in PRAGMA writable_schema=ON mode,
|
||||
** then raise the error.
|
||||
** B. Else if a trigger is created and the the table that the trigger is
|
||||
** attached to is in database zDb, then return 1.
|
||||
** C. Otherwise return NULL.
|
||||
*/
|
||||
static void renameTableTest(
|
||||
sqlite3_context *context,
|
||||
@ -1990,12 +2008,16 @@ static void renameTableTest(
|
||||
if( rc==SQLITE_OK ){
|
||||
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
|
||||
int i2 = sqlite3FindDbName(db, zDb);
|
||||
if( i1==i2 ) sqlite3_result_int(context, 1);
|
||||
if( i1==i2 ){
|
||||
/* Handle output case B */
|
||||
sqlite3_result_int(context, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK && zWhen ){
|
||||
if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){
|
||||
/* Output case A */
|
||||
renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
|
||||
}
|
||||
renameParseCleanup(&sParse);
|
||||
@ -2111,7 +2133,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
|
||||
}
|
||||
iCol = sqlite3ColumnIndex(pTab, zCol);
|
||||
if( iCol<0 ){
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol);
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName);
|
||||
goto exit_drop_column;
|
||||
}
|
||||
|
||||
@ -2135,6 +2157,12 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
/* Invoke the authorization callback. */
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){
|
||||
goto exit_drop_column;
|
||||
}
|
||||
#endif
|
||||
renameTestSchema(pParse, zDb, iDb==1, "", 0);
|
||||
renameFixQuotes(pParse, zDb, iDb==1);
|
||||
sqlite3NestedParse(pParse,
|
||||
|
||||
@ -391,7 +391,7 @@ static void codeAttach(
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pAuthArg ){
|
||||
if( ALWAYS(pAuthArg) ){
|
||||
char *zAuthArg;
|
||||
if( pAuthArg->op==TK_STRING ){
|
||||
assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
|
||||
|
||||
@ -85,14 +85,13 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
if( i==1 ){
|
||||
Parse sParse;
|
||||
int rc = 0;
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sParse.db = pDb;
|
||||
sqlite3ParseObjectInit(&sParse,pDb);
|
||||
if( sqlite3OpenTempDatabase(&sParse) ){
|
||||
sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
if( rc ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
239
src/btree.c
239
src/btree.c
@ -1225,18 +1225,32 @@ static void btreeParseCellPtr(
|
||||
**
|
||||
** pIter += getVarint(pIter, (u64*)&pInfo->nKey);
|
||||
**
|
||||
** The code is inlined to avoid a function call.
|
||||
** The code is inlined and the loop is unrolled for performance.
|
||||
** This routine is a high-runner.
|
||||
*/
|
||||
iKey = *pIter;
|
||||
if( iKey>=0x80 ){
|
||||
u8 *pEnd = &pIter[7];
|
||||
iKey &= 0x7f;
|
||||
while(1){
|
||||
iKey = (iKey<<7) | (*++pIter & 0x7f);
|
||||
if( (*pIter)<0x80 ) break;
|
||||
if( pIter>=pEnd ){
|
||||
iKey = (iKey<<8) | *++pIter;
|
||||
break;
|
||||
u8 x;
|
||||
iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x =*++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
|
||||
if( x>=0x80 ){
|
||||
iKey = (iKey<<8) | (*++pIter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1768,7 +1782,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
assert( iFreeBlk>iPtr || iFreeBlk==0 );
|
||||
assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
|
||||
|
||||
/* At this point:
|
||||
** iFreeBlk: First freeblock after iStart, or zero if none
|
||||
@ -2039,7 +2053,7 @@ static int btreeInitPage(MemPage *pPage){
|
||||
pPage->nOverflow = 0;
|
||||
pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
|
||||
pPage->aCellIdx = data + pPage->childPtrSize + 8;
|
||||
pPage->aDataEnd = pPage->aData + pBt->usableSize;
|
||||
pPage->aDataEnd = pPage->aData + pBt->pageSize;
|
||||
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
@ -2074,7 +2088,7 @@ static void zeroPage(MemPage *pPage, int flags){
|
||||
u8 hdr = pPage->hdrOffset;
|
||||
u16 first;
|
||||
|
||||
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
|
||||
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
|
||||
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
||||
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
|
||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
@ -2090,7 +2104,7 @@ static void zeroPage(MemPage *pPage, int flags){
|
||||
pPage->nFree = (u16)(pBt->usableSize - first);
|
||||
decodeFlags(pPage, flags);
|
||||
pPage->cellOffset = first;
|
||||
pPage->aDataEnd = &data[pBt->usableSize];
|
||||
pPage->aDataEnd = &data[pBt->pageSize];
|
||||
pPage->aCellIdx = &data[first];
|
||||
pPage->aDataOfst = &data[pPage->childPtrSize];
|
||||
pPage->nOverflow = 0;
|
||||
@ -2216,7 +2230,7 @@ static int getAndInitPage(
|
||||
goto getAndInitPage_error2;
|
||||
}
|
||||
}
|
||||
assert( (*ppPage)->pgno==pgno );
|
||||
assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
|
||||
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
|
||||
|
||||
/* If obtaining a child page for a cursor, we must verify that the page is
|
||||
@ -2693,30 +2707,38 @@ static int removeFromSharingList(BtShared *pBt){
|
||||
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
|
||||
** pointer.
|
||||
*/
|
||||
static void allocateTempSpace(BtShared *pBt){
|
||||
if( !pBt->pTmpSpace ){
|
||||
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
|
||||
|
||||
/* One of the uses of pBt->pTmpSpace is to format cells before
|
||||
** inserting them into a leaf page (function fillInCell()). If
|
||||
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
|
||||
** by the various routines that manipulate binary cells. Which
|
||||
** can mean that fillInCell() only initializes the first 2 or 3
|
||||
** bytes of pTmpSpace, but that the first 4 bytes are copied from
|
||||
** it into a database page. This is not actually a problem, but it
|
||||
** does cause a valgrind error when the 1 or 2 bytes of unitialized
|
||||
** data is passed to system call write(). So to avoid this error,
|
||||
** zero the first 4 bytes of temp space here.
|
||||
**
|
||||
** Also: Provide four bytes of initialized space before the
|
||||
** beginning of pTmpSpace as an area available to prepend the
|
||||
** left-child pointer to the beginning of a cell.
|
||||
*/
|
||||
if( pBt->pTmpSpace ){
|
||||
memset(pBt->pTmpSpace, 0, 8);
|
||||
pBt->pTmpSpace += 4;
|
||||
}
|
||||
static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
|
||||
assert( pBt!=0 );
|
||||
assert( pBt->pTmpSpace==0 );
|
||||
/* This routine is called only by btreeCursor() when allocating the
|
||||
** first write cursor for the BtShared object */
|
||||
assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
|
||||
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
|
||||
if( pBt->pTmpSpace==0 ){
|
||||
BtCursor *pCur = pBt->pCursor;
|
||||
pBt->pCursor = pCur->pNext; /* Unlink the cursor */
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
/* One of the uses of pBt->pTmpSpace is to format cells before
|
||||
** inserting them into a leaf page (function fillInCell()). If
|
||||
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
|
||||
** by the various routines that manipulate binary cells. Which
|
||||
** can mean that fillInCell() only initializes the first 2 or 3
|
||||
** bytes of pTmpSpace, but that the first 4 bytes are copied from
|
||||
** it into a database page. This is not actually a problem, but it
|
||||
** does cause a valgrind error when the 1 or 2 bytes of unitialized
|
||||
** data is passed to system call write(). So to avoid this error,
|
||||
** zero the first 4 bytes of temp space here.
|
||||
**
|
||||
** Also: Provide four bytes of initialized space before the
|
||||
** beginning of pTmpSpace as an area available to prepend the
|
||||
** left-child pointer to the beginning of a cell.
|
||||
*/
|
||||
memset(pBt->pTmpSpace, 0, 8);
|
||||
pBt->pTmpSpace += 4;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3213,9 +3235,13 @@ static int lockBtree(BtShared *pBt){
|
||||
pageSize-usableSize);
|
||||
return rc;
|
||||
}
|
||||
if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto page1_init_failed;
|
||||
if( nPage>nPageFile ){
|
||||
if( sqlite3WritableSchema(pBt->db)==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto page1_init_failed;
|
||||
}else{
|
||||
nPage = nPageFile;
|
||||
}
|
||||
}
|
||||
/* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to
|
||||
** be less than 480. In other words, if the page size is 512, then the
|
||||
@ -4457,10 +4483,6 @@ static int btreeCursor(
|
||||
assert( pBt->pPage1 && pBt->pPage1->aData );
|
||||
assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
|
||||
|
||||
if( wrFlag ){
|
||||
allocateTempSpace(pBt);
|
||||
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
if( iTable<=1 ){
|
||||
if( iTable<1 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
@ -4477,19 +4499,25 @@ static int btreeCursor(
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
pCur->pBtree = p;
|
||||
pCur->pBt = pBt;
|
||||
pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
|
||||
pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
|
||||
pCur->curFlags = 0;
|
||||
/* If there are two or more cursors on the same btree, then all such
|
||||
** cursors *must* have the BTCF_Multiple flag set. */
|
||||
for(pX=pBt->pCursor; pX; pX=pX->pNext){
|
||||
if( pX->pgnoRoot==iTable ){
|
||||
pX->curFlags |= BTCF_Multiple;
|
||||
pCur->curFlags |= BTCF_Multiple;
|
||||
pCur->curFlags = BTCF_Multiple;
|
||||
}
|
||||
}
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
pCur->pNext = pBt->pCursor;
|
||||
pBt->pCursor = pCur;
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
if( wrFlag ){
|
||||
pCur->curFlags |= BTCF_WriteFlag;
|
||||
pCur->curPagerFlags = 0;
|
||||
if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
|
||||
}else{
|
||||
pCur->curPagerFlags = PAGER_GET_READONLY;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int btreeCursorWithLock(
|
||||
@ -5264,7 +5292,7 @@ static int moveToRoot(BtCursor *pCur){
|
||||
while( --pCur->iPage ){
|
||||
releasePageNotNull(pCur->apPage[pCur->iPage]);
|
||||
}
|
||||
pCur->pPage = pCur->apPage[0];
|
||||
pRoot = pCur->pPage = pCur->apPage[0];
|
||||
goto skip_init;
|
||||
}
|
||||
}else if( pCur->pgnoRoot==0 ){
|
||||
@ -5289,7 +5317,7 @@ static int moveToRoot(BtCursor *pCur){
|
||||
pCur->curIntKey = pCur->pPage->intKey;
|
||||
}
|
||||
pRoot = pCur->pPage;
|
||||
assert( pRoot->pgno==pCur->pgnoRoot );
|
||||
assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );
|
||||
|
||||
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
|
||||
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
|
||||
@ -5311,7 +5339,6 @@ skip_init:
|
||||
pCur->info.nSize = 0;
|
||||
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
|
||||
pRoot = pCur->pPage;
|
||||
if( pRoot->nCell>0 ){
|
||||
pCur->eState = CURSOR_VALID;
|
||||
}else if( !pRoot->leaf ){
|
||||
@ -5552,7 +5579,6 @@ int sqlite3BtreeTableMoveto(
|
||||
upr = pPage->nCell-1;
|
||||
assert( biasRight==0 || biasRight==1 );
|
||||
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
|
||||
pCur->ix = (u16)idx;
|
||||
for(;;){
|
||||
i64 nCellKey;
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
@ -5694,7 +5720,6 @@ int sqlite3BtreeIndexMoveto(
|
||||
lwr = 0;
|
||||
upr = pPage->nCell-1;
|
||||
idx = upr>>1; /* idx = (lwr+upr)/2; */
|
||||
pCur->ix = (u16)idx;
|
||||
for(;;){
|
||||
int nCell; /* Size of the pCell cell in bytes */
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
@ -6386,7 +6411,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
|
||||
assert( CORRUPT_DB || iPage>1 );
|
||||
assert( !pMemPage || pMemPage->pgno==iPage );
|
||||
|
||||
if( NEVER(iPage<2) || iPage>pBt->nPage ){
|
||||
if( iPage<2 || iPage>pBt->nPage ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( pMemPage ){
|
||||
@ -6818,9 +6843,15 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
|
||||
assert( pPage->nFree>=0 );
|
||||
data = pPage->aData;
|
||||
ptr = &pPage->aCellIdx[2*idx];
|
||||
assert( pPage->pBt->usableSize > (int)(ptr-data) );
|
||||
assert( pPage->pBt->usableSize > (u32)(ptr-data) );
|
||||
pc = get2byte(ptr);
|
||||
hdr = pPage->hdrOffset;
|
||||
#if 0 /* Not required. Omit for efficiency */
|
||||
if( pc<hdr+pPage->nCell*2 ){
|
||||
*pRC = SQLITE_CORRUPT_BKPT;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
testcase( pc==(u32)get2byte(&data[hdr+5]) );
|
||||
testcase( pc+sz==pPage->pBt->usableSize );
|
||||
if( pc+sz > pPage->pBt->usableSize ){
|
||||
@ -8817,24 +8848,6 @@ int sqlite3BtreeInsert(
|
||||
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
|
||||
assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
|
||||
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
assert( pCur->skipNext!=SQLITE_OK );
|
||||
return pCur->skipNext;
|
||||
}
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
|
||||
&& pBt->inTransaction==TRANS_WRITE
|
||||
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
|
||||
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
||||
|
||||
/* Assert that the caller has been consistent. If this cursor was opened
|
||||
** expecting an index b-tree, then the caller should be inserting blob
|
||||
** keys with no associated data. If the cursor was opened expecting an
|
||||
** intkey table, the caller should be inserting integer keys with a
|
||||
** blob of associated data. */
|
||||
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
|
||||
|
||||
/* Save the positions of any other cursors open on this table.
|
||||
**
|
||||
** In some cases, the call to btreeMoveto() below is a no-op. For
|
||||
@ -8859,6 +8872,24 @@ int sqlite3BtreeInsert(
|
||||
}
|
||||
}
|
||||
|
||||
if( pCur->eState>=CURSOR_REQUIRESEEK ){
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc && rc!=SQLITE_EMPTY ) return rc;
|
||||
}
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
|
||||
&& pBt->inTransaction==TRANS_WRITE
|
||||
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
|
||||
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
||||
|
||||
/* Assert that the caller has been consistent. If this cursor was opened
|
||||
** expecting an index b-tree, then the caller should be inserting blob
|
||||
** keys with no associated data. If the cursor was opened expecting an
|
||||
** intkey table, the caller should be inserting integer keys with a
|
||||
** blob of associated data. */
|
||||
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
|
||||
|
||||
if( pCur->pKeyInfo==0 ){
|
||||
assert( pX->pKey==0 );
|
||||
/* If this is an insert into a table b-tree, invalidate any incrblob
|
||||
@ -8947,14 +8978,13 @@ int sqlite3BtreeInsert(
|
||||
}
|
||||
}
|
||||
assert( pCur->eState==CURSOR_VALID
|
||||
|| (pCur->eState==CURSOR_INVALID && loc)
|
||||
|| CORRUPT_DB );
|
||||
|| (pCur->eState==CURSOR_INVALID && loc) );
|
||||
|
||||
pPage = pCur->pPage;
|
||||
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
|
||||
assert( pPage->leaf || !pPage->intKey );
|
||||
if( pPage->nFree<0 ){
|
||||
if( NEVER(pCur->eState>CURSOR_INVALID) ){
|
||||
if( pCur->eState>CURSOR_INVALID ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = btreeComputeFreeSpace(pPage);
|
||||
@ -9220,14 +9250,13 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
|
||||
int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
Btree *p = pCur->pBtree;
|
||||
BtShared *pBt = p->pBt;
|
||||
int rc; /* Return code */
|
||||
MemPage *pPage; /* Page to delete cell from */
|
||||
unsigned char *pCell; /* Pointer to cell to delete */
|
||||
int iCellIdx; /* Index of cell to delete */
|
||||
int iCellDepth; /* Depth of node containing pCell */
|
||||
CellInfo info; /* Size of the cell being deleted */
|
||||
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
|
||||
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
|
||||
int rc; /* Return code */
|
||||
MemPage *pPage; /* Page to delete cell from */
|
||||
unsigned char *pCell; /* Pointer to cell to delete */
|
||||
int iCellIdx; /* Index of cell to delete */
|
||||
int iCellDepth; /* Depth of node containing pCell */
|
||||
CellInfo info; /* Size of the cell being deleted */
|
||||
u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( pBt->inTransaction==TRANS_WRITE );
|
||||
@ -9236,33 +9265,45 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
||||
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
|
||||
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
|
||||
if( pCur->eState==CURSOR_REQUIRESEEK ){
|
||||
rc = btreeRestoreCursorPosition(pCur);
|
||||
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
|
||||
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
|
||||
if( pCur->eState!=CURSOR_VALID ){
|
||||
if( pCur->eState>=CURSOR_REQUIRESEEK ){
|
||||
rc = btreeRestoreCursorPosition(pCur);
|
||||
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
|
||||
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
|
||||
}else{
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
|
||||
iCellDepth = pCur->iPage;
|
||||
iCellIdx = pCur->ix;
|
||||
pPage = pCur->pPage;
|
||||
if( pPage->nCell<=iCellIdx ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
pCell = findCell(pPage, iCellIdx);
|
||||
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( pPage->nCell<=iCellIdx ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
/* If the bPreserve flag is set to true, then the cursor position must
|
||||
/* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
|
||||
** be preserved following this delete operation. If the current delete
|
||||
** will cause a b-tree rebalance, then this is done by saving the cursor
|
||||
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
|
||||
** returning.
|
||||
**
|
||||
** Or, if the current delete will not cause a rebalance, then the cursor
|
||||
** If the current delete will not cause a rebalance, then the cursor
|
||||
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
|
||||
** before or after the deleted entry. In this case set bSkipnext to true. */
|
||||
** before or after the deleted entry.
|
||||
**
|
||||
** The bPreserve value records which path is required:
|
||||
**
|
||||
** bPreserve==0 Not necessary to save the cursor position
|
||||
** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position
|
||||
** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT.
|
||||
*/
|
||||
bPreserve = (flags & BTREE_SAVEPOSITION)!=0;
|
||||
if( bPreserve ){
|
||||
if( !pPage->leaf
|
||||
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
|
||||
@ -9273,7 +9314,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
rc = saveCursorKey(pCur);
|
||||
if( rc ) return rc;
|
||||
}else{
|
||||
bSkipnext = 1;
|
||||
bPreserve = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9373,8 +9414,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bSkipnext ){
|
||||
assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
|
||||
if( bPreserve>1 ){
|
||||
assert( (pCur->iPage==iCellDepth || CORRUPT_DB) );
|
||||
assert( pPage==pCur->pPage || CORRUPT_DB );
|
||||
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
|
||||
pCur->eState = CURSOR_SKIPNEXT;
|
||||
@ -9584,7 +9625,7 @@ static int clearDatabasePage(
|
||||
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
|
||||
if( rc ) return rc;
|
||||
if( (pBt->openFlags & BTREE_SINGLE)==0
|
||||
&& sqlite3PagerPageRefcount(pPage->pDbPage)!=1
|
||||
&& sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
|
||||
){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto cleardatabasepage_out;
|
||||
|
||||
@ -293,7 +293,9 @@ struct MemPage {
|
||||
u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
|
||||
BtShared *pBt; /* Pointer to BtShared that this page is part of */
|
||||
u8 *aData; /* Pointer to disk image of the page data */
|
||||
u8 *aDataEnd; /* One byte past the end of usable data */
|
||||
u8 *aDataEnd; /* One byte past the end of the entire page - not just
|
||||
** the usable space, the entire page. Used to prevent
|
||||
** corruption-induced of buffer overflow. */
|
||||
u8 *aCellIdx; /* The cell index area */
|
||||
u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
|
||||
DbPage *pDbPage; /* Pager page handle */
|
||||
|
||||
61
src/build.c
61
src/build.c
@ -143,11 +143,13 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
assert( pParse->pToplevel==0 );
|
||||
db = pParse->db;
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nested ) return;
|
||||
if( db->mallocFailed || pParse->nErr ){
|
||||
if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
|
||||
if( pParse->nErr ){
|
||||
if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM;
|
||||
return;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
|
||||
/* Begin by generating some termination code at the end of the
|
||||
** vdbe program
|
||||
@ -170,9 +172,10 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
int i;
|
||||
int reg;
|
||||
|
||||
if( pReturning->nRetCol==0 ){
|
||||
if( NEVER(pReturning->nRetCol==0) ){
|
||||
assert( CORRUPT_DB );
|
||||
}else{
|
||||
sqlite3VdbeAddOp0(v, OP_FkCheck);
|
||||
addrRewind =
|
||||
sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
|
||||
VdbeCoverage(v);
|
||||
@ -265,7 +268,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
if( pParse->bReturning ){
|
||||
Returning *pRet = pParse->u1.pReturning;
|
||||
if( pRet->nRetCol==0 ){
|
||||
if( NEVER(pRet->nRetCol==0) ){
|
||||
assert( CORRUPT_DB );
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
|
||||
@ -279,7 +282,9 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
/* Get the VDBE program ready for execution
|
||||
*/
|
||||
if( v && pParse->nErr==0 && !db->mallocFailed ){
|
||||
assert( v!=0 || pParse->nErr );
|
||||
assert( db->mallocFailed==0 || pParse->nErr );
|
||||
if( pParse->nErr==0 ){
|
||||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
assert( pParse->pAinc==0 || pParse->nTab>0 );
|
||||
@ -306,7 +311,6 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
char *zSql;
|
||||
char *zErrMsg = 0;
|
||||
sqlite3 *db = pParse->db;
|
||||
u32 savedDbFlags = db->mDbFlags;
|
||||
char saveBuf[PARSE_TAIL_SZ];
|
||||
@ -328,9 +332,10 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
|
||||
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
|
||||
db->mDbFlags |= DBFLAG_PreferBuiltin;
|
||||
sqlite3RunParser(pParse, zSql, &zErrMsg);
|
||||
sqlite3RunParser(pParse, zSql);
|
||||
sqlite3DbFree(db, pParse->zErrMsg);
|
||||
pParse->zErrMsg = 0;
|
||||
db->mDbFlags = savedDbFlags;
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
sqlite3DbFree(db, zSql);
|
||||
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
|
||||
pParse->nested--;
|
||||
@ -1290,7 +1295,8 @@ void sqlite3StartTable(
|
||||
pTable = sqlite3FindTable(db, zName, zDb);
|
||||
if( pTable ){
|
||||
if( !noErr ){
|
||||
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
|
||||
sqlite3ErrorMsg(pParse, "%s %T already exists",
|
||||
(IsView(pTable)? "view" : "table"), pName);
|
||||
}else{
|
||||
assert( !db->init.busy || CORRUPT_DB );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
@ -2385,10 +2391,11 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
pTab->iPKey = -1;
|
||||
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
|
||||
SQLITE_IDXTYPE_PRIMARYKEY);
|
||||
if( db->mallocFailed || pParse->nErr ){
|
||||
if( pParse->nErr ){
|
||||
pTab->tabFlags &= ~TF_WithoutRowid;
|
||||
return;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
assert( pPk->nKeyCol==1 );
|
||||
}else{
|
||||
@ -2819,6 +2826,11 @@ void sqlite3EndTable(
|
||||
int addrInsLoop; /* Top of the loop for inserting rows */
|
||||
Table *pSelTab; /* A table that describes the SELECT results */
|
||||
|
||||
if( IN_SPECIAL_PARSE ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
regYield = ++pParse->nMem;
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
@ -3129,10 +3141,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
*/
|
||||
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
|
||||
&pTable->nCol, &pTable->aCol);
|
||||
if( db->mallocFailed==0
|
||||
&& pParse->nErr==0
|
||||
if( pParse->nErr==0
|
||||
&& pTable->nCol==pSel->pEList->nExpr
|
||||
){
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
|
||||
SQLITE_AFF_NONE);
|
||||
}
|
||||
@ -3751,7 +3763,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
tnum = pIndex->tnum;
|
||||
}
|
||||
pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
|
||||
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
|
||||
assert( pKey!=0 || pParse->nErr );
|
||||
|
||||
/* Open the sorter cursor if we are to use one. */
|
||||
iSorter = pParse->nTab++;
|
||||
@ -3915,9 +3927,11 @@ void sqlite3CreateIndex(
|
||||
char *zExtra = 0; /* Extra space after the Index object */
|
||||
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
|
||||
|
||||
if( db->mallocFailed || pParse->nErr>0 ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
@ -3981,7 +3995,6 @@ void sqlite3CreateIndex(
|
||||
pDb = &db->aDb[iDb];
|
||||
|
||||
assert( pTab!=0 );
|
||||
assert( pParse->nErr==0 );
|
||||
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
|
||||
&& db->init.busy==0
|
||||
&& pTblName!=0
|
||||
@ -4405,13 +4418,13 @@ void sqlite3CreateIndex(
|
||||
/* Add an entry in sqlite_schema for this index
|
||||
*/
|
||||
sqlite3NestedParse(pParse,
|
||||
"INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
|
||||
db->aDb[iDb].zDbSName,
|
||||
pIndex->zName,
|
||||
pTab->zName,
|
||||
iMem,
|
||||
zStmt
|
||||
);
|
||||
"INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
|
||||
db->aDb[iDb].zDbSName,
|
||||
pIndex->zName,
|
||||
pTab->zName,
|
||||
iMem,
|
||||
zStmt
|
||||
);
|
||||
sqlite3DbFree(db, zStmt);
|
||||
|
||||
/* Fill the index with data and reparse the schema. Code an OP_Expire
|
||||
@ -4545,10 +4558,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
|
||||
assert( pParse->nErr==0 ); /* Never called with prior errors */
|
||||
if( db->mallocFailed ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
|
||||
assert( pName->nSrc==1 );
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto exit_drop_index;
|
||||
@ -4959,7 +4972,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
|
||||
pItem->pUsing = pUsing;
|
||||
return p;
|
||||
|
||||
append_from_error:
|
||||
append_from_error:
|
||||
assert( p==0 );
|
||||
sqlite3ExprDelete(db, pOn);
|
||||
sqlite3IdListDelete(db, pUsing);
|
||||
|
||||
@ -358,7 +358,6 @@ void sqlite3InsertBuiltinFuncs(
|
||||
const char *zName = aDef[i].zName;
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
int h = SQLITE_FUNC_HASH(zName[0], nName);
|
||||
assert( zName[0]>='a' && zName[0]<='z' );
|
||||
assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );
|
||||
pOther = sqlite3FunctionSearch(h, zName);
|
||||
if( pOther ){
|
||||
|
||||
23
src/ctime.c
23
src/ctime.c
@ -1,3 +1,11 @@
|
||||
/* DO NOT EDIT!
|
||||
** This file is automatically generated by the script in the canonical
|
||||
** SQLite source tree at tool/mkctimec.tcl.
|
||||
**
|
||||
** To modify this header, edit any of the various lists in that script
|
||||
** which specify categories of generated conditionals in this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
** 2010 February 23
|
||||
**
|
||||
@ -46,9 +54,6 @@
|
||||
*/
|
||||
static const char * const sqlite3azCompileOpt[] = {
|
||||
|
||||
/*
|
||||
** BEGIN CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
#ifdef SQLITE_32BIT_ROWID
|
||||
"32BIT_ROWID",
|
||||
#endif
|
||||
@ -257,9 +262,6 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
"ENABLE_IOTRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
"ENABLE_JSON1",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
@ -588,6 +590,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
||||
"OMIT_INTROSPECTION_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_JSON
|
||||
"OMIT_JSON",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
"OMIT_LIKE_OPTIMIZATION",
|
||||
#endif
|
||||
@ -776,10 +781,8 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#ifdef SQLITE_ZERO_MALLOC
|
||||
"ZERO_MALLOC",
|
||||
#endif
|
||||
/*
|
||||
** END CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
};
|
||||
|
||||
} ;
|
||||
|
||||
const char **sqlite3CompileOptions(int *pnOpt){
|
||||
*pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
|
||||
|
||||
312
src/date.c
312
src/date.c
@ -503,8 +503,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
|
||||
** is available. This routine returns 0 on success and
|
||||
** non-zero on any kind of error.
|
||||
**
|
||||
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
|
||||
** routine will always fail.
|
||||
** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
|
||||
** routine will always fail. If bLocaltimeFault is nonzero and
|
||||
** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
|
||||
** invoked in place of the OS-defined localtime() function.
|
||||
**
|
||||
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
|
||||
** library function localtime_r() is used to assist in the calculation of
|
||||
@ -520,14 +522,30 @@ static int osLocaltime(time_t *t, struct tm *pTm){
|
||||
sqlite3_mutex_enter(mutex);
|
||||
pX = localtime(t);
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
||||
if( sqlite3GlobalConfig.xAltLocaltime!=0
|
||||
&& 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
|
||||
){
|
||||
pX = pTm;
|
||||
}else{
|
||||
pX = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( pX ) *pTm = *pX;
|
||||
#if SQLITE_THREADSAFE>0
|
||||
sqlite3_mutex_leave(mutex);
|
||||
#endif
|
||||
rc = pX==0;
|
||||
#else
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
||||
if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
|
||||
return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if HAVE_LOCALTIME_R
|
||||
rc = localtime_r(t, pTm)==0;
|
||||
@ -542,67 +560,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){
|
||||
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
/*
|
||||
** Compute the difference (in milliseconds) between localtime and UTC
|
||||
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
|
||||
** return this value and set *pRc to SQLITE_OK.
|
||||
**
|
||||
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
|
||||
** is undefined in this case.
|
||||
** Assuming the input DateTime is UTC, move it to its localtime equivalent.
|
||||
*/
|
||||
static sqlite3_int64 localtimeOffset(
|
||||
DateTime *p, /* Date at which to calculate offset */
|
||||
sqlite3_context *pCtx, /* Write error here if one occurs */
|
||||
int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
|
||||
static int toLocaltime(
|
||||
DateTime *p, /* Date at which to calculate offset */
|
||||
sqlite3_context *pCtx /* Write error here if one occurs */
|
||||
){
|
||||
DateTime x, y;
|
||||
time_t t;
|
||||
struct tm sLocal;
|
||||
int iYearDiff;
|
||||
|
||||
/* Initialize the contents of sLocal to avoid a compiler warning. */
|
||||
memset(&sLocal, 0, sizeof(sLocal));
|
||||
|
||||
x = *p;
|
||||
computeYMD_HMS(&x);
|
||||
if( x.Y<1971 || x.Y>=2038 ){
|
||||
computeJD(p);
|
||||
if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
|
||||
|| p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
|
||||
){
|
||||
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
|
||||
** works for years between 1970 and 2037. For dates outside this range,
|
||||
** SQLite attempts to map the year into an equivalent year within this
|
||||
** range, do the calculation, then map the year back.
|
||||
*/
|
||||
x.Y = 2000;
|
||||
x.M = 1;
|
||||
x.D = 1;
|
||||
x.h = 0;
|
||||
x.m = 0;
|
||||
x.s = 0.0;
|
||||
} else {
|
||||
int s = (int)(x.s + 0.5);
|
||||
x.s = s;
|
||||
DateTime x = *p;
|
||||
computeYMD_HMS(&x);
|
||||
iYearDiff = (2000 + x.Y%4) - x.Y;
|
||||
x.Y += iYearDiff;
|
||||
x.validJD = 0;
|
||||
computeJD(&x);
|
||||
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
}else{
|
||||
iYearDiff = 0;
|
||||
t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
|
||||
}
|
||||
x.tz = 0;
|
||||
x.validJD = 0;
|
||||
computeJD(&x);
|
||||
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
if( osLocaltime(&t, &sLocal) ){
|
||||
sqlite3_result_error(pCtx, "local time unavailable", -1);
|
||||
*pRc = SQLITE_ERROR;
|
||||
return 0;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
y.Y = sLocal.tm_year + 1900;
|
||||
y.M = sLocal.tm_mon + 1;
|
||||
y.D = sLocal.tm_mday;
|
||||
y.h = sLocal.tm_hour;
|
||||
y.m = sLocal.tm_min;
|
||||
y.s = sLocal.tm_sec;
|
||||
y.validYMD = 1;
|
||||
y.validHMS = 1;
|
||||
y.validJD = 0;
|
||||
y.rawS = 0;
|
||||
y.validTZ = 0;
|
||||
y.isError = 0;
|
||||
computeJD(&y);
|
||||
*pRc = SQLITE_OK;
|
||||
return y.iJD - x.iJD;
|
||||
p->Y = sLocal.tm_year + 1900 - iYearDiff;
|
||||
p->M = sLocal.tm_mon + 1;
|
||||
p->D = sLocal.tm_mday;
|
||||
p->h = sLocal.tm_hour;
|
||||
p->m = sLocal.tm_min;
|
||||
p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
|
||||
p->validYMD = 1;
|
||||
p->validHMS = 1;
|
||||
p->validJD = 0;
|
||||
p->rawS = 0;
|
||||
p->validTZ = 0;
|
||||
p->isError = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_LOCALTIME */
|
||||
|
||||
@ -615,18 +622,17 @@ static sqlite3_int64 localtimeOffset(
|
||||
** of several units of time.
|
||||
*/
|
||||
static const struct {
|
||||
u8 eType; /* Transformation type code */
|
||||
u8 nName; /* Length of th name */
|
||||
char *zName; /* Name of the transformation */
|
||||
double rLimit; /* Maximum NNN value for this transform */
|
||||
double rXform; /* Constant used for this transform */
|
||||
u8 nName; /* Length of the name */
|
||||
char zName[7]; /* Name of the transformation */
|
||||
float rLimit; /* Maximum NNN value for this transform */
|
||||
float rXform; /* Constant used for this transform */
|
||||
} aXformType[] = {
|
||||
{ 0, 6, "second", 464269060800.0, 1000.0 },
|
||||
{ 0, 6, "minute", 7737817680.0, 60000.0 },
|
||||
{ 0, 4, "hour", 128963628.0, 3600000.0 },
|
||||
{ 0, 3, "day", 5373485.0, 86400000.0 },
|
||||
{ 1, 5, "month", 176546.0, 2592000000.0 },
|
||||
{ 2, 4, "year", 14713.0, 31536000000.0 },
|
||||
{ 6, "second", 4.6427e+14, 1.0 },
|
||||
{ 6, "minute", 7.7379e+12, 60.0 },
|
||||
{ 4, "hour", 1.2897e+11, 3600.0 },
|
||||
{ 3, "day", 5373485.0, 86400.0 },
|
||||
{ 5, "month", 176546.0, 2592000.0 },
|
||||
{ 4, "year", 14713.0, 31536000.0 },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -657,11 +663,55 @@ static int parseModifier(
|
||||
sqlite3_context *pCtx, /* Function context */
|
||||
const char *z, /* The text of the modifier */
|
||||
int n, /* Length of zMod in bytes */
|
||||
DateTime *p /* The date/time value to be modified */
|
||||
DateTime *p, /* The date/time value to be modified */
|
||||
int idx /* Parameter index of the modifier */
|
||||
){
|
||||
int rc = 1;
|
||||
double r;
|
||||
switch(sqlite3UpperToLower[(u8)z[0]] ){
|
||||
case 'a': {
|
||||
/*
|
||||
** auto
|
||||
**
|
||||
** If rawS is available, then interpret as a julian day number, or
|
||||
** a unix timestamp, depending on its magnitude.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "auto")==0 ){
|
||||
if( idx>1 ) return 1; /* IMP: R-33611-57934 */
|
||||
if( !p->rawS || p->validJD ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
}else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
|
||||
&& p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
|
||||
){
|
||||
r = p->s*1000.0 + 210866760000000.0;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD = (sqlite3_int64)(r + 0.5);
|
||||
p->validJD = 1;
|
||||
p->rawS = 0;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'j': {
|
||||
/*
|
||||
** julianday
|
||||
**
|
||||
** Always interpret the prior number as a julian-day value. If this
|
||||
** is not the first modifier, or if the prior argument is not a numeric
|
||||
** value in the allowed range of julian day numbers understood by
|
||||
** SQLite (0..5373484.5) then the result will be NULL.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "julianday")==0 ){
|
||||
if( idx>1 ) return 1; /* IMP: R-31176-64601 */
|
||||
if( p->validJD && p->rawS ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
case 'l': {
|
||||
/* localtime
|
||||
@ -670,9 +720,7 @@ static int parseModifier(
|
||||
** show local time.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
computeJD(p);
|
||||
p->iJD += localtimeOffset(p, pCtx, &rc);
|
||||
clearYMD_HMS_TZ(p);
|
||||
rc = toLocaltime(p, pCtx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -685,6 +733,7 @@ static int parseModifier(
|
||||
** seconds since 1970. Convert to a real julian day number.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
|
||||
if( idx>1 ) return 1; /* IMP: R-49255-55373 */
|
||||
r = p->s*1000.0 + 210866760000000.0;
|
||||
if( r>=0.0 && r<464269060800000.0 ){
|
||||
clearYMD_HMS_TZ(p);
|
||||
@ -697,18 +746,31 @@ static int parseModifier(
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
|
||||
if( p->tzSet==0 ){
|
||||
sqlite3_int64 c1;
|
||||
i64 iOrigJD; /* Original localtime */
|
||||
i64 iGuess; /* Guess at the corresponding utc time */
|
||||
int cnt = 0; /* Safety to prevent infinite loop */
|
||||
int iErr; /* Guess is off by this much */
|
||||
|
||||
computeJD(p);
|
||||
c1 = localtimeOffset(p, pCtx, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iJD -= c1;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
|
||||
}
|
||||
iGuess = iOrigJD = p->iJD;
|
||||
iErr = 0;
|
||||
do{
|
||||
DateTime new;
|
||||
memset(&new, 0, sizeof(new));
|
||||
iGuess -= iErr;
|
||||
new.iJD = iGuess;
|
||||
new.validJD = 1;
|
||||
rc = toLocaltime(&new, pCtx);
|
||||
if( rc ) return rc;
|
||||
computeJD(&new);
|
||||
iErr = new.iJD - iOrigJD;
|
||||
}while( iErr && cnt++<3 );
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->iJD = iGuess;
|
||||
p->validJD = 1;
|
||||
p->tzSet = 1;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@ -824,9 +886,10 @@ static int parseModifier(
|
||||
&& sqlite3_strnicmp(aXformType[i].zName, z, n)==0
|
||||
&& r>-aXformType[i].rLimit && r<aXformType[i].rLimit
|
||||
){
|
||||
switch( aXformType[i].eType ){
|
||||
case 1: { /* Special processing to add months */
|
||||
switch( i ){
|
||||
case 4: { /* Special processing to add months */
|
||||
int x;
|
||||
assert( strcmp(aXformType[i].zName,"month")==0 );
|
||||
computeYMD_HMS(p);
|
||||
p->M += (int)r;
|
||||
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
||||
@ -836,8 +899,9 @@ static int parseModifier(
|
||||
r -= (int)r;
|
||||
break;
|
||||
}
|
||||
case 2: { /* Special processing to add years */
|
||||
case 5: { /* Special processing to add years */
|
||||
int y = (int)r;
|
||||
assert( strcmp(aXformType[i].zName,"year")==0 );
|
||||
computeYMD_HMS(p);
|
||||
p->Y += y;
|
||||
p->validJD = 0;
|
||||
@ -846,7 +910,7 @@ static int parseModifier(
|
||||
}
|
||||
}
|
||||
computeJD(p);
|
||||
p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
|
||||
p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
@ -896,7 +960,7 @@ static int isDate(
|
||||
for(i=1; i<argc; i++){
|
||||
z = sqlite3_value_text(argv[i]);
|
||||
n = sqlite3_value_bytes(argv[i]);
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
|
||||
}
|
||||
computeJD(p);
|
||||
if( p->isError || !validJulianDay(p->iJD) ) return 1;
|
||||
@ -926,6 +990,24 @@ static void juliandayFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** unixepoch( TIMESTRING, MOD, MOD, ...)
|
||||
**
|
||||
** Return the number of seconds (including fractional seconds) since
|
||||
** the unix epoch of 1970-01-01 00:00:00 GMT.
|
||||
*/
|
||||
static void unixepochFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
computeJD(&x);
|
||||
sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** datetime( TIMESTRING, MOD, MOD, ...)
|
||||
**
|
||||
@ -938,11 +1020,38 @@ static void datetimeFunc(
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int Y, s;
|
||||
char zBuf[24];
|
||||
computeYMD_HMS(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
Y = x.Y;
|
||||
if( Y<0 ) Y = -Y;
|
||||
zBuf[1] = '0' + (Y/1000)%10;
|
||||
zBuf[2] = '0' + (Y/100)%10;
|
||||
zBuf[3] = '0' + (Y/10)%10;
|
||||
zBuf[4] = '0' + (Y)%10;
|
||||
zBuf[5] = '-';
|
||||
zBuf[6] = '0' + (x.M/10)%10;
|
||||
zBuf[7] = '0' + (x.M)%10;
|
||||
zBuf[8] = '-';
|
||||
zBuf[9] = '0' + (x.D/10)%10;
|
||||
zBuf[10] = '0' + (x.D)%10;
|
||||
zBuf[11] = ' ';
|
||||
zBuf[12] = '0' + (x.h/10)%10;
|
||||
zBuf[13] = '0' + (x.h)%10;
|
||||
zBuf[14] = ':';
|
||||
zBuf[15] = '0' + (x.m/10)%10;
|
||||
zBuf[16] = '0' + (x.m)%10;
|
||||
zBuf[17] = ':';
|
||||
s = (int)x.s;
|
||||
zBuf[18] = '0' + (s/10)%10;
|
||||
zBuf[19] = '0' + (s)%10;
|
||||
zBuf[20] = 0;
|
||||
if( x.Y<0 ){
|
||||
zBuf[0] = '-';
|
||||
sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,10 +1067,20 @@ static void timeFunc(
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int s;
|
||||
char zBuf[16];
|
||||
computeHMS(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
zBuf[0] = '0' + (x.h/10)%10;
|
||||
zBuf[1] = '0' + (x.h)%10;
|
||||
zBuf[2] = ':';
|
||||
zBuf[3] = '0' + (x.m/10)%10;
|
||||
zBuf[4] = '0' + (x.m)%10;
|
||||
zBuf[5] = ':';
|
||||
s = (int)x.s;
|
||||
zBuf[6] = '0' + (s/10)%10;
|
||||
zBuf[7] = '0' + (s)%10;
|
||||
zBuf[8] = 0;
|
||||
sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -977,10 +1096,28 @@ static void dateFunc(
|
||||
){
|
||||
DateTime x;
|
||||
if( isDate(context, argc, argv, &x)==0 ){
|
||||
char zBuf[100];
|
||||
int Y;
|
||||
char zBuf[16];
|
||||
computeYMD(&x);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
Y = x.Y;
|
||||
if( Y<0 ) Y = -Y;
|
||||
zBuf[1] = '0' + (Y/1000)%10;
|
||||
zBuf[2] = '0' + (Y/100)%10;
|
||||
zBuf[3] = '0' + (Y/10)%10;
|
||||
zBuf[4] = '0' + (Y)%10;
|
||||
zBuf[5] = '-';
|
||||
zBuf[6] = '0' + (x.M/10)%10;
|
||||
zBuf[7] = '0' + (x.M)%10;
|
||||
zBuf[8] = '-';
|
||||
zBuf[9] = '0' + (x.D/10)%10;
|
||||
zBuf[10] = '0' + (x.D)%10;
|
||||
zBuf[11] = 0;
|
||||
if( x.Y<0 ){
|
||||
zBuf[0] = '-';
|
||||
sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1202,6 +1339,7 @@ void sqlite3RegisterDateTimeFunctions(void){
|
||||
static FuncDef aDateTimeFuncs[] = {
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
|
||||
PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
|
||||
PURE_DATE(date, -1, 0, 0, dateFunc ),
|
||||
PURE_DATE(time, -1, 0, 0, timeFunc ),
|
||||
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
|
||||
|
||||
@ -156,6 +156,7 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
){
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
sqlite3VtabWriteAll(pIdxInfo);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
20
src/delete.c
20
src/delete.c
@ -44,6 +44,16 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
||||
return pTab;
|
||||
}
|
||||
|
||||
/* Generate byte-code that will report the number of rows modified
|
||||
** by a DELETE, INSERT, or UPDATE statement.
|
||||
*/
|
||||
void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
|
||||
sqlite3VdbeAddOp0(v, OP_FkCheck);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* Return true if table pTab is read-only.
|
||||
**
|
||||
** A table is read-only if any of the following are true:
|
||||
@ -283,9 +293,11 @@ void sqlite3DeleteFrom(
|
||||
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
assert( pTabList->nSrc==1 );
|
||||
|
||||
|
||||
@ -466,7 +478,7 @@ void sqlite3DeleteFrom(
|
||||
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
|
||||
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
|
||||
@ -619,9 +631,7 @@ void sqlite3DeleteFrom(
|
||||
** invoke the callback function.
|
||||
*/
|
||||
if( memCnt ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, memCnt, "rows deleted");
|
||||
}
|
||||
|
||||
delete_from_cleanup:
|
||||
|
||||
31
src/expr.c
31
src/expr.c
@ -769,9 +769,8 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){
|
||||
** if appropriate.
|
||||
*/
|
||||
static void exprSetHeight(Expr *p){
|
||||
int nHeight = 0;
|
||||
heightOfExpr(p->pLeft, &nHeight);
|
||||
heightOfExpr(p->pRight, &nHeight);
|
||||
int nHeight = p->pLeft ? p->pLeft->nHeight : 0;
|
||||
if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight;
|
||||
if( ExprUseXSelect(p) ){
|
||||
heightOfSelect(p->x.pSelect, &nHeight);
|
||||
}else if( p->x.pList ){
|
||||
@ -1070,6 +1069,7 @@ Expr *sqlite3ExprFunction(
|
||||
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
|
||||
return 0;
|
||||
}
|
||||
pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
|
||||
if( pList
|
||||
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
|
||||
&& !pParse->nested
|
||||
@ -1113,7 +1113,7 @@ void sqlite3ExprFunctionUsable(
|
||||
** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
|
||||
** that the schema is possibly tainted).
|
||||
*/
|
||||
sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
|
||||
sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1169,6 +1169,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
|
||||
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
|
||||
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
|
||||
return;
|
||||
}
|
||||
x = (ynVar)i;
|
||||
@ -1196,6 +1197,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
|
||||
pExpr->iColumn = x;
|
||||
if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||
sqlite3ErrorMsg(pParse, "too many SQL variables");
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2803,8 +2805,7 @@ int sqlite3FindInIndex(
|
||||
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
int j;
|
||||
|
||||
assert( pReq!=0 || pRhs->iColumn==XN_ROWID
|
||||
|| pParse->nErr || db->mallocFailed );
|
||||
assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
|
||||
for(j=0; j<nExpr; j++){
|
||||
if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
|
||||
assert( pIdx->azColl[j] );
|
||||
@ -3280,10 +3281,8 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
}
|
||||
pSel->iLimit = 0;
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
if( pParse->nErr ){
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_ERROR;
|
||||
}
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_ERROR;
|
||||
return 0;
|
||||
}
|
||||
pExpr->iTable = rReg = dest.iSDParm;
|
||||
@ -3500,10 +3499,9 @@ static void sqlite3ExprCodeIN(
|
||||
}else{
|
||||
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
|
||||
}
|
||||
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
|
||||
for(i=0; i<nVector; i++){
|
||||
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
|
||||
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
|
||||
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
|
||||
if( sqlite3ExprCanBeNull(p) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
|
||||
VdbeCoverage(v);
|
||||
@ -3641,11 +3639,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
c = sqlite3DecOrHexToI64(z, &value);
|
||||
if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
|
||||
sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr);
|
||||
#else
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
if( sqlite3_strnicmp(z,"0x",2)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
|
||||
sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T",
|
||||
negFlag?"-":"",pExpr);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
@ -4321,7 +4320,7 @@ expr_code_doover:
|
||||
|| NEVER(pExpr->iAgg>=pInfo->nFunc)
|
||||
){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
|
||||
sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr);
|
||||
}else{
|
||||
return pInfo->aFunc[pExpr->iAgg].iMem;
|
||||
}
|
||||
@ -4362,7 +4361,7 @@ expr_code_doover:
|
||||
}
|
||||
#endif
|
||||
if( pDef==0 || pDef->xFinalize!=0 ){
|
||||
sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
|
||||
sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
|
||||
break;
|
||||
}
|
||||
if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
|
||||
|
||||
@ -651,7 +651,7 @@ static void fkScanChildren(
|
||||
** clause. For each row found, increment either the deferred or immediate
|
||||
** foreign key constraint counter. */
|
||||
if( pParse->nErr==0 ){
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
|
||||
if( pWInfo ){
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
124
src/func.c
124
src/func.c
@ -97,6 +97,18 @@ static void typeofFunc(
|
||||
sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* subtype(X)
|
||||
**
|
||||
** Return the subtype of X
|
||||
*/
|
||||
static void subtypeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3_result_int(context, sqlite3_value_subtype(argv[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the length() function
|
||||
@ -258,7 +270,7 @@ endInstrOOM:
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the printf() function.
|
||||
** Implementation of the printf() (a.k.a. format()) SQL function.
|
||||
*/
|
||||
static void printfFunc(
|
||||
sqlite3_context *context,
|
||||
@ -1027,39 +1039,42 @@ static const char hexdigits[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function. This function takes a single
|
||||
** argument. If the argument is numeric, the return value is the same as
|
||||
** the argument. If the argument is NULL, the return value is the string
|
||||
** "NULL". Otherwise, the argument is enclosed in single quotes with
|
||||
** single-quote escapes.
|
||||
** Append to pStr text that is the SQL literal representation of the
|
||||
** value contained in pValue.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
switch( sqlite3_value_type(argv[0]) ){
|
||||
void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
|
||||
/* As currently implemented, the string must be initially empty.
|
||||
** we might relax this requirement in the future, but that will
|
||||
** require enhancements to the implementation. */
|
||||
assert( pStr!=0 && pStr->nChar==0 );
|
||||
|
||||
switch( sqlite3_value_type(pValue) ){
|
||||
case SQLITE_FLOAT: {
|
||||
double r1, r2;
|
||||
char zBuf[50];
|
||||
r1 = sqlite3_value_double(argv[0]);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
|
||||
sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
|
||||
const char *zVal;
|
||||
r1 = sqlite3_value_double(pValue);
|
||||
sqlite3_str_appendf(pStr, "%!.15g", r1);
|
||||
zVal = sqlite3_str_value(pStr);
|
||||
if( zVal ){
|
||||
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_str_reset(pStr);
|
||||
sqlite3_str_appendf(pStr, "%!.20e", r1);
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
sqlite3_result_value(context, argv[0]);
|
||||
sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
char *zText = 0;
|
||||
char const *zBlob = sqlite3_value_blob(argv[0]);
|
||||
int nBlob = sqlite3_value_bytes(argv[0]);
|
||||
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
|
||||
zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
|
||||
if( zText ){
|
||||
char const *zBlob = sqlite3_value_blob(pValue);
|
||||
int nBlob = sqlite3_value_bytes(pValue);
|
||||
assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */
|
||||
sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
|
||||
if( pStr->accError==0 ){
|
||||
char *zText = pStr->zText;
|
||||
int i;
|
||||
for(i=0; i<nBlob; i++){
|
||||
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
|
||||
@ -1069,42 +1084,48 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
zText[(nBlob*2)+3] = '\0';
|
||||
zText[0] = 'X';
|
||||
zText[1] = '\'';
|
||||
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(zText);
|
||||
pStr->nChar = nBlob*2 + 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
int i,j;
|
||||
u64 n;
|
||||
const unsigned char *zArg = sqlite3_value_text(argv[0]);
|
||||
char *z;
|
||||
|
||||
if( zArg==0 ) return;
|
||||
for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
|
||||
z = contextMalloc(context, ((i64)i)+((i64)n)+3);
|
||||
if( z ){
|
||||
z[0] = '\'';
|
||||
for(i=0, j=1; zArg[i]; i++){
|
||||
z[j++] = zArg[i];
|
||||
if( zArg[i]=='\'' ){
|
||||
z[j++] = '\'';
|
||||
}
|
||||
}
|
||||
z[j++] = '\'';
|
||||
z[j] = 0;
|
||||
sqlite3_result_text(context, z, j, sqlite3_free);
|
||||
}
|
||||
const unsigned char *zArg = sqlite3_value_text(pValue);
|
||||
sqlite3_str_appendf(pStr, "%Q", zArg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
|
||||
sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
|
||||
assert( sqlite3_value_type(pValue)==SQLITE_NULL );
|
||||
sqlite3_str_append(pStr, "NULL", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the QUOTE() function.
|
||||
**
|
||||
** The quote(X) function returns the text of an SQL literal which is the
|
||||
** value of its argument suitable for inclusion into an SQL statement.
|
||||
** Strings are surrounded by single-quotes with escapes on interior quotes
|
||||
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
|
||||
** embedded NUL characters cannot be represented as string literals in SQL
|
||||
** and hence the returned string literal is truncated prior to the first NUL.
|
||||
*/
|
||||
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3_str str;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
sqlite3QuoteValue(&str,argv[0]);
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
|
||||
SQLITE_DYNAMIC);
|
||||
if( str.accError!=SQLITE_OK ){
|
||||
sqlite3_result_null(context);
|
||||
sqlite3_result_error_code(context, str.accError);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The unicode() function. Return the integer unicode code-point value
|
||||
** for the first character of the input string.
|
||||
@ -2231,8 +2252,8 @@ void sqlite3RegisterBuiltinFunctions(void){
|
||||
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
|
||||
SQLITE_FUNC_TYPEOF),
|
||||
{1, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_OFFSET|SQLITE_FUNC_TYPEOF,
|
||||
0, 0, noopFunc, 0, 0, 0, "sqlite_offset", {0} },
|
||||
#endif
|
||||
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
|
||||
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
|
||||
@ -2249,9 +2270,11 @@ void sqlite3RegisterBuiltinFunctions(void){
|
||||
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
|
||||
SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
|
||||
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
FUNCTION(printf, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(format, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
@ -2350,6 +2373,7 @@ void sqlite3RegisterBuiltinFunctions(void){
|
||||
#endif
|
||||
sqlite3WindowFunctions();
|
||||
sqlite3RegisterDateTimeFunctions();
|
||||
sqlite3RegisterJsonFunctions();
|
||||
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
|
||||
|
||||
#if 0 /* Enable to print out how the built-in functions are hashed */
|
||||
|
||||
@ -295,6 +295,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
0, /* bLocaltimeFault */
|
||||
0, /* xAltLocaltime */
|
||||
0x7ffffffe, /* iOnceResetThreshold */
|
||||
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
|
||||
0, /* iPrngSeed */
|
||||
|
||||
27
src/insert.c
27
src/insert.c
@ -181,7 +181,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
||||
}
|
||||
|
||||
for(i=j=0; i<pTab->nCol; i++){
|
||||
assert( pTab->aCol[i].affinity!=0 );
|
||||
assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 );
|
||||
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
|
||||
zColAff[j++] = pTab->aCol[i].affinity;
|
||||
}
|
||||
@ -715,9 +715,11 @@ void sqlite3Insert(
|
||||
#endif
|
||||
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
@ -793,7 +795,11 @@ void sqlite3Insert(
|
||||
**
|
||||
** This is the 2nd template.
|
||||
*/
|
||||
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
|
||||
if( pColumn==0
|
||||
&& pSelect!=0
|
||||
&& pTrigger==0
|
||||
&& xferOptimization(pParse, pTab, pSelect, onError, iDb)
|
||||
){
|
||||
assert( !pTrigger );
|
||||
assert( pList==0 );
|
||||
goto insert_end;
|
||||
@ -893,7 +899,9 @@ void sqlite3Insert(
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
@ -1382,9 +1390,7 @@ insert_end:
|
||||
** invoke the callback function.
|
||||
*/
|
||||
if( regRowCount ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, regRowCount, "rows inserted");
|
||||
}
|
||||
|
||||
insert_cleanup:
|
||||
@ -2764,18 +2770,13 @@ static int xferOptimization(
|
||||
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
|
||||
int regData, regRowid; /* Registers holding data and rowid */
|
||||
|
||||
if( pSelect==0 ){
|
||||
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
|
||||
}
|
||||
assert( pSelect!=0 );
|
||||
if( pParse->pWith || pSelect->pWith ){
|
||||
/* Do not attempt to process this query if there are an WITH clauses
|
||||
** attached to it. Proceeding may generate a false "no such table: xxx"
|
||||
** error if pSelect reads from a CTE named "xxx". */
|
||||
return 0;
|
||||
}
|
||||
if( sqlite3TriggerList(pParse, pDest) ){
|
||||
return 0; /* tab1 must not have triggers */
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pDest) ){
|
||||
return 0; /* tab1 must not be a virtual table */
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension implements JSON functions. The interface is
|
||||
** modeled after MySQL JSON functions:
|
||||
** This SQLite JSON functions.
|
||||
**
|
||||
** https://dev.mysql.com/doc/refman/5.7/en/json.html
|
||||
** This file began as an extension in ext/misc/json1.c in 2015. That
|
||||
** extension proved so useful that it has now been moved into the core.
|
||||
**
|
||||
** For the time being, all JSON is stored as pure text. (We might add
|
||||
** a JSONB type in the future which stores a binary encoding of JSON in
|
||||
@ -21,48 +21,8 @@
|
||||
** This implementation parses JSON text at 250 MB/s, so it is hard to see
|
||||
** how JSONB might improve on that.)
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Mark a function parameter as unused, to suppress nuisance compiler
|
||||
** warnings. */
|
||||
#ifndef UNUSED_PARAM
|
||||
# define UNUSED_PARAM(X) (void)(X)
|
||||
#endif
|
||||
|
||||
#ifndef LARGEST_INT64
|
||||
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
|
||||
#endif
|
||||
|
||||
#ifndef deliberate_fall_through
|
||||
# define deliberate_fall_through
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Versions of isspace(), isalnum() and isdigit() to which it is safe
|
||||
** to pass signed char values.
|
||||
*/
|
||||
#ifdef sqlite3Isdigit
|
||||
/* Use the SQLite core versions if this routine is part of the
|
||||
** SQLite amalgamation */
|
||||
# define safe_isdigit(x) sqlite3Isdigit(x)
|
||||
# define safe_isalnum(x) sqlite3Isalnum(x)
|
||||
# define safe_isxdigit(x) sqlite3Isxdigit(x)
|
||||
#else
|
||||
/* Use the standard library for separate compilation */
|
||||
#include <ctype.h> /* amalgamator: keep */
|
||||
# define safe_isdigit(x) isdigit((unsigned char)(x))
|
||||
# define safe_isalnum(x) isalnum((unsigned char)(x))
|
||||
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_JSON
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Growing our own isspace() routine this way is twice as fast as
|
||||
@ -87,44 +47,14 @@ static const char jsonIsSpace[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
|
||||
#define fast_isspace(x) (jsonIsSpace[(unsigned char)x])
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/* Unsigned integer types. These are already defined in the sqliteInt.h,
|
||||
** but the definitions need to be repeated for separate compilation. */
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short int u16;
|
||||
typedef unsigned char u8;
|
||||
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
# endif
|
||||
# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
# elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
# else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
# endif
|
||||
# define testcase(X)
|
||||
#endif
|
||||
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST)
|
||||
# define VVA(X)
|
||||
#else
|
||||
# define VVA(X) X
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Some of the testcase() macros in this file are problematic for gcov
|
||||
** in that they generate false-miss errors randomly. This is a gcov problem,
|
||||
** not a problem in this case. But to work around it, we disable the
|
||||
** problematic test cases for production builds.
|
||||
*/
|
||||
#define json_testcase(X)
|
||||
|
||||
/* Objects */
|
||||
typedef struct JsonString JsonString;
|
||||
typedef struct JsonNode JsonNode;
|
||||
@ -582,10 +512,10 @@ static u8 jsonHexToInt(int h){
|
||||
*/
|
||||
static u32 jsonHexToInt4(const char *z){
|
||||
u32 v;
|
||||
assert( safe_isxdigit(z[0]) );
|
||||
assert( safe_isxdigit(z[1]) );
|
||||
assert( safe_isxdigit(z[2]) );
|
||||
assert( safe_isxdigit(z[3]) );
|
||||
assert( sqlite3Isxdigit(z[0]) );
|
||||
assert( sqlite3Isxdigit(z[1]) );
|
||||
assert( sqlite3Isxdigit(z[2]) );
|
||||
assert( sqlite3Isxdigit(z[3]) );
|
||||
v = (jsonHexToInt(z[0])<<12)
|
||||
+ (jsonHexToInt(z[1])<<8)
|
||||
+ (jsonHexToInt(z[2])<<4)
|
||||
@ -820,7 +750,7 @@ static int jsonParseAddNode(
|
||||
*/
|
||||
static int jsonIs4Hex(const char *z){
|
||||
int i;
|
||||
for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
|
||||
for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -839,13 +769,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
int x;
|
||||
JsonNode *pNode;
|
||||
const char *z = pParse->zJson;
|
||||
while( safe_isspace(z[i]) ){ i++; }
|
||||
while( fast_isspace(z[i]) ){ i++; }
|
||||
if( (c = z[i])=='{' ){
|
||||
/* Parse object */
|
||||
iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
|
||||
if( iThis<0 ) return -1;
|
||||
for(j=i+1;;j++){
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
|
||||
x = jsonParseValue(pParse, j);
|
||||
if( x<0 ){
|
||||
@ -858,14 +788,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
if( pNode->eType!=JSON_STRING ) return -1;
|
||||
pNode->jnFlags |= JNODE_LABEL;
|
||||
j = x;
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
if( z[j]!=':' ) return -1;
|
||||
j++;
|
||||
x = jsonParseValue(pParse, j);
|
||||
pParse->iDepth--;
|
||||
if( x<0 ) return -1;
|
||||
j = x;
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
c = z[j];
|
||||
if( c==',' ) continue;
|
||||
if( c!='}' ) return -1;
|
||||
@ -879,7 +809,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
if( iThis<0 ) return -1;
|
||||
memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u));
|
||||
for(j=i+1;;j++){
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
|
||||
x = jsonParseValue(pParse, j);
|
||||
pParse->iDepth--;
|
||||
@ -888,7 +818,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
return -1;
|
||||
}
|
||||
j = x;
|
||||
while( safe_isspace(z[j]) ){ j++; }
|
||||
while( fast_isspace(z[j]) ){ j++; }
|
||||
c = z[j];
|
||||
if( c==',' ) continue;
|
||||
if( c!=']' ) return -1;
|
||||
@ -925,17 +855,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
return j+1;
|
||||
}else if( c=='n'
|
||||
&& strncmp(z+i,"null",4)==0
|
||||
&& !safe_isalnum(z[i+4]) ){
|
||||
&& !sqlite3Isalnum(z[i+4]) ){
|
||||
jsonParseAddNode(pParse, JSON_NULL, 0, 0);
|
||||
return i+4;
|
||||
}else if( c=='t'
|
||||
&& strncmp(z+i,"true",4)==0
|
||||
&& !safe_isalnum(z[i+4]) ){
|
||||
&& !sqlite3Isalnum(z[i+4]) ){
|
||||
jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
|
||||
return i+4;
|
||||
}else if( c=='f'
|
||||
&& strncmp(z+i,"false",5)==0
|
||||
&& !safe_isalnum(z[i+5]) ){
|
||||
&& !sqlite3Isalnum(z[i+5]) ){
|
||||
jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
|
||||
return i+5;
|
||||
}else if( c=='-' || (c>='0' && c<='9') ){
|
||||
@ -1006,7 +936,7 @@ static int jsonParse(
|
||||
if( pParse->oom ) i = -1;
|
||||
if( i>0 ){
|
||||
assert( pParse->iDepth==0 );
|
||||
while( safe_isspace(zJson[i]) ) i++;
|
||||
while( fast_isspace(zJson[i]) ) i++;
|
||||
if( zJson[i] ) i = -1;
|
||||
}
|
||||
if( i<=0 ){
|
||||
@ -1234,7 +1164,7 @@ static JsonNode *jsonLookupStep(
|
||||
}else if( zPath[0]=='[' ){
|
||||
i = 0;
|
||||
j = 1;
|
||||
while( safe_isdigit(zPath[j]) ){
|
||||
while( sqlite3Isdigit(zPath[j]) ){
|
||||
i = i*10 + zPath[j] - '0';
|
||||
j++;
|
||||
}
|
||||
@ -1255,13 +1185,13 @@ static JsonNode *jsonLookupStep(
|
||||
j = 1;
|
||||
}
|
||||
j = 2;
|
||||
if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
|
||||
if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
|
||||
unsigned int x = 0;
|
||||
j = 3;
|
||||
do{
|
||||
x = x*10 + zPath[j] - '0';
|
||||
j++;
|
||||
}while( safe_isdigit(zPath[j]) );
|
||||
}while( sqlite3Isdigit(zPath[j]) );
|
||||
if( x>i ) return 0;
|
||||
i -= x;
|
||||
}
|
||||
@ -1480,7 +1410,7 @@ static void jsonTest1Func(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
@ -1501,7 +1431,7 @@ static void jsonQuoteFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString jx;
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendValue(&jx, argv[0]);
|
||||
@ -1572,13 +1502,34 @@ static void jsonArrayLengthFunc(
|
||||
sqlite3_result_int64(ctx, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Bit values for the flags passed into jsonExtractFunc() or
|
||||
** jsonSetFunc() via the user-data value.
|
||||
*/
|
||||
#define JSON_JSON 0x01 /* Result is always JSON */
|
||||
#define JSON_SQL 0x02 /* Result is always SQL */
|
||||
#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
|
||||
#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
|
||||
|
||||
/*
|
||||
** json_extract(JSON, PATH, ...)
|
||||
** "->"(JSON,PATH)
|
||||
** "->>"(JSON,PATH)
|
||||
**
|
||||
** Return the element described by PATH. Return NULL if there is no
|
||||
** PATH element. If there are multiple PATHs, then return a JSON array
|
||||
** with the result from each path. Throw an error if the JSON or any PATH
|
||||
** is malformed.
|
||||
** Return the element described by PATH. Return NULL if that PATH element
|
||||
** is not found.
|
||||
**
|
||||
** If JSON_JSON is set or if more that one PATH argument is supplied then
|
||||
** always return a JSON representation of the result. If JSON_SQL is set,
|
||||
** then always return an SQL representation of the result. If neither flag
|
||||
** is present and argc==2, then return JSON for objects and arrays and SQL
|
||||
** for all other values.
|
||||
**
|
||||
** When multiple PATH arguments are supplied, the result is a JSON array
|
||||
** containing the result of each PATH.
|
||||
**
|
||||
** Abbreviated JSON path expressions are allows if JSON_ABPATH, for
|
||||
** compatibility with PG.
|
||||
*/
|
||||
static void jsonExtractFunc(
|
||||
sqlite3_context *ctx,
|
||||
@ -1588,35 +1539,77 @@ static void jsonExtractFunc(
|
||||
JsonParse *p; /* The parse */
|
||||
JsonNode *pNode;
|
||||
const char *zPath;
|
||||
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
|
||||
JsonString jx;
|
||||
int i;
|
||||
|
||||
if( argc<2 ) return;
|
||||
p = jsonParseCached(ctx, argv, ctx);
|
||||
if( p==0 ) return;
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendChar(&jx, '[');
|
||||
for(i=1; i<argc; i++){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr ) break;
|
||||
if( argc>2 ){
|
||||
if( argc==2 ){
|
||||
/* With a single PATH argument */
|
||||
zPath = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( zPath==0 ) return;
|
||||
if( flags & JSON_ABPATH ){
|
||||
if( zPath[0]!='$' ){
|
||||
/* The -> and ->> operators accept abbreviated PATH arguments. This
|
||||
** is mostly for compatibility with PostgreSQL, but also for
|
||||
** convenience.
|
||||
**
|
||||
** NUMBER ==> $[NUMBER] // PG compatible
|
||||
** LABEL ==> $.LABEL // PG compatible
|
||||
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
|
||||
*/
|
||||
jsonInit(&jx, ctx);
|
||||
if( sqlite3Isdigit(zPath[0]) ){
|
||||
jsonAppendRaw(&jx, "$[", 2);
|
||||
jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
|
||||
jsonAppendRaw(&jx, "]", 2);
|
||||
}else{
|
||||
jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='['));
|
||||
jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
|
||||
jsonAppendChar(&jx, 0);
|
||||
}
|
||||
pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx);
|
||||
jsonReset(&jx);
|
||||
}else{
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
}
|
||||
if( pNode ){
|
||||
if( flags & JSON_JSON ){
|
||||
jsonReturnJson(pNode, ctx, 0);
|
||||
}else{
|
||||
jsonReturn(pNode, ctx, 0);
|
||||
sqlite3_result_subtype(ctx, 0);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0);
|
||||
}
|
||||
}else{
|
||||
/* Two or more PATH arguments results in a JSON array with each
|
||||
** element of the array being the value selected by one of the PATHs */
|
||||
int i;
|
||||
jsonInit(&jx, ctx);
|
||||
jsonAppendChar(&jx, '[');
|
||||
for(i=1; i<argc; i++){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
pNode = jsonLookup(p, zPath, 0, ctx);
|
||||
if( p->nErr ) break;
|
||||
jsonAppendSeparator(&jx);
|
||||
if( pNode ){
|
||||
jsonRenderNode(pNode, &jx, 0);
|
||||
}else{
|
||||
jsonAppendRaw(&jx, "null", 4);
|
||||
}
|
||||
}else if( pNode ){
|
||||
jsonReturn(pNode, ctx, 0);
|
||||
}
|
||||
if( i==argc ){
|
||||
jsonAppendChar(&jx, ']');
|
||||
jsonResult(&jx);
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
jsonReset(&jx);
|
||||
}
|
||||
if( argc>2 && i==argc ){
|
||||
jsonAppendChar(&jx, ']');
|
||||
jsonResult(&jx);
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
jsonReset(&jx);
|
||||
}
|
||||
|
||||
/* This is the RFC 7396 MergePatch algorithm.
|
||||
@ -1712,7 +1705,7 @@ static void jsonPatchFunc(
|
||||
JsonParse y; /* The patch */
|
||||
JsonNode *pResult; /* The result of the merge */
|
||||
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
|
||||
if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
|
||||
jsonParseReset(&x);
|
||||
@ -1833,7 +1826,7 @@ static void jsonReplaceFunc(
|
||||
if( x.nErr ) goto replace_err;
|
||||
if( pNode ){
|
||||
assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
|
||||
json_testcase( pNode->eU!=0 && pNode->eU!=1 );
|
||||
testcase( pNode->eU!=0 && pNode->eU!=1 );
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
VVA( pNode->eU = 4 );
|
||||
pNode->u.iReplace = i + 1;
|
||||
@ -1849,6 +1842,7 @@ replace_err:
|
||||
jsonParseReset(&x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** json_set(JSON, PATH, VALUE, ...)
|
||||
**
|
||||
@ -1871,7 +1865,7 @@ static void jsonSetFunc(
|
||||
const char *zPath;
|
||||
u32 i;
|
||||
int bApnd;
|
||||
int bIsSet = *(int*)sqlite3_user_data(ctx);
|
||||
int bIsSet = sqlite3_user_data(ctx)!=0;
|
||||
|
||||
if( argc<1 ) return;
|
||||
if( (argc&1)==0 ) {
|
||||
@ -1890,8 +1884,8 @@ static void jsonSetFunc(
|
||||
}else if( x.nErr ){
|
||||
goto jsonSetDone;
|
||||
}else if( pNode && (bApnd || bIsSet) ){
|
||||
json_testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 );
|
||||
assert( pNode->eU!=3 || pNode->eU!=5 );
|
||||
testcase( pNode->eU!=0 && pNode->eU!=1 );
|
||||
assert( pNode->eU!=3 && pNode->eU!=5 );
|
||||
VVA( pNode->eU = 4 );
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
pNode->u.iReplace = i + 1;
|
||||
@ -1911,8 +1905,8 @@ jsonSetDone:
|
||||
** json_type(JSON)
|
||||
** json_type(JSON, PATH)
|
||||
**
|
||||
** Return the top-level "type" of a JSON string. Throw an error if
|
||||
** either the JSON or PATH inputs are not well-formed.
|
||||
** Return the top-level "type" of a JSON string. json_type() raises an
|
||||
** error if either the JSON or PATH inputs are not well-formed.
|
||||
*/
|
||||
static void jsonTypeFunc(
|
||||
sqlite3_context *ctx,
|
||||
@ -1948,7 +1942,7 @@ static void jsonValidFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonParse *p; /* The parse */
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
p = jsonParseCached(ctx, argv, 0);
|
||||
sqlite3_result_int(ctx, p!=0);
|
||||
}
|
||||
@ -1968,7 +1962,7 @@ static void jsonArrayStep(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString *pStr;
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
@ -2028,8 +2022,8 @@ static void jsonGroupInverse(
|
||||
char *z;
|
||||
char c;
|
||||
JsonString *pStr;
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAM(argv);
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
#ifdef NEVER
|
||||
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
||||
@ -2073,7 +2067,7 @@ static void jsonObjectStep(
|
||||
JsonString *pStr;
|
||||
const char *z;
|
||||
u32 n;
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(argc);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
@ -2164,10 +2158,10 @@ static int jsonEachConnect(
|
||||
#define JEACH_JSON 8
|
||||
#define JEACH_ROOT 9
|
||||
|
||||
UNUSED_PARAM(pzErr);
|
||||
UNUSED_PARAM(argv);
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAM(pAux);
|
||||
UNUSED_PARAMETER(pzErr);
|
||||
UNUSED_PARAMETER(argv);
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(pAux);
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
|
||||
"json HIDDEN,root HIDDEN)");
|
||||
@ -2190,7 +2184,7 @@ static int jsonEachDisconnect(sqlite3_vtab *pVtab){
|
||||
static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
JsonEachCursor *pCur;
|
||||
|
||||
UNUSED_PARAM(p);
|
||||
UNUSED_PARAMETER(p);
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
@ -2250,7 +2244,7 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
|
||||
p->eType = pUp->eType;
|
||||
if( pUp->eType==JSON_ARRAY ){
|
||||
assert( pUp->eU==0 || pUp->eU==3 );
|
||||
json_testcase( pUp->eU==3 );
|
||||
testcase( pUp->eU==3 );
|
||||
VVA( pUp->eU = 3 );
|
||||
if( iUp==p->i-1 ){
|
||||
pUp->u.iKey = 0;
|
||||
@ -2437,7 +2431,7 @@ static int jsonEachBestIndex(
|
||||
/* This implementation assumes that JSON and ROOT are the last two
|
||||
** columns in the table */
|
||||
assert( JEACH_ROOT == JEACH_JSON+1 );
|
||||
UNUSED_PARAM(tab);
|
||||
UNUSED_PARAMETER(tab);
|
||||
aIdx[0] = aIdx[1] = -1;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
@ -2493,8 +2487,8 @@ static int jsonEachFilter(
|
||||
const char *zRoot = 0;
|
||||
sqlite3_int64 n;
|
||||
|
||||
UNUSED_PARAM(idxStr);
|
||||
UNUSED_PARAM(argc);
|
||||
UNUSED_PARAMETER(idxStr);
|
||||
UNUSED_PARAMETER(argc);
|
||||
jsonEachCursorReset(p);
|
||||
if( idxNum==0 ) return SQLITE_OK;
|
||||
z = (const char*)sqlite3_value_text(argv[0]);
|
||||
@ -2619,103 +2613,63 @@ static sqlite3_module jsonTreeModule = {
|
||||
0 /* xShadowName */
|
||||
};
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
#endif /* !defined(SQLITE_OMIT_JSON) */
|
||||
|
||||
/****************************************************************************
|
||||
** The following routines are the only publically visible identifiers in this
|
||||
** file. Call the following routines in order to register the various SQL
|
||||
** functions and the virtual table implemented by this file.
|
||||
****************************************************************************/
|
||||
|
||||
int sqlite3Json1Init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
static const struct {
|
||||
const char *zName;
|
||||
int nArg;
|
||||
int flag;
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} aFunc[] = {
|
||||
{ "json", 1, 0, jsonRemoveFunc },
|
||||
{ "json_array", -1, 0, jsonArrayFunc },
|
||||
{ "json_array_length", 1, 0, jsonArrayLengthFunc },
|
||||
{ "json_array_length", 2, 0, jsonArrayLengthFunc },
|
||||
{ "json_extract", -1, 0, jsonExtractFunc },
|
||||
{ "json_insert", -1, 0, jsonSetFunc },
|
||||
{ "json_object", -1, 0, jsonObjectFunc },
|
||||
{ "json_patch", 2, 0, jsonPatchFunc },
|
||||
{ "json_quote", 1, 0, jsonQuoteFunc },
|
||||
{ "json_remove", -1, 0, jsonRemoveFunc },
|
||||
{ "json_replace", -1, 0, jsonReplaceFunc },
|
||||
{ "json_set", -1, 1, jsonSetFunc },
|
||||
{ "json_type", 1, 0, jsonTypeFunc },
|
||||
{ "json_type", 2, 0, jsonTypeFunc },
|
||||
{ "json_valid", 1, 0, jsonValidFunc },
|
||||
|
||||
/*
|
||||
** Register JSON functions.
|
||||
*/
|
||||
void sqlite3RegisterJsonFunctions(void){
|
||||
#ifndef SQLITE_OMIT_JSON
|
||||
static FuncDef aJsonFunc[] = {
|
||||
JFUNCTION(json, 1, 0, jsonRemoveFunc),
|
||||
JFUNCTION(json_array, -1, 0, jsonArrayFunc),
|
||||
JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc),
|
||||
JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc),
|
||||
JFUNCTION(json_extract, -1, 0, jsonExtractFunc),
|
||||
JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc),
|
||||
JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc),
|
||||
JFUNCTION(json_insert, -1, 0, jsonSetFunc),
|
||||
JFUNCTION(json_object, -1, 0, jsonObjectFunc),
|
||||
JFUNCTION(json_patch, 2, 0, jsonPatchFunc),
|
||||
JFUNCTION(json_quote, 1, 0, jsonQuoteFunc),
|
||||
JFUNCTION(json_remove, -1, 0, jsonRemoveFunc),
|
||||
JFUNCTION(json_replace, -1, 0, jsonReplaceFunc),
|
||||
JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc),
|
||||
JFUNCTION(json_type, 1, 0, jsonTypeFunc),
|
||||
JFUNCTION(json_type, 2, 0, jsonTypeFunc),
|
||||
JFUNCTION(json_valid, 1, 0, jsonValidFunc),
|
||||
#if SQLITE_DEBUG
|
||||
/* DEBUG and TESTING functions */
|
||||
{ "json_parse", 1, 0, jsonParseFunc },
|
||||
{ "json_test1", 1, 0, jsonTest1Func },
|
||||
JFUNCTION(json_parse, 1, 0, jsonParseFunc),
|
||||
JFUNCTION(json_test1, 1, 0, jsonTest1Func),
|
||||
#endif
|
||||
WAGGREGATE(json_group_array, 1, 0, 0,
|
||||
jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
|
||||
SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS),
|
||||
WAGGREGATE(json_group_object, 2, 0, 0,
|
||||
jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
|
||||
SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
|
||||
};
|
||||
sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
||||
/*
|
||||
** Register the JSON table-valued functions
|
||||
*/
|
||||
int sqlite3JsonTableFunctions(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
static const struct {
|
||||
const char *zName;
|
||||
int nArg;
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
|
||||
void (*xFinal)(sqlite3_context*);
|
||||
void (*xValue)(sqlite3_context*);
|
||||
} aAgg[] = {
|
||||
{ "json_group_array", 1,
|
||||
jsonArrayStep, jsonArrayFinal, jsonArrayValue },
|
||||
{ "json_group_object", 2,
|
||||
jsonObjectStep, jsonObjectFinal, jsonObjectValue },
|
||||
};
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
static const struct {
|
||||
const char *zName;
|
||||
sqlite3_module *pModule;
|
||||
const char *zName;
|
||||
sqlite3_module *pModule;
|
||||
} aMod[] = {
|
||||
{ "json_each", &jsonEachModule },
|
||||
{ "json_tree", &jsonTreeModule },
|
||||
};
|
||||
#endif
|
||||
static const int enc =
|
||||
SQLITE_UTF8 |
|
||||
SQLITE_DETERMINISTIC |
|
||||
SQLITE_INNOCUOUS;
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, enc,
|
||||
(void*)&aFunc[i].flag,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
|
||||
SQLITE_SUBTYPE | enc, 0,
|
||||
aAgg[i].xStep, aAgg[i].xFinal,
|
||||
aAgg[i].xValue, jsonGroupInverse, 0);
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
unsigned int i;
|
||||
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_json_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return sqlite3Json1Init(db);
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */
|
||||
@ -485,6 +485,13 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_total_changes64,
|
||||
/* Version 3.37.0 and later */
|
||||
sqlite3_autovacuum_pages,
|
||||
/* Version 3.38.0 and later */
|
||||
sqlite3_error_offset,
|
||||
sqlite3_vtab_rhs_value,
|
||||
sqlite3_vtab_distinct,
|
||||
sqlite3_vtab_in,
|
||||
sqlite3_vtab_in_first,
|
||||
sqlite3_vtab_in_next
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
72
src/main.c
72
src/main.c
@ -50,9 +50,6 @@ int sqlite3Fts2Init(sqlite3*);
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
int sqlite3Fts5Init(sqlite3*);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
int sqlite3Json1Init(sqlite3*);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMTVTAB
|
||||
int sqlite3StmtVtabInit(sqlite3*);
|
||||
#endif
|
||||
@ -87,8 +84,8 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
|
||||
sqlite3DbstatRegister,
|
||||
#endif
|
||||
sqlite3TestExtInit,
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
sqlite3Json1Init,
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
||||
sqlite3JsonTableFunctions,
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMTVTAB
|
||||
sqlite3StmtVtabInit,
|
||||
@ -2597,6 +2594,19 @@ const char *sqlite3_errmsg(sqlite3 *db){
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the byte offset of the most recent error
|
||||
*/
|
||||
int sqlite3_error_offset(sqlite3 *db){
|
||||
int iOffset = -1;
|
||||
if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
iOffset = db->errByteOffset;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
return iOffset;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/*
|
||||
** Return UTF-16 encoded English language explanation of the most recent
|
||||
@ -4068,12 +4078,16 @@ int sqlite3_test_control(int op, ...){
|
||||
** sqlite3_test_control().
|
||||
*/
|
||||
case SQLITE_TESTCTRL_FAULT_INSTALL: {
|
||||
/* MSVC is picky about pulling func ptrs from va lists.
|
||||
** http://support.microsoft.com/kb/47961
|
||||
/* A bug in MSVC prevents it from understanding pointers to functions
|
||||
** types in the second argument to va_arg(). Work around the problem
|
||||
** using a typedef.
|
||||
** http://support.microsoft.com/kb/47961 <-- dead hyperlink
|
||||
** Search at http://web.archive.org/ to find the 2015-03-16 archive
|
||||
** of the link above to see the original text.
|
||||
** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
|
||||
*/
|
||||
typedef int(*TESTCALLBACKFUNC_t)(int);
|
||||
sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
|
||||
typedef int(*sqlite3FaultFuncType)(int);
|
||||
sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType);
|
||||
rc = sqlite3FaultSim(0);
|
||||
break;
|
||||
}
|
||||
@ -4200,13 +4214,27 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
|
||||
**
|
||||
** If parameter onoff is non-zero, subsequent calls to localtime()
|
||||
** and its variants fail. If onoff is zero, undo this setting.
|
||||
** If parameter onoff is 1, subsequent calls to localtime() fail.
|
||||
** If 2, then invoke xAlt() instead of localtime(). If 0, normal
|
||||
** processing.
|
||||
**
|
||||
** xAlt arguments are void pointers, but they really want to be:
|
||||
**
|
||||
** int xAlt(const time_t*, struct tm*);
|
||||
**
|
||||
** xAlt should write results in to struct tm object of its 2nd argument
|
||||
** and return zero on success, or return non-zero on failure.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
||||
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
|
||||
if( sqlite3GlobalConfig.bLocaltimeFault==2 ){
|
||||
typedef int(*sqlite3LocaltimeType)(const void*,void*);
|
||||
sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType);
|
||||
}else{
|
||||
sqlite3GlobalConfig.xAltLocaltime = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4396,6 +4424,26 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
|
||||
** double fIn, // Input value
|
||||
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
|
||||
** u64 *pInt, // sqlite3LogEstToInt(*pLogEst)
|
||||
** int *pLogEst2 // sqlite3LogEst(*pInt)
|
||||
** );
|
||||
**
|
||||
** Test access for the LogEst conversion routines.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_LOGEST: {
|
||||
double rIn = va_arg(ap, double);
|
||||
LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
|
||||
u64 iInt = sqlite3LogEstToInt(rLogEst);
|
||||
va_arg(ap, int*)[0] = rLogEst;
|
||||
va_arg(ap, u64*)[0] = iInt;
|
||||
va_arg(ap, int*)[0] = sqlite3LogEst(iInt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
|
||||
**
|
||||
|
||||
11
src/malloc.c
11
src/malloc.c
@ -770,8 +770,15 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
|
||||
** has happened. This routine will set db->mallocFailed, and also
|
||||
** temporarily disable the lookaside memory allocator and interrupt
|
||||
** any running VDBEs.
|
||||
**
|
||||
** Always return a NULL pointer so that this routine can be invoked using
|
||||
**
|
||||
** return sqlite3OomFault(db);
|
||||
**
|
||||
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
|
||||
** common case where no OOM occurs.
|
||||
*/
|
||||
void sqlite3OomFault(sqlite3 *db){
|
||||
void *sqlite3OomFault(sqlite3 *db){
|
||||
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
|
||||
db->mallocFailed = 1;
|
||||
if( db->nVdbeExec>0 ){
|
||||
@ -779,9 +786,11 @@ void sqlite3OomFault(sqlite3 *db){
|
||||
}
|
||||
DisableLookaside;
|
||||
if( db->pParse ){
|
||||
sqlite3ErrorMsg(db->pParse, "out of memory");
|
||||
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -178,6 +178,9 @@ static int memjrnlCreateFile(MemJournal *p){
|
||||
}
|
||||
|
||||
|
||||
/* Forward reference */
|
||||
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size);
|
||||
|
||||
/*
|
||||
** Write data to the file.
|
||||
*/
|
||||
@ -207,23 +210,21 @@ static int memjrnlWrite(
|
||||
** access writes are not required. The only exception to this is when
|
||||
** the in-memory journal is being used by a connection using the
|
||||
** atomic-write optimization. In this case the first 28 bytes of the
|
||||
** journal file may be written as part of committing the transaction. */
|
||||
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
|
||||
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|
||||
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
||||
** journal file may be written as part of committing the transaction. */
|
||||
assert( iOfst<=p->endpoint.iOffset );
|
||||
if( iOfst>0 && iOfst!=p->endpoint.iOffset ){
|
||||
memjrnlTruncate(pJfd, iOfst);
|
||||
}
|
||||
if( iOfst==0 && p->pFirst ){
|
||||
assert( p->nChunkSize>iAmt );
|
||||
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
|
||||
}else
|
||||
#else
|
||||
assert( iOfst>0 || p->pFirst==0 );
|
||||
#endif
|
||||
{
|
||||
}else{
|
||||
while( nWrite>0 ){
|
||||
FileChunk *pChunk = p->endpoint.pChunk;
|
||||
int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
|
||||
int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset);
|
||||
|
||||
assert( pChunk!=0 || iChunkOffset==0 );
|
||||
if( iChunkOffset==0 ){
|
||||
/* New chunk is required to extend the file. */
|
||||
FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize));
|
||||
@ -238,10 +239,11 @@ static int memjrnlWrite(
|
||||
assert( !p->pFirst );
|
||||
p->pFirst = pNew;
|
||||
}
|
||||
p->endpoint.pChunk = pNew;
|
||||
pChunk = p->endpoint.pChunk = pNew;
|
||||
}
|
||||
|
||||
memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace);
|
||||
assert( pChunk!=0 );
|
||||
memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace);
|
||||
zWrite += iSpace;
|
||||
nWrite -= iSpace;
|
||||
p->endpoint.iOffset += iSpace;
|
||||
|
||||
@ -4910,11 +4910,17 @@ static int unixShmLock(
|
||||
int flags /* What to do with the lock */
|
||||
){
|
||||
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
|
||||
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
|
||||
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
|
||||
unixShm *p; /* The shared memory being locked */
|
||||
unixShmNode *pShmNode; /* The underlying file iNode */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
u16 mask; /* Mask of locks to take or release */
|
||||
int *aLock = pShmNode->aLock;
|
||||
int *aLock;
|
||||
|
||||
p = pDbFd->pShm;
|
||||
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
|
||||
pShmNode = p->pShmNode;
|
||||
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
|
||||
aLock = pShmNode->aLock;
|
||||
|
||||
assert( pShmNode==pDbFd->pInode->pShmNode );
|
||||
assert( pShmNode->pInode==pDbFd->pInode );
|
||||
|
||||
@ -4070,10 +4070,14 @@ static int winShmLock(
|
||||
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
|
||||
winShm *p = pDbFd->pShm; /* The shared memory being locked */
|
||||
winShm *pX; /* For looping over all siblings */
|
||||
winShmNode *pShmNode = p->pShmNode;
|
||||
winShmNode *pShmNode;
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
u16 mask; /* Mask of locks to take or release */
|
||||
|
||||
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
|
||||
pShmNode = p->pShmNode;
|
||||
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
|
||||
|
||||
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
||||
assert( n>=1 );
|
||||
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
||||
|
||||
43
src/pager.c
43
src/pager.c
@ -2945,6 +2945,9 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
goto end_playback;
|
||||
}
|
||||
pPager->dbSize = mxPg;
|
||||
if( pPager->mxPgno<mxPg ){
|
||||
pPager->mxPgno = mxPg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy original pages out of the journal and back into the
|
||||
@ -4004,8 +4007,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
||||
** current database image, in pages, OR
|
||||
**
|
||||
** b) if the page content were written at this time, it would not
|
||||
** be necessary to write the current content out to the sub-journal
|
||||
** (as determined by function subjRequiresPage()).
|
||||
** be necessary to write the current content out to the sub-journal.
|
||||
**
|
||||
** If the condition asserted by this function were not true, and the
|
||||
** dirty page were to be discarded from the cache via the pagerStress()
|
||||
@ -4020,8 +4022,16 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG)
|
||||
static void assertTruncateConstraintCb(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
assert( pPg->flags&PGHDR_DIRTY );
|
||||
assert( pPg->pgno<=pPg->pPager->dbSize || !subjRequiresPage(pPg) );
|
||||
if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */
|
||||
Pgno pgno = pPg->pgno;
|
||||
int i;
|
||||
for(i=0; i<pPg->pPager->nSavepoint; i++){
|
||||
PagerSavepoint *p = &pPager->aSavepoint[i];
|
||||
assert( p->nOrig<pgno || sqlite3BitvecTestNotNull(p->pInSavepoint,pgno) );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void assertTruncateConstraint(Pager *pPager){
|
||||
sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
|
||||
@ -4043,7 +4053,6 @@ static void assertTruncateConstraint(Pager *pPager){
|
||||
*/
|
||||
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
|
||||
assert( pPager->dbSize>=nPage || CORRUPT_DB );
|
||||
testcase( pPager->dbSize<nPage );
|
||||
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
|
||||
pPager->dbSize = nPage;
|
||||
|
||||
@ -5785,6 +5794,7 @@ int sqlite3PagerGet(
|
||||
DbPage **ppPage, /* Write a pointer to the page here */
|
||||
int flags /* PAGER_GET_XXX flags */
|
||||
){
|
||||
/* printf("PAGE %u\n", pgno); fflush(stdout); */
|
||||
return pPager->xGet(pPager, pgno, ppPage, flags);
|
||||
}
|
||||
|
||||
@ -7433,12 +7443,12 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
||||
u8 eOld = pPager->journalMode; /* Prior journalmode */
|
||||
|
||||
/* The eMode parameter is always valid */
|
||||
assert( eMode==PAGER_JOURNALMODE_DELETE
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| eMode==PAGER_JOURNALMODE_OFF
|
||||
|| eMode==PAGER_JOURNALMODE_WAL
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY );
|
||||
assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST /* 1 */
|
||||
|| eMode==PAGER_JOURNALMODE_OFF /* 2 */
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY /* 4 */
|
||||
|| eMode==PAGER_JOURNALMODE_WAL /* 5 */ );
|
||||
|
||||
/* This routine is only called from the OP_JournalMode opcode, and
|
||||
** the logic there will never allow a temporary file to be changed
|
||||
@ -7475,7 +7485,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
||||
|
||||
assert( isOpen(pPager->fd) || pPager->exclusiveMode );
|
||||
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
|
||||
|
||||
/* In this case we would like to delete the journal file. If it is
|
||||
** not possible, then that is not a problem. Deleting the journal file
|
||||
** here is an optimization only.
|
||||
@ -7587,6 +7596,18 @@ int sqlite3PagerCheckpoint(
|
||||
int *pnCkpt /* OUT: Final number of checkpointed frames */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
||||
/* This only happens when a database file is zero bytes in size opened and
|
||||
** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint()
|
||||
** is invoked without any intervening transactions. We need to start
|
||||
** a transaction to initialize pWal. The PRAGMA table_list statement is
|
||||
** used for this since it starts transactions on every database file,
|
||||
** including all ATTACHed databases. This seems expensive for a single
|
||||
** sqlite3_wal_checkpoint() call, but it happens very rarely.
|
||||
** https://sqlite.org/forum/forumpost/fd0f19d229156939
|
||||
*/
|
||||
sqlite3_exec(db, "PRAGMA table_list",0,0,0);
|
||||
}
|
||||
if( pPager->pWal ){
|
||||
rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
|
||||
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
|
||||
|
||||
36
src/parse.y
36
src/parse.y
@ -286,7 +286,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
|
||||
%left BITAND BITOR LSHIFT RSHIFT.
|
||||
%left PLUS MINUS.
|
||||
%left STAR SLASH REM.
|
||||
%left CONCAT.
|
||||
%left CONCAT PTR.
|
||||
%left COLLATE.
|
||||
%right BITNOT.
|
||||
%nonassoc ON.
|
||||
@ -659,7 +659,7 @@ selcollist(A) ::= sclp(A) scanpt STAR. {
|
||||
}
|
||||
selcollist(A) ::= sclp(A) scanpt nm(X) DOT STAR. {
|
||||
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
|
||||
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
|
||||
Expr *pLeft = tokenExpr(pParse, TK_ID, X);
|
||||
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
|
||||
A = sqlite3ExprListAppend(pParse,A, pDot);
|
||||
}
|
||||
@ -1025,10 +1025,7 @@ idlist(A) ::= nm(Y).
|
||||
|
||||
%include {
|
||||
|
||||
/* Construct a new Expr object from a single identifier. Use the
|
||||
** new Expr to populate pOut. Set the span of pOut to be the identifier
|
||||
** that created the expression.
|
||||
*/
|
||||
/* Construct a new Expr object from a single token */
|
||||
static Expr *tokenExpr(Parse *pParse, int op, Token t){
|
||||
Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
|
||||
if( p ){
|
||||
@ -1048,6 +1045,7 @@ idlist(A) ::= nm(Y).
|
||||
p->u.zToken = (char*)&p[1];
|
||||
memcpy(p->u.zToken, t.z, t.n);
|
||||
p->u.zToken[t.n] = 0;
|
||||
p->w.iOfst = (int)(t.z - pParse->zTail);
|
||||
if( sqlite3Isquote(p->u.zToken[0]) ){
|
||||
sqlite3DequoteExpr(p);
|
||||
}
|
||||
@ -1068,22 +1066,17 @@ expr(A) ::= LP expr(X) RP. {A = X;}
|
||||
expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
|
||||
expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/}
|
||||
expr(A) ::= nm(X) DOT nm(Y). {
|
||||
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
|
||||
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenMap(pParse, (void*)temp2, &Y);
|
||||
sqlite3RenameTokenMap(pParse, (void*)temp1, &X);
|
||||
}
|
||||
Expr *temp1 = tokenExpr(pParse,TK_ID,X);
|
||||
Expr *temp2 = tokenExpr(pParse,TK_ID,Y);
|
||||
A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
|
||||
}
|
||||
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
|
||||
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
|
||||
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
|
||||
Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1);
|
||||
Expr *temp1 = tokenExpr(pParse,TK_ID,X);
|
||||
Expr *temp2 = tokenExpr(pParse,TK_ID,Y);
|
||||
Expr *temp3 = tokenExpr(pParse,TK_ID,Z);
|
||||
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenMap(pParse, (void*)temp3, &Z);
|
||||
sqlite3RenameTokenMap(pParse, (void*)temp2, &Y);
|
||||
sqlite3RenameTokenRemap(pParse, 0, temp1);
|
||||
}
|
||||
A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
|
||||
}
|
||||
@ -1091,6 +1084,7 @@ term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
|
||||
term(A) ::= STRING(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/}
|
||||
term(A) ::= INTEGER(X). {
|
||||
A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
|
||||
if( A ) A->w.iOfst = (int)(X.z - pParse->zTail);
|
||||
}
|
||||
expr(A) ::= VARIABLE(X). {
|
||||
if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
|
||||
@ -1235,6 +1229,12 @@ expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] {
|
||||
/*A-overwrites-B*/
|
||||
}
|
||||
|
||||
expr(A) ::= expr(B) PTR(C) expr(D). {
|
||||
ExprList *pList = sqlite3ExprListAppend(pParse, 0, B);
|
||||
pList = sqlite3ExprListAppend(pParse, pList, D);
|
||||
A = sqlite3ExprFunction(pParse, pList, &C, 0);
|
||||
}
|
||||
|
||||
%type between_op {int}
|
||||
between_op(A) ::= BETWEEN. {A = 0;}
|
||||
between_op(A) ::= NOT BETWEEN. {A = 1;}
|
||||
@ -1587,7 +1587,7 @@ expr(A) ::= RAISE LP IGNORE RP. {
|
||||
}
|
||||
}
|
||||
expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. {
|
||||
A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
|
||||
A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
|
||||
if( A ) {
|
||||
A->affExpr = (char)T;
|
||||
}
|
||||
|
||||
@ -551,7 +551,8 @@ void sqlite3PcacheDrop(PgHdr *p){
|
||||
** make it so.
|
||||
*/
|
||||
void sqlite3PcacheMakeDirty(PgHdr *p){
|
||||
assert( p->nRef>0 );
|
||||
assert( p->nRef>0 || p->pCache->bPurgeable==0 );
|
||||
testcase( p->nRef==0 );
|
||||
assert( sqlite3PcachePageSanity(p) );
|
||||
if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
p->flags &= ~PGHDR_DONT_WRITE;
|
||||
|
||||
@ -1265,6 +1265,10 @@ void sqlite3Pragma(
|
||||
(void)sqlite3_finalize(pDummy);
|
||||
sqlite3DbFree(db, zSql);
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
sqlite3ErrorMsg(db->pParse, "out of memory");
|
||||
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pHash = &db->aDb[ii].pSchema->tblHash;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -389,7 +389,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
pDb = &db->aDb[iDb];
|
||||
}else
|
||||
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
|
||||
if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
|
||||
/* Hack: If the SQLITE_NoSchemaError flag is set, then consider
|
||||
** the schema loaded, even if errors (other than OOM) occurred. In
|
||||
** this situation the current sqlite3_prepare() operation will fail,
|
||||
@ -568,8 +568,14 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
|
||||
/*
|
||||
** Free all memory allocations in the pParse object
|
||||
*/
|
||||
void sqlite3ParserReset(Parse *pParse){
|
||||
void sqlite3ParseObjectReset(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( db!=0 );
|
||||
assert( db->pParse==pParse );
|
||||
assert( pParse->nested==0 );
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
sqlite3DbFree(db, pParse->aTableLock);
|
||||
#endif
|
||||
while( pParse->pCleanup ){
|
||||
ParseCleanup *pCleanup = pParse->pCleanup;
|
||||
pParse->pCleanup = pCleanup->pNext;
|
||||
@ -580,11 +586,12 @@ void sqlite3ParserReset(Parse *pParse){
|
||||
if( pParse->pConstExpr ){
|
||||
sqlite3ExprListDelete(db, pParse->pConstExpr);
|
||||
}
|
||||
if( db ){
|
||||
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
||||
db->lookaside.bDisable -= pParse->disableLookaside;
|
||||
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
|
||||
}
|
||||
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
||||
db->lookaside.bDisable -= pParse->disableLookaside;
|
||||
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
|
||||
assert( pParse->db->pParse==pParse );
|
||||
db->pParse = pParse->pOuterParse;
|
||||
pParse->db = 0;
|
||||
pParse->disableLookaside = 0;
|
||||
}
|
||||
|
||||
@ -597,7 +604,7 @@ void sqlite3ParserReset(Parse *pParse){
|
||||
** cost for this mechansim (an extra malloc), so it should not be used
|
||||
** for common cleanups that happen on most calls. But for less
|
||||
** common cleanups, we save a single NULL-pointer comparison in
|
||||
** sqlite3ParserReset(), which reduces the total CPU cycle count.
|
||||
** sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
|
||||
**
|
||||
** If a memory allocation error occurs, then the cleanup happens immediately.
|
||||
** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
|
||||
@ -637,6 +644,25 @@ void *sqlite3ParserAddCleanup(
|
||||
return pPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn bulk memory into a valid Parse object and link that Parse object
|
||||
** into database connection db.
|
||||
**
|
||||
** Call sqlite3ParseObjectReset() to undo this operation.
|
||||
**
|
||||
** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which
|
||||
** is generated by Lemon.
|
||||
*/
|
||||
void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
|
||||
memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
|
||||
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
|
||||
assert( db->pParse!=pParse );
|
||||
pParse->pOuterParse = db->pParse;
|
||||
db->pParse = pParse;
|
||||
pParse->db = db;
|
||||
if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory");
|
||||
}
|
||||
|
||||
/*
|
||||
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
|
||||
*/
|
||||
@ -649,16 +675,19 @@ static int sqlite3Prepare(
|
||||
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
){
|
||||
char *zErrMsg = 0; /* Error message */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
int i; /* Loop counter */
|
||||
Parse sParse; /* Parsing context */
|
||||
|
||||
memset(&sParse, 0, PARSE_HDR_SZ);
|
||||
/* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
|
||||
memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
|
||||
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
|
||||
sParse.pOuterParse = db->pParse;
|
||||
db->pParse = &sParse;
|
||||
sParse.db = db;
|
||||
sParse.pReprepare = pReprepare;
|
||||
assert( ppStmt && *ppStmt==0 );
|
||||
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
|
||||
if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory");
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
||||
/* For a long-term use prepared statement avoid the use of
|
||||
@ -711,7 +740,6 @@ static int sqlite3Prepare(
|
||||
|
||||
sqlite3VtabUnlockList(db);
|
||||
|
||||
sParse.db = db;
|
||||
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
|
||||
char *zSqlCopy;
|
||||
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
|
||||
@ -724,14 +752,14 @@ static int sqlite3Prepare(
|
||||
}
|
||||
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
|
||||
if( zSqlCopy ){
|
||||
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
|
||||
sqlite3RunParser(&sParse, zSqlCopy);
|
||||
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
|
||||
sqlite3DbFree(db, zSqlCopy);
|
||||
}else{
|
||||
sParse.zTail = &zSql[nBytes];
|
||||
}
|
||||
}else{
|
||||
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
||||
sqlite3RunParser(&sParse, zSql);
|
||||
}
|
||||
assert( 0==sParse.nQueryLoop );
|
||||
|
||||
@ -755,14 +783,14 @@ static int sqlite3Prepare(
|
||||
}
|
||||
assert( 0==(*ppStmt) );
|
||||
rc = sParse.rc;
|
||||
if( zErrMsg ){
|
||||
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
if( sParse.zErrMsg ){
|
||||
sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg);
|
||||
sqlite3DbFree(db, sParse.zErrMsg);
|
||||
}else{
|
||||
sqlite3Error(db, rc);
|
||||
}
|
||||
}else{
|
||||
assert( zErrMsg==0 );
|
||||
assert( sParse.zErrMsg==0 );
|
||||
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
|
||||
rc = SQLITE_OK;
|
||||
sqlite3ErrorClear(db);
|
||||
@ -778,7 +806,7 @@ static int sqlite3Prepare(
|
||||
|
||||
end_prepare:
|
||||
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
return rc;
|
||||
}
|
||||
static int sqlite3LockAndPrepare(
|
||||
|
||||
58
src/printf.c
58
src/printf.c
@ -849,12 +849,22 @@ void sqlite3_str_vappendf(
|
||||
goto adjust_width_for_utf8;
|
||||
}
|
||||
case etTOKEN: {
|
||||
Token *pToken;
|
||||
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
|
||||
pToken = va_arg(ap, Token*);
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
||||
if( flag_alternateform ){
|
||||
/* %#T means an Expr pointer that uses Expr.u.zToken */
|
||||
Expr *pExpr = va_arg(ap,Expr*);
|
||||
if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
|
||||
sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
|
||||
sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
|
||||
}
|
||||
}else{
|
||||
/* %T means a Token pointer */
|
||||
Token *pToken = va_arg(ap, Token*);
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
||||
sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
|
||||
}
|
||||
}
|
||||
length = width = 0;
|
||||
break;
|
||||
@ -909,6 +919,42 @@ void sqlite3_str_vappendf(
|
||||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
|
||||
/*
|
||||
** The z string points to the first character of a token that is
|
||||
** associated with an error. If db does not already have an error
|
||||
** byte offset recorded, try to compute the error byte offset for
|
||||
** z and set the error byte offset in db.
|
||||
*/
|
||||
void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
|
||||
const Parse *pParse;
|
||||
const char *zText;
|
||||
const char *zEnd;
|
||||
assert( z!=0 );
|
||||
if( NEVER(db==0) ) return;
|
||||
if( db->errByteOffset!=(-2) ) return;
|
||||
pParse = db->pParse;
|
||||
if( NEVER(pParse==0) ) return;
|
||||
zText =pParse->zTail;
|
||||
if( NEVER(zText==0) ) return;
|
||||
zEnd = &zText[strlen(zText)];
|
||||
if( SQLITE_WITHIN(z,zText,zEnd) ){
|
||||
db->errByteOffset = (int)(z-zText);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If pExpr has a byte offset for the start of a token, record that as
|
||||
** as the error offset.
|
||||
*/
|
||||
void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
|
||||
while( pExpr && (ExprHasProperty(pExpr,EP_FromJoin) || pExpr->w.iOfst<=0) ){
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
if( pExpr==0 ) return;
|
||||
db->errByteOffset = pExpr->w.iOfst;
|
||||
}
|
||||
|
||||
/*
|
||||
** Enlarge the memory allocation on a StrAccum object so that it is
|
||||
** able to accept at least N more bytes of text.
|
||||
@ -916,7 +962,7 @@ void sqlite3_str_vappendf(
|
||||
** Return the number of bytes of text that StrAccum is able to accept
|
||||
** after the attempted enlargement. The value returned might be zero.
|
||||
*/
|
||||
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
|
||||
@ -320,8 +320,9 @@ static int lookupName(
|
||||
}
|
||||
if( hit || zTab==0 ) continue;
|
||||
}
|
||||
if( zDb && pTab->pSchema!=pSchema ){
|
||||
continue;
|
||||
if( zDb ){
|
||||
if( pTab->pSchema!=pSchema ) continue;
|
||||
if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue;
|
||||
}
|
||||
if( zTab ){
|
||||
const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
|
||||
@ -452,6 +453,7 @@ static int lookupName(
|
||||
pExpr->y.pTab = pTab;
|
||||
if( pParse->bReturning ){
|
||||
eNewExprOp = TK_REGISTER;
|
||||
pExpr->op2 = TK_COLUMN;
|
||||
pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
|
||||
sqlite3TableColumnToStorage(pTab, iCol) + 1;
|
||||
}else{
|
||||
@ -618,6 +620,7 @@ static int lookupName(
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
|
||||
}
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
|
||||
pParse->checkSchema = 1;
|
||||
pTopNC->nNcErr++;
|
||||
}
|
||||
@ -726,7 +729,8 @@ static void notValidImpl(
|
||||
Parse *pParse, /* Leave error message here */
|
||||
NameContext *pNC, /* The name context */
|
||||
const char *zMsg, /* Type of error */
|
||||
Expr *pExpr /* Invalidate this expression on error */
|
||||
Expr *pExpr, /* Invalidate this expression on error */
|
||||
Expr *pError /* Associate error with this expression */
|
||||
){
|
||||
const char *zIn = "partial index WHERE clauses";
|
||||
if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
|
||||
@ -738,10 +742,11 @@ static void notValidImpl(
|
||||
#endif
|
||||
sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
|
||||
if( pExpr ) pExpr->op = TK_NULL;
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
|
||||
}
|
||||
#define sqlite3ResolveNotValid(P,N,M,X,E) \
|
||||
#define sqlite3ResolveNotValid(P,N,M,X,E,R) \
|
||||
assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
|
||||
if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E);
|
||||
if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R);
|
||||
|
||||
/*
|
||||
** Expression p should encode a floating point value between 1.0 and 0.0.
|
||||
@ -876,7 +881,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pNC->ncFlags & NC_IdxExpr );
|
||||
testcase( pNC->ncFlags & NC_GenCol );
|
||||
sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
|
||||
NC_IdxExpr|NC_GenCol, 0);
|
||||
NC_IdxExpr|NC_GenCol, 0, pExpr);
|
||||
pRight = pExpr->pRight;
|
||||
if( pRight->op==TK_ID ){
|
||||
zDb = 0;
|
||||
@ -907,7 +912,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
int no_such_func = 0; /* True if no such function exists */
|
||||
int wrong_num_args = 0; /* True if wrong number of arguments */
|
||||
int is_agg = 0; /* True if is an aggregate function */
|
||||
int nId; /* Number of characters in function name */
|
||||
const char *zId; /* The function name. */
|
||||
FuncDef *pDef; /* Information about the function */
|
||||
u8 enc = ENC(pParse->db); /* The database encoding */
|
||||
@ -917,7 +921,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
#endif
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
|
||||
zId = pExpr->u.zToken;
|
||||
nId = sqlite3Strlen30(zId);
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
|
||||
if( pDef==0 ){
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
|
||||
@ -934,8 +937,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
pExpr->iTable = exprProbability(pList->a[1].pExpr);
|
||||
if( pExpr->iTable<0 ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"second argument to likelihood() must be a "
|
||||
"constant between 0.0 and 1.0");
|
||||
"second argument to %#T() must be a "
|
||||
"constant between 0.0 and 1.0", pExpr);
|
||||
pNC->nNcErr++;
|
||||
}
|
||||
}else{
|
||||
@ -956,8 +959,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
|
||||
if( auth!=SQLITE_OK ){
|
||||
if( auth==SQLITE_DENY ){
|
||||
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
|
||||
pDef->zName);
|
||||
sqlite3ErrorMsg(pParse, "not authorized to use function: %#T",
|
||||
pExpr);
|
||||
pNC->nNcErr++;
|
||||
}
|
||||
pExpr->op = TK_NULL;
|
||||
@ -980,7 +983,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
|
||||
** all this. */
|
||||
sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
|
||||
NC_IdxExpr|NC_PartIdx|NC_GenCol, 0);
|
||||
NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
|
||||
}else{
|
||||
assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
|
||||
pExpr->op2 = pNC->ncFlags & NC_SelfRef;
|
||||
@ -993,7 +996,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* Internal-use-only functions are disallowed unless the
|
||||
** SQL is being compiled using sqlite3NestedParse() or
|
||||
** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
|
||||
** used to activate internal functionsn for testing purposes */
|
||||
** used to activate internal functions for testing purposes */
|
||||
no_such_func = 1;
|
||||
pDef = 0;
|
||||
}else
|
||||
@ -1012,7 +1015,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
);
|
||||
if( pDef && pDef->xValue==0 && pWin ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"%.*s() may not be used as a window function", nId, zId
|
||||
"%#T() may not be used as a window function", pExpr
|
||||
);
|
||||
pNC->nNcErr++;
|
||||
}else if(
|
||||
@ -1026,13 +1029,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}else{
|
||||
zType = "aggregate";
|
||||
}
|
||||
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
|
||||
sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr);
|
||||
pNC->nNcErr++;
|
||||
is_agg = 0;
|
||||
}
|
||||
#else
|
||||
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
|
||||
sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
|
||||
sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr);
|
||||
pNC->nNcErr++;
|
||||
is_agg = 0;
|
||||
}
|
||||
@ -1042,18 +1045,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
&& pParse->explain==0
|
||||
#endif
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
|
||||
sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
|
||||
pNC->nNcErr++;
|
||||
}else if( wrong_num_args ){
|
||||
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
|
||||
nId, zId);
|
||||
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()",
|
||||
pExpr);
|
||||
pNC->nNcErr++;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"FILTER may not be used with non-aggregate %.*s()",
|
||||
nId, zId
|
||||
"FILTER may not be used with non-aggregate %#T()",
|
||||
pExpr
|
||||
);
|
||||
pNC->nNcErr++;
|
||||
}
|
||||
@ -1138,7 +1141,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pNC->ncFlags & NC_IdxExpr );
|
||||
testcase( pNC->ncFlags & NC_GenCol );
|
||||
if( pNC->ncFlags & NC_SelfRef ){
|
||||
notValidImpl(pParse, pNC, "subqueries", pExpr);
|
||||
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
|
||||
}else{
|
||||
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
|
||||
}
|
||||
@ -1156,7 +1159,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pNC->ncFlags & NC_IdxExpr );
|
||||
testcase( pNC->ncFlags & NC_GenCol );
|
||||
sqlite3ResolveNotValid(pParse, pNC, "parameters",
|
||||
NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
|
||||
NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr);
|
||||
break;
|
||||
}
|
||||
case TK_IS:
|
||||
@ -1208,11 +1211,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_ISNOT );
|
||||
testcase( pExpr->op==TK_BETWEEN );
|
||||
sqlite3ErrorMsg(pParse, "row value misused");
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
|
||||
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
|
||||
return pParse->nErr ? WRC_Abort : WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1320,11 +1325,13 @@ static void resolveOutOfRangeError(
|
||||
Parse *pParse, /* The error context into which to write the error */
|
||||
const char *zType, /* "ORDER" or "GROUP" */
|
||||
int i, /* The index (1-based) of the term out of range */
|
||||
int mx /* Largest permissible value of i */
|
||||
int mx, /* Largest permissible value of i */
|
||||
Expr *pError /* Associate the error with the expression */
|
||||
){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"%r %s BY term out of range - should be "
|
||||
"between 1 and %d", i, zType, mx);
|
||||
sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1380,7 +1387,7 @@ static int resolveCompoundOrderBy(
|
||||
if( NEVER(pE==0) ) continue;
|
||||
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
||||
if( iCol<=0 || iCol>pEList->nExpr ){
|
||||
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
|
||||
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
|
||||
return 1;
|
||||
}
|
||||
}else{
|
||||
@ -1476,7 +1483,7 @@ int sqlite3ResolveOrderGroupBy(
|
||||
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
||||
if( pItem->u.x.iOrderByCol ){
|
||||
if( pItem->u.x.iOrderByCol>pEList->nExpr ){
|
||||
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
|
||||
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0);
|
||||
return 1;
|
||||
}
|
||||
resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
|
||||
@ -1568,7 +1575,7 @@ static int resolveOrderGroupBy(
|
||||
** number so that sqlite3ResolveOrderGroupBy() will convert the
|
||||
** order-by term to a copy of the result-set expression */
|
||||
if( iCol<1 || iCol>0xffff ){
|
||||
resolveOutOfRangeError(pParse, zType, i+1, nResult);
|
||||
resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
|
||||
return 1;
|
||||
}
|
||||
pItem->u.x.iOrderByCol = (u16)iCol;
|
||||
@ -1626,7 +1633,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
*/
|
||||
if( (p->selFlags & SF_Expanded)==0 ){
|
||||
sqlite3SelectPrep(pParse, p, pOuterNC);
|
||||
return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
|
||||
return pParse->nErr ? WRC_Abort : WRC_Prune;
|
||||
}
|
||||
|
||||
isCompound = p->pPrior!=0;
|
||||
@ -1674,7 +1681,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
|
||||
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
|
||||
pParse->zAuthContext = zSavedContext;
|
||||
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
|
||||
if( pParse->nErr ) return WRC_Abort;
|
||||
assert( db->mallocFailed==0 );
|
||||
|
||||
/* If the number of references to the outer context changed when
|
||||
** expressions in the sub-select were resolved, the sub-select
|
||||
|
||||
109
src/select.c
109
src/select.c
@ -354,14 +354,14 @@ static void addWhereTerm(
|
||||
ExprSetProperty(pEq, EP_FromJoin);
|
||||
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(pEq, EP_NoReduce);
|
||||
pEq->iRightJoinTable = pE2->iTable;
|
||||
pEq->w.iRightJoinTable = pE2->iTable;
|
||||
}
|
||||
*ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the EP_FromJoin property on all terms of the given expression.
|
||||
** And set the Expr.iRightJoinTable to iTable for every term in the
|
||||
** And set the Expr.w.iRightJoinTable to iTable for every term in the
|
||||
** expression.
|
||||
**
|
||||
** The EP_FromJoin property is used on terms of an expression to tell
|
||||
@ -371,8 +371,8 @@ static void addWhereTerm(
|
||||
** WHERE clause during join processing but we need to remember that they
|
||||
** originated in the ON or USING clause.
|
||||
**
|
||||
** The Expr.iRightJoinTable tells the WHERE clause processing that the
|
||||
** expression depends on table iRightJoinTable even if that table is not
|
||||
** The Expr.w.iRightJoinTable tells the WHERE clause processing that the
|
||||
** expression depends on table w.iRightJoinTable even if that table is not
|
||||
** explicitly mentioned in the expression. That information is needed
|
||||
** for cases like this:
|
||||
**
|
||||
@ -390,7 +390,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
|
||||
ExprSetProperty(p, EP_FromJoin);
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(p, EP_NoReduce);
|
||||
p->iRightJoinTable = iTable;
|
||||
p->w.iRightJoinTable = iTable;
|
||||
if( p->op==TK_FUNCTION ){
|
||||
assert( ExprUseXList(p) );
|
||||
if( p->x.pList ){
|
||||
@ -406,7 +406,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
|
||||
}
|
||||
|
||||
/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
|
||||
** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
|
||||
** term that is marked with EP_FromJoin and w.iRightJoinTable==iTable into
|
||||
** an ordinary term that omits the EP_FromJoin mark.
|
||||
**
|
||||
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
|
||||
@ -414,7 +414,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
|
||||
static void unsetJoinExpr(Expr *p, int iTable){
|
||||
while( p ){
|
||||
if( ExprHasProperty(p, EP_FromJoin)
|
||||
&& (iTable<0 || p->iRightJoinTable==iTable) ){
|
||||
&& (iTable<0 || p->w.iRightJoinTable==iTable) ){
|
||||
ExprClearProperty(p, EP_FromJoin);
|
||||
}
|
||||
if( p->op==TK_COLUMN && p->iTable==iTable ){
|
||||
@ -1404,7 +1404,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
|
||||
p->nRef = 1;
|
||||
memset(&p[1], 0, nExtra);
|
||||
}else{
|
||||
sqlite3OomFault(db);
|
||||
return (KeyInfo*)sqlite3OomFault(db);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@ -1575,6 +1575,9 @@ static void generateSortTail(
|
||||
|
||||
iTab = pSort->iECursor;
|
||||
if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
|
||||
if( eDest==SRT_Mem && p->iOffset ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst);
|
||||
}
|
||||
regRowid = 0;
|
||||
regRow = pDest->iSdst;
|
||||
}else{
|
||||
@ -3296,6 +3299,8 @@ static int multiSelectOrderBy(
|
||||
){
|
||||
int i, j; /* Loop counters */
|
||||
Select *pPrior; /* Another SELECT immediately to our left */
|
||||
Select *pSplit; /* Left-most SELECT in the right-hand group */
|
||||
int nSelect; /* Number of SELECT statements in the compound */
|
||||
Vdbe *v; /* Generate code to this VDBE */
|
||||
SelectDest destA; /* Destination for coroutine A */
|
||||
SelectDest destB; /* Destination for coroutine B */
|
||||
@ -3341,8 +3346,7 @@ static int multiSelectOrderBy(
|
||||
/* Patch up the ORDER BY clause
|
||||
*/
|
||||
op = p->op;
|
||||
pPrior = p->pPrior;
|
||||
assert( pPrior->pOrderBy==0 );
|
||||
assert( p->pPrior->pOrderBy==0 );
|
||||
pOrderBy = p->pOrderBy;
|
||||
assert( pOrderBy );
|
||||
nOrderBy = pOrderBy->nExpr;
|
||||
@ -3392,11 +3396,6 @@ static int multiSelectOrderBy(
|
||||
pKeyMerge = 0;
|
||||
}
|
||||
|
||||
/* Reattach the ORDER BY clause to the query.
|
||||
*/
|
||||
p->pOrderBy = pOrderBy;
|
||||
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
|
||||
|
||||
/* Allocate a range of temporary registers and the KeyInfo needed
|
||||
** for the logic that removes duplicate result rows when the
|
||||
** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
|
||||
@ -3421,12 +3420,30 @@ static int multiSelectOrderBy(
|
||||
|
||||
/* Separate the left and the right query from one another
|
||||
*/
|
||||
p->pPrior = 0;
|
||||
pPrior->pNext = 0;
|
||||
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
|
||||
if( pPrior->pPrior==0 ){
|
||||
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
|
||||
nSelect = 1;
|
||||
if( (op==TK_ALL || op==TK_UNION)
|
||||
&& OptimizationEnabled(db, SQLITE_BalancedMerge)
|
||||
){
|
||||
for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){
|
||||
nSelect++;
|
||||
assert( pSplit->pPrior->pNext==pSplit );
|
||||
}
|
||||
}
|
||||
if( nSelect<=3 ){
|
||||
pSplit = p;
|
||||
}else{
|
||||
pSplit = p;
|
||||
for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; }
|
||||
}
|
||||
pPrior = pSplit->pPrior;
|
||||
assert( pPrior!=0 );
|
||||
pSplit->pPrior = 0;
|
||||
pPrior->pNext = 0;
|
||||
assert( p->pOrderBy == pOrderBy );
|
||||
assert( pOrderBy!=0 || db->mallocFailed );
|
||||
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
|
||||
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
|
||||
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
|
||||
|
||||
/* Compute the limit registers */
|
||||
computeLimitRegisters(pParse, p, labelEnd);
|
||||
@ -3577,12 +3594,11 @@ static int multiSelectOrderBy(
|
||||
|
||||
/* Reassembly the compound query so that it will be freed correctly
|
||||
** by the calling function */
|
||||
if( p->pPrior ){
|
||||
sqlite3SelectDelete(db, p->pPrior);
|
||||
if( pSplit->pPrior ){
|
||||
sqlite3SelectDelete(db, pSplit->pPrior);
|
||||
}
|
||||
p->pPrior = pPrior;
|
||||
pPrior->pNext = p;
|
||||
|
||||
pSplit->pPrior = pPrior;
|
||||
pPrior->pNext = pSplit;
|
||||
sqlite3ExprListDelete(db, pPrior->pOrderBy);
|
||||
pPrior->pOrderBy = 0;
|
||||
|
||||
@ -3632,9 +3648,9 @@ static Expr *substExpr(
|
||||
){
|
||||
if( pExpr==0 ) return 0;
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin)
|
||||
&& pExpr->iRightJoinTable==pSubst->iTable
|
||||
&& pExpr->w.iRightJoinTable==pSubst->iTable
|
||||
){
|
||||
pExpr->iRightJoinTable = pSubst->iNewTable;
|
||||
pExpr->w.iRightJoinTable = pSubst->iNewTable;
|
||||
}
|
||||
if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iTable==pSubst->iTable
|
||||
@ -3673,7 +3689,7 @@ static Expr *substExpr(
|
||||
ExprSetProperty(pNew, EP_CanBeNull);
|
||||
}
|
||||
if( ExprHasProperty(pExpr,EP_FromJoin) ){
|
||||
sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
|
||||
sqlite3SetJoinExpr(pNew, pExpr->w.iRightJoinTable);
|
||||
}
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
pExpr = pNew;
|
||||
@ -3838,7 +3854,7 @@ static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
|
||||
renumberCursorDoMapping(pWalker, &pExpr->iTable);
|
||||
}
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable);
|
||||
renumberCursorDoMapping(pWalker, &pExpr->w.iRightJoinTable);
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
@ -4848,11 +4864,13 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
if( isLeftJoin
|
||||
&& (ExprHasProperty(pWhere,EP_FromJoin)==0
|
||||
|| pWhere->iRightJoinTable!=iCursor)
|
||||
|| pWhere->w.iRightJoinTable!=iCursor)
|
||||
){
|
||||
return 0; /* restriction (4) */
|
||||
}
|
||||
if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
|
||||
if( ExprHasProperty(pWhere,EP_FromJoin)
|
||||
&& pWhere->w.iRightJoinTable!=iCursor
|
||||
){
|
||||
return 0; /* restriction (5) */
|
||||
}
|
||||
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
|
||||
@ -5572,7 +5590,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
|
||||
/* Process NATURAL keywords, and ON and USING clauses of joins.
|
||||
*/
|
||||
if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
|
||||
assert( db->mallocFailed==0 || pParse->nErr!=0 );
|
||||
if( pParse->nErr || sqliteProcessJoin(pParse, p) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
@ -5869,12 +5888,13 @@ void sqlite3SelectPrep(
|
||||
NameContext *pOuterNC /* Name context for container */
|
||||
){
|
||||
assert( p!=0 || pParse->db->mallocFailed );
|
||||
assert( pParse->db->pParse==pParse );
|
||||
if( pParse->db->mallocFailed ) return;
|
||||
if( p->selFlags & SF_HasTypeInfo ) return;
|
||||
sqlite3SelectExpand(pParse, p);
|
||||
if( pParse->nErr || pParse->db->mallocFailed ) return;
|
||||
if( pParse->nErr ) return;
|
||||
sqlite3ResolveSelectNames(pParse, p, pOuterNC);
|
||||
if( pParse->nErr || pParse->db->mallocFailed ) return;
|
||||
if( pParse->nErr ) return;
|
||||
sqlite3SelectAddTypeInfo(pParse, p);
|
||||
}
|
||||
|
||||
@ -5891,8 +5911,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
int i;
|
||||
struct AggInfo_func *pFunc;
|
||||
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
|
||||
assert( pParse->db->pParse==pParse );
|
||||
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
|
||||
if( nReg==0 ) return;
|
||||
if( pParse->nErr || pParse->db->mallocFailed ) return;
|
||||
if( pParse->nErr ) return;
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Verify that all AggInfo registers are within the range specified by
|
||||
** AggInfo.mnReg..AggInfo.mxReg */
|
||||
@ -6315,10 +6337,12 @@ int sqlite3Select(
|
||||
u8 minMaxFlag; /* Flag for min/max queries */
|
||||
|
||||
db = pParse->db;
|
||||
assert( pParse==db->pParse );
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( p==0 || db->mallocFailed || pParse->nErr ){
|
||||
if( p==0 || pParse->nErr ){
|
||||
return 1;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
|
||||
#if SELECTTRACE_ENABLED
|
||||
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
|
||||
@ -6353,9 +6377,10 @@ int sqlite3Select(
|
||||
p->selFlags |= SF_NoopOrderBy;
|
||||
}
|
||||
sqlite3SelectPrep(pParse, p, 0);
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
if( pParse->nErr ){
|
||||
goto select_end;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
assert( p->pEList!=0 );
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x104 ){
|
||||
@ -6399,7 +6424,7 @@ int sqlite3Select(
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( sqlite3WindowRewrite(pParse, p) ){
|
||||
assert( db->mallocFailed || pParse->nErr>0 );
|
||||
assert( pParse->nErr );
|
||||
goto select_end;
|
||||
}
|
||||
#if SELECTTRACE_ENABLED
|
||||
@ -6875,7 +6900,7 @@ int sqlite3Select(
|
||||
/* Begin the database scan. */
|
||||
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
|
||||
p->pEList, wctrlFlags, p->nSelectRow);
|
||||
p->pEList, p, wctrlFlags, p->nSelectRow);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
|
||||
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
|
||||
@ -7139,7 +7164,7 @@ int sqlite3Select(
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
|
||||
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
|
||||
0, (WHERE_GROUPBY|(orderByGrp ? WHERE_SORTBYGROUP : 0)|distFlag), 0
|
||||
);
|
||||
if( pWInfo==0 ){
|
||||
sqlite3ExprListDelete(db, pDistinct);
|
||||
@ -7437,7 +7462,7 @@ int sqlite3Select(
|
||||
|
||||
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
|
||||
pDistinct, minMaxFlag|distFlag, 0);
|
||||
pDistinct, 0, minMaxFlag|distFlag, 0);
|
||||
if( pWInfo==0 ){
|
||||
goto select_end;
|
||||
}
|
||||
@ -7494,7 +7519,7 @@ int sqlite3Select(
|
||||
*/
|
||||
select_end:
|
||||
assert( db->mallocFailed==0 || db->mallocFailed==1 );
|
||||
pParse->nErr += db->mallocFailed;
|
||||
assert( db->mallocFailed==0 || pParse->nErr!=0 );
|
||||
sqlite3ExprListDelete(db, pMinMaxOrderBy);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pAggInfo && !db->mallocFailed ){
|
||||
|
||||
1102
src/shell.c.in
1102
src/shell.c.in
File diff suppressed because it is too large
Load Diff
372
src/sqlite.h.in
372
src/sqlite.h.in
@ -566,7 +566,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
||||
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
||||
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@ -3824,13 +3824,14 @@ void sqlite3_free_filename(char*);
|
||||
** sqlite3_extended_errcode() might change with each API call.
|
||||
** Except, there are some interfaces that are guaranteed to never
|
||||
** change the value of the error code. The error-code preserving
|
||||
** interfaces are:
|
||||
** interfaces include the following:
|
||||
**
|
||||
** <ul>
|
||||
** <li> sqlite3_errcode()
|
||||
** <li> sqlite3_extended_errcode()
|
||||
** <li> sqlite3_errmsg()
|
||||
** <li> sqlite3_errmsg16()
|
||||
** <li> sqlite3_error_offset()
|
||||
** </ul>
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
@ -3845,6 +3846,13 @@ void sqlite3_free_filename(char*);
|
||||
** ^(Memory to hold the error message string is managed internally
|
||||
** and must not be freed by the application)^.
|
||||
**
|
||||
** ^If the most recent error references a specific token in the input
|
||||
** SQL, the sqlite3_error_offset() interface returns the byte offset
|
||||
** of the start of that token. ^The byte offset returned by
|
||||
** sqlite3_error_offset() assumes that the input SQL is UTF8.
|
||||
** ^If the most recent error does not reference a specific token in the input
|
||||
** SQL, then the sqlite3_error_offset() function returns -1.
|
||||
**
|
||||
** When the serialized [threading mode] is in use, it might be the
|
||||
** case that a second error occurs on a separate thread in between
|
||||
** the time of the first error and the call to these interfaces.
|
||||
@ -3864,6 +3872,7 @@ int sqlite3_extended_errcode(sqlite3 *db);
|
||||
const char *sqlite3_errmsg(sqlite3*);
|
||||
const void *sqlite3_errmsg16(sqlite3*);
|
||||
const char *sqlite3_errstr(int);
|
||||
int sqlite3_error_offset(sqlite3 *db);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Object
|
||||
@ -4275,6 +4284,10 @@ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
||||
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
|
||||
** read-only no-op if the table already exists, but
|
||||
** sqlite3_stmt_readonly() still returns false for such a statement.
|
||||
**
|
||||
** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
|
||||
** statement, then sqlite3_stmt_readonly(X) returns the same value as
|
||||
** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
|
||||
*/
|
||||
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
@ -4343,6 +4356,8 @@ int sqlite3_stmt_busy(sqlite3_stmt*);
|
||||
**
|
||||
** ^The sqlite3_value objects that are passed as parameters into the
|
||||
** implementation of [application-defined SQL functions] are protected.
|
||||
** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
|
||||
** are protected.
|
||||
** ^The sqlite3_value object returned by
|
||||
** [sqlite3_column_value()] is unprotected.
|
||||
** Unprotected sqlite3_value objects may only be used as arguments
|
||||
@ -4964,6 +4979,10 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** even empty strings, are always zero-terminated. ^The return
|
||||
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
|
||||
**
|
||||
** ^Strings returned by sqlite3_column_text16() always have the endianness
|
||||
** which is native to the platform, regardless of the text encoding set
|
||||
** for the database.
|
||||
**
|
||||
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
|
||||
** [unprotected sqlite3_value] object. In a multithreaded environment,
|
||||
** an unprotected sqlite3_value object may only be used safely with
|
||||
@ -4977,7 +4996,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** [application-defined SQL functions] or [virtual tables], not within
|
||||
** top-level application code.
|
||||
**
|
||||
** The these routines may attempt to convert the datatype of the result.
|
||||
** These routines may attempt to convert the datatype of the result.
|
||||
** ^For example, if the internal representation is FLOAT and a text result
|
||||
** is requested, [sqlite3_snprintf()] is used internally to perform the
|
||||
** conversion automatically. ^(The following table details the conversions
|
||||
@ -5002,7 +5021,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** <tr><td> TEXT <td> BLOB <td> No change
|
||||
** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
|
||||
** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
|
||||
** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
|
||||
** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
|
||||
** </table>
|
||||
** </blockquote>)^
|
||||
**
|
||||
@ -7182,24 +7201,56 @@ struct sqlite3_index_info {
|
||||
**
|
||||
** These macros define the allowed values for the
|
||||
** [sqlite3_index_info].aConstraint[].op field. Each value represents
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** an operator that is part of a constraint term in the WHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
**
|
||||
** ^The left-hand operand of the operator is given by the corresponding
|
||||
** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
|
||||
** operand is the rowid.
|
||||
** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
** operators have no left-hand operand, and so for those operators the
|
||||
** corresponding aConstraint[].iColumn is meaningless and should not be
|
||||
** used.
|
||||
**
|
||||
** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
|
||||
** value 255 are reserved to represent functions that are overloaded
|
||||
** by the [xFindFunction|xFindFunction method] of the virtual table
|
||||
** implementation.
|
||||
**
|
||||
** The right-hand operands for each constraint might be accessible using
|
||||
** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand
|
||||
** operand is only available if it appears as a single constant literal
|
||||
** in the input SQL. If the right-hand operand is another column or an
|
||||
** expression (even a constant expression) or a parameter, then the
|
||||
** sqlite3_vtab_rhs_value() probably will not be able to extract it.
|
||||
** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
|
||||
** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
|
||||
** and hence calls to sqlite3_vtab_rhs_value() for those operators will
|
||||
** always return SQLITE_NOTFOUND.
|
||||
**
|
||||
** The collating sequence to be used for comparison can be found using
|
||||
** the [sqlite3_vtab_collation()] interface. For most real-world virtual
|
||||
** tables, the collating sequence of constraints does not matter (for example
|
||||
** because the constraints are numeric) and so the sqlite3_vtab_collation()
|
||||
** interface is no commonly needed.
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
|
||||
#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
|
||||
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
@ -7228,7 +7279,7 @@ struct sqlite3_index_info {
|
||||
** destructor.
|
||||
**
|
||||
** ^If the third parameter (the pointer to the sqlite3_module object) is
|
||||
** NULL then no new module is create and any existing modules with the
|
||||
** NULL then no new module is created and any existing modules with the
|
||||
** same name are dropped.
|
||||
**
|
||||
** See also: [sqlite3_drop_modules()]
|
||||
@ -8004,7 +8055,8 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
@ -8527,6 +8579,16 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
** The counter is incremented on the first [sqlite3_step()] call of each
|
||||
** cycle.
|
||||
**
|
||||
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
|
||||
** [[SQLITE_STMTSTATUS_FILTER HIT]]
|
||||
** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
|
||||
** SQLITE_STMTSTATUS_FILTER_MISS</dt>
|
||||
** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
|
||||
** step was bypassed because a Bloom filter returned not-found. The
|
||||
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
|
||||
** times that the Bloom filter returned a find, and thus the join step
|
||||
** had to be processed as normal.
|
||||
**
|
||||
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
|
||||
** <dd>^This is the approximate number of bytes of heap memory
|
||||
** used to store the prepared statement. ^This value is not actually
|
||||
@ -8541,6 +8603,8 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
#define SQLITE_STMTSTATUS_VM_STEP 4
|
||||
#define SQLITE_STMTSTATUS_REPREPARE 5
|
||||
#define SQLITE_STMTSTATUS_RUN 6
|
||||
#define SQLITE_STMTSTATUS_FILTER_MISS 7
|
||||
#define SQLITE_STMTSTATUS_FILTER_HIT 8
|
||||
#define SQLITE_STMTSTATUS_MEMUSED 99
|
||||
|
||||
/*
|
||||
@ -9509,19 +9573,269 @@ int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This function may only be called from within a call to the [xBestIndex]
|
||||
** method of a [virtual table].
|
||||
** method of a [virtual table]. This function returns a pointer to a string
|
||||
** that is the name of the appropriate collation sequence to use for text
|
||||
** comparisons on the constraint identified by its arguments.
|
||||
**
|
||||
** The first argument must be the sqlite3_index_info object that is the
|
||||
** first parameter to the xBestIndex() method. The second argument must be
|
||||
** an index into the aConstraint[] array belonging to the sqlite3_index_info
|
||||
** structure passed to xBestIndex. This function returns a pointer to a buffer
|
||||
** containing the name of the collation sequence for the corresponding
|
||||
** constraint.
|
||||
** The first argument must be the pointer to the [sqlite3_index_info] object
|
||||
** that is the first parameter to the xBestIndex() method. The second argument
|
||||
** must be an index into the aConstraint[] array belonging to the
|
||||
** sqlite3_index_info structure passed to xBestIndex.
|
||||
**
|
||||
** Important:
|
||||
** The first parameter must be the same pointer that is passed into the
|
||||
** xBestMethod() method. The first parameter may not be a pointer to a
|
||||
** different [sqlite3_index_info] object, even an exact copy.
|
||||
**
|
||||
** The return value is computed as follows:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p> If the constraint comes from a WHERE clause expression that contains
|
||||
** a [COLLATE operator], then the name of the collation specified by
|
||||
** that COLLATE operator is returned.
|
||||
** <li><p> If there is no COLLATE operator, but the column that is the subject
|
||||
** of the constraint specifies an alternative collating sequence via
|
||||
** a [COLLATE clause] on the column definition within the CREATE TABLE
|
||||
** statement that was passed into [sqlite3_declare_vtab()], then the
|
||||
** name of that alternative collating sequence is returned.
|
||||
** <li><p> Otherwise, "BINARY" is returned.
|
||||
** </ol>
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine if a virtual table query is DISTINCT
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This API may only be used from within an [xBestIndex|xBestIndex method]
|
||||
** of a [virtual table] implementation. The result of calling this
|
||||
** interface from outside of xBestIndex() is undefined and probably harmful.
|
||||
**
|
||||
** ^The sqlite3_vtab_distinct() interface returns an integer that is
|
||||
** either 0, 1, or 2. The integer returned by sqlite3_vtab_distinct()
|
||||
** gives the virtual table additional information about how the query
|
||||
** planner wants the output to be ordered. As long as the virtual table
|
||||
** can meet the ordering requirements of the query planner, it may set
|
||||
** the "orderByConsumed" flag.
|
||||
**
|
||||
** <ol><li value="0"><p>
|
||||
** ^If the sqlite3_vtab_distinct() interface returns 0, that means
|
||||
** that the query planner needs the virtual table to return all rows in the
|
||||
** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
|
||||
** [sqlite3_index_info] object. This is the default expectation. If the
|
||||
** virtual table outputs all rows in sorted order, then it is always safe for
|
||||
** the xBestIndex method to set the "orderByConsumed" flag, regardless of
|
||||
** the return value from sqlite3_vtab_distinct().
|
||||
** <li value="1"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
|
||||
** that the query planner does not need the rows to be returned in sorted order
|
||||
** as long as all rows with the same values in all columns identified by the
|
||||
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
|
||||
** is doing a GROUP BY.
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** </ol>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
** (or "IS NOT DISTINCT FROM") and not "==".
|
||||
**
|
||||
** If a virtual table implementation is unable to meet the requirements
|
||||
** specified above, then it must not set the "orderByConsumed" flag in the
|
||||
** [sqlite3_index_info] object or an incorrect answer may result.
|
||||
**
|
||||
** ^A virtual table implementation is always free to return rows in any order
|
||||
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
|
||||
** the "orderByConsumed" flag is unset, the query planner will add extra
|
||||
** [bytecode] to ensure that the final results returned by the SQL query are
|
||||
** ordered correctly. The use of the "orderByConsumed" flag and the
|
||||
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
|
||||
** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
|
||||
** flag might help queries against a virtual table to run faster. Being
|
||||
** overly aggressive and setting the "orderByConsumed" flag when it is not
|
||||
** valid to do so, on the other hand, might cause SQLite to return incorrect
|
||||
** results.
|
||||
*/
|
||||
int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Identify and handle IN constraints in xBestIndex
|
||||
**
|
||||
** This interface may only be used from within an
|
||||
** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
|
||||
** The result of invoking this interface from any other context is
|
||||
** undefined and probably harmful.
|
||||
**
|
||||
** ^(A constraint on a virtual table of the form
|
||||
** "[IN operator|column IN (...)]" is
|
||||
** communicated to the xBestIndex method as a
|
||||
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
|
||||
** this constraint, it must set the corresponding
|
||||
** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
|
||||
** the usual mode of handling IN operators, SQLite generates [bytecode]
|
||||
** that invokes the [xFilter|xFilter() method] once for each value
|
||||
** on the right-hand side of the IN operator.)^ Thus the virtual table
|
||||
** only sees a single value from the right-hand side of the IN operator
|
||||
** at a time.
|
||||
**
|
||||
** In some cases, however, it would be advantageous for the virtual
|
||||
** table to see all values on the right-hand of the IN operator all at
|
||||
** once. The sqlite3_vtab_in() interfaces facilitates this in two ways:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p>
|
||||
** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero)
|
||||
** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint
|
||||
** is an [IN operator] that can be processed all at once. ^In other words,
|
||||
** sqlite3_vtab_in() with -1 in the third argument is a mechanism
|
||||
** by which the virtual table can ask SQLite if all-at-once processing
|
||||
** of the IN operator is even possible.
|
||||
**
|
||||
** <li><p>
|
||||
** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
|
||||
** to SQLite that the virtual table does or does not want to process
|
||||
** the IN operator all-at-once, respectively. ^Thus when the third
|
||||
** parameter (F) is non-negative, this interface is the mechanism by
|
||||
** which the virtual table tells SQLite how it wants to process the
|
||||
** IN operator.
|
||||
** </ol>
|
||||
**
|
||||
** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
|
||||
** within the same xBestIndex method call. ^For any given P,N pair,
|
||||
** the return value from sqlite3_vtab_in(P,N,F) will always be the same
|
||||
** within the same xBestIndex call. ^If the interface returns true
|
||||
** (non-zero), that means that the constraint is an IN operator
|
||||
** that can be processed all-at-once. ^If the constraint is not an IN
|
||||
** operator or cannot be processed all-at-once, then the interface returns
|
||||
** false.
|
||||
**
|
||||
** ^(All-at-once processing of the IN operator is selected if both of the
|
||||
** following conditions are met:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
|
||||
** integer. This is how the virtual table tells SQLite that it wants to
|
||||
** use the N-th constraint.
|
||||
**
|
||||
** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was
|
||||
** non-negative had F>=1.
|
||||
** </ol>)^
|
||||
**
|
||||
** ^If either or both of the conditions above are false, then SQLite uses
|
||||
** the traditional one-at-a-time processing strategy for the IN constraint.
|
||||
** ^If both conditions are true, then the argvIndex-th parameter to the
|
||||
** xFilter method will be an [sqlite3_value] that appears to be NULL,
|
||||
** but which can be passed to [sqlite3_vtab_in_first()] and
|
||||
** [sqlite3_vtab_in_next()] to find all values on the right-hand side
|
||||
** of the IN constraint.
|
||||
*/
|
||||
int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
|
||||
**
|
||||
** These interfaces are only useful from within the
|
||||
** [xFilter|xFilter() method] of a [virtual table] implementation.
|
||||
** The result of invoking these interfaces from any other context
|
||||
** is undefined and probably harmful.
|
||||
**
|
||||
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
|
||||
** sqlite3_vtab_in_next(X,P) must be one of the parameters to the
|
||||
** xFilter method which invokes these routines, and specifically
|
||||
** a parameter that was previously selected for all-at-once IN constraint
|
||||
** processing use the [sqlite3_vtab_in()] interface in the
|
||||
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
|
||||
** an xFilter argument that was selected for all-at-once IN constraint
|
||||
** processing, then these routines return [SQLITE_MISUSE])^ or perhaps
|
||||
** exhibit some other undefined or harmful behavior.
|
||||
**
|
||||
** ^(Use these routines to access all values on the right-hand side
|
||||
** of the IN constraint using code like the following:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** for(rc=sqlite3_vtab_in_first(pList, &pVal);
|
||||
** rc==SQLITE_OK && pVal
|
||||
** rc=sqlite3_vtab_in_next(pList, &pVal)
|
||||
** ){
|
||||
** // do something with pVal
|
||||
** }
|
||||
** if( rc!=SQLITE_OK ){
|
||||
** // an error has occurred
|
||||
** }
|
||||
** </pre></blockquote>)^
|
||||
**
|
||||
** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
|
||||
** routines return SQLITE_OK and set *P to point to the first or next value
|
||||
** on the RHS of the IN constraint. ^If there are no more values on the
|
||||
** right hand side of the IN constraint, then *P is set to NULL and these
|
||||
** routines return [SQLITE_DONE]. ^The return value might be
|
||||
** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
|
||||
**
|
||||
** The *ppOut values returned by these routines are only valid until the
|
||||
** next call to either of these routines or until the end of the xFilter
|
||||
** method from which these routines were called. If the virtual table
|
||||
** implementation needs to retain the *ppOut values for longer, it must make
|
||||
** copies. The *ppOut values are [protected sqlite3_value|protected].
|
||||
*/
|
||||
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constraint values in xBestIndex()
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This API may only be used from within the [xBestIndex|xBestIndex method]
|
||||
** of a [virtual table] implementation. The result of calling this interface
|
||||
** from outside of an xBestIndex method are undefined and probably harmful.
|
||||
**
|
||||
** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
|
||||
** the [xBestIndex] method of a [virtual table] implementation, with P being
|
||||
** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
|
||||
** J being a 0-based index into P->aConstraint[], then this routine
|
||||
** attempts to set *V to the value of the right-hand operand of
|
||||
** that constraint if the right-hand operand is known. ^If the
|
||||
** right-hand operand is not known, then *V is set to a NULL pointer.
|
||||
** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
|
||||
** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
|
||||
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
|
||||
** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
|
||||
** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
|
||||
** something goes wrong.
|
||||
**
|
||||
** The sqlite3_vtab_rhs_value() interface is usually only successful if
|
||||
** the right-hand operand of a constraint is a literal value in the original
|
||||
** SQL statement. If the right-hand operand is an expression or a reference
|
||||
** to some other column or a [host parameter], then sqlite3_vtab_rhs_value()
|
||||
** will probably return [SQLITE_NOTFOUND].
|
||||
**
|
||||
** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
|
||||
** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
|
||||
** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
|
||||
**
|
||||
** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value
|
||||
** and remains valid for the duration of the xBestIndex method call.
|
||||
** ^When xBestIndex returns, the sqlite3_value object returned by
|
||||
** sqlite3_vtab_rhs_value() is automatically deallocated.
|
||||
**
|
||||
** The "_rhs_" in the name of this routine is an abbreviation for
|
||||
** "Right-Hand Side".
|
||||
*/
|
||||
int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
|
||||
@ -344,6 +344,13 @@ struct sqlite3_api_routines {
|
||||
int (*autovacuum_pages)(sqlite3*,
|
||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||
void*, void(*)(void*));
|
||||
/* Version 3.38.0 and later */
|
||||
int (*error_offset)(sqlite3*);
|
||||
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
|
||||
int (*vtab_distinct)(sqlite3_index_info*);
|
||||
int (*vtab_in)(sqlite3_index_info*,int,int);
|
||||
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
|
||||
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -655,6 +662,13 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_total_changes64 sqlite3_api->total_changes64
|
||||
/* Version 3.37.0 and later */
|
||||
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
|
||||
/* Version 3.38.0 and later */
|
||||
#define sqlite3_error_offset sqlite3_api->error_offset
|
||||
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
|
||||
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
|
||||
#define sqlite3_vtab_in sqlite3_api->vtab_in
|
||||
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
|
||||
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
@ -1231,10 +1231,11 @@ typedef struct With With;
|
||||
/*
|
||||
** A bit in a Bitmask
|
||||
*/
|
||||
#define MASKBIT(n) (((Bitmask)1)<<(n))
|
||||
#define MASKBIT64(n) (((u64)1)<<(n))
|
||||
#define MASKBIT32(n) (((unsigned int)1)<<(n))
|
||||
#define ALLBITS ((Bitmask)-1)
|
||||
#define MASKBIT(n) (((Bitmask)1)<<(n))
|
||||
#define MASKBIT64(n) (((u64)1)<<(n))
|
||||
#define MASKBIT32(n) (((unsigned int)1)<<(n))
|
||||
#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
|
||||
#define ALLBITS ((Bitmask)-1)
|
||||
|
||||
/* A VList object records a mapping between parameters/variables/wildcards
|
||||
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
|
||||
@ -1527,6 +1528,7 @@ struct sqlite3 {
|
||||
u32 nSchemaLock; /* Do not reset the schema when non-zero */
|
||||
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
|
||||
int errCode; /* Most recent error code (SQLITE_*) */
|
||||
int errByteOffset; /* Byte offset of error in SQL statement */
|
||||
int errMask; /* & result codes with this before returning */
|
||||
int iSysErrno; /* Errno value from last system error */
|
||||
u32 dbOptFlags; /* Flags to enable/disable optimizations */
|
||||
@ -1761,6 +1763,9 @@ struct sqlite3 {
|
||||
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
|
||||
#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
|
||||
/* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
|
||||
#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */
|
||||
#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */
|
||||
#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
|
||||
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@ -1934,7 +1939,7 @@ struct FuncDestructor {
|
||||
** are interpreted in the same way as the first 4 parameters to
|
||||
** FUNCTION().
|
||||
**
|
||||
** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
|
||||
** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
|
||||
** Used to create an aggregate function definition implemented by
|
||||
** the C functions xStep and xFinal. The first four parameters
|
||||
** are interpreted in the same way as the first 4 parameters to
|
||||
@ -1961,6 +1966,10 @@ struct FuncDestructor {
|
||||
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define JFUNCTION(zName, nArg, iArg, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|\
|
||||
SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|\
|
||||
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
||||
@ -2815,7 +2824,10 @@ struct Expr {
|
||||
** TK_VARIABLE: variable number (always >= 1).
|
||||
** TK_SELECT_COLUMN: column of the result vector */
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
union {
|
||||
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
int iOfst; /* else: start of token from start of statement */
|
||||
} w;
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
union {
|
||||
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
|
||||
@ -3577,6 +3589,7 @@ 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 */
|
||||
|
||||
/************************************************************************
|
||||
@ -3627,7 +3640,8 @@ struct Parse {
|
||||
/*
|
||||
** Sizes and pointers of various parts of the Parse object.
|
||||
*/
|
||||
#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
|
||||
#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
|
||||
#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
|
||||
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
|
||||
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
|
||||
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
|
||||
@ -3922,6 +3936,7 @@ struct Sqlite3Config {
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
|
||||
int iOnceResetThreshold; /* When to reset OP_Once counters */
|
||||
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
|
||||
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
|
||||
@ -4402,7 +4417,7 @@ void sqlite3DequoteExpr(Expr*);
|
||||
void sqlite3DequoteToken(Token*);
|
||||
void sqlite3TokenInit(Token*,char*);
|
||||
int sqlite3KeywordCode(const unsigned char*, int);
|
||||
int sqlite3RunParser(Parse*, const char*, char **);
|
||||
int sqlite3RunParser(Parse*, const char*);
|
||||
void sqlite3FinishCoding(Parse*);
|
||||
int sqlite3GetTempReg(Parse*);
|
||||
void sqlite3ReleaseTempReg(Parse*,int);
|
||||
@ -4569,10 +4584,12 @@ void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
||||
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
|
||||
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
|
||||
#endif
|
||||
void sqlite3CodeChangeCount(Vdbe*,int,const char*);
|
||||
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
|
||||
Upsert*);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
|
||||
ExprList*,Select*,u16,int);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
|
||||
int sqlite3WhereIsDistinct(WhereInfo*);
|
||||
@ -4687,9 +4704,14 @@ Select *sqlite3SelectDup(sqlite3*,const Select*,int);
|
||||
FuncDef *sqlite3FunctionSearch(int,const char*);
|
||||
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
|
||||
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
|
||||
void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
|
||||
void sqlite3RegisterBuiltinFunctions(void);
|
||||
void sqlite3RegisterDateTimeFunctions(void);
|
||||
void sqlite3RegisterJsonFunctions(void);
|
||||
void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
||||
int sqlite3JsonTableFunctions(sqlite3*);
|
||||
#endif
|
||||
int sqlite3SafetyCheckOk(sqlite3*);
|
||||
int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
||||
void sqlite3ChangeCookie(Parse*, int);
|
||||
@ -4779,14 +4801,8 @@ int sqlite3Utf8CharLen(const char *pData, int nByte);
|
||||
u32 sqlite3Utf8Read(const u8**);
|
||||
LogEst sqlite3LogEst(u64);
|
||||
LogEst sqlite3LogEstAdd(LogEst,LogEst);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
LogEst sqlite3LogEstFromDouble(double);
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
|
||||
defined(SQLITE_ENABLE_STAT4) || \
|
||||
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
||||
u64 sqlite3LogEstToInt(LogEst);
|
||||
#endif
|
||||
VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
|
||||
const char *sqlite3VListNumToName(VList*,int);
|
||||
int sqlite3VListNameToNum(VList*,const char*,int);
|
||||
@ -4973,17 +4989,20 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
|
||||
FuncDestructor *pDestructor
|
||||
);
|
||||
void sqlite3NoopDestructor(void*);
|
||||
void sqlite3OomFault(sqlite3*);
|
||||
void *sqlite3OomFault(sqlite3*);
|
||||
void sqlite3OomClear(sqlite3*);
|
||||
int sqlite3ApiExit(sqlite3 *db, int);
|
||||
int sqlite3OpenTempDatabase(Parse *);
|
||||
|
||||
void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
|
||||
int sqlite3StrAccumEnlarge(StrAccum*, int);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumSetError(StrAccum*, u8);
|
||||
void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
||||
void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
|
||||
void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*);
|
||||
|
||||
void sqlite3BackupRestart(sqlite3_backup *);
|
||||
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
|
||||
@ -5088,11 +5107,17 @@ int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
||||
int sqlite3VtabCallConnect(Parse*, Table*);
|
||||
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
|
||||
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
void sqlite3VtabWriteAll(sqlite3_index_info*);
|
||||
#endif
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
void sqlite3ParserReset(Parse*);
|
||||
void sqlite3ParseObjectInit(Parse*,sqlite3*);
|
||||
void sqlite3ParseObjectReset(Parse*);
|
||||
void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
char *sqlite3Normalize(Vdbe*, const char*);
|
||||
|
||||
@ -1943,15 +1943,16 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
"close", "collate", "collation_needed",
|
||||
"commit_hook", "complete", "config",
|
||||
"copy", "deserialize", "enable_load_extension",
|
||||
"errorcode", "eval", "exists",
|
||||
"function", "incrblob", "interrupt",
|
||||
"last_insert_rowid", "nullvalue", "onecolumn",
|
||||
"preupdate", "profile", "progress",
|
||||
"rekey", "restore", "rollback_hook",
|
||||
"serialize", "status", "timeout",
|
||||
"total_changes", "trace", "trace_v2",
|
||||
"transaction", "unlock_notify", "update_hook",
|
||||
"version", "wal_hook", 0
|
||||
"errorcode", "erroroffset", "eval",
|
||||
"exists", "function", "incrblob",
|
||||
"interrupt", "last_insert_rowid", "nullvalue",
|
||||
"onecolumn", "preupdate", "profile",
|
||||
"progress", "rekey", "restore",
|
||||
"rollback_hook", "serialize", "status",
|
||||
"timeout", "total_changes", "trace",
|
||||
"trace_v2", "transaction", "unlock_notify",
|
||||
"update_hook", "version", "wal_hook",
|
||||
0
|
||||
};
|
||||
enum DB_enum {
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
|
||||
@ -1959,15 +1960,15 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
|
||||
DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
|
||||
DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
|
||||
DB_ERRORCODE, DB_EVAL, DB_EXISTS,
|
||||
DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
|
||||
DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
|
||||
DB_PREUPDATE, DB_PROFILE, DB_PROGRESS,
|
||||
DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK,
|
||||
DB_SERIALIZE, DB_STATUS, DB_TIMEOUT,
|
||||
DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2,
|
||||
DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK,
|
||||
DB_VERSION, DB_WAL_HOOK
|
||||
DB_ERRORCODE, DB_ERROROFFSET, DB_EVAL,
|
||||
DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
|
||||
DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
|
||||
DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
|
||||
DB_PROGRESS, DB_REKEY, DB_RESTORE,
|
||||
DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
|
||||
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
|
||||
DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
|
||||
DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK,
|
||||
};
|
||||
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
||||
|
||||
@ -2730,6 +2731,17 @@ deserialize_error:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db erroroffset
|
||||
**
|
||||
** Return the numeric error code that was returned by the most recent
|
||||
** call to sqlite3_exec().
|
||||
*/
|
||||
case DB_ERROROFFSET: {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_error_offset(pDb->db)));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** $db exists $sql
|
||||
** $db onecolumn $sql
|
||||
|
||||
187
src/test1.c
187
src/test1.c
@ -1125,7 +1125,7 @@ static int SQLITE_TCLAPI test_drop_modules(
|
||||
){
|
||||
sqlite3 *db;
|
||||
|
||||
if( argc!=2 ){
|
||||
if( argc<2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" DB\"", 0);
|
||||
return TCL_ERROR;
|
||||
@ -4005,6 +4005,102 @@ static int SQLITE_TCLAPI test_bind_blob(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_bind_value_from_preupdate STMT N NEW|OLD IDX
|
||||
**
|
||||
** Test the sqlite3_bind_value interface using sqlite3_value objects
|
||||
** obtained from either sqlite3_preupdate_new() (if arg[3]=="new") or
|
||||
** sqlite3_preupdate_old() if (arg[3]=="old"). IDX is the index to
|
||||
** pass to the sqlite3_preupdate_xxx() function.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_bind_value_from_preupdate(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int idx;
|
||||
int bidx;
|
||||
const char *z3 = 0;
|
||||
sqlite3 *db = 0;
|
||||
sqlite3_value *pVal = 0;
|
||||
|
||||
if( objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT N NEW|OLD IDX");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
||||
z3 = Tcl_GetString(objv[3]);
|
||||
if( Tcl_GetIntFromObj(interp, objv[4], &bidx) ) return TCL_ERROR;
|
||||
db = sqlite3_db_handle(pStmt);
|
||||
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
if( z3[0]=='n' ){
|
||||
sqlite3_preupdate_new(db, bidx, &pVal);
|
||||
}else if( z3[0]=='o' ){
|
||||
sqlite3_preupdate_old(db, bidx, &pVal);
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "expected new or old, got: ", z3, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_bind_value(pStmt, idx, pVal);
|
||||
#endif
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_bind_value_from_select STMT N SELECT
|
||||
**
|
||||
** Test the sqlite3_bind_value interface. STMT is a prepared statement.
|
||||
** N is the index of a wildcard in the prepared statement.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_bind_value_from_select(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
sqlite3_stmt *pStmt2;
|
||||
int idx;
|
||||
const char *zSql = 0;
|
||||
sqlite3 *db = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT N SELECT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
||||
zSql = Tcl_GetString(objv[3]);
|
||||
db = sqlite3_db_handle(pStmt);
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt2, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in SQL: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( sqlite3_step(pStmt2)==SQLITE_ROW ){
|
||||
sqlite3_value *pVal = sqlite3_column_value(pStmt2, 0);
|
||||
sqlite3_bind_value(pStmt, idx, pVal);
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt2);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp,
|
||||
"error runnning SQL: ", sqlite3_errmsg(db), (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
@ -4394,6 +4490,34 @@ static int SQLITE_TCLAPI test_errmsg(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_error_offset DB
|
||||
**
|
||||
** Return the byte offset into the input UTF8 SQL for the most recent
|
||||
** error, or -1 of the error does not refer to a specific token.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_error_offset(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int iByteOffset;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetString(objv[0]), " DB", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
iByteOffset = sqlite3_error_offset(db);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iByteOffset));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: test_errmsg16 DB
|
||||
**
|
||||
@ -7111,6 +7235,55 @@ static int SQLITE_TCLAPI test_print_eqp(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
|
||||
#include <time.h>
|
||||
/*
|
||||
** This is an alternative localtime_r() implementation used for testing
|
||||
** the 'localtime' and 'utc' modifiers of date-time functions. Because
|
||||
** the OS-supplied localtime_r() is locale-dependent, this alternative is
|
||||
** provided as a stable test platform.
|
||||
**
|
||||
** Operation:
|
||||
**
|
||||
** (1) Localtime is 30 minutes earlier than (west of) UTC on
|
||||
** even days (counting from 1970-01-01)
|
||||
**
|
||||
** (2) Localtime is 30 minutes later than (east of) UTC on odd days.
|
||||
**
|
||||
** (3) The function fails for the specific date/time value
|
||||
** of 2000-05-29 14:16:00 in order to test the ability of
|
||||
** SQLite to deal with localtime_r() failures.
|
||||
*/
|
||||
static int testLocaltime(const void *aliasT, void *aliasTM){
|
||||
const time_t t = *(const time_t*)aliasT;
|
||||
struct tm *pTm = (struct tm *)aliasTM;
|
||||
time_t altT;
|
||||
sqlite3_int64 iJD;
|
||||
int Z, A, B, C, D, E, X1, S;
|
||||
|
||||
if( (t/86400) & 1 ){
|
||||
altT = t + 1800; /* 30 minutes later on odd days */
|
||||
}else{
|
||||
altT = t - 1800; /* 30 minutes earlier on even days */
|
||||
}
|
||||
iJD = (sqlite3_int64)(altT + 210866760000);
|
||||
Z = (int)((iJD + 43200)/86400);
|
||||
A = (int)((Z - 1867216.25)/36524.25);
|
||||
A = Z + 1 + A - (A/4);
|
||||
B = A + 1524;
|
||||
C = (int)((B - 122.1)/365.25);
|
||||
D = (36525*(C&32767))/100;
|
||||
E = (int)((B-D)/30.6001);
|
||||
X1 = (int)(30.6001*E);
|
||||
pTm->tm_mday = B - D - X1;
|
||||
pTm->tm_mon = E<14 ? E-2 : E-14;
|
||||
pTm->tm_year = (pTm->tm_mon>1 ? C - 4716 : C - 4715) - 1900;
|
||||
S = (int)((iJD + 43200)%86400);
|
||||
pTm->tm_hour = S/3600;
|
||||
pTm->tm_min = (S/60)%60;
|
||||
pTm->tm_sec = S % 60;
|
||||
return t==959609760; /* Special case: 2000-05-29 14:16:00 fails */
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_test_control VERB ARGS...
|
||||
*/
|
||||
@ -7158,11 +7331,11 @@ static int SQLITE_TCLAPI test_test_control(
|
||||
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
||||
int val;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "0|1|2");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
|
||||
sqlite3_test_control(iFlag, val);
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR;
|
||||
sqlite3_test_control(iFlag, val, testLocaltime);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7512,6 +7685,7 @@ static int SQLITE_TCLAPI optimization_control(
|
||||
{ "stat4", SQLITE_Stat4 },
|
||||
{ "skip-scan", SQLITE_SkipScan },
|
||||
{ "push-down", SQLITE_PushDown },
|
||||
{ "balanced-merge", SQLITE_BalancedMerge },
|
||||
};
|
||||
|
||||
if( objc!=4 ){
|
||||
@ -7567,6 +7741,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
#endif
|
||||
extern int sqlite3_qpvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@ -7597,6 +7772,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
{ "prefixes", sqlite3_prefixes_init },
|
||||
#endif
|
||||
{ "qpvtab", sqlite3_qpvtab_init },
|
||||
{ "regexp", sqlite3_regexp_init },
|
||||
{ "remember", sqlite3_remember_init },
|
||||
{ "series", sqlite3_series_init },
|
||||
@ -8439,6 +8615,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_bind_text", test_bind_text ,0 },
|
||||
{ "sqlite3_bind_text16", test_bind_text16 ,0 },
|
||||
{ "sqlite3_bind_blob", test_bind_blob ,0 },
|
||||
{ "sqlite3_bind_value_from_select",test_bind_value_from_select ,0 },
|
||||
{ "sqlite3_bind_value_from_preupdate",test_bind_value_from_preupdate ,0 },
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
{ "sqlite3_carray_bind", test_carray_bind ,0 },
|
||||
#endif
|
||||
@ -8450,6 +8628,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_errcode", test_errcode ,0 },
|
||||
{ "sqlite3_extended_errcode", test_ex_errcode ,0 },
|
||||
{ "sqlite3_errmsg", test_errmsg ,0 },
|
||||
{ "sqlite3_error_offset", test_error_offset ,0 },
|
||||
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
|
||||
{ "sqlite3_open", test_open ,0 },
|
||||
{ "sqlite3_open16", test_open16 ,0 },
|
||||
|
||||
@ -299,7 +299,21 @@ static int tclFilter(
|
||||
const char *zVal = (const char*)sqlite3_value_text(argv[ii]);
|
||||
Tcl_Obj *pVal;
|
||||
if( zVal==0 ){
|
||||
sqlite3_value *pMem;
|
||||
pVal = Tcl_NewObj();
|
||||
for(rc=sqlite3_vtab_in_first(argv[ii], &pMem);
|
||||
rc==SQLITE_OK && pMem;
|
||||
rc=sqlite3_vtab_in_next(argv[ii], &pMem)
|
||||
){
|
||||
Tcl_Obj *pVal2 = 0;
|
||||
zVal = (const char*)sqlite3_value_text(pMem);
|
||||
if( zVal ){
|
||||
pVal2 = Tcl_NewStringObj(zVal, -1);
|
||||
}else{
|
||||
pVal2 = Tcl_NewObj();
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pVal, pVal2);
|
||||
}
|
||||
}else{
|
||||
pVal = Tcl_NewStringObj(zVal, -1);
|
||||
}
|
||||
@ -374,20 +388,13 @@ static int tclEof(sqlite3_vtab_cursor *pVtabCursor){
|
||||
return (pCsr->pStmt==0);
|
||||
}
|
||||
|
||||
static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
tcl_vtab *pTab = (tcl_vtab*)tab;
|
||||
Tcl_Interp *interp = pTab->interp;
|
||||
Tcl_Obj *pArg;
|
||||
Tcl_Obj *pScript;
|
||||
static void testBestIndexObjConstraints(
|
||||
Tcl_Interp *interp,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int ii;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pScript = Tcl_DuplicateObj(pTab->pCmd);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1));
|
||||
|
||||
pArg = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pArg);
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRes);
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
|
||||
Tcl_Obj *pElem = Tcl_NewObj();
|
||||
@ -424,6 +431,10 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
zOp = "isnull"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_IS:
|
||||
zOp = "is"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIMIT:
|
||||
zOp = "limit"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_OFFSET:
|
||||
zOp = "offset"; break;
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
|
||||
@ -433,15 +444,21 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1));
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->usable));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pArg, pElem);
|
||||
Tcl_ListObjAppendElement(0, pRes, pElem);
|
||||
Tcl_DecrRefCount(pElem);
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pScript, pArg);
|
||||
Tcl_DecrRefCount(pArg);
|
||||
Tcl_SetObjResult(interp, pRes);
|
||||
Tcl_DecrRefCount(pRes);
|
||||
}
|
||||
|
||||
pArg = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pArg);
|
||||
static void testBestIndexObjOrderby(
|
||||
Tcl_Interp *interp,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int ii;
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRes);
|
||||
for(ii=0; ii<pIdxInfo->nOrderBy; ii++){
|
||||
struct sqlite3_index_orderby const *pOrder = &pIdxInfo->aOrderBy[ii];
|
||||
Tcl_Obj *pElem = Tcl_NewObj();
|
||||
@ -452,17 +469,150 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("desc", -1));
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pOrder->desc));
|
||||
|
||||
Tcl_ListObjAppendElement(0, pArg, pElem);
|
||||
Tcl_ListObjAppendElement(0, pRes, pElem);
|
||||
Tcl_DecrRefCount(pElem);
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pScript, pArg);
|
||||
Tcl_DecrRefCount(pArg);
|
||||
Tcl_SetObjResult(interp, pRes);
|
||||
Tcl_DecrRefCount(pRes);
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pScript, Tcl_NewWideIntObj(pIdxInfo->colUsed));
|
||||
/*
|
||||
** Implementation of the handle passed to each xBestIndex callback. This
|
||||
** object features the following sub-commands:
|
||||
**
|
||||
** $hdl constraints
|
||||
** $hdl orderby
|
||||
** $hdl mask
|
||||
**
|
||||
** $hdl distinct
|
||||
** Return the result (an integer) of calling sqlite3_vtab_distinct()
|
||||
** on the index-info structure.
|
||||
**
|
||||
** $hdl in IDX BOOLEAN
|
||||
** Wrapper around sqlite3_vtab_in(). Returns an integer.
|
||||
**
|
||||
** $hdl rhs_value IDX ?DEFAULT?
|
||||
** Wrapper around sqlite3_vtab_rhs_value().
|
||||
*/
|
||||
static int SQLITE_TCLAPI testBestIndexObj(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
const char *azSub[] = {
|
||||
"constraints", /* 0 */
|
||||
"orderby", /* 1 */
|
||||
"mask", /* 2 */
|
||||
"distinct", /* 3 */
|
||||
"in", /* 4 */
|
||||
"rhs_value", /* 5 */
|
||||
0
|
||||
};
|
||||
int ii;
|
||||
sqlite3_index_info *pIdxInfo = (sqlite3_index_info*)clientData;
|
||||
|
||||
if( objc<2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIndexFromObj(interp, objv[1], azSub, "sub-command", 0, &ii) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( ii<4 && objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( ii==4 && objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "INDEX BOOLEAN");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( ii==5 && objc!=3 && objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "INDEX ?DEFAULT?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
switch( ii ){
|
||||
case 0: assert( sqlite3_stricmp(azSub[ii], "constraints")==0 );
|
||||
testBestIndexObjConstraints(interp, pIdxInfo);
|
||||
break;
|
||||
|
||||
case 1: assert( sqlite3_stricmp(azSub[ii], "orderby")==0 );
|
||||
testBestIndexObjOrderby(interp, pIdxInfo);
|
||||
break;
|
||||
|
||||
case 2: assert( sqlite3_stricmp(azSub[ii], "mask")==0 );
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pIdxInfo->colUsed));
|
||||
break;
|
||||
|
||||
case 3: assert( sqlite3_stricmp(azSub[ii], "distinct")==0 ); {
|
||||
int bDistinct = sqlite3_vtab_distinct(pIdxInfo);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(bDistinct));
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: assert( sqlite3_stricmp(azSub[ii], "in")==0 ); {
|
||||
int iCons;
|
||||
int bHandle;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iCons)
|
||||
|| Tcl_GetBooleanFromObj(interp, objv[3], &bHandle)
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewIntObj(sqlite3_vtab_in(pIdxInfo, iCons, bHandle))
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case 5: assert( sqlite3_stricmp(azSub[ii], "rhs_value")==0 ); {
|
||||
int iCons = 0;
|
||||
int rc;
|
||||
sqlite3_value *pVal = 0;
|
||||
const char *zVal = "";
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iCons) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_vtab_rhs_value(pIdxInfo, iCons, &pVal);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_NOTFOUND ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( pVal ){
|
||||
zVal = (const char*)sqlite3_value_text(pVal);
|
||||
}else if( objc==4 ){
|
||||
zVal = Tcl_GetString(objv[3]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zVal, -1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
tcl_vtab *pTab = (tcl_vtab*)tab;
|
||||
Tcl_Interp *interp = pTab->interp;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
static int iNext = 43;
|
||||
char zHdl[24];
|
||||
Tcl_Obj *pScript;
|
||||
|
||||
pScript = Tcl_DuplicateObj(pTab->pCmd);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("xBestIndex", -1));
|
||||
|
||||
sqlite3_snprintf(sizeof(zHdl), zHdl, "bestindex%d", iNext++);
|
||||
Tcl_CreateObjCommand(interp, zHdl, testBestIndexObj, pIdxInfo, 0);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zHdl, -1));
|
||||
rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
|
||||
Tcl_DeleteCommand(interp, zHdl);
|
||||
Tcl_DecrRefCount(pScript);
|
||||
|
||||
if( rc!=TCL_OK ){
|
||||
const char *zErr = Tcl_GetStringResult(interp);
|
||||
rc = SQLITE_ERROR;
|
||||
@ -489,6 +639,7 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
rc = SQLITE_ERROR;
|
||||
pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
|
||||
}else{
|
||||
int ii;
|
||||
int iArgv = 1;
|
||||
for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
|
||||
const char *zCmd = Tcl_GetString(apElem[ii]);
|
||||
|
||||
@ -239,7 +239,7 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "geopoly", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_JSON1
|
||||
#ifndef SQLITE_OMIT_JSON
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
|
||||
|
||||
@ -499,7 +499,8 @@ static void test_extract(
|
||||
mem.db = db;
|
||||
mem.enc = ENC(db);
|
||||
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
|
||||
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType);
|
||||
|
||||
if( iCurrent==iIdx ){
|
||||
sqlite3_result_value(context, &mem);
|
||||
@ -547,7 +548,8 @@ static void test_decode(
|
||||
mem.db = db;
|
||||
mem.enc = ENC(db);
|
||||
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
|
||||
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType);
|
||||
|
||||
switch( sqlite3_value_type(&mem) ){
|
||||
case SQLITE_TEXT:
|
||||
|
||||
@ -290,6 +290,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
|
||||
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
|
||||
return i;
|
||||
}else if( z[1]=='>' ){
|
||||
*tokenType = TK_PTR;
|
||||
return 2 + (z[2]=='>');
|
||||
}
|
||||
*tokenType = TK_MINUS;
|
||||
return 1;
|
||||
@ -559,13 +562,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
}
|
||||
|
||||
/*
|
||||
** Run the parser on the given SQL string. The parser structure is
|
||||
** passed in. An SQLITE_ status code is returned. If an error occurs
|
||||
** then an and attempt is made to write an error message into
|
||||
** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
|
||||
** error message.
|
||||
** Run the parser on the given SQL string.
|
||||
*/
|
||||
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
int sqlite3RunParser(Parse *pParse, const char *zSql){
|
||||
int nErr = 0; /* Number of errors encountered */
|
||||
void *pEngine; /* The LEMON-generated LALR(1) parser */
|
||||
int n = 0; /* Length of the next token token */
|
||||
@ -586,7 +585,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
}
|
||||
pParse->rc = SQLITE_OK;
|
||||
pParse->zTail = zSql;
|
||||
assert( pzErrMsg!=0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db->flags & SQLITE_ParserTrace ){
|
||||
printf("parser: [[[%s]]]\n", zSql);
|
||||
@ -629,6 +627,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
pParse->rc = SQLITE_INTERRUPT;
|
||||
pParse->nErr++;
|
||||
break;
|
||||
}
|
||||
if( tokenType==TK_SPACE ){
|
||||
@ -658,7 +657,10 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
|
||||
Token x;
|
||||
x.z = zSql;
|
||||
x.n = n;
|
||||
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -686,41 +688,26 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
if( db->mallocFailed ){
|
||||
pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
|
||||
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
|
||||
}
|
||||
assert( pzErrMsg!=0 );
|
||||
if( pParse->zErrMsg ){
|
||||
*pzErrMsg = pParse->zErrMsg;
|
||||
sqlite3_log(pParse->rc, "%s in \"%s\"",
|
||||
*pzErrMsg, pParse->zTail);
|
||||
pParse->zErrMsg = 0;
|
||||
if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
|
||||
if( pParse->zErrMsg==0 ){
|
||||
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
|
||||
}
|
||||
sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
|
||||
nErr++;
|
||||
}
|
||||
pParse->zTail = zSql;
|
||||
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
|
||||
sqlite3VdbeDelete(pParse->pVdbe);
|
||||
pParse->pVdbe = 0;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
if( pParse->nested==0 ){
|
||||
sqlite3DbFree(db, pParse->aTableLock);
|
||||
pParse->aTableLock = 0;
|
||||
pParse->nTableLock = 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_free(pParse->apVtabLock);
|
||||
#endif
|
||||
|
||||
if( !IN_SPECIAL_PARSE ){
|
||||
if( pParse->pNewTable && !IN_SPECIAL_PARSE ){
|
||||
/* If the pParse->declareVtab flag is set, do not delete any table
|
||||
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
|
||||
** will take responsibility for freeing the Table structure.
|
||||
*/
|
||||
sqlite3DeleteTable(db, pParse->pNewTable);
|
||||
}
|
||||
if( !IN_RENAME_OBJECT ){
|
||||
if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
}
|
||||
sqlite3DbFree(db, pParse->pVList);
|
||||
|
||||
@ -412,7 +412,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
sqlite3_str_appendf(&x, " fg.af=%x.%c",
|
||||
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable);
|
||||
sqlite3_str_appendf(&x, " iRJT=%d", pExpr->w.iRightJoinTable);
|
||||
}
|
||||
if( ExprHasProperty(pExpr, EP_FromDDL) ){
|
||||
sqlite3_str_appendf(&x, " DDL");
|
||||
|
||||
@ -446,6 +446,7 @@ static TriggerStep *triggerStepAllocate(
|
||||
sqlite3 *db = pParse->db;
|
||||
TriggerStep *pTriggerStep;
|
||||
|
||||
if( pParse->nErr ) return 0;
|
||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
|
||||
if( pTriggerStep ){
|
||||
char *z = (char*)&pTriggerStep[1];
|
||||
@ -918,6 +919,7 @@ static void codeReturningTrigger(
|
||||
|
||||
assert( v!=0 );
|
||||
assert( pParse->bReturning );
|
||||
assert( db->pParse==pParse );
|
||||
pReturning = pParse->u1.pReturning;
|
||||
assert( pTrigger == &(pReturning->retTrig) );
|
||||
memset(&sSelect, 0, sizeof(sSelect));
|
||||
@ -928,7 +930,8 @@ static void codeReturningTrigger(
|
||||
sFrom.a[0].pTab = pTab;
|
||||
sFrom.a[0].iCursor = -1;
|
||||
sqlite3SelectPrep(pParse, &sSelect, 0);
|
||||
if( db->mallocFailed==0 && pParse->nErr==0 ){
|
||||
if( pParse->nErr==0 ){
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3GenerateColumnNames(pParse, &sSelect);
|
||||
}
|
||||
sqlite3ExprListDelete(db, sSelect.pEList);
|
||||
@ -946,7 +949,7 @@ static void codeReturningTrigger(
|
||||
pParse->eTriggerOp = pTrigger->op;
|
||||
pParse->pTriggerTab = pTab;
|
||||
if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK
|
||||
&& !db->mallocFailed
|
||||
&& ALWAYS(!db->mallocFailed)
|
||||
){
|
||||
int i;
|
||||
int nCol = pNew->nExpr;
|
||||
@ -957,6 +960,9 @@ static void codeReturningTrigger(
|
||||
Expr *pCol = pNew->a[i].pExpr;
|
||||
assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
|
||||
sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
|
||||
if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
|
||||
@ -1107,8 +1113,8 @@ static TriggerPrg *codeRowTrigger(
|
||||
Vdbe *v; /* Temporary VM */
|
||||
NameContext sNC; /* Name context for sub-vdbe */
|
||||
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
|
||||
Parse *pSubParse; /* Parse context for sub-vdbe */
|
||||
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
|
||||
Parse sSubParse; /* Parse context for sub-vdbe */
|
||||
|
||||
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
|
||||
assert( pTop->pVdbe );
|
||||
@ -1130,19 +1136,17 @@ static TriggerPrg *codeRowTrigger(
|
||||
|
||||
/* Allocate and populate a new Parse context to use for coding the
|
||||
** trigger sub-program. */
|
||||
pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
|
||||
if( !pSubParse ) return 0;
|
||||
sqlite3ParseObjectInit(&sSubParse, db);
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = pSubParse;
|
||||
pSubParse->db = db;
|
||||
pSubParse->pTriggerTab = pTab;
|
||||
pSubParse->pToplevel = pTop;
|
||||
pSubParse->zAuthContext = pTrigger->zName;
|
||||
pSubParse->eTriggerOp = pTrigger->op;
|
||||
pSubParse->nQueryLoop = pParse->nQueryLoop;
|
||||
pSubParse->disableVtab = pParse->disableVtab;
|
||||
sNC.pParse = &sSubParse;
|
||||
sSubParse.pTriggerTab = pTab;
|
||||
sSubParse.pToplevel = pTop;
|
||||
sSubParse.zAuthContext = pTrigger->zName;
|
||||
sSubParse.eTriggerOp = pTrigger->op;
|
||||
sSubParse.nQueryLoop = pParse->nQueryLoop;
|
||||
sSubParse.disableVtab = pParse->disableVtab;
|
||||
|
||||
v = sqlite3GetVdbe(pSubParse);
|
||||
v = sqlite3GetVdbe(&sSubParse);
|
||||
if( v ){
|
||||
VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
|
||||
pTrigger->zName, onErrorText(orconf),
|
||||
@ -1168,14 +1172,14 @@ static TriggerPrg *codeRowTrigger(
|
||||
if( db->mallocFailed==0
|
||||
&& SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
|
||||
){
|
||||
iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
|
||||
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
|
||||
iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse);
|
||||
sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
sqlite3ExprDelete(db, pWhen);
|
||||
}
|
||||
|
||||
/* Code the trigger program into the sub-vdbe. */
|
||||
codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
|
||||
codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf);
|
||||
|
||||
/* Insert an OP_Halt at the end of the sub-program. */
|
||||
if( iEndTrigger ){
|
||||
@ -1183,23 +1187,24 @@ static TriggerPrg *codeRowTrigger(
|
||||
}
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
|
||||
transferParseError(pParse, &sSubParse);
|
||||
|
||||
transferParseError(pParse, pSubParse);
|
||||
if( db->mallocFailed==0 && pParse->nErr==0 ){
|
||||
if( pParse->nErr==0 ){
|
||||
assert( db->mallocFailed==0 );
|
||||
pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
|
||||
}
|
||||
pProgram->nMem = pSubParse->nMem;
|
||||
pProgram->nCsr = pSubParse->nTab;
|
||||
pProgram->nMem = sSubParse.nMem;
|
||||
pProgram->nCsr = sSubParse.nTab;
|
||||
pProgram->token = (void *)pTrigger;
|
||||
pPrg->aColmask[0] = pSubParse->oldmask;
|
||||
pPrg->aColmask[1] = pSubParse->newmask;
|
||||
pPrg->aColmask[0] = sSubParse.oldmask;
|
||||
pPrg->aColmask[1] = sSubParse.newmask;
|
||||
sqlite3VdbeDelete(v);
|
||||
}else{
|
||||
transferParseError(pParse, &sSubParse);
|
||||
}
|
||||
|
||||
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
|
||||
sqlite3ParserReset(pSubParse);
|
||||
sqlite3StackFree(db, pSubParse);
|
||||
|
||||
assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg );
|
||||
sqlite3ParseObjectReset(&sSubParse);
|
||||
return pPrg;
|
||||
}
|
||||
|
||||
@ -1232,6 +1237,7 @@ static TriggerPrg *getRowTrigger(
|
||||
/* If an existing TriggerPrg could not be located, create a new one. */
|
||||
if( !pPrg ){
|
||||
pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
|
||||
pParse->db->errByteOffset = -1;
|
||||
}
|
||||
|
||||
return pPrg;
|
||||
@ -1254,7 +1260,7 @@ void sqlite3CodeRowTriggerDirect(
|
||||
Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
|
||||
TriggerPrg *pPrg;
|
||||
pPrg = getRowTrigger(pParse, p, pTab, orconf);
|
||||
assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
|
||||
assert( pPrg || pParse->nErr );
|
||||
|
||||
/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
|
||||
** is a pointer to the sub-vdbe containing the trigger program. */
|
||||
|
||||
14
src/update.c
14
src/update.c
@ -347,9 +347,11 @@ void sqlite3Update(
|
||||
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
db = pParse->db;
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
assert( db->pParse==pParse );
|
||||
if( pParse->nErr ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
assert( db->mallocFailed==0 );
|
||||
|
||||
/* Locate the table which we want to update.
|
||||
*/
|
||||
@ -721,7 +723,7 @@ void sqlite3Update(
|
||||
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
|
||||
flags |= WHERE_ONEPASS_MULTIROW;
|
||||
}
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags,iIdxCur);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur);
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
|
||||
/* A one-pass strategy that might update more than one row may not
|
||||
@ -1121,9 +1123,7 @@ void sqlite3Update(
|
||||
** that information.
|
||||
*/
|
||||
if( regRowCount ){
|
||||
sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
|
||||
sqlite3CodeChangeCount(v, regRowCount, "rows updated");
|
||||
}
|
||||
|
||||
update_cleanup:
|
||||
@ -1245,7 +1245,9 @@ static void updateVirtualTable(
|
||||
regRowid = ++pParse->nMem;
|
||||
|
||||
/* Start scanning the virtual table */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc,pWhere,0,0,WHERE_ONEPASS_DESIRED,0);
|
||||
pWInfo = sqlite3WhereBegin(
|
||||
pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0
|
||||
);
|
||||
if( pWInfo==0 ) return;
|
||||
|
||||
/* Populate the argument registers. */
|
||||
|
||||
51
src/util.c
51
src/util.c
@ -117,7 +117,11 @@ static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){
|
||||
void sqlite3Error(sqlite3 *db, int err_code){
|
||||
assert( db!=0 );
|
||||
db->errCode = err_code;
|
||||
if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
|
||||
if( err_code || db->pErr ){
|
||||
sqlite3ErrorFinish(db, err_code);
|
||||
}else{
|
||||
db->errByteOffset = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,6 +131,7 @@ void sqlite3Error(sqlite3 *db, int err_code){
|
||||
void sqlite3ErrorClear(sqlite3 *db){
|
||||
assert( db!=0 );
|
||||
db->errCode = SQLITE_OK;
|
||||
db->errByteOffset = -1;
|
||||
if( db->pErr ) sqlite3ValueSetNull(db->pErr);
|
||||
}
|
||||
|
||||
@ -147,17 +152,8 @@ void sqlite3SystemError(sqlite3 *db, int rc){
|
||||
** handle "db". The error code is set to "err_code".
|
||||
**
|
||||
** If it is not NULL, string zFormat specifies the format of the
|
||||
** error string in the style of the printf functions: The following
|
||||
** format characters are allowed:
|
||||
**
|
||||
** %s Insert a string
|
||||
** %z A string that should be freed after use
|
||||
** %d Insert an integer
|
||||
** %T Insert a token
|
||||
** %S Insert the first element of a SrcList
|
||||
**
|
||||
** zFormat and any string tokens that follow it are assumed to be
|
||||
** encoded in UTF-8.
|
||||
** error string. zFormat and any string tokens that follow it are
|
||||
** assumed to be encoded in UTF-8.
|
||||
**
|
||||
** To clear the most recent error for sqlite handle "db", sqlite3Error
|
||||
** should be called with err_code set to SQLITE_OK and zFormat set
|
||||
@ -181,13 +177,6 @@ void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){
|
||||
|
||||
/*
|
||||
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
|
||||
** The following formatting characters are allowed:
|
||||
**
|
||||
** %s Insert a string
|
||||
** %z A string that should be freed after use
|
||||
** %d Insert an integer
|
||||
** %T Insert a token
|
||||
** %S Insert the first element of a SrcList
|
||||
**
|
||||
** This function should be used to report any error that occurs while
|
||||
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
|
||||
@ -200,11 +189,19 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
|
||||
char *zMsg;
|
||||
va_list ap;
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( db!=0 );
|
||||
assert( db->pParse==pParse );
|
||||
db->errByteOffset = -2;
|
||||
va_start(ap, zFormat);
|
||||
zMsg = sqlite3VMPrintf(db, zFormat, ap);
|
||||
va_end(ap);
|
||||
if( db->errByteOffset<-1 ) db->errByteOffset = -1;
|
||||
if( db->suppressErr ){
|
||||
sqlite3DbFree(db, zMsg);
|
||||
if( db->mallocFailed ){
|
||||
pParse->nErr++;
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
pParse->nErr++;
|
||||
sqlite3DbFree(db, pParse->zErrMsg);
|
||||
@ -1588,7 +1585,6 @@ LogEst sqlite3LogEst(u64 x){
|
||||
return a[x&7] + y - 10;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Convert a double into a LogEst
|
||||
** In other words, compute an approximation for 10*log2(x).
|
||||
@ -1603,16 +1599,9 @@ LogEst sqlite3LogEstFromDouble(double x){
|
||||
e = (a>>52) - 1022;
|
||||
return e*10;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
|
||||
defined(SQLITE_ENABLE_STAT4) || \
|
||||
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
||||
/*
|
||||
** Convert a LogEst into an integer.
|
||||
**
|
||||
** Note that this routine is only used when one or more of various
|
||||
** non-standard compile-time options is enabled.
|
||||
*/
|
||||
u64 sqlite3LogEstToInt(LogEst x){
|
||||
u64 n;
|
||||
@ -1620,17 +1609,9 @@ u64 sqlite3LogEstToInt(LogEst x){
|
||||
x /= 10;
|
||||
if( n>=5 ) n -= 2;
|
||||
else if( n>=1 ) n -= 1;
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
|
||||
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
||||
if( x>60 ) return (u64)LARGEST_INT64;
|
||||
#else
|
||||
/* If only SQLITE_ENABLE_STAT4 is on, then the largest input
|
||||
** possible to this routine is 310, resulting in a maximum x of 31 */
|
||||
assert( x<=60 );
|
||||
#endif
|
||||
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
|
||||
}
|
||||
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
|
||||
|
||||
/*
|
||||
** Add a new name/number pair to a VList. This might require that the
|
||||
|
||||
218
src/vdbe.c
218
src/vdbe.c
@ -241,7 +241,6 @@ static VdbeCursor *allocateCursor(
|
||||
Vdbe *p, /* The virtual machine */
|
||||
int iCur, /* Index of the new VdbeCursor */
|
||||
int nField, /* Number of fields in the table or index */
|
||||
int iDb, /* Database the cursor belongs to, or -1 */
|
||||
u8 eCurType /* Type of the new cursor */
|
||||
){
|
||||
/* Find the memory cell that will be used to store the blob of memory
|
||||
@ -298,7 +297,6 @@ static VdbeCursor *allocateCursor(
|
||||
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
|
||||
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
|
||||
pCx->eCurType = eCurType;
|
||||
pCx->iDb = iDb;
|
||||
pCx->nField = nField;
|
||||
pCx->aOffset = &pCx->aType[nField];
|
||||
if( eCurType==CURTYPE_BTREE ){
|
||||
@ -671,6 +669,29 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
|
||||
** with pOp->p3. Return the hash.
|
||||
*/
|
||||
static u64 filterHash(const Mem *aMem, const Op *pOp){
|
||||
int i, mx;
|
||||
u64 h = 0;
|
||||
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){
|
||||
const Mem *p = &aMem[i];
|
||||
if( p->flags & (MEM_Int|MEM_IntReal) ){
|
||||
h += p->u.i;
|
||||
}else if( p->flags & MEM_Real ){
|
||||
h += sqlite3VdbeIntValue(p);
|
||||
}else if( p->flags & (MEM_Str|MEM_Blob) ){
|
||||
h += p->n;
|
||||
if( p->flags & MEM_Zero ) h += p->u.nZero;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the symbolic name for the data type of a pMem
|
||||
*/
|
||||
@ -1325,12 +1346,18 @@ case OP_SoftNull: {
|
||||
** Synopsis: r[P2]=P4 (len=P1)
|
||||
**
|
||||
** P4 points to a blob of data P1 bytes long. Store this
|
||||
** blob in register P2.
|
||||
** blob in register P2. If P4 is a NULL pointer, then construct
|
||||
** a zero-filled blob that is P1 bytes long in P2.
|
||||
*/
|
||||
case OP_Blob: { /* out2 */
|
||||
assert( pOp->p1 <= SQLITE_MAX_LENGTH );
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
|
||||
if( pOp->p4.z==0 ){
|
||||
sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1);
|
||||
if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem;
|
||||
}else{
|
||||
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
|
||||
}
|
||||
pOut->enc = encoding;
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
break;
|
||||
@ -1479,24 +1506,22 @@ case OP_IntCopy: { /* out2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ChngCntRow P1 P2 * * *
|
||||
** Synopsis: output=r[P1]
|
||||
/* Opcode: FkCheck * * * * *
|
||||
**
|
||||
** Output value in register P1 as the chance count for a DML statement,
|
||||
** due to the "PRAGMA count_changes=ON" setting. Or, if there was a
|
||||
** foreign key error in the statement, trigger the error now.
|
||||
** Halt with an SQLITE_CONSTRAINT error if there are any unresolved
|
||||
** foreign key constraint violations. If there are no foreign key
|
||||
** constraint violations, this is a no-op.
|
||||
**
|
||||
** This opcode is a variant of OP_ResultRow that checks the foreign key
|
||||
** immediate constraint count and throws an error if the count is
|
||||
** non-zero. The P2 opcode must be 1.
|
||||
** FK constraint violations are also checked when the prepared statement
|
||||
** exits. This opcode is used to raise foreign key constraint errors prior
|
||||
** to returning results such as a row change count or the result of a
|
||||
** RETURNING clause.
|
||||
*/
|
||||
case OP_ChngCntRow: {
|
||||
assert( pOp->p2==1 );
|
||||
case OP_FkCheck: {
|
||||
if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
/* Fall through to the next case, OP_ResultRow */
|
||||
/* no break */ deliberate_fall_through
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ResultRow P1 P2 * * *
|
||||
@ -2134,7 +2159,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
||||
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
||||
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
||||
if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
|
||||
if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str;
|
||||
}
|
||||
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
||||
testcase( pIn3->flags & MEM_Int );
|
||||
@ -2602,10 +2627,18 @@ case OP_Offset: { /* out3 */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
pOut = &p->aMem[pOp->p3];
|
||||
if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
|
||||
if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
}else{
|
||||
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
|
||||
if( pC->deferredMoveto ){
|
||||
rc = sqlite3VdbeFinishMoveto(pC);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
}
|
||||
if( sqlite3BtreeEof(pC->uc.pCursor) ){
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
}else{
|
||||
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2664,6 +2697,7 @@ case OP_Column: {
|
||||
assert( pC!=0 );
|
||||
assert( p2<(u32)pC->nField );
|
||||
aOffset = pC->aOffset;
|
||||
assert( aOffset==pC->aType+pC->nField );
|
||||
assert( pC->eCurType!=CURTYPE_VTAB );
|
||||
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
|
||||
assert( pC->eCurType!=CURTYPE_SORTER );
|
||||
@ -2959,6 +2993,8 @@ case OP_TypeCheck: {
|
||||
break;
|
||||
}
|
||||
case COLTYPE_REAL: {
|
||||
testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real );
|
||||
testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal );
|
||||
if( pIn1->flags & MEM_Int ){
|
||||
/* When applying REAL affinity, if the result is still an MEM_Int
|
||||
** that will fit in 6 bytes, then change the type to MEM_IntReal
|
||||
@ -2976,7 +3012,7 @@ case OP_TypeCheck: {
|
||||
pIn1->flags |= MEM_Real;
|
||||
pIn1->flags &= ~MEM_Int;
|
||||
}
|
||||
}else if( (pIn1->flags & MEM_Real)==0 ){
|
||||
}else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){
|
||||
goto vdbe_type_error;
|
||||
}
|
||||
break;
|
||||
@ -3215,7 +3251,7 @@ case OP_MakeRecord: {
|
||||
testcase( uu==127 ); testcase( uu==128 );
|
||||
testcase( uu==32767 ); testcase( uu==32768 );
|
||||
testcase( uu==8388607 ); testcase( uu==8388608 );
|
||||
testcase( uu==2147483647 ); testcase( uu==2147483648 );
|
||||
testcase( uu==2147483647 ); testcase( uu==2147483648LL );
|
||||
testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL );
|
||||
if( uu<=127 ){
|
||||
if( (i&1)==i && file_format>=4 ){
|
||||
@ -3343,7 +3379,7 @@ case OP_MakeRecord: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Count P1 P2 p3 * *
|
||||
/* Opcode: Count P1 P2 P3 * *
|
||||
** Synopsis: r[P2]=count()
|
||||
**
|
||||
** Store the number of entries (an integer value) in the table or index
|
||||
@ -3991,8 +4027,9 @@ case OP_OpenWrite:
|
||||
assert( pOp->p1>=0 );
|
||||
assert( nField>=0 );
|
||||
testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
|
||||
pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE);
|
||||
pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE);
|
||||
if( pCur==0 ) goto no_mem;
|
||||
pCur->iDb = iDb;
|
||||
pCur->nullRow = 1;
|
||||
pCur->isOrdered = 1;
|
||||
pCur->pgnoRoot = p2;
|
||||
@ -4034,7 +4071,7 @@ case OP_OpenDup: {
|
||||
assert( pOrig );
|
||||
assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */
|
||||
|
||||
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
|
||||
pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->nullRow = 1;
|
||||
pCx->isEphemeral = 1;
|
||||
@ -4042,10 +4079,10 @@ case OP_OpenDup: {
|
||||
pCx->isTable = pOrig->isTable;
|
||||
pCx->pgnoRoot = pOrig->pgnoRoot;
|
||||
pCx->isOrdered = pOrig->isOrdered;
|
||||
pCx->pBtx = pOrig->pBtx;
|
||||
pCx->ub.pBtx = pOrig->ub.pBtx;
|
||||
pCx->hasBeenDuped = 1;
|
||||
pOrig->hasBeenDuped = 1;
|
||||
rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
|
||||
rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
|
||||
pCx->pKeyInfo, pCx->uc.pCursor);
|
||||
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
|
||||
** opened for a database. Since there is already an open cursor when this
|
||||
@ -4118,16 +4155,16 @@ case OP_OpenEphemeral: {
|
||||
assert( pCx->isEphemeral );
|
||||
pCx->seqCount = 0;
|
||||
pCx->cacheStatus = CACHE_STALE;
|
||||
rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
|
||||
rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0);
|
||||
}else{
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->isEphemeral = 1;
|
||||
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
|
||||
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx,
|
||||
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
|
||||
vfsFlags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If a transient index is required, create it by calling
|
||||
** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
|
||||
@ -4136,26 +4173,26 @@ case OP_OpenEphemeral: {
|
||||
*/
|
||||
if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
|
||||
assert( pOp->p4type==P4_KEYINFO );
|
||||
rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
|
||||
rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot,
|
||||
BTREE_BLOBKEY | pOp->p5);
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
|
||||
assert( pKeyInfo->db==db );
|
||||
assert( pKeyInfo->enc==ENC(db) );
|
||||
rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
|
||||
rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
|
||||
pKeyInfo, pCx->uc.pCursor);
|
||||
}
|
||||
pCx->isTable = 0;
|
||||
}else{
|
||||
pCx->pgnoRoot = SCHEMA_ROOT;
|
||||
rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
|
||||
rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR,
|
||||
0, pCx->uc.pCursor);
|
||||
pCx->isTable = 1;
|
||||
}
|
||||
}
|
||||
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
|
||||
if( rc ){
|
||||
sqlite3BtreeClose(pCx->pBtx);
|
||||
sqlite3BtreeClose(pCx->ub.pBtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4179,7 +4216,7 @@ case OP_SorterOpen: {
|
||||
|
||||
assert( pOp->p1>=0 );
|
||||
assert( pOp->p2>=0 );
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER);
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
||||
assert( pCx->pKeyInfo->db==db );
|
||||
@ -4228,7 +4265,7 @@ case OP_OpenPseudo: {
|
||||
|
||||
assert( pOp->p1>=0 );
|
||||
assert( pOp->p3>=0 );
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->nullRow = 1;
|
||||
pCx->seekResult = pOp->p2;
|
||||
@ -5680,6 +5717,10 @@ case OP_Rowid: { /* out2 */
|
||||
** Move the cursor P1 to a null row. Any OP_Column operations
|
||||
** that occur while the cursor is on the null row will always
|
||||
** write a NULL.
|
||||
**
|
||||
** Or, if P1 is a Pseudo-Cursor (a cursor opened using OP_OpenPseudo)
|
||||
** just reset the cache for that cursor. This causes the row of
|
||||
** content held by the pseudo-cursor to be reparsed.
|
||||
*/
|
||||
case OP_NullRow: {
|
||||
VdbeCursor *pC;
|
||||
@ -6168,9 +6209,9 @@ case OP_IdxRowid: { /* out2 */
|
||||
pTabCur->movetoTarget = rowid;
|
||||
pTabCur->deferredMoveto = 1;
|
||||
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
|
||||
pTabCur->aAltMap = pOp->p4.ai;
|
||||
assert( !pC->isEphemeral );
|
||||
assert( !pTabCur->isEphemeral );
|
||||
pTabCur->ub.aAltMap = pOp->p4.ai;
|
||||
assert( !pC->isEphemeral );
|
||||
pTabCur->pAltCursor = pC;
|
||||
}else{
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
@ -7692,7 +7733,7 @@ case OP_VOpen: {
|
||||
pVCur->pVtab = pVtab;
|
||||
|
||||
/* Initialize vdbe cursor object */
|
||||
pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB);
|
||||
pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB);
|
||||
if( pCur ){
|
||||
pCur->uc.pVCur = pVCur;
|
||||
pVtab->nRef++;
|
||||
@ -7705,6 +7746,34 @@ case OP_VOpen: {
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VInitIn P1 P2 P3 * *
|
||||
** Synopsis: r[P2]=ValueList(P1,P3)
|
||||
**
|
||||
** Set register P2 to be a pointer to a ValueList object for cursor P1
|
||||
** with cache register P3 and output register P3+1. This ValueList object
|
||||
** can be used as the first argument to sqlite3_vtab_in_first() and
|
||||
** sqlite3_vtab_in_next() to extract all of the values stored in the P1
|
||||
** cursor. Register P3 is used to hold the values returned by
|
||||
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next().
|
||||
*/
|
||||
case OP_VInitIn: { /* out2 */
|
||||
VdbeCursor *pC; /* The cursor containing the RHS values */
|
||||
ValueList *pRhs; /* New ValueList object to put in reg[P2] */
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
pRhs = sqlite3_malloc64( sizeof(*pRhs) );
|
||||
if( pRhs==0 ) goto no_mem;
|
||||
pRhs->pCsr = pC->uc.pCursor;
|
||||
pRhs->pOut = &aMem[pOp->p3];
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
pOut->flags = MEM_Null;
|
||||
sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Opcode: VFilter P1 P2 P3 P4 *
|
||||
** Synopsis: iplan=r[P3] zplan='P4'
|
||||
@ -8130,6 +8199,77 @@ case OP_Function: { /* group */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: FilterAdd P1 * P3 P4 *
|
||||
** Synopsis: filter(P1) += key(P3@P4)
|
||||
**
|
||||
** Compute a hash on the P4 registers starting with r[P3] and
|
||||
** add that hash to the bloom filter contained in r[P1].
|
||||
*/
|
||||
case OP_FilterAdd: {
|
||||
u64 h;
|
||||
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pIn1->flags & MEM_Blob );
|
||||
assert( pIn1->n>0 );
|
||||
h = filterHash(aMem, pOp);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db->flags&SQLITE_VdbeTrace ){
|
||||
int ii;
|
||||
for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
|
||||
registerTrace(ii, &aMem[ii]);
|
||||
}
|
||||
printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
|
||||
}
|
||||
#endif
|
||||
h %= pIn1->n;
|
||||
pIn1->z[h/8] |= 1<<(h&7);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Filter P1 P2 P3 P4 *
|
||||
** Synopsis: if key(P3@P4) not in filter(P1) goto P2
|
||||
**
|
||||
** Compute a hash on the key contained in the P4 registers starting
|
||||
** with r[P3]. Check to see if that hash is found in the
|
||||
** bloom filter hosted by register P1. If it is not present then
|
||||
** maybe jump to P2. Otherwise fall through.
|
||||
**
|
||||
** False negatives are harmless. It is always safe to fall through,
|
||||
** even if the value is in the bloom filter. A false negative causes
|
||||
** more CPU cycles to be used, but it should still yield the correct
|
||||
** answer. However, an incorrect answer may well arise from a
|
||||
** false positive - if the jump is taken when it should fall through.
|
||||
*/
|
||||
case OP_Filter: { /* jump */
|
||||
u64 h;
|
||||
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Blob)!=0 );
|
||||
assert( pIn1->n >= 1 );
|
||||
h = filterHash(aMem, pOp);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db->flags&SQLITE_VdbeTrace ){
|
||||
int ii;
|
||||
for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
|
||||
registerTrace(ii, &aMem[ii]);
|
||||
}
|
||||
printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
|
||||
}
|
||||
#endif
|
||||
h %= pIn1->n;
|
||||
if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){
|
||||
VdbeBranchTaken(1, 2);
|
||||
p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++;
|
||||
goto jump_to_p2;
|
||||
}else{
|
||||
p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++;
|
||||
VdbeBranchTaken(0, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Trace P1 P2 * P4 *
|
||||
**
|
||||
** Write P4 on the statement trace output if statement tracing is
|
||||
|
||||
@ -75,7 +75,7 @@ typedef struct AuxData AuxData;
|
||||
typedef struct VdbeCursor VdbeCursor;
|
||||
struct VdbeCursor {
|
||||
u8 eCurType; /* One of the CURTYPE_* values above */
|
||||
i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
|
||||
i8 iDb; /* Index of cursor database in db->aDb[] */
|
||||
u8 nullRow; /* True if pointing to a row with no data */
|
||||
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
|
||||
u8 isTable; /* True for rowid tables. False for indexes */
|
||||
@ -88,9 +88,11 @@ struct VdbeCursor {
|
||||
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
|
||||
Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */
|
||||
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
|
||||
Btree *pBtx; /* Separate file holding temporary table */
|
||||
union { /* pBtx for isEphermeral. pAltMap otherwise */
|
||||
Btree *pBtx; /* Separate file holding temporary table */
|
||||
u32 *aAltMap; /* Mapping from table to index column numbers */
|
||||
} ub;
|
||||
i64 seqCount; /* Sequence counter */
|
||||
u32 *aAltMap; /* Mapping from table to index column numbers */
|
||||
|
||||
/* Cached OP_Column parse information is only valid if cacheStatus matches
|
||||
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
|
||||
@ -430,7 +432,7 @@ struct Vdbe {
|
||||
bft bIsReader:1; /* True for statements that read */
|
||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
|
||||
u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */
|
||||
char *zSql; /* Text of the SQL statement that generated this */
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
char *zNormSql; /* Normalization of the associated SQL statement */
|
||||
@ -480,6 +482,24 @@ struct PreUpdate {
|
||||
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of this object is used to pass an vector of values into
|
||||
** OP_VFilter, the xFilter method of a virtual table. The vector is the
|
||||
** set of values on the right-hand side of an IN constraint.
|
||||
**
|
||||
** The value as passed into xFilter is an sqlite3_value with a "pointer"
|
||||
** type, such as is generated by sqlite3_result_pointer() and read by
|
||||
** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null
|
||||
** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces
|
||||
** know how to use this object to step through all the values in the
|
||||
** right operand of the IN constraint.
|
||||
*/
|
||||
typedef struct ValueList ValueList;
|
||||
struct ValueList {
|
||||
BtCursor *pCsr; /* An ephemeral table holding all values */
|
||||
sqlite3_value *pOut; /* Register to hold each decoded output value */
|
||||
};
|
||||
|
||||
/*
|
||||
** Function prototypes
|
||||
*/
|
||||
@ -492,7 +512,7 @@ int sqlite3VdbeCursorRestore(VdbeCursor*);
|
||||
u32 sqlite3VdbeSerialTypeLen(u32);
|
||||
u8 sqlite3VdbeOneByteSerialTypeLen(u8);
|
||||
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
|
||||
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
|
||||
|
||||
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||
@ -538,7 +558,7 @@ int sqlite3VdbeMemSetRowSet(Mem*);
|
||||
int sqlite3VdbeMemMakeWriteable(Mem*);
|
||||
int sqlite3VdbeMemStringify(Mem*, u8, u8);
|
||||
int sqlite3IntFloatCompare(i64,double);
|
||||
i64 sqlite3VdbeIntValue(Mem*);
|
||||
i64 sqlite3VdbeIntValue(const Mem*);
|
||||
int sqlite3VdbeMemIntegerify(Mem*);
|
||||
double sqlite3VdbeRealValue(Mem*);
|
||||
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
|
||||
|
||||
@ -846,6 +846,70 @@ int sqlite3_vtab_nochange(sqlite3_context *p){
|
||||
return sqlite3_value_nochange(p->pOut);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of sqlite3_vtab_in_first() (if bNext==0) and
|
||||
** sqlite3_vtab_in_next() (if bNext!=0).
|
||||
*/
|
||||
static int valueFromValueList(
|
||||
sqlite3_value *pVal, /* Pointer to the ValueList object */
|
||||
sqlite3_value **ppOut, /* Store the next value from the list here */
|
||||
int bNext /* 1 for _next(). 0 for _first() */
|
||||
){
|
||||
int rc;
|
||||
ValueList *pRhs;
|
||||
|
||||
*ppOut = 0;
|
||||
if( pVal==0 ) return SQLITE_MISUSE;
|
||||
pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList");
|
||||
if( pRhs==0 ) return SQLITE_MISUSE;
|
||||
if( bNext ){
|
||||
rc = sqlite3BtreeNext(pRhs->pCsr, 0);
|
||||
}else{
|
||||
int dummy = 0;
|
||||
rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy);
|
||||
assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) );
|
||||
if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
u32 sz; /* Size of current row in bytes */
|
||||
Mem sMem; /* Raw content of current row */
|
||||
memset(&sMem, 0, sizeof(sMem));
|
||||
sz = sqlite3BtreePayloadSize(pRhs->pCsr);
|
||||
rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *zBuf = (u8*)sMem.z;
|
||||
u32 iSerial;
|
||||
sqlite3_value *pOut = pRhs->pOut;
|
||||
int iOff = 1 + getVarint32(&zBuf[1], iSerial);
|
||||
sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut);
|
||||
pOut->enc = ENC(pOut->db);
|
||||
if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
*ppOut = pOut;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeMemRelease(&sMem);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the iterator value pVal to point to the first value in the set.
|
||||
** Set (*ppOut) to point to this value before returning.
|
||||
*/
|
||||
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){
|
||||
return valueFromValueList(pVal, ppOut, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the iterator value pVal to point to the next value in the set.
|
||||
** Set (*ppOut) to point to this value before returning.
|
||||
*/
|
||||
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){
|
||||
return valueFromValueList(pVal, ppOut, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time for a statement. If the current time
|
||||
** is requested more than once within the same run of a single prepared
|
||||
@ -1530,7 +1594,10 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
|
||||
break;
|
||||
}
|
||||
case SQLITE_FLOAT: {
|
||||
rc = sqlite3_bind_double(pStmt, i, pValue->u.r);
|
||||
assert( pValue->flags & (MEM_Real|MEM_IntReal) );
|
||||
rc = sqlite3_bind_double(pStmt, i,
|
||||
(pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i
|
||||
);
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
|
||||
@ -1378,8 +1378,7 @@ void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
|
||||
*/
|
||||
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
|
||||
assert( p->nOp>0 || p->aOp==0 );
|
||||
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
|
||||
|| p->pParse->nErr>0 );
|
||||
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 );
|
||||
if( p->nOp ){
|
||||
assert( p->aOp );
|
||||
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
|
||||
@ -2470,8 +2469,6 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
if( pCx==0 ){
|
||||
return;
|
||||
}
|
||||
assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
|
||||
assert( pCx->pBtx==0 || pCx->isEphemeral );
|
||||
switch( pCx->eCurType ){
|
||||
case CURTYPE_SORTER: {
|
||||
sqlite3VdbeSorterClose(p->db, pCx);
|
||||
@ -3252,6 +3249,7 @@ int sqlite3VdbeTransferError(Vdbe *p){
|
||||
sqlite3ValueSetNull(db->pErr);
|
||||
}
|
||||
db->errCode = rc;
|
||||
db->errByteOffset = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3573,7 +3571,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){
|
||||
if( p->deferredMoveto ){
|
||||
u32 iMap;
|
||||
assert( !p->isEphemeral );
|
||||
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
|
||||
if( p->ub.aAltMap && (iMap = p->ub.aAltMap[1+*piCol])>0 && !p->nullRow ){
|
||||
*pp = p->pAltCursor;
|
||||
*piCol = iMap - 1;
|
||||
return SQLITE_OK;
|
||||
@ -3851,14 +3849,14 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
||||
|
||||
/*
|
||||
** Deserialize the data blob pointed to by buf as serial type serial_type
|
||||
** and store the result in pMem. Return the number of bytes read.
|
||||
** and store the result in pMem.
|
||||
**
|
||||
** This function is implemented as two separate routines for performance.
|
||||
** The few cases that require local variables are broken out into a separate
|
||||
** routine so that in most cases the overhead of moving the stack pointer
|
||||
** is avoided.
|
||||
*/
|
||||
static u32 serialGet(
|
||||
static void serialGet(
|
||||
const unsigned char *buf, /* Buffer to deserialize from */
|
||||
u32 serial_type, /* Serial type to deserialize */
|
||||
Mem *pMem /* Memory cell to write value into */
|
||||
@ -3892,9 +3890,8 @@ static u32 serialGet(
|
||||
memcpy(&pMem->u.r, &x, sizeof(x));
|
||||
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
u32 sqlite3VdbeSerialGet(
|
||||
void sqlite3VdbeSerialGet(
|
||||
const unsigned char *buf, /* Buffer to deserialize from */
|
||||
u32 serial_type, /* Serial type to deserialize */
|
||||
Mem *pMem /* Memory cell to write value into */
|
||||
@ -3905,13 +3902,13 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->flags = MEM_Null|MEM_Zero;
|
||||
pMem->n = 0;
|
||||
pMem->u.nZero = 0;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
case 11: /* Reserved for future use */
|
||||
case 0: { /* Null */
|
||||
/* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
|
||||
pMem->flags = MEM_Null;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
/* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement
|
||||
@ -3919,7 +3916,7 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->u.i = ONE_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
case 2: { /* 2-byte signed integer */
|
||||
/* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit
|
||||
@ -3927,7 +3924,7 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->u.i = TWO_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 2;
|
||||
return;
|
||||
}
|
||||
case 3: { /* 3-byte signed integer */
|
||||
/* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit
|
||||
@ -3935,7 +3932,7 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->u.i = THREE_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 3;
|
||||
return;
|
||||
}
|
||||
case 4: { /* 4-byte signed integer */
|
||||
/* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
|
||||
@ -3947,7 +3944,7 @@ u32 sqlite3VdbeSerialGet(
|
||||
#endif
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 4;
|
||||
return;
|
||||
}
|
||||
case 5: { /* 6-byte signed integer */
|
||||
/* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
|
||||
@ -3955,13 +3952,14 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 6;
|
||||
return;
|
||||
}
|
||||
case 6: /* 8-byte signed integer */
|
||||
case 7: { /* IEEE floating point */
|
||||
/* These use local variables, so do them in a separate routine
|
||||
** to avoid having to move the frame pointer in the common case */
|
||||
return serialGet(buf,serial_type,pMem);
|
||||
serialGet(buf,serial_type,pMem);
|
||||
return;
|
||||
}
|
||||
case 8: /* Integer 0 */
|
||||
case 9: { /* Integer 1 */
|
||||
@ -3969,7 +3967,7 @@ u32 sqlite3VdbeSerialGet(
|
||||
/* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */
|
||||
pMem->u.i = serial_type-8;
|
||||
pMem->flags = MEM_Int;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
/* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in
|
||||
@ -3980,10 +3978,10 @@ u32 sqlite3VdbeSerialGet(
|
||||
pMem->z = (char *)buf;
|
||||
pMem->n = (serial_type-12)/2;
|
||||
pMem->flags = aFlag[serial_type&1];
|
||||
return pMem->n;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** This routine is used to allocate sufficient space for an UnpackedRecord
|
||||
@ -4046,7 +4044,8 @@ void sqlite3VdbeRecordUnpack(
|
||||
/* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
|
||||
pMem->szMalloc = 0;
|
||||
pMem->z = 0;
|
||||
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
|
||||
sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
|
||||
d += sqlite3VdbeSerialTypeLen(serial_type);
|
||||
pMem++;
|
||||
if( (++u)>=p->nField ) break;
|
||||
}
|
||||
@ -4130,7 +4129,8 @@ static int vdbeRecordCompareDebug(
|
||||
|
||||
/* Extract the values to be compared.
|
||||
*/
|
||||
d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
|
||||
sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
|
||||
d1 += sqlite3VdbeSerialTypeLen(serial_type1);
|
||||
|
||||
/* Do the comparison
|
||||
*/
|
||||
|
||||
@ -152,10 +152,9 @@ int sqlite3_blob_open(
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
|
||||
do {
|
||||
memset(&sParse, 0, sizeof(Parse));
|
||||
while(1){
|
||||
sqlite3ParseObjectInit(&sParse,db);
|
||||
if( !pBlob ) goto blob_open_out;
|
||||
sParse.db = db;
|
||||
sqlite3DbFree(db, zErr);
|
||||
zErr = 0;
|
||||
|
||||
@ -332,7 +331,9 @@ int sqlite3_blob_open(
|
||||
goto blob_open_out;
|
||||
}
|
||||
rc = blobSeekToRow(pBlob, iRow, &zErr);
|
||||
} while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
|
||||
if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break;
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
}
|
||||
|
||||
blob_open_out:
|
||||
if( rc==SQLITE_OK && db->mallocFailed==0 ){
|
||||
@ -343,7 +344,7 @@ blob_open_out:
|
||||
}
|
||||
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
|
||||
@ -596,12 +596,12 @@ static SQLITE_NOINLINE i64 doubleToInt64(double r){
|
||||
**
|
||||
** If pMem represents a string value, its encoding might be changed.
|
||||
*/
|
||||
static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
|
||||
static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){
|
||||
i64 value = 0;
|
||||
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
|
||||
return value;
|
||||
}
|
||||
i64 sqlite3VdbeIntValue(Mem *pMem){
|
||||
i64 sqlite3VdbeIntValue(const Mem *pMem){
|
||||
int flags;
|
||||
assert( pMem!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
@ -916,6 +916,7 @@ void sqlite3VdbeMemSetPointer(
|
||||
void (*xDestructor)(void*)
|
||||
){
|
||||
assert( pMem->flags==MEM_Null );
|
||||
vdbeMemClear(pMem);
|
||||
pMem->u.zPType = zPType ? zPType : "";
|
||||
pMem->z = pPtr;
|
||||
pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
|
||||
@ -1530,11 +1531,7 @@ static int valueFromExpr(
|
||||
|
||||
assert( pExpr!=0 );
|
||||
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
if( op==TK_REGISTER ) op = pExpr->op2;
|
||||
#else
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
#endif
|
||||
|
||||
/* Compressed expressions only appear when parsing the DEFAULT clause
|
||||
** on a table column definition, and hence only when pCtx==0. This
|
||||
@ -1649,7 +1646,7 @@ static int valueFromExpr(
|
||||
|
||||
no_mem:
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
if( pCtx==0 || pCtx->pParse->nErr==0 )
|
||||
if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) )
|
||||
#endif
|
||||
sqlite3OomFault(db);
|
||||
sqlite3DbFree(db, zVal);
|
||||
|
||||
@ -960,7 +960,8 @@ int sqlite3VdbeSorterInit(
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
|
||||
assert( pCsr->pKeyInfo );
|
||||
assert( !pCsr->isEphemeral );
|
||||
assert( pCsr->eCurType==CURTYPE_SORTER );
|
||||
szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
|
||||
sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
|
||||
|
||||
19
src/vtab.c
19
src/vtab.c
@ -807,7 +807,6 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
VtabCtx *pCtx;
|
||||
int rc = SQLITE_OK;
|
||||
Table *pTab;
|
||||
char *zErr = 0;
|
||||
Parse sParse;
|
||||
int initBusy;
|
||||
|
||||
@ -826,9 +825,9 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
pTab = pCtx->pTab;
|
||||
assert( IsVirtual(pTab) );
|
||||
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sqlite3ParseObjectInit(&sParse, db);
|
||||
sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
|
||||
sParse.db = db;
|
||||
sParse.disableTriggers = 1;
|
||||
/* We should never be able to reach this point while loading the
|
||||
** schema. Nevertheless, defend against that (turn off db->init.busy)
|
||||
** in case a bug arises. */
|
||||
@ -836,11 +835,12 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
initBusy = db->init.busy;
|
||||
db->init.busy = 0;
|
||||
sParse.nQueryLoop = 1;
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
|
||||
&& sParse.pNewTable
|
||||
&& !db->mallocFailed
|
||||
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable)
|
||||
&& ALWAYS(sParse.pNewTable!=0)
|
||||
&& ALWAYS(!db->mallocFailed)
|
||||
&& IsOrdinaryTable(sParse.pNewTable)
|
||||
){
|
||||
assert( sParse.zErrMsg==0 );
|
||||
if( !pTab->aCol ){
|
||||
Table *pNew = sParse.pNewTable;
|
||||
Index *pIdx;
|
||||
@ -870,8 +870,9 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
}
|
||||
pCtx->bDeclared = 1;
|
||||
}else{
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR,
|
||||
(sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg);
|
||||
sqlite3DbFree(db, sParse.zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sParse.eParseMode = PARSE_MODE_NORMAL;
|
||||
@ -880,7 +881,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
sqlite3VdbeFinalize(sParse.pVdbe);
|
||||
}
|
||||
sqlite3DeleteTable(db, sParse.pNewTable);
|
||||
sqlite3ParserReset(&sParse);
|
||||
sqlite3ParseObjectReset(&sParse);
|
||||
db->init.busy = initBusy;
|
||||
|
||||
assert( (rc&0xff)==rc );
|
||||
|
||||
@ -2603,7 +2603,9 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
|
||||
}
|
||||
|
||||
/* Allocate a buffer to read frames into */
|
||||
szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE;
|
||||
assert( (pWal->szPage & (pWal->szPage-1))==0 );
|
||||
assert( pWal->szPage>=512 && pWal->szPage<=65536 );
|
||||
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
|
||||
aFrame = (u8 *)sqlite3_malloc64(szFrame);
|
||||
if( aFrame==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
@ -2617,7 +2619,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
|
||||
** the caller. */
|
||||
aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
|
||||
aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
|
||||
for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
|
||||
for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage);
|
||||
iOffset+szFrame<=szWal;
|
||||
iOffset+=szFrame
|
||||
){
|
||||
|
||||
865
src/where.c
865
src/where.c
File diff suppressed because it is too large
Load Diff
@ -64,6 +64,7 @@ struct WhereLevel {
|
||||
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
|
||||
int addrLikeRep; /* LIKE range processing address */
|
||||
#endif
|
||||
int regFilter; /* Bloom filter */
|
||||
u8 iFrom; /* Which entry in the FROM clause */
|
||||
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
|
||||
int p1, p2; /* Operands of the opcode used to end the loop */
|
||||
@ -122,10 +123,12 @@ struct WhereLoop {
|
||||
} btree;
|
||||
struct { /* Information for virtual tables */
|
||||
int idxNum; /* Index number */
|
||||
u8 needFree; /* True if sqlite3_free(idxStr) is needed */
|
||||
u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
|
||||
u32 bOmitOffset : 1; /* True to let virtual table handle offset */
|
||||
i8 isOrdered; /* True if satisfies ORDER BY */
|
||||
u16 omitMask; /* Terms that may be omitted */
|
||||
char *idxStr; /* Index identifier string */
|
||||
u32 mHandleIn; /* Terms to handle as IN(...) instead of == */
|
||||
} vtab;
|
||||
} u;
|
||||
u32 wsFlags; /* WHERE_* flags describing the plan */
|
||||
@ -269,7 +272,7 @@ struct WhereTerm {
|
||||
#define TERM_COPIED 0x0008 /* Has a child */
|
||||
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
|
||||
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
|
||||
#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
|
||||
#define TERM_OK 0x0040 /* Used during OR-clause processing */
|
||||
#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
|
||||
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
|
||||
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
|
||||
@ -282,6 +285,7 @@ struct WhereTerm {
|
||||
#else
|
||||
# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */
|
||||
#endif
|
||||
#define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */
|
||||
|
||||
/*
|
||||
** An instance of the WhereScan object is used as an iterator for locating
|
||||
@ -292,11 +296,11 @@ struct WhereScan {
|
||||
WhereClause *pWC; /* WhereClause currently being scanned */
|
||||
const char *zCollName; /* Required collating sequence, if not NULL */
|
||||
Expr *pIdxExpr; /* Search for this index expression */
|
||||
char idxaff; /* Must match this affinity, if zCollName!=NULL */
|
||||
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
|
||||
unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
|
||||
u32 opMask; /* Acceptable operators */
|
||||
int k; /* Resume scanning at this->pWC->a[this->k] */
|
||||
u32 opMask; /* Acceptable operators */
|
||||
char idxaff; /* Must match this affinity, if zCollName!=NULL */
|
||||
unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */
|
||||
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
|
||||
int aiCur[11]; /* Cursors in the equivalence class */
|
||||
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
|
||||
};
|
||||
@ -320,6 +324,7 @@ struct WhereClause {
|
||||
u8 hasOr; /* True if any a[].eOperator is WO_OR */
|
||||
int nTerm; /* Number of terms */
|
||||
int nSlot; /* Number of entries in a[] */
|
||||
int nBase; /* Number of terms through the last non-Virtual */
|
||||
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
|
||||
#if defined(SQLITE_SMALL_STACK)
|
||||
WhereTerm aStatic[1]; /* Initial static space for a[] */
|
||||
@ -377,11 +382,6 @@ struct WhereMaskSet {
|
||||
int ix[BMS]; /* Cursor assigned to each bit */
|
||||
};
|
||||
|
||||
/*
|
||||
** Initialize a WhereMaskSet object
|
||||
*/
|
||||
#define initMaskSet(P) (P)->n=0
|
||||
|
||||
/*
|
||||
** This object is a convenience wrapper holding all information needed
|
||||
** to construct WhereLoop objects for a particular query.
|
||||
@ -389,7 +389,6 @@ struct WhereMaskSet {
|
||||
struct WhereLoopBuilder {
|
||||
WhereInfo *pWInfo; /* Information about this WHERE */
|
||||
WhereClause *pWC; /* WHERE clause terms */
|
||||
ExprList *pOrderBy; /* ORDER BY clause */
|
||||
WhereLoop *pNew; /* Template WhereLoop */
|
||||
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
@ -457,6 +456,9 @@ struct WhereInfo {
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pResultSet; /* Result set of the query */
|
||||
Expr *pWhere; /* The complete WHERE clause */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */
|
||||
#endif
|
||||
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
int iBreak; /* Jump here to break out of the loop */
|
||||
@ -510,8 +512,14 @@ int sqlite3WhereExplainOneScan(
|
||||
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
|
||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||
);
|
||||
int sqlite3WhereExplainBloomFilter(
|
||||
const Parse *pParse, /* Parse context */
|
||||
const WhereInfo *pWInfo, /* WHERE clause */
|
||||
const WhereLevel *pLevel /* Bloom filter on this level */
|
||||
);
|
||||
#else
|
||||
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
|
||||
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
void sqlite3WhereAddScanStatus(
|
||||
@ -536,6 +544,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
|
||||
void sqlite3WhereClauseClear(WhereClause*);
|
||||
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
|
||||
void sqlite3WhereAddLimit(WhereClause*, Select*);
|
||||
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
|
||||
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
|
||||
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
|
||||
@ -604,5 +613,8 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
|
||||
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
|
||||
#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
|
||||
#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
|
||||
#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */
|
||||
#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */
|
||||
#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */
|
||||
|
||||
#endif /* !defined(SQLITE_WHEREINT_H) */
|
||||
|
||||
264
src/wherecode.c
264
src/wherecode.c
@ -176,19 +176,27 @@ int sqlite3WhereExplainOneScan(
|
||||
explainIndexRange(&str, pLoop);
|
||||
}
|
||||
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
|
||||
const char *zRangeOp;
|
||||
char cRangeOp;
|
||||
#if 0 /* Better output, but breaks many tests */
|
||||
const Table *pTab = pItem->pTab;
|
||||
const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName:
|
||||
"rowid";
|
||||
#else
|
||||
const char *zRowid = "rowid";
|
||||
#endif
|
||||
sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid);
|
||||
if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
|
||||
zRangeOp = "=";
|
||||
cRangeOp = '=';
|
||||
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
|
||||
zRangeOp = ">? AND rowid<";
|
||||
sqlite3_str_appendf(&str, ">? AND %s", zRowid);
|
||||
cRangeOp = '<';
|
||||
}else if( flags&WHERE_BTM_LIMIT ){
|
||||
zRangeOp = ">";
|
||||
cRangeOp = '>';
|
||||
}else{
|
||||
assert( flags&WHERE_TOP_LIMIT);
|
||||
zRangeOp = "<";
|
||||
cRangeOp = '<';
|
||||
}
|
||||
sqlite3_str_appendf(&str,
|
||||
" USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
|
||||
sqlite3_str_appendf(&str, "%c?)", cRangeOp);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
|
||||
@ -211,6 +219,56 @@ int sqlite3WhereExplainOneScan(
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a single OP_Explain opcode that describes a Bloom filter.
|
||||
**
|
||||
** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or
|
||||
** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not
|
||||
** required and this routine is a no-op.
|
||||
**
|
||||
** If an OP_Explain opcode is added to the VM, its address is returned.
|
||||
** Otherwise, if no OP_Explain is coded, zero is returned.
|
||||
*/
|
||||
int sqlite3WhereExplainBloomFilter(
|
||||
const Parse *pParse, /* Parse context */
|
||||
const WhereInfo *pWInfo, /* WHERE clause */
|
||||
const WhereLevel *pLevel /* Bloom filter on this level */
|
||||
){
|
||||
int ret = 0;
|
||||
SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom];
|
||||
Vdbe *v = pParse->pVdbe; /* VM being constructed */
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
char *zMsg; /* Text to add to EQP output */
|
||||
int i; /* Loop counter */
|
||||
WhereLoop *pLoop; /* The where loop */
|
||||
StrAccum str; /* EQP output string */
|
||||
char zBuf[100]; /* Initial space for EQP output string */
|
||||
|
||||
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
|
||||
str.printfFlags = SQLITE_PRINTF_INTERNAL;
|
||||
sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
|
||||
pLoop = pLevel->pWLoop;
|
||||
if( pLoop->wsFlags & WHERE_IPK ){
|
||||
const Table *pTab = pItem->pTab;
|
||||
if( pTab->iPKey>=0 ){
|
||||
sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
|
||||
}else{
|
||||
sqlite3_str_appendf(&str, "rowid=?");
|
||||
}
|
||||
}else{
|
||||
for(i=pLoop->nSkip; i<pLoop->u.btree.nEq; i++){
|
||||
const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i);
|
||||
if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5);
|
||||
sqlite3_str_appendf(&str, "%s=?", z);
|
||||
}
|
||||
}
|
||||
sqlite3_str_append(&str, ")", 1);
|
||||
zMsg = sqlite3StrAccumFinish(&str);
|
||||
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
|
||||
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
|
||||
return ret;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
@ -734,6 +792,7 @@ static int codeAllEqualityTerms(
|
||||
VdbeCoverageIf(v, bRev!=0);
|
||||
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
|
||||
j = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
assert( pLevel->addrSkip==0 );
|
||||
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
|
||||
iIdxCur, 0, regBase, nSkip);
|
||||
VdbeCoverageIf(v, bRev==0);
|
||||
@ -766,6 +825,9 @@ static int codeAllEqualityTerms(
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=nSkip; j<nEq; j++){
|
||||
pTerm = pLoop->aLTerm[j];
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
if( pTerm->pExpr->flags & EP_xIsSelect ){
|
||||
/* No affinity ever needs to be (or should be) applied to a value
|
||||
@ -780,7 +842,8 @@ static int codeAllEqualityTerms(
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( pParse->db->mallocFailed==0 && pParse->nErr==0 ){
|
||||
if( pParse->nErr==0 ){
|
||||
assert( pParse->db->mallocFailed==0 );
|
||||
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
|
||||
zAff[j] = SQLITE_AFF_BLOB;
|
||||
}
|
||||
@ -970,7 +1033,7 @@ static void codeCursorHint(
|
||||
sWalker.pParse = pParse;
|
||||
sWalker.u.pCCurHint = &sHint;
|
||||
pWC = &pWInfo->sWC;
|
||||
for(i=0; i<pWC->nTerm; i++){
|
||||
for(i=0; i<pWC->nBase; i++){
|
||||
pTerm = &pWC->a[i];
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( pTerm->prereqAll & pLevel->notReady ) continue;
|
||||
@ -1000,7 +1063,7 @@ static void codeCursorHint(
|
||||
if( pTabItem->fg.jointype & JT_LEFT ){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( !ExprHasProperty(pExpr, EP_FromJoin)
|
||||
|| pExpr->iRightJoinTable!=pTabItem->iCursor
|
||||
|| pExpr->w.iRightJoinTable!=pTabItem->iCursor
|
||||
){
|
||||
sWalker.eCode = 0;
|
||||
sWalker.xExprCallback = codeCursorHintIsOrFunction;
|
||||
@ -1301,6 +1364,65 @@ static void whereApplyPartialIndexConstraints(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called right after An OP_Filter has been generated and
|
||||
** before the corresponding index search has been performed. This routine
|
||||
** checks to see if there are additional Bloom filters in inner loops that
|
||||
** can be checked prior to doing the index lookup. If there are available
|
||||
** inner-loop Bloom filters, then evaluate those filters now, before the
|
||||
** index lookup. The idea is that a Bloom filter check is way faster than
|
||||
** an index lookup, and the Bloom filter might return false, meaning that
|
||||
** the index lookup can be skipped.
|
||||
**
|
||||
** We know that an inner loop uses a Bloom filter because it has the
|
||||
** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked,
|
||||
** then clear the WhereLevel.regFilter value to prevent the Bloom filter
|
||||
** from being checked a second time when the inner loop is evaluated.
|
||||
*/
|
||||
static SQLITE_NOINLINE void filterPullDown(
|
||||
Parse *pParse, /* Parsing context */
|
||||
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
|
||||
int iLevel, /* Which level of pWInfo->a[] should be coded */
|
||||
int addrNxt, /* Jump here to bypass inner loops */
|
||||
Bitmask notReady /* Loops that are not ready */
|
||||
){
|
||||
while( ++iLevel < pWInfo->nLevel ){
|
||||
WhereLevel *pLevel = &pWInfo->a[iLevel];
|
||||
WhereLoop *pLoop = pLevel->pWLoop;
|
||||
if( pLevel->regFilter==0 ) continue;
|
||||
if( pLevel->pWLoop->nSkip ) continue;
|
||||
/* ,--- Because sqlite3ConstructBloomFilter() has will not have set
|
||||
** vvvvv--' pLevel->regFilter if this were true. */
|
||||
if( NEVER(pLoop->prereq & notReady) ) continue;
|
||||
if( pLoop->wsFlags & WHERE_IPK ){
|
||||
WhereTerm *pTerm = pLoop->aLTerm[0];
|
||||
int regRowid;
|
||||
assert( pTerm!=0 );
|
||||
assert( pTerm->pExpr!=0 );
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
|
||||
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
|
||||
addrNxt, regRowid, 1);
|
||||
VdbeCoverage(pParse->pVdbe);
|
||||
}else{
|
||||
u16 nEq = pLoop->u.btree.nEq;
|
||||
int r1;
|
||||
char *zStartAff;
|
||||
|
||||
assert( pLoop->wsFlags & WHERE_INDEXED );
|
||||
assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 );
|
||||
r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
|
||||
codeApplyAffinity(pParse, r1, nEq, zStartAff);
|
||||
sqlite3DbFree(pParse->db, zStartAff);
|
||||
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
|
||||
addrNxt, r1, nEq);
|
||||
VdbeCoverage(pParse->pVdbe);
|
||||
}
|
||||
pLevel->regFilter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
** implementation described by pWInfo.
|
||||
@ -1403,7 +1525,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
int iReg; /* P3 Value for OP_VFilter */
|
||||
int addrNotFound;
|
||||
int nConstraint = pLoop->nLTerm;
|
||||
int iIn; /* Counter for IN constraints */
|
||||
|
||||
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
|
||||
addrNotFound = pLevel->addrBrk;
|
||||
@ -1412,11 +1533,27 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pTerm = pLoop->aLTerm[j];
|
||||
if( NEVER(pTerm==0) ) continue;
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
|
||||
addrNotFound = pLevel->addrNxt;
|
||||
if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){
|
||||
int iTab = pParse->nTab++;
|
||||
int iCache = ++pParse->nMem;
|
||||
sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab);
|
||||
sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache);
|
||||
}else{
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
|
||||
addrNotFound = pLevel->addrNxt;
|
||||
}
|
||||
}else{
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
codeExprOrVector(pParse, pRight, iTarget, 1);
|
||||
if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
&& pLoop->u.vtab.bOmitOffset
|
||||
){
|
||||
assert( pTerm->eOperator==WO_AUX );
|
||||
assert( pWInfo->pLimit!=0 );
|
||||
assert( pWInfo->pLimit->iOffset>0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset);
|
||||
VdbeComment((v,"Zero OFFSET counter"));
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
|
||||
@ -1433,44 +1570,54 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
|
||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||
if( pLoop->wsFlags & WHERE_IN_ABLE ){
|
||||
iIn = pLevel->u.in.nIn;
|
||||
}else{
|
||||
iIn = 0;
|
||||
}
|
||||
for(j=nConstraint-1; j>=0; j--){
|
||||
|
||||
for(j=0; j<nConstraint; j++){
|
||||
pTerm = pLoop->aLTerm[j];
|
||||
if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
|
||||
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
|
||||
disableTerm(pLevel, pTerm);
|
||||
}else if( (pTerm->eOperator & WO_IN)!=0
|
||||
&& sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
|
||||
continue;
|
||||
}
|
||||
if( (pTerm->eOperator & WO_IN)!=0
|
||||
&& (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0
|
||||
&& !db->mallocFailed
|
||||
){
|
||||
Expr *pCompare; /* The comparison operator */
|
||||
Expr *pRight; /* RHS of the comparison */
|
||||
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
|
||||
int iIn; /* IN loop corresponding to the j-th constraint */
|
||||
|
||||
/* Reload the constraint value into reg[iReg+j+2]. The same value
|
||||
** was loaded into the same register prior to the OP_VFilter, but
|
||||
** the xFilter implementation might have changed the datatype or
|
||||
** encoding of the value in the register, so it *must* be reloaded. */
|
||||
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
|
||||
if( !db->mallocFailed ){
|
||||
assert( iIn>=0 && iIn<pLevel->u.in.nIn );
|
||||
** encoding of the value in the register, so it *must* be reloaded.
|
||||
*/
|
||||
for(iIn=0; ALWAYS(iIn<pLevel->u.in.nIn); iIn++){
|
||||
pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
|
||||
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
|
||||
assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
|
||||
assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
|
||||
testcase( pOp->opcode==OP_Rowid );
|
||||
sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
|
||||
if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2)
|
||||
|| (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2)
|
||||
){
|
||||
testcase( pOp->opcode==OP_Rowid );
|
||||
sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate code that will continue to the next row if
|
||||
** the IN constraint is not satisfied */
|
||||
** the IN constraint is not satisfied
|
||||
*/
|
||||
pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0);
|
||||
assert( pCompare!=0 || db->mallocFailed );
|
||||
if( pCompare ){
|
||||
pCompare->pLeft = pTerm->pExpr->pLeft;
|
||||
if( !db->mallocFailed ){
|
||||
int iFld = pTerm->u.x.iField;
|
||||
Expr *pLeft = pTerm->pExpr->pLeft;
|
||||
assert( pLeft!=0 );
|
||||
if( iFld>0 ){
|
||||
assert( pLeft->op==TK_VECTOR );
|
||||
assert( ExprUseXList(pLeft) );
|
||||
assert( iFld<=pLeft->x.pList->nExpr );
|
||||
pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr;
|
||||
}else{
|
||||
pCompare->pLeft = pLeft;
|
||||
}
|
||||
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
|
||||
if( pRight ){
|
||||
pRight->iTable = iReg+j+2;
|
||||
@ -1479,11 +1626,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
);
|
||||
}
|
||||
pCompare->pLeft = 0;
|
||||
sqlite3ExprDelete(db, pCompare);
|
||||
}
|
||||
sqlite3ExprDelete(db, pCompare);
|
||||
}
|
||||
}
|
||||
assert( iIn==0 || db->mallocFailed );
|
||||
|
||||
/* These registers need to be preserved in case there is an IN operator
|
||||
** loop. So we could deallocate the registers here (and potentially
|
||||
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
|
||||
@ -1511,6 +1658,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
|
||||
if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
addrNxt = pLevel->addrNxt;
|
||||
if( pLevel->regFilter ){
|
||||
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
|
||||
iRowidReg, 1);
|
||||
VdbeCoverage(v);
|
||||
filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
|
||||
VdbeCoverage(v);
|
||||
pLevel->op = OP_Noop;
|
||||
@ -1836,6 +1989,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
|
||||
VdbeComment((v, "NULL-scan pass ctr"));
|
||||
}
|
||||
if( pLevel->regFilter ){
|
||||
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
|
||||
regBase, nEq);
|
||||
VdbeCoverage(v);
|
||||
filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
|
||||
}
|
||||
|
||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||
assert( op!=0 );
|
||||
@ -2163,7 +2322,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
|
||||
|
||||
/* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
|
||||
** Then for every term xN, evaluate as the subexpression: xN AND z
|
||||
** Then for every term xN, evaluate as the subexpression: xN AND y
|
||||
** That way, terms in y that are factored into the disjunction will
|
||||
** be picked up by the recursive calls to sqlite3WhereBegin() below.
|
||||
**
|
||||
@ -2175,6 +2334,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** This optimization also only applies if the (x1 OR x2 OR ...) term
|
||||
** is not contained in the ON clause of a LEFT JOIN.
|
||||
** See ticket http://www.sqlite.org/src/info/f2369304e4
|
||||
**
|
||||
** 2022-02-04: Do not push down slices of a row-value comparison.
|
||||
** In other words, "w" or "y" may not be a slice of a vector. Otherwise,
|
||||
** the initialization of the right-hand operand of the vector comparison
|
||||
** might not occur, or might occur only in an OR branch that is not
|
||||
** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.
|
||||
**
|
||||
** 2022-03-03: Do not push down expressions that involve subqueries.
|
||||
** The subquery might get coded as a subroutine. Any table-references
|
||||
** in the subquery might be resolved to index-references for the index on
|
||||
** the OR branch in which the subroutine is coded. But if the subroutine
|
||||
** is invoked from a different OR branch that uses a different index, such
|
||||
** index-references will not work. tag-20220303a
|
||||
** https://sqlite.org/forum/forumpost/36937b197273d403
|
||||
*/
|
||||
if( pWC->nTerm>1 ){
|
||||
int iTerm;
|
||||
@ -2183,9 +2356,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( &pWC->a[iTerm] == pTerm ) continue;
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
|
||||
if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_SLICE );
|
||||
if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){
|
||||
continue;
|
||||
}
|
||||
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
|
||||
if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */
|
||||
pExpr = sqlite3ExprDup(db, pExpr, 0);
|
||||
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
|
||||
}
|
||||
@ -2226,9 +2402,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
|
||||
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0,
|
||||
WHERE_OR_SUBCLAUSE, iCovCur);
|
||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||
assert( pSubWInfo || pParse->nErr );
|
||||
if( pSubWInfo ){
|
||||
WhereLoop *pSubLoop;
|
||||
int addrExplain = sqlite3WhereExplainOneScan(
|
||||
@ -2467,7 +2643,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** then we cannot use the "t1.a=t2.b" constraint, but we can code
|
||||
** the implied "t1.a=123" constraint.
|
||||
*/
|
||||
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
||||
for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
|
||||
Expr *pE, sEAlt;
|
||||
WhereTerm *pAlt;
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
@ -2512,7 +2688,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
|
||||
VdbeComment((v, "record LEFT JOIN hit"));
|
||||
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
|
||||
for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
testcase( pTerm->wtFlags & TERM_CODED );
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
|
||||
241
src/whereexpr.c
241
src/whereexpr.c
@ -79,6 +79,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
||||
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm;
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
|
||||
}else{
|
||||
@ -421,7 +422,7 @@ static int isAuxiliaryVtabOperator(
|
||||
assert( pVtab!=0 );
|
||||
assert( pVtab->pModule!=0 );
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
if( pMod->xFindFunction!=0 ){
|
||||
i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed);
|
||||
if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
|
||||
@ -465,7 +466,7 @@ static int isAuxiliaryVtabOperator(
|
||||
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
|
||||
if( pDerived ){
|
||||
pDerived->flags |= pBase->flags & EP_FromJoin;
|
||||
pDerived->iRightJoinTable = pBase->iRightJoinTable;
|
||||
pDerived->w.iRightJoinTable = pBase->w.iRightJoinTable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,7 +796,7 @@ static void exprAnalyzeOrTerm(
|
||||
pOrTerm = pOrWc->a;
|
||||
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
|
||||
assert( pOrTerm->eOperator & WO_EQ );
|
||||
pOrTerm->wtFlags &= ~TERM_OR_OK;
|
||||
pOrTerm->wtFlags &= ~TERM_OK;
|
||||
if( pOrTerm->leftCursor==iCursor ){
|
||||
/* This is the 2-bit case and we are on the second iteration and
|
||||
** current term is from the first iteration. So skip this term. */
|
||||
@ -836,7 +837,7 @@ static void exprAnalyzeOrTerm(
|
||||
assert( pOrTerm->eOperator & WO_EQ );
|
||||
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
if( pOrTerm->leftCursor!=iCursor ){
|
||||
pOrTerm->wtFlags &= ~TERM_OR_OK;
|
||||
pOrTerm->wtFlags &= ~TERM_OK;
|
||||
}else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
|
||||
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
|
||||
)){
|
||||
@ -852,7 +853,7 @@ static void exprAnalyzeOrTerm(
|
||||
if( affRight!=0 && affRight!=affLeft ){
|
||||
okToChngToIN = 0;
|
||||
}else{
|
||||
pOrTerm->wtFlags |= TERM_OR_OK;
|
||||
pOrTerm->wtFlags |= TERM_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -869,7 +870,7 @@ static void exprAnalyzeOrTerm(
|
||||
Expr *pNew; /* The complete IN operator */
|
||||
|
||||
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
|
||||
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
|
||||
if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
|
||||
assert( pOrTerm->eOperator & WO_EQ );
|
||||
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
assert( pOrTerm->leftCursor==iCursor );
|
||||
@ -1070,10 +1071,13 @@ static void exprAnalyze(
|
||||
if( db->mallocFailed ){
|
||||
return;
|
||||
}
|
||||
assert( pWC->nTerm > idxTerm );
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pMaskSet = &pWInfo->sMaskSet;
|
||||
pExpr = pTerm->pExpr;
|
||||
assert( pExpr!=0 ); /* Because malloc() has not failed */
|
||||
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
|
||||
pMaskSet->bVarSelect = 0;
|
||||
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
|
||||
op = pExpr->op;
|
||||
if( op==TK_IN ){
|
||||
@ -1084,16 +1088,30 @@ static void exprAnalyze(
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
|
||||
}
|
||||
}else if( op==TK_ISNULL ){
|
||||
pTerm->prereqRight = 0;
|
||||
prereqAll = prereqLeft | pTerm->prereqRight;
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
|
||||
if( pExpr->pLeft==0
|
||||
|| ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow)
|
||||
|| pExpr->x.pList!=0
|
||||
){
|
||||
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
|
||||
}else{
|
||||
prereqAll = prereqLeft | pTerm->prereqRight;
|
||||
}
|
||||
}
|
||||
pMaskSet->bVarSelect = 0;
|
||||
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
|
||||
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
|
||||
printf("\n*** Incorrect prereqAll computed for:\n");
|
||||
sqlite3TreeViewExpr(0,pExpr,0);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
|
||||
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iRightJoinTable);
|
||||
prereqAll |= x;
|
||||
extraRight = x-1; /* ON clause terms may not be used with an index
|
||||
** on left table of a LEFT JOIN. Ticket #3015 */
|
||||
@ -1361,7 +1379,10 @@ static void exprAnalyze(
|
||||
** no longer used.
|
||||
**
|
||||
** This is only required if at least one side of the comparison operation
|
||||
** is not a sub-select. */
|
||||
** is not a sub-select.
|
||||
**
|
||||
** tag-20220128a
|
||||
*/
|
||||
if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
|
||||
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
|
||||
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
|
||||
@ -1378,7 +1399,7 @@ static void exprAnalyze(
|
||||
|
||||
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE);
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
}
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
@ -1408,7 +1429,7 @@ static void exprAnalyze(
|
||||
int i;
|
||||
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
|
||||
int idxNew;
|
||||
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
|
||||
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
|
||||
pWC->a[idxNew].u.x.iField = i+1;
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
@ -1441,7 +1462,7 @@ static void exprAnalyze(
|
||||
0, sqlite3ExprDup(db, pRight, 0));
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
|
||||
ExprSetProperty(pNewExpr, EP_FromJoin);
|
||||
pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
|
||||
pNewExpr->w.iRightJoinTable = pExpr->w.iRightJoinTable;
|
||||
}
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
@ -1504,6 +1525,113 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or
|
||||
** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the
|
||||
** where-clause passed as the first argument. The value for the term
|
||||
** is found in register iReg.
|
||||
**
|
||||
** In the common case where the value is a simple integer
|
||||
** (example: "LIMIT 5 OFFSET 10") then the expression codes as a
|
||||
** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value().
|
||||
** If not, then it codes as a TK_REGISTER expression.
|
||||
*/
|
||||
static void whereAddLimitExpr(
|
||||
WhereClause *pWC, /* Add the constraint to this WHERE clause */
|
||||
int iReg, /* Register that will hold value of the limit/offset */
|
||||
Expr *pExpr, /* Expression that defines the limit/offset */
|
||||
int iCsr, /* Cursor to which the constraint applies */
|
||||
int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */
|
||||
){
|
||||
Parse *pParse = pWC->pWInfo->pParse;
|
||||
sqlite3 *db = pParse->db;
|
||||
Expr *pNew;
|
||||
int iVal = 0;
|
||||
|
||||
if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
|
||||
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
|
||||
if( pVal==0 ) return;
|
||||
ExprSetProperty(pVal, EP_IntValue);
|
||||
pVal->u.iValue = iVal;
|
||||
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
|
||||
}else{
|
||||
Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0);
|
||||
if( pVal==0 ) return;
|
||||
pVal->iTable = iReg;
|
||||
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
|
||||
}
|
||||
if( pNew ){
|
||||
WhereTerm *pTerm;
|
||||
int idx;
|
||||
idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL);
|
||||
pTerm = &pWC->a[idx];
|
||||
pTerm->leftCursor = iCsr;
|
||||
pTerm->eOperator = WO_AUX;
|
||||
pTerm->eMatchOp = eMatchOp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the
|
||||
** SELECT statement passed as the second argument. These terms are only
|
||||
** added if:
|
||||
**
|
||||
** 1. The SELECT statement has a LIMIT clause, and
|
||||
** 2. The SELECT statement is not an aggregate or DISTINCT query, and
|
||||
** 3. The SELECT statement has exactly one object in its from clause, and
|
||||
** that object is a virtual table, and
|
||||
** 4. There are no terms in the WHERE clause that will not be passed
|
||||
** to the virtual table xBestIndex method.
|
||||
** 5. The ORDER BY clause, if any, will be made available to the xBestIndex
|
||||
** method.
|
||||
**
|
||||
** LIMIT and OFFSET terms are ignored by most of the planner code. They
|
||||
** exist only so that they may be passed to the xBestIndex method of the
|
||||
** single virtual table in the FROM clause of the SELECT.
|
||||
*/
|
||||
void sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) );
|
||||
if( (p && p->pLimit) /* 1 */
|
||||
&& (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */
|
||||
&& (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */
|
||||
){
|
||||
ExprList *pOrderBy = p->pOrderBy;
|
||||
int iCsr = p->pSrc->a[0].iCursor;
|
||||
int ii;
|
||||
|
||||
/* Check condition (4). Return early if it is not met. */
|
||||
for(ii=0; ii<pWC->nTerm; ii++){
|
||||
if( pWC->a[ii].wtFlags & TERM_CODED ){
|
||||
/* This term is a vector operation that has been decomposed into
|
||||
** other, subsequent terms. It can be ignored. See tag-20220128a */
|
||||
assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
|
||||
assert( pWC->a[ii].eOperator==0 );
|
||||
continue;
|
||||
}
|
||||
if( pWC->a[ii].leftCursor!=iCsr ) return;
|
||||
}
|
||||
|
||||
/* Check condition (5). Return early if it is not met. */
|
||||
if( pOrderBy ){
|
||||
for(ii=0; ii<pOrderBy->nExpr; ii++){
|
||||
Expr *pExpr = pOrderBy->a[ii].pExpr;
|
||||
if( pExpr->op!=TK_COLUMN ) return;
|
||||
if( pExpr->iTable!=iCsr ) return;
|
||||
if( pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_BIGNULL ) return;
|
||||
}
|
||||
}
|
||||
|
||||
/* All conditions are met. Add the terms to the where-clause object. */
|
||||
assert( p->pLimit->op==TK_LIMIT );
|
||||
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
|
||||
if( p->iOffset>0 ){
|
||||
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
|
||||
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize a preallocated WhereClause structure.
|
||||
*/
|
||||
@ -1515,6 +1643,7 @@ void sqlite3WhereClauseInit(
|
||||
pWC->hasOr = 0;
|
||||
pWC->pOuter = 0;
|
||||
pWC->nTerm = 0;
|
||||
pWC->nBase = 0;
|
||||
pWC->nSlot = ArraySize(pWC->aStatic);
|
||||
pWC->a = pWC->aStatic;
|
||||
}
|
||||
@ -1525,17 +1654,34 @@ void sqlite3WhereClauseInit(
|
||||
** sqlite3WhereClauseInit().
|
||||
*/
|
||||
void sqlite3WhereClauseClear(WhereClause *pWC){
|
||||
int i;
|
||||
WhereTerm *a;
|
||||
sqlite3 *db = pWC->pWInfo->pParse->db;
|
||||
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
|
||||
if( a->wtFlags & TERM_DYNAMIC ){
|
||||
sqlite3ExprDelete(db, a->pExpr);
|
||||
assert( pWC->nTerm>=pWC->nBase );
|
||||
if( pWC->nTerm>0 ){
|
||||
WhereTerm *a = pWC->a;
|
||||
WhereTerm *aLast = &pWC->a[pWC->nTerm-1];
|
||||
#ifdef SQLITE_DEBUG
|
||||
int i;
|
||||
/* Verify that every term past pWC->nBase is virtual */
|
||||
for(i=pWC->nBase; i<pWC->nTerm; i++){
|
||||
assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 );
|
||||
}
|
||||
if( a->wtFlags & TERM_ORINFO ){
|
||||
whereOrInfoDelete(db, a->u.pOrInfo);
|
||||
}else if( a->wtFlags & TERM_ANDINFO ){
|
||||
whereAndInfoDelete(db, a->u.pAndInfo);
|
||||
#endif
|
||||
while(1){
|
||||
assert( a->eMatchOp==0 || a->eOperator==WO_AUX );
|
||||
if( a->wtFlags & TERM_DYNAMIC ){
|
||||
sqlite3ExprDelete(db, a->pExpr);
|
||||
}
|
||||
if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){
|
||||
if( a->wtFlags & TERM_ORINFO ){
|
||||
assert( (a->wtFlags & TERM_ANDINFO)==0 );
|
||||
whereOrInfoDelete(db, a->u.pOrInfo);
|
||||
}else{
|
||||
assert( (a->wtFlags & TERM_ANDINFO)!=0 );
|
||||
whereAndInfoDelete(db, a->u.pAndInfo);
|
||||
}
|
||||
}
|
||||
if( a==aLast ) break;
|
||||
a++;
|
||||
}
|
||||
}
|
||||
if( pWC->a!=pWC->aStatic ){
|
||||
@ -1548,15 +1694,38 @@ void sqlite3WhereClauseClear(WhereClause *pWC){
|
||||
** These routines walk (recursively) an expression tree and generate
|
||||
** a bitmask indicating which tables are used in that expression
|
||||
** tree.
|
||||
**
|
||||
** sqlite3WhereExprUsage(MaskSet, Expr) ->
|
||||
**
|
||||
** Return a Bitmask of all tables referenced by Expr. Expr can be
|
||||
** be NULL, in which case 0 is returned.
|
||||
**
|
||||
** sqlite3WhereExprUsageNN(MaskSet, Expr) ->
|
||||
**
|
||||
** Same as sqlite3WhereExprUsage() except that Expr must not be
|
||||
** NULL. The "NN" suffix on the name stands for "Not Null".
|
||||
**
|
||||
** sqlite3WhereExprListUsage(MaskSet, ExprList) ->
|
||||
**
|
||||
** Return a Bitmask of all tables referenced by every expression
|
||||
** in the expression list ExprList. ExprList can be NULL, in which
|
||||
** case 0 is returned.
|
||||
**
|
||||
** sqlite3WhereExprUsageFull(MaskSet, ExprList) ->
|
||||
**
|
||||
** Internal use only. Called only by sqlite3WhereExprUsageNN() for
|
||||
** complex expressions that require pushing register values onto
|
||||
** the stack. Many calls to sqlite3WhereExprUsageNN() do not need
|
||||
** the more complex analysis done by this routine. Hence, the
|
||||
** computations done by this routine are broken out into a separate
|
||||
** "no-inline" function to avoid the stack push overhead in the
|
||||
** common case where it is not needed.
|
||||
*/
|
||||
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
|
||||
static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull(
|
||||
WhereMaskSet *pMaskSet,
|
||||
Expr *p
|
||||
){
|
||||
Bitmask mask;
|
||||
if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
|
||||
return sqlite3WhereGetMask(pMaskSet, p->iTable);
|
||||
}else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
assert( p->op!=TK_IF_NULL_ROW );
|
||||
return 0;
|
||||
}
|
||||
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
|
||||
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
|
||||
if( p->pRight ){
|
||||
@ -1578,6 +1747,15 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
|
||||
#endif
|
||||
return mask;
|
||||
}
|
||||
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
|
||||
if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
|
||||
return sqlite3WhereGetMask(pMaskSet, p->iTable);
|
||||
}else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
assert( p->op!=TK_IF_NULL_ROW );
|
||||
return 0;
|
||||
}
|
||||
return sqlite3WhereExprUsageFull(pMaskSet, p);
|
||||
}
|
||||
Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
|
||||
return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
|
||||
}
|
||||
@ -1647,6 +1825,7 @@ void sqlite3WhereTabFuncArgs(
|
||||
pColRef->iColumn = k++;
|
||||
assert( ExprUseYTab(pColRef) );
|
||||
pColRef->y.pTab = pTab;
|
||||
pItem->colUsed |= sqlite3ExprColUsed(pColRef);
|
||||
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
|
||||
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
|
||||
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
|
||||
|
||||
14
src/window.c
14
src/window.c
@ -957,7 +957,11 @@ static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
|
||||
*/
|
||||
int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->pWin && p->pPrior==0 && ALWAYS((p->selFlags & SF_WinRewrite)==0) ){
|
||||
if( p->pWin
|
||||
&& p->pPrior==0
|
||||
&& ALWAYS((p->selFlags & SF_WinRewrite)==0)
|
||||
&& ALWAYS(!IN_RENAME_OBJECT)
|
||||
){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
sqlite3 *db = pParse->db;
|
||||
Select *pSub = 0; /* The subquery */
|
||||
@ -1032,6 +1036,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
ExprList *pArgs;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
assert( pWin->pFunc!=0 );
|
||||
pArgs = pWin->pOwner->x.pList;
|
||||
if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
|
||||
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
|
||||
@ -1106,12 +1111,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab);
|
||||
}
|
||||
|
||||
if( rc ){
|
||||
if( pParse->nErr==0 ){
|
||||
assert( pParse->db->mallocFailed );
|
||||
sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
|
||||
}
|
||||
}
|
||||
assert( rc==SQLITE_OK || pParse->nErr!=0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -99,6 +99,7 @@ do_auth_test 1.2 {
|
||||
do_auth_test 1.3 {
|
||||
ALTER TABLE t2 DROP COLUMN c;
|
||||
} {
|
||||
{SQLITE_ALTER_TABLE main t2 c {}}
|
||||
{SQLITE_FUNCTION {} like {} {}}
|
||||
{SQLITE_FUNCTION {} sqlite_drop_column {} {}}
|
||||
{SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user