Compare commits
184 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e088a6c0a | |||
| 51f1c6f3ec | |||
| 5051194270 | |||
| 8b2d8de3e2 | |||
| cdb6ce980b | |||
| 95063d8c90 | |||
| 451f89a896 | |||
| 065e4a8d29 | |||
| 23bef340be | |||
| 9f603fcefd | |||
| e238e31413 | |||
| ec9a25c7c7 | |||
| 7d9ad75a56 | |||
| 07f9e8f4f3 | |||
| ab2172e69f | |||
| 742efb6749 | |||
| 5415ab49b4 | |||
| 542bd6521e | |||
| fc7f31742d | |||
| 4d34766f4e | |||
| 6ef2dc137d | |||
| 9a1bb3f616 | |||
| 480620c713 | |||
| 3b9f154bb7 | |||
| 541ef2c36c | |||
| 45248de39a | |||
| 871f45441c | |||
| 7a43100afb | |||
| 1d9ea27f7e | |||
| 054a081555 | |||
| 7576a68c8c | |||
| c39b121a95 | |||
| f05dd03a6e | |||
| e6a85962e7 | |||
| 43e862723e | |||
| 75b5f22c01 | |||
| 4b3282d8a0 | |||
| aa0696ee9a | |||
| 2d99f95721 | |||
| b3120fdf5b | |||
| 4047bdfd2c | |||
| d44390c8c5 | |||
| 85f2c76cf9 | |||
| 47f8ef32a0 | |||
| 2e52a9c611 | |||
| c59b4acf5d | |||
| a96a69b7db | |||
| eb110d9687 | |||
| c415d91007 | |||
| 4db7ab53f9 | |||
| fb99e388ec | |||
| 49d01abaac | |||
| e1cd73f671 | |||
| 91654b2016 | |||
| c004bd54e3 | |||
| e0ef4e2b47 | |||
| e065a18a4b | |||
| 892edb69c4 | |||
| 3e42b99175 | |||
| 218da8c6f1 | |||
| b1243a6d9c | |||
| 97ccc1bd11 | |||
| 8f78a528d5 | |||
| c5eeacd58b | |||
| 95b395901a | |||
| cdbb28154e | |||
| 8e9297fb79 | |||
| 7797207554 | |||
| cf08f08d2c | |||
| 0518d06117 | |||
| eeb55d8694 | |||
| 8c5163a697 | |||
| cb49f5468e | |||
| 356cd76aa8 | |||
| 691b5c54b8 | |||
| 74a07986ce | |||
| f7f6dbf501 | |||
| 7d76fad8eb | |||
| 31f170f396 | |||
| 465c2b8964 | |||
| 2c3629e1c9 | |||
| 62b6e1d042 | |||
| 2aee514b4c | |||
| 00bd55e1ae | |||
| ec8e689a20 | |||
| 589c787620 | |||
| f0a2172d1d | |||
| 91a23dc299 | |||
| 553948e514 | |||
| 14c98a4f40 | |||
| ba25c7e29f | |||
| 576d0a9fd9 | |||
| 2267a7fa87 | |||
| 9b258c54e4 | |||
| 38dfbdae8a | |||
| 8d5cea6b61 | |||
| e7375bfa72 | |||
| 5cf1b611a2 | |||
| 24e399038b | |||
| 0c76e892d9 | |||
| 088489e8d9 | |||
| afa1ecac9b | |||
| ccb3781673 | |||
| 45dc9ca46b | |||
| ed5e66881e | |||
| db9cb17dc7 | |||
| 0ea2d42ac3 | |||
| 42a630b1da | |||
| 4cf2121e1c | |||
| f5cfe6f2c4 | |||
| d346fe0ab5 | |||
| b3f0d92b91 | |||
| 39b3bcf8ef | |||
| a2ec2e4843 | |||
| 7f05d52c4c | |||
| 0a21ea997d | |||
| 4a3a3eb3d7 | |||
| 2826918d10 | |||
| 9e5ecdc172 | |||
| be284e4ece | |||
| 67e2bb92df | |||
| 47a60d4518 | |||
| df97d43930 | |||
| a8781d9d93 | |||
| f575c1cf06 | |||
| f06cdde2cf | |||
| 35d3cb80c4 | |||
| 2ed1b0e753 | |||
| 0990c415f6 | |||
| cea1951e80 | |||
| 5c19346451 | |||
| 89efac94fd | |||
| e8c4f03266 | |||
| 8a64d62d31 | |||
| 5f69512404 | |||
| 1cfee74a28 | |||
| 4b9e736898 | |||
| 4defdddc31 | |||
| 0184a256e3 | |||
| 78d1d225d8 | |||
| bf48ce49f7 | |||
| ac9e184e1f | |||
| fdfd45aef3 | |||
| ab7fdca2ee | |||
| 0ba3621592 | |||
| 77c9b3ccb3 | |||
| efdba1a8b3 | |||
| 41aa442cf4 | |||
| df9b5cab93 | |||
| b6664744c0 | |||
| dc4f6fc099 | |||
| b48c0d59fa | |||
| c84ad31851 | |||
| 0de19cac43 | |||
| c879c4eac0 | |||
| 5bdad79f01 | |||
| fcbc673752 | |||
| 2a74006087 | |||
| 3cdc820544 | |||
| 92a27f7bf2 | |||
| 40d1db8d20 | |||
| 51f37b2bb8 | |||
| 081ce2042c | |||
| 9dce0ef4ca | |||
| d7b10d74e1 | |||
| 745befd13f | |||
| 1eac966076 | |||
| 7aedd5d70b | |||
| d03f77ae46 | |||
| 759e9cc064 | |||
| 48118e4060 | |||
| ffd3fd0c30 | |||
| 9ca9a53a42 | |||
| 02a95eb9bb | |||
| 925ab5c17e | |||
| fbfd113365 | |||
| 4b2f45be34 | |||
| b9f2e5f777 | |||
| 562fd18b9d | |||
| f54f105446 | |||
| 532b0d23fd | |||
| 9a3bdeba3e | |||
| 8122c6e9be | |||
| 78b5220328 |
+12
-1
@@ -190,7 +190,8 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||
update.lo userauth.lo upsert.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
vdbetrace.lo vdbevtab.lo \
|
||||
wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
window.lo utf.lo vtab.lo
|
||||
|
||||
# Object files for the amalgamation.
|
||||
@@ -296,6 +297,7 @@ SRC = \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbesort.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbevtab.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/vxworks.h \
|
||||
@@ -502,6 +504,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/vdbe.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbevtab.c \
|
||||
$(TOP)/src/where.c \
|
||||
$(TOP)/src/wherecode.c \
|
||||
$(TOP)/src/whereexpr.c \
|
||||
@@ -607,6 +610,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
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
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
@@ -619,6 +623,7 @@ FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
|
||||
@@ -688,6 +693,7 @@ DBFUZZ2_OPTS = \
|
||||
-DSQLITE_ENABLE_DESERIALIZE \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_ENABLE_FTS5
|
||||
@@ -1004,6 +1010,9 @@ vdbesort.lo: $(TOP)/src/vdbesort.c $(HDR)
|
||||
vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c
|
||||
|
||||
vdbevtab.lo: $(TOP)/src/vdbevtab.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbevtab.c
|
||||
|
||||
vtab.lo: $(TOP)/src/vtab.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c
|
||||
|
||||
@@ -1069,6 +1078,7 @@ SHELL_SRC = \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
@@ -1210,6 +1220,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
|
||||
|
||||
@@ -357,6 +357,7 @@ 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
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
@@ -1353,6 +1354,7 @@ SRC01 = \
|
||||
$(TOP)\src\vdbemem.c \
|
||||
$(TOP)\src\vdbesort.c \
|
||||
$(TOP)\src\vdbetrace.c \
|
||||
$(TOP)\src\vdbevtab.c \
|
||||
$(TOP)\src\vtab.c \
|
||||
$(TOP)\src\wal.c \
|
||||
$(TOP)\src\walker.c \
|
||||
@@ -1684,6 +1686,7 @@ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
@@ -2109,6 +2112,9 @@ vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR)
|
||||
vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c
|
||||
|
||||
vdbevtab.lo: $(TOP)\src\vdbevtab.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbevtab.c
|
||||
|
||||
vtab.lo: $(TOP)\src\vtab.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c
|
||||
|
||||
@@ -2182,6 +2188,7 @@ SHELL_SRC = \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
@@ -2352,6 +2359,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
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_ENABLE_DESERIALIZE=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so you can encode the package version directly into the source files.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite], [3.31.0])
|
||||
AC_INIT([sqlite], [3.32.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.31.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.32.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.31.0'
|
||||
PACKAGE_STRING='sqlite 3.31.0'
|
||||
PACKAGE_VERSION='3.32.0'
|
||||
PACKAGE_STRING='sqlite 3.32.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1467,7 +1467,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 sqlite 3.31.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.32.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1532,7 +1532,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.31.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.32.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1659,7 +1659,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.31.0
|
||||
sqlite configure 3.32.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2078,7 +2078,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 sqlite $as_me 3.31.0, which was
|
||||
It was created by sqlite $as_me 3.32.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12243,7 +12243,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 sqlite $as_me 3.31.0, which was
|
||||
This file was extended by sqlite $as_me 3.32.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12309,7 +12309,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="\\
|
||||
sqlite config.status 3.31.0
|
||||
sqlite config.status 3.32.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+6
-6
@@ -123,7 +123,7 @@ Suppress generation of the report file.
|
||||
<li><b>-r</b>
|
||||
Do not sort or renumber the parser states as part of optimization.
|
||||
<li><b>-s</b>
|
||||
Show parser statistics before existing.
|
||||
Show parser statistics before exiting.
|
||||
<li><b>-T<i>file</i></b>
|
||||
Use <i>file</i> as the template for the generated C-code parser implementation.
|
||||
<li><b>-x</b>
|
||||
@@ -488,7 +488,7 @@ is an error.</p>
|
||||
The precedence of a grammar rule is equal to the precedence of the
|
||||
left-most terminal symbol in the rule for which a precedence is
|
||||
defined. This is normally what you want, but in those cases where
|
||||
you want to precedence of a grammar rule to be something different,
|
||||
you want the precedence of a grammar rule to be something different,
|
||||
you can specify an alternative precedence symbol by putting the
|
||||
symbol in square braces after the period at the end of the rule and
|
||||
before any C-code. For example:</p>
|
||||
@@ -689,7 +689,7 @@ on Parse().
|
||||
<a name='extractx'></a>
|
||||
<h4>The <tt>%extra_context</tt> directive</h4>
|
||||
|
||||
The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
|
||||
The <tt>%extra_context</tt> directive instructs Lemon to add a 2nd parameter
|
||||
to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
|
||||
doesn't do anything itself with these extra argument, but it does
|
||||
store the value make it available to C-code action routines, destructors,
|
||||
@@ -699,9 +699,9 @@ and so forth. For example, if the grammar file contains:</p>
|
||||
%extra_context { MyStruct *pAbc }
|
||||
</pre></p>
|
||||
|
||||
<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
|
||||
<p>Then the ParseAlloc() and ParseInit() functions will have an 2nd parameter
|
||||
of type "MyStruct*" and all action routines will have access to
|
||||
a variable named "pAbc" that is the value of that 2th parameter.</p>
|
||||
a variable named "pAbc" that is the value of that 2nd parameter.</p>
|
||||
|
||||
<p>The <tt>%extra_argument</tt> directive works the same except that it
|
||||
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
|
||||
@@ -996,7 +996,7 @@ on the parser's stack associated with terminal and non-terminal
|
||||
symbols. The values of all terminal symbols must be of the same
|
||||
type. This turns out to be the same data type as the 3rd parameter
|
||||
to the Parse() function generated by Lemon. Typically, you will
|
||||
make the value of a terminal symbol by a pointer to some kind of
|
||||
make the value of a terminal symbol be a pointer to some kind of
|
||||
token structure. Like this:</p>
|
||||
|
||||
<p><pre>
|
||||
|
||||
+11
-4
@@ -37,6 +37,9 @@ proc squish {txt} {
|
||||
|
||||
proc do_setup_rec_test {tn setup sql res} {
|
||||
reset_db
|
||||
if {[info exists ::set_main_db_name]} {
|
||||
dbconfig_maindbname_icecube db
|
||||
}
|
||||
db eval $setup
|
||||
uplevel [list do_rec_test $tn $sql $res]
|
||||
}
|
||||
@@ -76,6 +79,10 @@ foreach {tn setup} {
|
||||
}
|
||||
}
|
||||
3 {
|
||||
if {[info commands sqlite3_expert_new]==""} { continue }
|
||||
set ::set_main_db_name 1
|
||||
}
|
||||
4 {
|
||||
if {![file executable $CLI]} { continue }
|
||||
|
||||
proc do_rec_test {tn sql res} {
|
||||
@@ -336,7 +343,7 @@ proc do_candidates_test {tn sql res} {
|
||||
|
||||
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(c, d);
|
||||
|
||||
@@ -346,7 +353,7 @@ do_execsql_test 4.0 {
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
|
||||
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
|
||||
}
|
||||
do_candidates_test 4.1 {
|
||||
do_candidates_test 5.1 {
|
||||
SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
|
||||
@@ -355,14 +362,14 @@ do_candidates_test 4.1 {
|
||||
CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
|
||||
}
|
||||
|
||||
do_candidates_test 4.2 {
|
||||
do_candidates_test 5.2 {
|
||||
SELECT * FROM t1,t2 WHERE a=? AND b=? AND c=? AND d=?
|
||||
} {
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 17
|
||||
CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
|
||||
}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
do_execsql_test 5.3 {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 16
|
||||
|
||||
+29
-11
@@ -962,6 +962,22 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
|
||||
return zRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Buffer z contains a positive integer value encoded as utf-8 text.
|
||||
** Decode this value and store it in *pnOut, returning the number of bytes
|
||||
** consumed. If an overflow error occurs return a negative value.
|
||||
*/
|
||||
int sqlite3Fts3ReadInt(const char *z, int *pnOut){
|
||||
u64 iVal = 0;
|
||||
int i;
|
||||
for(i=0; z[i]>='0' && z[i]<='9'; i++){
|
||||
iVal = iVal*10 + (z[i] - '0');
|
||||
if( iVal>0x7FFFFFFF ) return -1;
|
||||
}
|
||||
*pnOut = (int)iVal;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function interprets the string at (*pp) as a non-negative integer
|
||||
** value. It reads the integer and sets *pnOut to the value read, then
|
||||
@@ -977,19 +993,17 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
|
||||
*/
|
||||
static int fts3GobbleInt(const char **pp, int *pnOut){
|
||||
const int MAX_NPREFIX = 10000000;
|
||||
const char *p; /* Iterator pointer */
|
||||
int nInt = 0; /* Output value */
|
||||
|
||||
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
|
||||
nInt = nInt * 10 + (p[0] - '0');
|
||||
if( nInt>MAX_NPREFIX ){
|
||||
nInt = 0;
|
||||
break;
|
||||
}
|
||||
int nByte;
|
||||
nByte = sqlite3Fts3ReadInt(*pp, &nInt);
|
||||
if( nInt>MAX_NPREFIX ){
|
||||
nInt = 0;
|
||||
}
|
||||
if( nByte==0 ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( p==*pp ) return SQLITE_ERROR;
|
||||
*pnOut = nInt;
|
||||
*pp = p;
|
||||
*pp += nByte;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1884,6 +1898,7 @@ static int fts3ScanInteriorNode(
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
** interior node. Then load the blockid of the left-child of the b-tree
|
||||
@@ -1908,12 +1923,15 @@ static int fts3ScanInteriorNode(
|
||||
int cmp; /* memcmp() result */
|
||||
int nSuffix; /* Size of term suffix */
|
||||
int nPrefix = 0; /* Size of term prefix */
|
||||
int nBuffer; /* Total term size */
|
||||
|
||||
/* Load the next term on the node into zBuffer. Use realloc() to expand
|
||||
** the size of zBuffer if required. */
|
||||
if( !isFirstTerm ){
|
||||
zCsr += fts3GetVarint32(zCsr, &nPrefix);
|
||||
if( nPrefix>nBuffer ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
}
|
||||
isFirstTerm = 0;
|
||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
@@ -591,6 +591,7 @@ int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
|
||||
int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
|
||||
void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
|
||||
int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
|
||||
int sqlite3Fts3ReadInt(const char *z, int *pnOut);
|
||||
|
||||
/* fts3_tokenizer.c */
|
||||
const char *sqlite3Fts3NextToken(const char *, int *);
|
||||
|
||||
@@ -446,10 +446,7 @@ static int getNextNode(
|
||||
if( pKey->eType==FTSQUERY_NEAR ){
|
||||
assert( nKey==4 );
|
||||
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
||||
nNear = 0;
|
||||
for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
|
||||
nNear = nNear * 10 + (zInput[nKey] - '0');
|
||||
}
|
||||
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ static int fts3tokFilterMethod(
|
||||
if( pCsr->zInput==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memcpy(pCsr->zInput, zByte, nByte);
|
||||
if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
|
||||
pCsr->zInput[nByte] = 0;
|
||||
rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+11
-4
@@ -1415,6 +1415,7 @@ static int fts3SegReaderNext(
|
||||
*/
|
||||
if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|
||||
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
|
||||
|| pReader->nDoclist==0
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -2502,7 +2503,7 @@ static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
|
||||
sqlite3_bind_int64(pStmt, 2,
|
||||
((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
||||
(((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
||||
);
|
||||
|
||||
*pbMax = 0;
|
||||
@@ -3068,11 +3069,11 @@ static void fts3ReadEndBlockField(
|
||||
if( zText ){
|
||||
int i;
|
||||
int iMul = 1;
|
||||
i64 iVal = 0;
|
||||
u64 iVal = 0;
|
||||
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*piEndBlock = iVal;
|
||||
*piEndBlock = (i64)iVal;
|
||||
while( zText[i]==' ' ) i++;
|
||||
iVal = 0;
|
||||
if( zText[i]=='-' ){
|
||||
@@ -3082,7 +3083,7 @@ static void fts3ReadEndBlockField(
|
||||
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
*pnByte = (iVal * (i64)iMul);
|
||||
*pnByte = ((i64)iVal * (i64)iMul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4953,6 +4954,12 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
** Exit early in this case. */
|
||||
if( nSeg<=0 ) break;
|
||||
|
||||
assert( nMod<=0x7FFFFFFF );
|
||||
if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Open a cursor to iterate through the contents of the oldest nSeg
|
||||
** indexes of absolute level iAbsLevel. If this cursor is opened using
|
||||
** the 'hint' parameters, it is possible that there are less than nSeg
|
||||
|
||||
@@ -5732,8 +5732,8 @@ static int fts5QueryCksum(
|
||||
** contain valid utf-8, return non-zero.
|
||||
*/
|
||||
static int fts5TestUtf8(const char *z, int n){
|
||||
assert_nc( n>0 );
|
||||
int i = 0;
|
||||
assert_nc( n>0 );
|
||||
while( i<n ){
|
||||
if( (z[i] & 0x80)==0x00 ){
|
||||
i++;
|
||||
|
||||
@@ -50,6 +50,7 @@ struct Fts5VocabTable {
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* FTS5 global object for this database */
|
||||
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
|
||||
unsigned bBusy; /* True if busy */
|
||||
};
|
||||
|
||||
struct Fts5VocabCursor {
|
||||
@@ -332,6 +333,12 @@ static int fts5VocabOpenMethod(
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *zSql = 0;
|
||||
|
||||
if( pTab->bBusy ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
zSql = sqlite3Fts5Mprintf(&rc,
|
||||
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
||||
pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
|
||||
@@ -343,10 +350,12 @@ static int fts5VocabOpenMethod(
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
|
||||
|
||||
pTab->bBusy = 1;
|
||||
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
i64 iId = sqlite3_column_int64(pStmt, 0);
|
||||
pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
|
||||
}
|
||||
pTab->bBusy = 0;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pFts5==0 ){
|
||||
|
||||
@@ -500,14 +500,18 @@ do_execsql_test 15.0 {
|
||||
INSERT INTO t1 VALUES('c', 'd');
|
||||
}
|
||||
|
||||
if {$tcl_platform(byteOrder)=="littleEndian"} {
|
||||
set res {X'02000000'}
|
||||
} else {
|
||||
set res {X'00000002'}
|
||||
}
|
||||
do_execsql_test 15.1 {
|
||||
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
|
||||
} {X'02000000'}
|
||||
|
||||
} $res
|
||||
do_execsql_test 15.2 {
|
||||
DELETE FROM t1_content WHERE rowid=1;
|
||||
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
|
||||
} {X'02000000'}
|
||||
} $res
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 15.3 {
|
||||
@@ -517,4 +521,3 @@ do_execsql_test 15.3 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -542,5 +542,16 @@ do_execsql_test 10.7.3 {
|
||||
SELECT * FROM t2 WHERE term=?;
|
||||
}
|
||||
|
||||
finish_test
|
||||
# 2020-02-16 Detect recursively define fts5vocab() tables.
|
||||
# Error found by dbsqlfuzz.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 11.100 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab(rowid , 'col');
|
||||
CREATE VIRTUAL TABLE rowid USING fts5vocab(rowid , 'instance');
|
||||
} {}
|
||||
do_catchsql_test 11.110 {
|
||||
SELECT rowid+1,rowid, * FROM t3 WHERE null>rowid ;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
finish_test
|
||||
|
||||
+3
-3
@@ -143,7 +143,7 @@ static int icuLikeCompare(
|
||||
** 3. uPattern is an unescaped escape character, or
|
||||
** 4. uPattern is to be handled as an ordinary character
|
||||
*/
|
||||
if( !prevEscape && uPattern==MATCH_ALL ){
|
||||
if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
||||
/* Case 1. */
|
||||
uint8_t c;
|
||||
|
||||
@@ -169,12 +169,12 @@ static int icuLikeCompare(
|
||||
}
|
||||
return 0;
|
||||
|
||||
}else if( !prevEscape && uPattern==MATCH_ONE ){
|
||||
}else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
||||
/* Case 2. */
|
||||
if( *zString==0 ) return 0;
|
||||
SQLITE_ICU_SKIP_UTF8(zString);
|
||||
|
||||
}else if( !prevEscape && uPattern==(uint32_t)uEsc){
|
||||
}else if( uPattern==(uint32_t)uEsc && !prevEscape ){
|
||||
/* Case 3. */
|
||||
prevEscape = 1;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
** rootpage INT, -- The root page of the btree
|
||||
** sql TEXT, -- SQL for this btree - from sqlite_master
|
||||
** hasRowid BOOLEAN, -- True if the btree has a rowid
|
||||
** nEntry INT, -- Estimated number of enteries
|
||||
** nEntry INT, -- Estimated number of entries
|
||||
** nPage INT, -- Estimated number of pages
|
||||
** depth INT, -- Depth of the btree
|
||||
** szPage INT, -- Size of each page in bytes
|
||||
|
||||
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
** 2020-04-20
|
||||
**
|
||||
** 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 VFS shim that writes a checksum on each page
|
||||
** of an SQLite database file. When reading pages, the checksum is verified
|
||||
** and an error is raised if the checksum is incorrect.
|
||||
**
|
||||
** COMPILING
|
||||
**
|
||||
** This extension requires SQLite 3.32.0 or later. It uses the
|
||||
** sqlite3_database_file_object() interface which was added in
|
||||
** version 3.32.0, so it will not link with an earlier version of
|
||||
** SQLite.
|
||||
**
|
||||
** To build this extension as a separately loaded shared library or
|
||||
** DLL, use compiler command-lines similar to the following:
|
||||
**
|
||||
** (linux) gcc -fPIC -shared cksumvfs.c -o cksumvfs.so
|
||||
** (mac) clang -fPIC -dynamiclib cksumvfs.c -o cksumvfs.dylib
|
||||
** (windows) cl cksumvfs.c -link -dll -out:cksumvfs.dll
|
||||
**
|
||||
** You may want to add additional compiler options, of course,
|
||||
** according to the needs of your project.
|
||||
**
|
||||
** If you want to statically link this extension with your product,
|
||||
** then compile it like any other C-language module but add the
|
||||
** "-DSQLITE_CKSUMVFS_STATIC" option so that this module knows that
|
||||
** it is being statically linked rather than dynamically linked
|
||||
**
|
||||
** LOADING
|
||||
**
|
||||
** To load this extension as a shared library, you first have to
|
||||
** bring up a dummy SQLite database connection to use as the argument
|
||||
** to the sqlite3_load_extension() API call. Then you invoke the
|
||||
** sqlite3_load_extension() API and shutdown the dummy database
|
||||
** connection. All subsequent database connections that are opened
|
||||
** will include this extension. For example:
|
||||
**
|
||||
** sqlite3 *db;
|
||||
** sqlite3_open(":memory:", &db);
|
||||
** sqlite3_load_extention(db, "./cksumvfs");
|
||||
** sqlite3_close(db);
|
||||
**
|
||||
** If this extension is compiled with -DSQLITE_CKSUMVFS_STATIC and
|
||||
** statically linked against the application, initialize it using
|
||||
** a single API call as follows:
|
||||
**
|
||||
** sqlite3_cksumvfs_init();
|
||||
**
|
||||
** Cksumvfs is a VFS Shim. When loaded, "cksmvfs" becomes the new
|
||||
** default VFS and it uses the prior default VFS as the next VFS
|
||||
** down in the stack. This is normally what you want. However, it
|
||||
** complex situations where multiple VFS shims are being loaded,
|
||||
** it might be important to ensure that cksumvfs is loaded in the
|
||||
** correct order so that it sequences itself into the default VFS
|
||||
** Shim stack in the right order.
|
||||
**
|
||||
** USING
|
||||
**
|
||||
** Open database connections using the sqlite3_open() or
|
||||
** sqlite3_open_v2() interfaces, as normal. Ordinary database files
|
||||
** (without a checksum) will operate normally. Databases with
|
||||
** checksums will return an SQLITE_IOERR_DATA error if a page is
|
||||
** encountered that contains an invalid checksum.
|
||||
**
|
||||
** Checksumming only works on databases that have a reserve-bytes
|
||||
** value of exactly 8. The default value for reserve-bytes is 0.
|
||||
** Hence, newly created database files will omit the checksum by
|
||||
** default. To create a database that includes a checksum, change
|
||||
** the reserve-bytes value to 8 by runing:
|
||||
**
|
||||
** int n = 8;
|
||||
** sqlite3_file_control(db, 0, SQLITE_FCNTL_RESERVED_BYTES, &n);
|
||||
**
|
||||
** If you do this immediately after creating a new database file,
|
||||
** before anything else has been written into the file, then that
|
||||
** might be all that you need to do. Otherwise, the API call
|
||||
** above should be followed by:
|
||||
**
|
||||
** sqlite3_exec(db, "VACUUM", 0, 0, 0);
|
||||
**
|
||||
** It never hurts to run the VACUUM, even if you don't need it.
|
||||
** If the database is in WAL mode, you should shutdown and
|
||||
** reopen all database connections before continuing.
|
||||
**
|
||||
** From the CLI, use the ".filectrl reserve_bytes 8" command,
|
||||
** followed by "VACUUM;".
|
||||
**
|
||||
** Note that SQLite allows the number of reserve-bytes to be
|
||||
** increased but not decreased. So if a database file already
|
||||
** has a reserve-bytes value greater than 8, there is no way to
|
||||
** activate checksumming on that database, other than to dump
|
||||
** and restore the database file. Note also that other extensions
|
||||
** might also make use of the reserve-bytes. Checksumming will
|
||||
** be incompatible with those other extensions.
|
||||
**
|
||||
** VERIFICATION OF CHECKSUMS
|
||||
**
|
||||
** If any checksum is incorrect, the "PRAGMA quick_check" command
|
||||
** will find it. To verify that checksums are actually enabled
|
||||
** and running, use the following query:
|
||||
**
|
||||
** SELECT count(*), verify_checksum(data)
|
||||
** FROM sqlite_dbpage
|
||||
** GROUP BY 2;
|
||||
**
|
||||
** There are three possible outputs form the verify_checksum()
|
||||
** function: 1, 0, and NULL. 1 is returned if the checksum is
|
||||
** correct. 0 is returned if the checksum is incorrect. NULL
|
||||
** is returned if the page is unreadable. If checksumming is
|
||||
** enabled, the read will fail if the checksum is wrong, so the
|
||||
** usual result from verify_checksum() on a bad checksum is NULL.
|
||||
**
|
||||
** If everything is OK, the query above should return a single
|
||||
** row where the second column is 1. Any other result indicates
|
||||
** either that there is a checksum error, or checksum validation
|
||||
** is disabled.
|
||||
**
|
||||
** CONTROLLING CHECKSUM VERIFICATION
|
||||
**
|
||||
** The cksumvfs extension implements a new PRAGMA statement that can
|
||||
** be used to disable, re-enable, or query the status of checksum
|
||||
** verification:
|
||||
**
|
||||
** PRAGMA checksum_verification; -- query status
|
||||
** PRAGMA checksum_verification=OFF; -- disable verification
|
||||
** PRAGMA checksum_verification=ON; -- re-enable verification
|
||||
**
|
||||
** The "checksum_verification" pragma will return "1" (true) or "0"
|
||||
** (false) if checksum verification is enabled or disabled, respectively.
|
||||
** "Verification" in this context means the feature that causes
|
||||
** SQLITE_IOERR_DATA errors if a checksum mismatch is detected while
|
||||
** reading. Checksums are always kept up-to-date as long as the
|
||||
** reserve-bytes value of the database is 8, regardless of the setting
|
||||
** of this pragma. Checksum verification can be disabled (for example)
|
||||
** to do forensic analysis of a database that has previously reported
|
||||
** a checksum error.
|
||||
**
|
||||
** The "checksum_verification" pragma will always respond with "0" if
|
||||
** the database file does not have a reserve-bytes value of 8. The
|
||||
** pragma will return no rows at all if the cksumvfs extension is
|
||||
** not loaded.
|
||||
**
|
||||
** IMPLEMENTATION NOTES
|
||||
**
|
||||
** The checksum is stored in the last 8 bytes of each page. This
|
||||
** module only operates if the "bytes of reserved space on each page"
|
||||
** value at offset 20 the SQLite database header is exactly 8. If
|
||||
** the reserved-space value is not 8, this module is a no-op.
|
||||
*/
|
||||
#ifdef SQLITE_CKSUMVFS_STATIC
|
||||
# include "sqlite3.h"
|
||||
#else
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this utility
|
||||
*/
|
||||
typedef struct sqlite3_vfs CksmVfs;
|
||||
typedef struct CksmFile CksmFile;
|
||||
|
||||
/*
|
||||
** Useful datatype abbreviations
|
||||
*/
|
||||
#if !defined(SQLITE_CORE)
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned int u32;
|
||||
#endif
|
||||
|
||||
/* Access to a lower-level VFS that (might) implement dynamic loading,
|
||||
** access to randomness, etc.
|
||||
*/
|
||||
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
||||
#define ORIGFILE(p) ((sqlite3_file*)(((CksmFile*)(p))+1))
|
||||
|
||||
/* An open file */
|
||||
struct CksmFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
const char *zFName; /* Original name of the file */
|
||||
char computeCksm; /* True to compute checksums.
|
||||
** Always true if reserve size is 8. */
|
||||
char verifyCksm; /* True to verify checksums */
|
||||
char isWal; /* True if processing a WAL file */
|
||||
CksmFile *pPartner; /* Ptr from WAL to main-db, or from main-db to WAL */
|
||||
};
|
||||
|
||||
/*
|
||||
** Methods for CksmFile
|
||||
*/
|
||||
static int cksmClose(sqlite3_file*);
|
||||
static int cksmRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||
static int cksmWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
||||
static int cksmTruncate(sqlite3_file*, sqlite3_int64 size);
|
||||
static int cksmSync(sqlite3_file*, int flags);
|
||||
static int cksmFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
||||
static int cksmLock(sqlite3_file*, int);
|
||||
static int cksmUnlock(sqlite3_file*, int);
|
||||
static int cksmCheckReservedLock(sqlite3_file*, int *pResOut);
|
||||
static int cksmFileControl(sqlite3_file*, int op, void *pArg);
|
||||
static int cksmSectorSize(sqlite3_file*);
|
||||
static int cksmDeviceCharacteristics(sqlite3_file*);
|
||||
static int cksmShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
||||
static int cksmShmLock(sqlite3_file*, int offset, int n, int flags);
|
||||
static void cksmShmBarrier(sqlite3_file*);
|
||||
static int cksmShmUnmap(sqlite3_file*, int deleteFlag);
|
||||
static int cksmFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
||||
static int cksmUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
||||
|
||||
/*
|
||||
** Methods for CksmVfs
|
||||
*/
|
||||
static int cksmOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
||||
static int cksmDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
||||
static int cksmAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
||||
static int cksmFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
||||
static void *cksmDlOpen(sqlite3_vfs*, const char *zFilename);
|
||||
static void cksmDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
||||
static void (*cksmDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
||||
static void cksmDlClose(sqlite3_vfs*, void*);
|
||||
static int cksmRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||
static int cksmSleep(sqlite3_vfs*, int microseconds);
|
||||
static int cksmCurrentTime(sqlite3_vfs*, double*);
|
||||
static int cksmGetLastError(sqlite3_vfs*, int, char *);
|
||||
static int cksmCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||
static int cksmSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
|
||||
static sqlite3_syscall_ptr cksmGetSystemCall(sqlite3_vfs*, const char *z);
|
||||
static const char *cksmNextSystemCall(sqlite3_vfs*, const char *zName);
|
||||
|
||||
static sqlite3_vfs cksm_vfs = {
|
||||
3, /* iVersion (set when registered) */
|
||||
0, /* szOsFile (set when registered) */
|
||||
1024, /* mxPathname */
|
||||
0, /* pNext */
|
||||
"cksmvfs", /* zName */
|
||||
0, /* pAppData (set when registered) */
|
||||
cksmOpen, /* xOpen */
|
||||
cksmDelete, /* xDelete */
|
||||
cksmAccess, /* xAccess */
|
||||
cksmFullPathname, /* xFullPathname */
|
||||
cksmDlOpen, /* xDlOpen */
|
||||
cksmDlError, /* xDlError */
|
||||
cksmDlSym, /* xDlSym */
|
||||
cksmDlClose, /* xDlClose */
|
||||
cksmRandomness, /* xRandomness */
|
||||
cksmSleep, /* xSleep */
|
||||
cksmCurrentTime, /* xCurrentTime */
|
||||
cksmGetLastError, /* xGetLastError */
|
||||
cksmCurrentTimeInt64, /* xCurrentTimeInt64 */
|
||||
cksmSetSystemCall, /* xSetSystemCall */
|
||||
cksmGetSystemCall, /* xGetSystemCall */
|
||||
cksmNextSystemCall /* xNextSystemCall */
|
||||
};
|
||||
|
||||
static const sqlite3_io_methods cksm_io_methods = {
|
||||
3, /* iVersion */
|
||||
cksmClose, /* xClose */
|
||||
cksmRead, /* xRead */
|
||||
cksmWrite, /* xWrite */
|
||||
cksmTruncate, /* xTruncate */
|
||||
cksmSync, /* xSync */
|
||||
cksmFileSize, /* xFileSize */
|
||||
cksmLock, /* xLock */
|
||||
cksmUnlock, /* xUnlock */
|
||||
cksmCheckReservedLock, /* xCheckReservedLock */
|
||||
cksmFileControl, /* xFileControl */
|
||||
cksmSectorSize, /* xSectorSize */
|
||||
cksmDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||
cksmShmMap, /* xShmMap */
|
||||
cksmShmLock, /* xShmLock */
|
||||
cksmShmBarrier, /* xShmBarrier */
|
||||
cksmShmUnmap, /* xShmUnmap */
|
||||
cksmFetch, /* xFetch */
|
||||
cksmUnfetch /* xUnfetch */
|
||||
};
|
||||
|
||||
/* Do byte swapping on a unsigned 32-bit integer */
|
||||
#define BYTESWAP32(x) ( \
|
||||
(((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
|
||||
+ (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
|
||||
)
|
||||
|
||||
/* Compute a checksum on a buffer */
|
||||
static void cksmCompute(
|
||||
u8 *a, /* Content to be checksummed */
|
||||
int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
|
||||
u8 *aOut /* OUT: Final 8-byte checksum value output */
|
||||
){
|
||||
u32 s1 = 0, s2 = 0;
|
||||
u32 *aData = (u32*)a;
|
||||
u32 *aEnd = (u32*)&a[nByte];
|
||||
u32 x = 1;
|
||||
|
||||
assert( nByte>=8 );
|
||||
assert( (nByte&0x00000007)==0 );
|
||||
assert( nByte<=65536 );
|
||||
|
||||
if( 1 == *(u8*)&x ){
|
||||
/* Little-endian */
|
||||
do {
|
||||
s1 += *aData++ + s2;
|
||||
s2 += *aData++ + s1;
|
||||
}while( aData<aEnd );
|
||||
}else{
|
||||
/* Big-endian */
|
||||
do {
|
||||
s1 += BYTESWAP32(aData[0]) + s2;
|
||||
s2 += BYTESWAP32(aData[1]) + s1;
|
||||
aData += 2;
|
||||
}while( aData<aEnd );
|
||||
s1 = BYTESWAP32(s1);
|
||||
s2 = BYTESWAP32(s2);
|
||||
}
|
||||
memcpy(aOut, &s1, 4);
|
||||
memcpy(aOut+4, &s2, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL function: verify_checksum(BLOB)
|
||||
**
|
||||
** Return 0 or 1 if the checksum is invalid or valid. Or return
|
||||
** NULL if the input is not a BLOB that is the right size for a
|
||||
** database page.
|
||||
*/
|
||||
static void cksmVerifyFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int nByte;
|
||||
u8 *data;
|
||||
u8 cksum[8];
|
||||
data = (u8*)sqlite3_value_blob(argv[0]);
|
||||
if( data==0 ) return;
|
||||
if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ) return;
|
||||
nByte = sqlite3_value_bytes(argv[0]);
|
||||
if( nByte<512 || nByte>65536 || (nByte & (nByte-1))!=0 ) return;
|
||||
cksmCompute(data, nByte-8, cksum);
|
||||
sqlite3_result_int(context, memcmp(data+nByte-8,cksum,8)==0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a cksm-file.
|
||||
*/
|
||||
static int cksmClose(sqlite3_file *pFile){
|
||||
CksmFile *p = (CksmFile *)pFile;
|
||||
if( p->pPartner ){
|
||||
assert( p->pPartner->pPartner==p );
|
||||
p->pPartner->pPartner = 0;
|
||||
p->pPartner = 0;
|
||||
}
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xClose(pFile);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from a cksm-file.
|
||||
*/
|
||||
static int cksmRead(
|
||||
sqlite3_file *pFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
int rc;
|
||||
CksmFile *p = (CksmFile *)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
rc = pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iOfst==0 && iAmt>=100 && memcmp(zBuf,"SQLite format 3",16)==0 ){
|
||||
u8 *d = (u8*)zBuf;
|
||||
char hasCorrectReserveSize = (d[20]==8);
|
||||
if( hasCorrectReserveSize!=p->computeCksm ){
|
||||
p->computeCksm = p->verifyCksm = hasCorrectReserveSize;
|
||||
}
|
||||
}
|
||||
/* Verify the checksum if (1) the size seems appropriate for a database
|
||||
** page, and if (2) checksum verification is enabled. But (3) do not
|
||||
** verify the checksums on a WAL page if the main database file
|
||||
** has subsequently turned off checksums.
|
||||
*/
|
||||
if( iAmt>=512 /* (1) */
|
||||
&& p->verifyCksm /* (2) */
|
||||
&& (!p->isWal || (p->pPartner!=0 && p->pPartner->verifyCksm)) /* (3) */
|
||||
){
|
||||
u8 cksum[8];
|
||||
cksmCompute((u8*)zBuf, iAmt-8, cksum);
|
||||
if( memcmp(zBuf+iAmt-8, cksum, 8)!=0 ){
|
||||
sqlite3_log(SQLITE_IOERR_DATA,
|
||||
"checksum fault offset %lld of \"%s\"",
|
||||
iOfst, p->zFName);
|
||||
rc = SQLITE_IOERR_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to a cksm-file.
|
||||
*/
|
||||
static int cksmWrite(
|
||||
sqlite3_file *pFile,
|
||||
const void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
CksmFile *p = (CksmFile *)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
if( iOfst==0 && iAmt>=100 && memcmp(zBuf,"SQLite format 3",16)==0 ){
|
||||
u8 *d = (u8*)zBuf;
|
||||
char hasCorrectReserveSize = (d[20]==8);
|
||||
if( hasCorrectReserveSize!=p->computeCksm ){
|
||||
p->computeCksm = p->verifyCksm = hasCorrectReserveSize;
|
||||
}
|
||||
}
|
||||
/* If the write size is appropriate for a database page and if
|
||||
** checksums where ever enabled, then it will be safe to compute
|
||||
** the checksums. The reserve byte size might have increased, but
|
||||
** it will never decrease. And because it cannot decrease, the
|
||||
** checksum will not overwrite anything.
|
||||
*/
|
||||
if( iAmt>=512 && p->computeCksm ){
|
||||
cksmCompute((u8*)zBuf, iAmt-8, ((u8*)zBuf)+iAmt-8);
|
||||
}
|
||||
return pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst);
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate a cksm-file.
|
||||
*/
|
||||
static int cksmTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xTruncate(pFile, size);
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync a cksm-file.
|
||||
*/
|
||||
static int cksmSync(sqlite3_file *pFile, int flags){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xSync(pFile, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current file-size of a cksm-file.
|
||||
*/
|
||||
static int cksmFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
CksmFile *p = (CksmFile *)pFile;
|
||||
pFile = ORIGFILE(p);
|
||||
return pFile->pMethods->xFileSize(pFile, pSize);
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock a cksm-file.
|
||||
*/
|
||||
static int cksmLock(sqlite3_file *pFile, int eLock){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xLock(pFile, eLock);
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock a cksm-file.
|
||||
*/
|
||||
static int cksmUnlock(sqlite3_file *pFile, int eLock){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xUnlock(pFile, eLock);
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on a cksm-file.
|
||||
*/
|
||||
static int cksmCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
|
||||
}
|
||||
|
||||
/*
|
||||
** File control method. For custom operations on a cksm-file.
|
||||
*/
|
||||
static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
int rc;
|
||||
CksmFile *p = (CksmFile*)pFile;
|
||||
pFile = ORIGFILE(pFile);
|
||||
if( op==SQLITE_FCNTL_PRAGMA ){
|
||||
char **azArg = (char**)pArg;
|
||||
assert( azArg[1]!=0 );
|
||||
if( sqlite3_stricmp(azArg[1],"checksum_verification")==0 ){
|
||||
char *zArg = azArg[2];
|
||||
if( zArg!=0 ){
|
||||
if( (zArg[0]>='1' && zArg[0]<='9')
|
||||
|| sqlite3_strlike("enable%",zArg,0)==0
|
||||
|| sqlite3_stricmp("yes",zArg)==0
|
||||
|| sqlite3_stricmp("on",zArg)==0
|
||||
){
|
||||
p->verifyCksm = p->computeCksm;
|
||||
}else{
|
||||
p->verifyCksm = 0;
|
||||
}
|
||||
}
|
||||
azArg[0] = sqlite3_mprintf("%d",p->verifyCksm);
|
||||
return SQLITE_OK;
|
||||
}else if( p->computeCksm && azArg[2]!=0
|
||||
&& sqlite3_stricmp(azArg[1], "page_size")==0 ){
|
||||
/* Do not allow page size changes on a checksum database */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
|
||||
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
|
||||
*(char**)pArg = sqlite3_mprintf("cksm/%z", *(char**)pArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the sector-size in bytes for a cksm-file.
|
||||
*/
|
||||
static int cksmSectorSize(sqlite3_file *pFile){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xSectorSize(pFile);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the device characteristic flags supported by a cksm-file.
|
||||
*/
|
||||
static int cksmDeviceCharacteristics(sqlite3_file *pFile){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xDeviceCharacteristics(pFile);
|
||||
}
|
||||
|
||||
/* Create a shared memory file mapping */
|
||||
static int cksmShmMap(
|
||||
sqlite3_file *pFile,
|
||||
int iPg,
|
||||
int pgsz,
|
||||
int bExtend,
|
||||
void volatile **pp
|
||||
){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
|
||||
}
|
||||
|
||||
/* Perform locking on a shared-memory segment */
|
||||
static int cksmShmLock(sqlite3_file *pFile, int offset, int n, int flags){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xShmLock(pFile,offset,n,flags);
|
||||
}
|
||||
|
||||
/* Memory barrier operation on shared memory */
|
||||
static void cksmShmBarrier(sqlite3_file *pFile){
|
||||
pFile = ORIGFILE(pFile);
|
||||
pFile->pMethods->xShmBarrier(pFile);
|
||||
}
|
||||
|
||||
/* Unmap a shared memory segment */
|
||||
static int cksmShmUnmap(sqlite3_file *pFile, int deleteFlag){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
|
||||
}
|
||||
|
||||
/* Fetch a page of a memory-mapped file */
|
||||
static int cksmFetch(
|
||||
sqlite3_file *pFile,
|
||||
sqlite3_int64 iOfst,
|
||||
int iAmt,
|
||||
void **pp
|
||||
){
|
||||
CksmFile *p = (CksmFile *)pFile;
|
||||
if( p->computeCksm ){
|
||||
*pp = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xFetch(pFile, iOfst, iAmt, pp);
|
||||
}
|
||||
|
||||
/* Release a memory-mapped page */
|
||||
static int cksmUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
||||
pFile = ORIGFILE(pFile);
|
||||
return pFile->pMethods->xUnfetch(pFile, iOfst, pPage);
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a cksm file handle.
|
||||
*/
|
||||
static int cksmOpen(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
CksmFile *p;
|
||||
sqlite3_file *pSubFile;
|
||||
sqlite3_vfs *pSubVfs;
|
||||
int rc;
|
||||
pSubVfs = ORIGVFS(pVfs);
|
||||
if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){
|
||||
return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
|
||||
}
|
||||
p = (CksmFile*)pFile;
|
||||
memset(p, 0, sizeof(*p));
|
||||
pSubFile = ORIGFILE(pFile);
|
||||
p->base.pMethods = &cksm_io_methods;
|
||||
rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
|
||||
if( rc ) goto cksm_open_done;
|
||||
if( flags & SQLITE_OPEN_WAL ){
|
||||
sqlite3_file *pDb = sqlite3_database_file_object(zName);
|
||||
p->pPartner = (CksmFile*)pDb;
|
||||
assert( p->pPartner->pPartner==0 );
|
||||
p->pPartner->pPartner = p;
|
||||
p->isWal = 1;
|
||||
p->computeCksm = p->pPartner->computeCksm;
|
||||
}else{
|
||||
p->isWal = 0;
|
||||
p->computeCksm = 0;
|
||||
}
|
||||
p->zFName = zName;
|
||||
cksm_open_done:
|
||||
if( rc ) pFile->pMethods = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** All other VFS methods are pass-thrus.
|
||||
*/
|
||||
static int cksmDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
|
||||
}
|
||||
static int cksmAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
|
||||
}
|
||||
static int cksmFullPathname(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
|
||||
}
|
||||
static void *cksmDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
|
||||
}
|
||||
static void cksmDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
|
||||
}
|
||||
static void (*cksmDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
|
||||
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
|
||||
}
|
||||
static void cksmDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
|
||||
}
|
||||
static int cksmRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
|
||||
}
|
||||
static int cksmSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
|
||||
}
|
||||
static int cksmCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
|
||||
}
|
||||
static int cksmGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
||||
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
|
||||
}
|
||||
static int cksmCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
||||
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
|
||||
}
|
||||
static int cksmSetSystemCall(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_syscall_ptr pCall
|
||||
){
|
||||
return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
|
||||
}
|
||||
static sqlite3_syscall_ptr cksmGetSystemCall(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName
|
||||
){
|
||||
return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
|
||||
}
|
||||
static const char *cksmNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
|
||||
return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
|
||||
}
|
||||
|
||||
/* Register the verify_checksum() SQL function.
|
||||
*/
|
||||
static int cksmRegisterFunc(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc;
|
||||
if( db==0 ) return SQLITE_OK;
|
||||
rc = sqlite3_create_function(db, "verify_checksum", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
0, cksmVerifyFunc, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register the cksum VFS as the default VFS for the system.
|
||||
** Also make arrangements to automatically register the "verify_checksum()"
|
||||
** SQL function on each new database connection.
|
||||
*/
|
||||
static int cksmRegisterVfs(void){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_vfs *pOrig;
|
||||
if( sqlite3_vfs_find("cksum")!=0 ) return SQLITE_OK;
|
||||
pOrig = sqlite3_vfs_find(0);
|
||||
cksm_vfs.iVersion = pOrig->iVersion;
|
||||
cksm_vfs.pAppData = pOrig;
|
||||
cksm_vfs.szOsFile = pOrig->szOsFile + sizeof(CksmFile);
|
||||
rc = sqlite3_vfs_register(&cksm_vfs, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_auto_extension((void(*)(void))cksmRegisterFunc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_CKSUMVFS_STATIC)
|
||||
/* This variant of the initializer runs when the extension is
|
||||
** statically linked.
|
||||
*/
|
||||
int sqlite3_register_cksumvfs(const char *NotUsed){
|
||||
(void)NotUsed;
|
||||
return cksmRegisterVfs();
|
||||
}
|
||||
#endif /* defined(SQLITE_CKSUMVFS_STATIC */
|
||||
|
||||
#if !defined(SQLITE_CKSUMVFS_STATIC)
|
||||
/* This variant of the initializer function is used when the
|
||||
** extension is shared library to be loaded at run-time.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
/*
|
||||
** This routine is called by sqlite3_load_extension() when the
|
||||
** extension is first loaded.
|
||||
***/
|
||||
int sqlite3_cksumvfs_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* not used */
|
||||
rc = cksmRegisterFunc(db, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = cksmRegisterVfs();
|
||||
}
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
|
||||
return rc;
|
||||
}
|
||||
#endif /* !defined(SQLITE_CKSUMVFS_STATIC) */
|
||||
@@ -394,6 +394,7 @@ static int writeFile(
|
||||
|
||||
if( mtime>=0 ){
|
||||
#if defined(_WIN32)
|
||||
#if !SQLITE_OS_WINRT
|
||||
/* Windows */
|
||||
FILETIME lastAccess;
|
||||
FILETIME lastWrite;
|
||||
@@ -424,6 +425,7 @@ static int writeFile(
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
|
||||
/* Recent unix */
|
||||
struct timespec times[2];
|
||||
|
||||
+3
-2
@@ -381,8 +381,9 @@ int sqlite3_sha_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
||||
sha1Func, 0, 0);
|
||||
rc = sqlite3_create_function(db, "sha1", 1,
|
||||
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
|
||||
0, sha1Func, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "sha1_query", 1,
|
||||
SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** 2020-04-14
|
||||
**
|
||||
** 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 SQLite extension implements the UINT collating sequence.
|
||||
**
|
||||
** UINT works like BINARY for text, except that embedded strings
|
||||
** of digits compare in numeric order.
|
||||
**
|
||||
** * Leading zeros are handled properly, in the sense that
|
||||
** they do not mess of the maginitude comparison of embedded
|
||||
** strings of digits. "x00123y" is equal to "x123y".
|
||||
**
|
||||
** * Only unsigned integers are recognized. Plus and minus
|
||||
** signs are ignored. Decimal points and exponential notation
|
||||
** are ignored.
|
||||
**
|
||||
** * Embedded integers can be of arbitrary length. Comparison
|
||||
** is *not* limited integers that can be expressed as a
|
||||
** 64-bit machine integer.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
** Compare text in lexicographic order, except strings of digits
|
||||
** compare in numeric order.
|
||||
*/
|
||||
static int uintCollFunc(
|
||||
void *notUsed,
|
||||
int nKey1, const void *pKey1,
|
||||
int nKey2, const void *pKey2
|
||||
){
|
||||
const unsigned char *zA = (const unsigned char*)pKey1;
|
||||
const unsigned char *zB = (const unsigned char*)pKey2;
|
||||
int i=0, j=0, x;
|
||||
while( i<nKey1 && j<nKey2 ){
|
||||
x = zA[i] - zB[j];
|
||||
if( isdigit(zA[i]) ){
|
||||
int k;
|
||||
if( !isdigit(zB[j]) ) return x;
|
||||
while( i<nKey1 && zA[i]=='0' ){ i++; }
|
||||
while( j<nKey2 && zB[j]=='0' ){ j++; }
|
||||
k = 0;
|
||||
while( i+k<nKey1 && isdigit(zA[i+k])
|
||||
&& j+k<nKey2 && isdigit(zB[j+k]) ){
|
||||
k++;
|
||||
}
|
||||
if( i+k<nKey1 && isdigit(zA[i+k]) ){
|
||||
return +1;
|
||||
}else if( j+k<nKey2 && isdigit(zB[j+k]) ){
|
||||
return -1;
|
||||
}else{
|
||||
x = memcmp(zA+i, zB+j, k);
|
||||
if( x ) return x;
|
||||
i += k;
|
||||
j += k;
|
||||
}
|
||||
}else if( x ){
|
||||
return x;
|
||||
}else{
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return (nKey1 - i) - (nKey2 - j);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_uint_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
|
||||
}
|
||||
+3
-1
@@ -3746,8 +3746,10 @@ static int rtreeInit(
|
||||
}else if( pRtree->nAux>0 ){
|
||||
break;
|
||||
}else{
|
||||
static const char *azFormat[] = {",%.*s REAL", ",%.*s INT"};
|
||||
pRtree->nDim2++;
|
||||
sqlite3_str_appendf(pSql, ",%.*s NUM", rtreeTokenLength(zArg), zArg);
|
||||
sqlite3_str_appendf(pSql, azFormat[eCoordType],
|
||||
rtreeTokenLength(zArg), zArg);
|
||||
}
|
||||
}
|
||||
sqlite3_str_appendf(pSql, ");");
|
||||
|
||||
+13
-1
@@ -716,6 +716,18 @@ do_execsql_test 18.0 {
|
||||
SELECT rt0.c1 > '-1' FROM rt0;
|
||||
} {9 1}
|
||||
|
||||
|
||||
expand_all_sql db
|
||||
|
||||
# 2020-02-28 ticket e63b4d1a65546532
|
||||
reset_db
|
||||
do_execsql_test 19.0 {
|
||||
CREATE VIRTUAL TABLE rt0 USING rtree(a,b,c);
|
||||
INSERT INTO rt0(a,b,c) VALUES(0,0.0,0.0);
|
||||
CREATE VIEW v0(x) AS SELECT DISTINCT rt0.b FROM rt0;
|
||||
SELECT v0.x FROM v0, rt0;
|
||||
} {0.0}
|
||||
do_execsql_test 19.1 {
|
||||
SELECT v0.x FROM v0, rt0 WHERE v0.x = rt0.b;
|
||||
} {0.0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -34,5 +34,51 @@ do_test 1.0 {
|
||||
compare_db db db2
|
||||
} {}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
db2 close
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO main.t1 VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
db eval {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(10, 11, 12);
|
||||
DELETE FROM t1 WHERE a=1;
|
||||
UPDATE t1 SET b='five', c='six' WHERE a=4;
|
||||
}
|
||||
|
||||
set C [S changeset]
|
||||
db eval ROLLBACK
|
||||
S delete
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO temp.t1 VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
|
||||
}
|
||||
|
||||
set ::conflict [list]
|
||||
proc xConflict {args} { lappend ::conflict $args ; return "" }
|
||||
do_test 2.3 {
|
||||
sqlite3changeset_apply db $C xConflict
|
||||
set ::conflict
|
||||
} {}
|
||||
do_execsql_test 2.4 {
|
||||
SELECT * FROM main.t1;
|
||||
SELECT '****';
|
||||
SELECT * FROM temp.t1;
|
||||
} {
|
||||
4 five six 7 8 9 10 11 12
|
||||
****
|
||||
1 2 3 4 5 6 7 8 9
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -3513,7 +3513,7 @@ static int sessionDeleteRow(
|
||||
SessionBuffer buf = {0, 0, 0};
|
||||
int nPk = 0;
|
||||
|
||||
sessionAppendStr(&buf, "DELETE FROM ", &rc);
|
||||
sessionAppendStr(&buf, "DELETE FROM main.", &rc);
|
||||
sessionAppendIdent(&buf, zTab, &rc);
|
||||
sessionAppendStr(&buf, " WHERE ", &rc);
|
||||
|
||||
@@ -3596,7 +3596,7 @@ static int sessionUpdateRow(
|
||||
SessionBuffer buf = {0, 0, 0};
|
||||
|
||||
/* Append "UPDATE tbl SET " */
|
||||
sessionAppendStr(&buf, "UPDATE ", &rc);
|
||||
sessionAppendStr(&buf, "UPDATE main.", &rc);
|
||||
sessionAppendIdent(&buf, zTab, &rc);
|
||||
sessionAppendStr(&buf, " SET ", &rc);
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@ LIBOBJ+= vdbe.o parse.o \
|
||||
table.o threads.o tokenize.o treeview.o trigger.o \
|
||||
update.o upsert.o userauth.o util.o vacuum.o \
|
||||
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
|
||||
vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
|
||||
vdbetrace.o vdbevtab.o \
|
||||
wal.o walker.o where.o wherecode.o whereexpr.o \
|
||||
utf.o vtab.o window.o
|
||||
|
||||
LIBOBJ += sqlite3session.o
|
||||
@@ -173,6 +174,7 @@ SRC = \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbesort.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbevtab.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/vxworks.h \
|
||||
@@ -526,6 +528,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
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
|
||||
@@ -536,6 +539,7 @@ FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
DBFUZZ_OPT =
|
||||
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
ST_OPT = -DSQLITE_THREADSAFE=0
|
||||
@@ -586,6 +590,7 @@ DBFUZZ2_OPTS = \
|
||||
-DSQLITE_ENABLE_DESERIALIZE \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
||||
-DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_ENABLE_FTS5
|
||||
@@ -733,6 +738,7 @@ SHELL_SRC = \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
@@ -894,6 +900,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
|
||||
|
||||
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
C Version\s3.31.0
|
||||
D 2020-01-22T18:38:59.573
|
||||
C Corner-case\schanges\sto\sthe\sbytecode\svirtual\stable\sfor\stestability\sand\ncorrectness.
|
||||
D 2020-05-02T00:01:39.619
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 9dfc7936f675785309b74d09202bb656732325e65df889e5aaa18cc8932e5b0c
|
||||
F Makefile.in 280cf54350738dfd567bd97ae1bff1bf68c64658c4d5ff21be9cae117e92f063
|
||||
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
|
||||
F Makefile.msc fab23c6b10cb6f06a7e9c407fc2e35cb184a6d653f1b793bda87fcee2eafa4f6
|
||||
F Makefile.msc d9232f9339da7d2b82611cb148734d36be4cc90e17a968882e71d9bf75e512df
|
||||
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
|
||||
F VERSION 081500f0aeaadc989d85aafbc717af45512018aebc73d89e5c2368fe62a600ff
|
||||
F VERSION 980d78a2ce04a1fd0ebefbaabd665f7f9186563820629ee29c6e350e96f19b52
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
@@ -22,7 +22,7 @@ F autoconf/configure.ac 3cd933b959fe514eebd1ca1717dfddbf2c9b825b6bc2c5f744deaf5d
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
F autoconf/tea/configure.ac 6f379dfd46ace5caa97791acae07675eff62cada9800fc7bb36c789ecb7f17ac
|
||||
F autoconf/tea/configure.ac ea61e07340d97e4a79a081f0b8977198a6073edd060738dbb3ae5cb8d5e96f1c
|
||||
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
|
||||
@@ -34,11 +34,11 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
|
||||
F configure aae28230005acf833d466c8a160bd4c70cf42984f5a6756fa327e15e7f473477 x
|
||||
F configure 4bbb5f13998f2faf929b9ae708aea9fbcb08a46cb6dd3150e36c3f09c0a05a75 x
|
||||
F configure.ac 798a24cee2879325ca5b688a618199eb32cc77ed8136edbaa43d9137b470d54e
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3
|
||||
F doc/lemon.html 857495c0ce060a4e2f2ad7111135ad7e28041a32c10612279ab398eddf678f58
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
@@ -48,7 +48,7 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
|
||||
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test e2afc53a27610e8251e44c7f961806607a5490ff204b3db342740d558e052662
|
||||
F ext/expert/expert1.test 2e10ff875c31c9e6fc5e324767624181273859771fe34c5daeeadf3f2974a4f7
|
||||
F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
@@ -82,11 +82,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 52c09f459364732b5df73eff0373f991fd6af8f0f60fcdbb4b649205e88a7568
|
||||
F ext/fts3/fts3.c de2cc136ccc6128e948ffd5d74636756014b2430d6237d7002c3bc3ceb1ae3ae
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h f091030b976045e7df91af2337935952b477cdbd9f48058c44c965684484cb50
|
||||
F ext/fts3/fts3Int.h 2c59cc46aefde134c1782e89a6a5384710ddcd4e783071337aa5d43d07269be3
|
||||
F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
|
||||
F ext/fts3/fts3_expr.c b132af223e90e35b9f9efa9fe63d6ae737d34153a3b6066736086df8abc78a1f
|
||||
F ext/fts3/fts3_expr.c f081e38da641724cd72c20e23b71db2bf4d0c9517c14637442f6910259f11a34
|
||||
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
|
||||
@@ -94,13 +94,13 @@ F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c 052b35ad746349ffb53820379bacdb23ff3ac60d3cc13d986e56d42822ef5a9a
|
||||
F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
|
||||
F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39
|
||||
F ext/fts3/fts3_tokenize_vtab.c 1de9a61acfa2a0445ed989310c31839c57f6b6086dd9d5c97177ae734a17fd8b
|
||||
F ext/fts3/fts3_tokenize_vtab.c cb792f59212f7799bf2891c7d4579bbf568f124ce8fbb0a9902aa5bd577e8b75
|
||||
F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
|
||||
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
|
||||
F ext/fts3/fts3_write.c 6f9dd5d774003ea81b8b32daa7d0819f9aaf01bf2b5f33498a69aab096094ed3
|
||||
F ext/fts3/fts3_write.c ed869b24d074f2498bdbef915d6db1f88c604ca5811502112061932a0bed5133
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
@@ -117,7 +117,7 @@ F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6
|
||||
F ext/fts5/fts5_config.c b447948f35ad3354e8fe5e242e0a7e7b5b941555400b9404259944e3aa570037
|
||||
F ext/fts5/fts5_expr.c 2be456484786333d559dc2987a00f2750981fab91d52db8452a8046278c5f22e
|
||||
F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
|
||||
F ext/fts5/fts5_index.c e3573c88ce8238f7a5892c777a9ddf646c1355012780337d783fb2dfc3dca650
|
||||
F ext/fts5/fts5_index.c f25bec3c00bf050fa2d702d97b773d0706692661172026ddac8df1f164b8b198
|
||||
F ext/fts5/fts5_main.c e881a2ea0bf01b3a3ff0bc1b31373c58fd54b6c9f3c43ea3d431bea4e5d4025e
|
||||
F ext/fts5/fts5_storage.c 3ecda8edadc1f62a355d6789776be0da609f8658c50d72e422674093ab7e1528
|
||||
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
|
||||
@@ -126,7 +126,7 @@ F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3
|
||||
F ext/fts5/fts5_tokenize.c 2e508c6a3bd8ee56c48e98a38052e1a650e49b32a484cce9b189984114bc3b88
|
||||
F ext/fts5/fts5_unicode2.c 8bd0cd07396b74c1a05590e4070d635bccfc849812c305619f109e6c0485e250
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c c3f12188570abb423303cd193b16dd19ba54e21c2e930e9b748d743de3b385f5
|
||||
F ext/fts5/fts5_vocab.c 7a071833064dc8bca236c3c323e56aac36f583aa2c46ce916d52e31ce87462c9
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
|
||||
@@ -187,7 +187,7 @@ F ext/fts5/test/fts5integrity.test 8ffabcd91b058d812aba3e3e0a06f76ce165ba402a18c
|
||||
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
|
||||
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
|
||||
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
|
||||
F ext/fts5/test/fts5matchinfo.test 50d86da66ec5b27603dcd90ba0227f5d9deb10351cbc52974a88e24f6fc9b076
|
||||
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
|
||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test 088ac5f0f5de1ad45b0f83197ab5263bcae8130156cdc901bff2375ff2b8af86
|
||||
@@ -223,7 +223,7 @@ F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef
|
||||
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
|
||||
F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
|
||||
F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc67e468f7cfdf97fd6a
|
||||
F ext/fts5/test/fts5vocab.test 648fb2fe86b55e08295e34504704718d92fba3e2cf3e1f5d72fa3682df4cd0f0
|
||||
F ext/fts5/test/fts5vocab.test 7ed80d9af1ddaaa1637da05e406327b5aac250848bc604c1c1cc667908b87760
|
||||
F ext/fts5/test/fts5vocab2.test e0fdc3a3095f6eda68ac9bf9a443ff929a124d46f00af19933604085712e9d47
|
||||
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
|
||||
F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
|
||||
@@ -231,7 +231,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt a295e91db742b153e8dce8f7efd31d28ad1eea4df31ef4daa3eedc85be2f5138
|
||||
F ext/icu/icu.c 7adfe8a72dd4f54b47684dc9b88523399c6ef119d733b73e17371445f7428dd1
|
||||
F ext/icu/icu.c 91c021c7e3e8bbba286960810fa303295c622e323567b2e6def4ce58e4466e60
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9
|
||||
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
|
||||
@@ -283,8 +283,9 @@ F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2
|
||||
F ext/misc/btreeinfo.c 26004b7a6be320ec08fc20ca8d0f01fccb00a98cbe0f3197446794ff2a506aa3
|
||||
F ext/misc/carray.c 91e9a7f512fda934894bed30464552fffa7d3073b5be04189ae0bd0c59f26bfd
|
||||
F ext/misc/cksumvfs.c 755627c9112a000bc89653cb5038e080e69c58fa0a5c8e9ebd747f24e5fc01c9
|
||||
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
|
||||
F ext/misc/completion.c a0efe03edfdc4f717c61e6c9b0bfe2708ff7878010dae3174980a68fdf76aabc
|
||||
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
|
||||
@@ -293,7 +294,7 @@ F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf9
|
||||
F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287c336
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f
|
||||
F ext/misc/fileio.c bfa11a207da4eed8e5f84a1e3954608492f25f8850f9f00d0d2076f4648d7608
|
||||
F ext/misc/fileio.c 9b69e25da3b51d4a1d905a464ccb96709792ad627a742ba09215bc0d1447e7bd
|
||||
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
|
||||
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
|
||||
F ext/misc/ieee754.c eaffd9b364d7c8371727e9c43fc8bec38cdacc4d11fc26beffaa3ca05a0ea9d6
|
||||
@@ -312,7 +313,7 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
|
||||
F ext/misc/series.c 4057dda3579b38ff88b2d3b13b4dd92dbd9d6f90dac2b55c19b0a8ed87ee4959
|
||||
F ext/misc/sha1.c 1190aec0d9d886d9f5ffdf891142a626812327d11472c0cade3489db3b7b140a
|
||||
F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
|
||||
F ext/misc/shathree.c 135b7c145db4a09b1650c3e7aff9cb538763a9a361e834c015dd1aaf8d5c9a00
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
|
||||
@@ -320,6 +321,7 @@ F ext/misc/sqlar.c c9e5d58544e1506135806a1e0f525f92d4bb6bb125348dce469d778fb334f
|
||||
F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da93d
|
||||
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
|
||||
F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
|
||||
F ext/misc/uint.c 5870865fb5f6153db18db443f3ecdcdb17a06567ee47ecd9fd26e3ec7e5f6ce8
|
||||
F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
|
||||
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
|
||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||
@@ -384,9 +386,9 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c cac70b5502742bd0ba8877a1329a74e86a379c78567546a2a18cf5f9c3787f73
|
||||
F ext/rtree/rtree.c 84b939a9a558edd0461bb976b98f60012e3e574b3b17a0f44533d6f2a9aa2f2e
|
||||
F ext/rtree/rtree.c 0ee39cc787b95aa03a012e09e6090b0fa452154fa812af9a379898560fd6c00f
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 4092a8bd2b5eafc4fafe4fe9024249c12b13e4bab23c2c3eaff57412fdf805fa
|
||||
F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
|
||||
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
|
||||
@@ -433,7 +435,7 @@ F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973
|
||||
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
|
||||
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
|
||||
F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c
|
||||
F ext/session/sessionH.test a417559f29a7e775950fc5fc82b3d01256a7cbe793ddf1180df234df823d56e2
|
||||
F ext/session/sessionH.test b17afdbd3b8f17e9bab91e235acf167cf35485db2ab2df0ea8893fbb914741a4
|
||||
F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b
|
||||
F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
|
||||
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
|
||||
@@ -444,7 +446,7 @@ F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b295
|
||||
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
|
||||
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
|
||||
F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
|
||||
F ext/session/sqlite3session.c a4dfb372f270df93422b0dc7666fd46849e6979b62a152f11287c21eed4ac21b
|
||||
F ext/session/sqlite3session.c e25b345896fa3646ff8b6c4058b3d9e365dc7eab4afe80b110808681098551c8
|
||||
F ext/session/sqlite3session.h a2db5b72b938d12c727b4b4ec632254ca493670a9c0de597af3271a7f774fc57
|
||||
F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
@@ -453,7 +455,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 7ce055f3df31a4f7d21e38f493f907c21db1f673863a573e231f55e2ab005023
|
||||
F main.mk 0c20162946c82e216ae3abab6334d52f1c9b09035c13619ade404b5e7fe3ce21
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -465,38 +467,38 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de
|
||||
F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c
|
||||
F src/attach.c df0ead9091042c68964856ecc08dba55d5403ad5f3ca865d9d396d71528c511a
|
||||
F src/alter.c fa2c3be9b0ebecfafb7062072a0ae6eda126d3e5a9fd51b2eded5acd95dc783c
|
||||
F src/analyze.c 831bb090988477a00d3b4c000746e1b0454dcc93b10b793e6ebe1c47f25d193a
|
||||
F src/attach.c ff2daea0fe62080192e3f262670e4f61f5a86c1e7bea9cec34e960fe79852aa1
|
||||
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
|
||||
F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
|
||||
F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 7af5ff0f88ba856c2681f6eeb457590b24f787e994f18cbdb44c2de2d33f757e
|
||||
F src/btree.h 6111552f19ed7a40f029cf4b33badc6fef9880314fffd80a945f0b7f43ab7471
|
||||
F src/btreeInt.h 6794084fad08c9750b45145743c0e3e5c27c94dee89f26dd8df7073314934fd2
|
||||
F src/build.c 2394d2c853088106dfc1cf485d609f20e6421d7c84892b795824e454f78e50ad
|
||||
F src/callback.c c547d00963ae28100117b4fb1f0f32242109b5804374ee3bfe01138a54da7f76
|
||||
F src/btree.c 02376eb7d49ccf31b53c2504f045ad74687c142a5c15ca837516e59e737867dc
|
||||
F src/btree.h 32672fa1aa74a7e9ab3aae822f94ffc8e732b1eb005988dc2283f91dc7573398
|
||||
F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0
|
||||
F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36
|
||||
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
|
||||
F src/date.c 6c408fdd2e9ddf6e8431aba76315a2d061bea2cec8fbb75e25d7c1ba08274712
|
||||
F src/ctime.c 6892999ee100bd72b64f84dd7a8f737817d72872648705fbf8ed9575e1f1dd1a
|
||||
F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384
|
||||
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
|
||||
F src/dbstat.c 0f55297469d4244ab7df395849e1af98eb5e95816af7c661e7d2d8402dea23da
|
||||
F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4
|
||||
F src/expr.c 003c59158b33d7f3b198122cb0d1e13c06517cc3932e56b42283eb0e96696d66
|
||||
F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f
|
||||
F src/delete.c 11000121c4281c0bce4e41db29addfaea0038eaa127ece02557c9207bc3e541d
|
||||
F src/expr.c d1e1d42cbdec08bb867a1ab43a59b401d82ff2bc88bdcb4af20e479a5facb6d8
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847
|
||||
F src/func.c 92249abc3fd7e52b249ca8eb2d15a617f70819d2fa4c777a4a33552b89bfb322
|
||||
F src/global.c 59601d885a0dbbfbd22ed2d030424a5e7f1b9809a17ca46686058bbc4a55e980
|
||||
F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41
|
||||
F src/func.c f3dcdc0e95509864767c1f0991b19360f969e44177f4e058fd51da9a6154f47e
|
||||
F src/global.c 79a988b56b06ce2d08ebefe1d35da9aa25b3851faa47ea5233361c4827185a64
|
||||
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
|
||||
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 2fe4d7f67078a68650f16e4efe73207899e21702e6b9d2e8ad1894c76dcad352
|
||||
F src/insert.c 8e4211d04eb460c0694d486c6ba1c068d468c6f653c3f237869a802ad82854de
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 8cd803f1747c03a50b32fe87ebfb5851998d0cdafefe02737daa95e0616b42bb
|
||||
F src/main.c 430db07f140a2455784b504af1a56fe49134a79dd479a203370490031708d48f
|
||||
F src/malloc.c eaa4dc9602ce28b077f7de2eb275db2be270c5cc56d7fec5466301bd9b80e2f5
|
||||
F src/loadext.c 421310045bd78afefb772294a99e50f37d87ae578786a6169074e6291e30d969
|
||||
F src/main.c 7e07ff5ec447451d28398d528fda25c272f86cce67bc59a9846ee5bdfb23e1d9
|
||||
F src/malloc.c a3e13b001f988ecec6bdb90c0ea8912c8c786e623724d7098da623d8d01d19b1
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
@@ -505,7 +507,7 @@ F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c 02a5fcec19b9d40dd449ca802dc1b2e8f93f255fbf2a886277a3c3800d8d35db
|
||||
F src/memjournal.c 7561c01c90958f3ba9bc6cb2d857123d932bdfa5539ea34427a0957b2e35154d
|
||||
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
|
||||
F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
|
||||
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58
|
||||
@@ -515,33 +517,33 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285
|
||||
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c ad7640c04eed946052a3b12856362a773d0a717696707313037186df0e2b59f2
|
||||
F src/os_unix.c 7ef8b60222558a373d89c18d0c3bc44365b45273a528183d40bec5bb76ce23fc
|
||||
F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 302a18da8b247881808cd65009e1ac7c8b6e5cefb22ed9a1c330ed47b73e94ab
|
||||
F src/pager.h 71fe1d5016ec54d0cc5d344cd474e563450b438c59f535e8c1ec8a13b1373f14
|
||||
F src/parse.y c8d2de64db469fd56e0fa24da46cd8ec8523eb98626567d2708df371b47fdc3f
|
||||
F src/pager.c 52cee2f72710be47b5b13ff66b339ca3855e5bc48e92a94114d2affedc70041f
|
||||
F src/pager.h 3b33619a90180e0874c7eca31d6f6ceb464d9322c6fb4e9a7bbb318c8a17bdb3
|
||||
F src/parse.y c8eff38606f443d5ba245263fa7abc05e4116d95656e050c4b78e9bfbf931add
|
||||
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
|
||||
F src/pragma.c 0d49d43b22d66397aa026db505457f6683d8a66cd0a4f9db2e6776156bda716c
|
||||
F src/pragma.h 9f86a3a3a0099e651189521c8ad03768df598974e7bbdc21c7f9bb6125592fbd
|
||||
F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057
|
||||
F src/pragma.c 5fd004b89c77319008ddff6d65dcc83ccca9584d3048f4f66b108b5906a20dba
|
||||
F src/pragma.h 9473160d220416456b40f27323bb4b316d4e4e08ffbf8bf88c5f7045d49c38e5
|
||||
F src/prepare.c 8d4d6c8aa6afefc48027c54b41cdf134b4d6bc2fc4badbe483ad7fd9e1728a28
|
||||
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c f0781c9e180028b279bc4ff079ad54f4727223d470c8d2343643fcaf79b67740
|
||||
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
|
||||
F src/select.c 3f7aecf64b08b018b89e4fe16ea621cc9a0e3f3801e9e5638cfe1a6035fa1581
|
||||
F src/shell.c.in c2e20c43a44fb5588a6c27ce60589538fbf4794fd7686f5b2598eca22eaae1fa
|
||||
F src/sqlite.h.in 75d0304247a2154122d6d06f12219c1e29291d72304f0eeef4c1ec6b1409b443
|
||||
F src/resolve.c d36a2b1639e1c33d7b508abfd3452a63e7fd81737f6f3940bfef085fca6f21f4
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c c310de94bf67315054587c18a16e7a3e3dc3a98dc79168f0c2b776548d43f6cd
|
||||
F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b6
|
||||
F src/sqlite.h.in b20d5dc52765ff82f3701395a7e670611ddf138ee0ae84482452ad3a0b5f24b5
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h b0f776a0d042b23b6bcbb6b0943e8a3768c7f0b438a275e7168f0204e223a4db
|
||||
F src/sqliteInt.h 7a29ba700a51eeb925731749a570cf3859f6a58ed94797ecf47508875b0ba279
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
|
||||
F src/sqliteInt.h 0f3848c46310d197246003f052985b72d1cdbfc0b31e069db76cb5231062fa1d
|
||||
F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
|
||||
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 97590069efaba5a4928ecffb606e3771dd93ee8e6bf248a62a6507c37a2b2e46
|
||||
F src/test1.c 4d0ab2f67053a4fff87d1d3586ecc0e5322a1fc45dd4119ab11dc96de44f17a1
|
||||
F src/tclsqlite.c d0aa320416efe88c4dbb0156ed6c494f2f9958871a940e46984ee57b3e7fcc50
|
||||
F src/test1.c 5e8b8cc54e8c88906ea8a084387aa79bad245e539f4cee73149e5c0527e1db16
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb
|
||||
@@ -556,7 +558,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c e25826d693039cdd45963de378cbf39e3af0e8aa7a8a6fc159876f4e7b5a4f8c
|
||||
F src/test_config.c 5ea19bf0972a9d91728518b4d30e91477acce80496003ecbef3a7fb18d0bd081
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
|
||||
F src/test_devsym.c 6109b45c3db3ef7b002320947ed448c027356ab8b885156ff535fd8684d4a571
|
||||
@@ -570,7 +572,7 @@ F src/test_journal.c a0b9709b2f12b1ec819eea8a1176f283bca6d688a6d4a502bd6fd79786f
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
|
||||
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
F src/test_multiplex.c 46e278397bef99b10530c1a695b4f6f23823fde6d6589b182f14e9bd43440b57
|
||||
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
|
||||
F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
|
||||
F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
|
||||
@@ -586,7 +588,7 @@ F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
|
||||
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
|
||||
F src/test_tclsh.c eeafce33ad2136d57e5dec10f1e9a4347447eb72ffd504a1c7b9c6bfe2e71578
|
||||
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
|
||||
F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
|
||||
F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
|
||||
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
|
||||
F src/test_vfs.c 36822d696789535bdd0260f07d2c9a46546082fea8bb1d0a7354c7f9366e37ea
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
@@ -595,33 +597,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 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
|
||||
F src/treeview.c 438c1000587b33faba35e87596bebcf7f40638d98f33781cdd9e04711b18b09c
|
||||
F src/trigger.c a40d50e88bd3355f1d2a73f0a3b2d6b42eae26ca4219001b82ef0d064439badc
|
||||
F src/update.c 9ad19af96aff95dc02a923a99f97c1bc0b909009a29a2914b796f786b9ac0c60
|
||||
F src/tokenize.c eee7bae3ec0bc4abee951554bf46a8ba567c0f7752ac90c820ed8afff4c612dc
|
||||
F src/treeview.c 82c6391a3ba76215d4185fd4719a56ec4caf186a40c8a7b6e6ba4ae4467c2742
|
||||
F src/trigger.c 4ada1037cc99777f647a882cdacbd1a4deb6567b69daf02946286401b88cdc04
|
||||
F src/update.c 3eb778c42155d944377a4ee5e440b04520f07094804ed6ce63d2528f619614d9
|
||||
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
|
||||
F src/utf.c 736ff76753236ffbc8b5b939f5e0607f28aeaa7c780b3a56b419228f0a81c87b
|
||||
F src/util.c d035b09df9cecbc0e8f07c34b815acbf0d43c8adc8d2c540e3dc92eecb27855a
|
||||
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
|
||||
F src/vdbe.c e3dd230ece613409507523e68436764cc20638bb77ba2f416097de5b37235ce1
|
||||
F src/vdbe.h defd693289c7bb8d325f109be9490c77138061211a116827da7244b6015a4934
|
||||
F src/vdbeInt.h 30d3e8b991547cdf39025e416a0a737b0416d46747af70ae058f60e2e0466fe7
|
||||
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
|
||||
F src/vdbeaux.c ff690e6c9314ef281de7c06f8c8c33393f0afca80aabb1fe69836dcf2d60b0bf
|
||||
F src/utf.c 95fb6e03a5ca679045c5adccd05380f0addccabef5911abddcb06af069500ab7
|
||||
F src/util.c 3b6cedf7a0c69bd6e1acce832873952d416212d6293b18d03064e07d7a9b5118
|
||||
F src/vacuum.c f25d3b39681595e321a8a4e7fca3e5971cb14a401213d0742c9bf7d4ce8c2a1a
|
||||
F src/vdbe.c 972999395eee88702091fb5d50cf4effd07889c371807d222a7f517388e6378e
|
||||
F src/vdbe.h 07b8c636a87df8b6e58f29d6badd7f10d5844353deff1d7c88ed1c2bfe3bbd35
|
||||
F src/vdbeInt.h 571413068b5ac07e2ed8ca7a02fa529622fd5455ae6981498376e5e492d2e5ef
|
||||
F src/vdbeapi.c d176ee7251d5344de7bb2a0d2dd0fe536834e5843d9bc2389e0f5cdcd5374141
|
||||
F src/vdbeaux.c 319a6e44cff0e8ba710a8374778043609d11cf82cb4ab2ba0a80dde52e607a08
|
||||
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
|
||||
F src/vdbemem.c 6200af702c87105d5b00d8ac5f5fa2c6d8f796aa974dbe2d15dcd95379ba1fa7
|
||||
F src/vdbesort.c a3be032cc3fee0e3af31773af4a7a6f931b7230a34f53282ccf1d9a2a72343be
|
||||
F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22
|
||||
F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
|
||||
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
|
||||
F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653
|
||||
F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c dbc77159e6734c2d64343cb8624ad245d89dd79a5010750fce8118b3fa7be2e8
|
||||
F src/wal.c ea8dad28bb0e2b85ac1ab7618968687ff5fd522af8a1a38d6960ec176ebc8ee6
|
||||
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
|
||||
F src/walker.c a137468bf36c92e64d2275caa80c83902e3a0fc59273591b96c6416d3253d05d
|
||||
F src/where.c 2005d0511e05e5f7b6fb3be514b44f264f23d45f3b0cc5e150c63e3006a003e5
|
||||
F src/whereInt.h 9157228db086f436a574589f8cc5749bd971e94017c552305ad9ec472ed2e098
|
||||
F src/wherecode.c ec8870d6fe79668dd12d7edc65ae9771828d6cdfe478348c8abd872a89fdbadd
|
||||
F src/whereexpr.c 4b34be1434183e7bb8a05d4bf42bd53ea53021b0b060936fbd12062b4ff6b396
|
||||
F src/window.c f8ba2ee12a19b51d3ba42c16277c74185ee9215306bc0d5a03974ade8b5bc98f
|
||||
F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed
|
||||
F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9
|
||||
F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c
|
||||
F src/wherecode.c 7b939de85d65cc4b4bfa197513136b9e0ae03167e3b82842ca5a0ba1055ba65d
|
||||
F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
|
||||
F src/window.c ba1ffb78d73c5831433681aab7ee634230ee32f14ad508efa585044662141d5a
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -639,7 +642,7 @@ F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f1
|
||||
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
|
||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
||||
F test/altertab.test bd61e5b73d495ec4707133db91b07f09d57e339d988de5ec5a76d34a2198e8f2
|
||||
F test/altertab.test 523ba6368e0da19f462f7c05563c569675736d946724cac1c4ae848f76783434
|
||||
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
|
||||
F test/altertab3.test 155b8dc225ce484454a7fb4c8ba745680b6fa0fc3e08919cbbc19f9309d128ff
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
@@ -655,6 +658,7 @@ F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46e
|
||||
F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
|
||||
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
||||
F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
|
||||
F test/analyzeG.test a48c0f324dd14de9a40d52abe5ca2637f682b9a791d2523dd619f6efa14e345b
|
||||
F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
@@ -665,7 +669,7 @@ F test/atof1.test 1ccfc96a6888566597b83d882c81b3c04258dc39317e8c1cec89ba481eaa2f
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c ec92d56d8fbed9eb3e11aaf1ab98cf7dd59e69dae31f128013f1d97e54e7dfed
|
||||
F test/attach.test 21bce8681f780a8d631a5ec7ecd0d849bfe84611257b038ae4ffeccc609d8a4e
|
||||
F test/attach.test d42862c72fef3d54367d962d41dcfb5363442a4a1bd898c22ae950cea1aa0dd3
|
||||
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test aa05b1d8218b24eba5a7cccf4f224f514ba57ba705c9267f09d2bb63fed0eea1
|
||||
@@ -699,6 +703,7 @@ F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b792
|
||||
F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
|
||||
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
|
||||
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
|
||||
F test/bestindex7.test f36ada201973d3022cf7afffffe08de9e58341996020e7a2df9a1d2f2be20132
|
||||
F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -732,7 +737,7 @@ F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bc
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 2906ccab6a3ebd147ffa63304b635be903ce58264110d0a0eb4fd9939422bb53
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test b21a76546c2115af2674280566a8eba577e72adfec330c3d9a8a466d41f8eb0d
|
||||
F test/check.test 9776af795bb5d0f197b7f8fe248052e3ca2ed35304d863efcdbf8b1316e11f65
|
||||
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
|
||||
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
|
||||
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
|
||||
@@ -775,7 +780,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
|
||||
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
|
||||
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
|
||||
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
|
||||
F test/corruptL.test 4f28fbef85a6f27489542bb915ab7938dcd68f896e8f62a7d23de02b32489e5d
|
||||
F test/corruptL.test 13ef74a93223af25015d223add0df4c2d375f0b958b546a2a72033f2fdab7a70
|
||||
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
|
||||
F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
|
||||
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
|
||||
@@ -792,7 +797,7 @@ F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3
|
||||
F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c
|
||||
F test/csv01.test c9c3af0d58c34e9ac970c5875a77939edb958762c8aafb95409e19a3f088b6cd
|
||||
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
@@ -808,7 +813,7 @@ F test/dbfuzz2.c c2c9cb40082a77b7e95ffb8b2da1e93322efadfb1c8c1e0001c95a0af1e156c
|
||||
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
|
||||
F test/default.test 3e46c421eebefd2787c2f96673efabf792d360f3a1d5073918cbe450ce672a62
|
||||
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
|
||||
F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
@@ -818,7 +823,7 @@ F test/descidx1.test edc8adee58d491b06c7157c50364eaf1c3605c9c19f8093cb1ea2b6184f
|
||||
F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298
|
||||
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 8b6c652f0b2d477f0830884736f2a1cd2e8f7fc10a04aa6d571a401fa13ed88b
|
||||
F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
|
||||
F test/distinct2.test 11b0594c932098e969d084ba45ab81d5040f4d4e766db65d49146705a305ed98
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
|
||||
@@ -826,10 +831,10 @@ F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
|
||||
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
|
||||
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
|
||||
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
|
||||
F test/e_createtable.test 1c602347e73ab80b11b9fa083f47155861aaafcff8054aac9e0b76d0df33b0a7
|
||||
F test/e_createtable.test ea27082d6f84df61e1d9e383f3fd79220418856a4a8afc41af75d458b8e7ac33
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test 328d2d7c84f8e53e942a13eac771b337bcdfcf4c3569324001868b5639f3c857
|
||||
F test/e_fkey.test 2febb2084aef9b0186782421c07bc9d377abf067c9cb4efd49d9647ae31f5afe
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
@@ -847,7 +852,7 @@ F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
|
||||
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
|
||||
F test/e_walhook.test 01b494287ba9e60b70f6ebf3c6c62e0ffe01788e344a4846b08e5de0b344cb66
|
||||
F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
|
||||
F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
|
||||
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
@@ -940,10 +945,10 @@ F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd4
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
||||
F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
|
||||
F test/fts3corrupt.test ce7f7b5eaeee5f1804584d061b978d85e64abf2af9adaa7577589fac6f7eae01
|
||||
F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6
|
||||
F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
|
||||
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
|
||||
F test/fts3corrupt4.test e407c7b4f4cd3335080833aff3a8855d520e531b79f84dcc77be4623af2342d4
|
||||
F test/fts3corrupt4.test 6a1331bb51dc27acc063d26e0f1b610863b56a833ee54fa32767d17cf96bda4a
|
||||
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
|
||||
F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
|
||||
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
|
||||
@@ -964,7 +969,7 @@ F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11e
|
||||
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
|
||||
F test/fts3misc.test c47d2c1ea1351c51c32c688545b02c8180a3f22156d1aedc206a8c09b9d95905
|
||||
F test/fts3misc.test 9ec15e7c0b5831a6353bd4c46bf3acdf1360eda5d9f396f667db4d05bcf92ecf
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
|
||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||
@@ -978,7 +983,7 @@ F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 0b84a3fd4eba8a39f3687523804d18f3b322e6d4539a55bf342079c3614f2ada
|
||||
F test/fts4aa.test 4338ea7a67f7e19269bf6e6fb4a291352aa32296e7daed87f9823d57016a1ef7
|
||||
F test/fts4aa.test 0e6bfd6a81695a39b23e448dda25d864e63dda75bde6949c45ddc95426c6c3f5
|
||||
F test/fts4check.test 6259f856604445d7b684c9b306b2efb6346834c3f50e8fc4a59a2ca6d5319ad0
|
||||
F test/fts4content.test 73bbb123420d2c46ef2fb3b24761e9acdb78b0877179d3a5d7d57aada08066f6
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
@@ -992,6 +997,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
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/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
|
||||
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
|
||||
@@ -1000,11 +1006,11 @@ F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3c
|
||||
F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
|
||||
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test b7f1a706d1bb8de103a24bd0c30c9e3dc3eedf0df24aabc54b0a4f6e08742622
|
||||
F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/func4.test a94858a8c1f10a408b0b3db439c990b59dbb2349411d503de011ac4e2b5f27a6
|
||||
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
|
||||
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
|
||||
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
|
||||
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
@@ -1013,15 +1019,15 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c a9746aa49843827f960bc875cc70e04b0cfcd3e10e6676e3abc402ad190e165f
|
||||
F test/fuzzcheck.c 656ee850f331872a784e7d6a10649efe2af123bdaacb728b5a03e4faee8b959c
|
||||
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
|
||||
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac640639711
|
||||
F test/fuzzdata8.db 8bd41f8e1b9c61af011bf5cf16a85fb7f718fdd3348e476b78ba36adab872653
|
||||
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
|
||||
F test/fuzzdata8.db fb701c5653f0a75a58e2ee0f8baf5b207faa7702dda88c913ebbe2abb3b33de3
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
@@ -1033,15 +1039,15 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 1604b3b2f5931430087540404555c1b6be3618600b81558657c66b533ed70b13
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a
|
||||
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
|
||||
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
F test/in.test 3e9bd58597a444123a40a9ac94cae0fec8897e17e9f519b02fc370bcf5ba5175
|
||||
F test/in.test ae4ba0fe3232fdd84ef1090a68c5cd6ccd93f1f8774d5c967dd0c1b301492eed
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test 65460600d48933adba4283c6ebd089aae173d16136ab9d01f74c89089090c5a5
|
||||
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
|
||||
F test/in6.test 62d943a02f722948f4410ee0b53c3cb39acd7c41afb083df8d7004238fe90a20
|
||||
F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
|
||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -1089,7 +1095,7 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a
|
||||
F test/join.test bca044589e94bb466e4c1e91fb6fecdc3f3326ca6b3f590f555f1958156eb321
|
||||
F test/join2.test 659bc6193f5c3fe20fa444dd2c91713db8c33e376b098b860644e175e87b8dbc
|
||||
F test/join2.test 7d24d095ab88d3910228d53a3b548b7baf2e0e7d8aac6731a273e300e1b34b61
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
|
||||
@@ -1110,9 +1116,9 @@ F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
|
||||
F test/like.test 3d702d79bf871fa32985b1ce334294c587e3948d3ab972001e811a58577e8b3c
|
||||
F test/like.test 47b81d5de2ff19d996d49a65d50ec9754246aacbe0e950b48d186d9d8171eaf0
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 4f940ad275c006319950054a7a65661f476772171b82b6fdf795e4dda36f246f
|
||||
F test/like3.test 03d1bdf848483b78d2cfd1db283d75c4ec2e37c8b8eccc006813f3978d78fbbd
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
|
||||
F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04
|
||||
@@ -1170,7 +1176,7 @@ F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db
|
||||
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 4f21954012e4eb0a923c54a311f38c81bf6798ccdd7b51584db46d4007f63daa
|
||||
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
|
||||
F test/misc8.test 8782708f4c8a459591c3e8fe1215bd2048bffb4024b3df249e9b9ed407dc61ed
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
|
||||
F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626
|
||||
@@ -1194,7 +1200,7 @@ F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
|
||||
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/nulls1.test fe4153fd59a3786b4b9f3663a3e65a3aa43a318c7b4d7dcb3f6c3ed5652c9095
|
||||
F test/nulls1.test 82c5bc33148405f21205865abf13c786084438d573a4ac4e87e11b6091cde526
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
|
||||
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
|
||||
@@ -1206,7 +1212,7 @@ F test/orderby1.test 6bf0ce45cbfb1cf4779dd418ac5e8cf66abfa04de2c1d2edf1e0e85f152
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
F test/orderby5.test 5f4d6cb93cc2f6d3f4228354310a2ce1fbd95d5bbffcba8c6482eeb62a466407
|
||||
F test/orderby5.test bd7d9e3380e87e5dcf6ea817ebaab6d15da213c7804b38767e1b3e695e85650b
|
||||
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
||||
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
@@ -1229,7 +1235,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 8587800fe1a0eb01456a3f4500b821e54e3347e78acf11dbf05f4990530f6cee
|
||||
F test/permutations.test c83339862d72b6272f957905205f874e6eefdbad2823380452c4f0128fd3d906
|
||||
F test/pg_common.tcl 222a1bad1c41c308fa366313cd7b51b3be7e9b21c8736a421b974ac941693b54
|
||||
F test/pragma.test 59becdfd720b80d463ab750f69f7118fde10dfd556aa5d554f3bf6b7e5ea7533
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
@@ -1300,8 +1306,8 @@ F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2f
|
||||
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test 009a6d8eacd9684d046302b8d13b50846a87e39d6f08e92178aa13e95ea29a2d
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 3905450067c28766bc83ee397f6d87342de868baa60f2bcfd00f286dfbd62cb9
|
||||
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
|
||||
F test/select3.test ddd1bc6d0c8dece136321c11bd26d0d8ad17f2b27c72935fdd6574d8cb99d1d4
|
||||
F test/select4.test e8a2502e3623f3058871030599a48abb35789d2244d5b380ecf3696873fdd4a4
|
||||
F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
|
||||
F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
@@ -1330,11 +1336,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 3c9707dce15e8fdca529503378660f099777d3ddcedccf801a37589a405c5942
|
||||
F test/shell1.test 5bd10014ec494744f5e966a1521334e9d612119a0afcfa5251684a4e1f2ffc66
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
|
||||
F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
|
||||
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
|
||||
F test/shell5.test 84a30b55722a95a5b72989e691c469a999ca7591e7aa00b7fabc783ea5c9a6fe
|
||||
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
|
||||
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
|
||||
F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
|
||||
@@ -1371,7 +1377,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c f3bfe3c6a87cbd88e4c4e38005d972bcc1019d1b2fe9569425f86629b11f6c31
|
||||
F test/speedtest1.c d564e7689a731f691adfe2cf3f3f735d3e11f100eebb065e2a0a267fdc39fb26
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1412,7 +1418,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl abba168acd7f01dbfa3ffdbf402d151eb97e8a824d9208e845ab34c194441483
|
||||
F test/tester.tcl fd9d134a7cc4e31b307ad028a195f51cdcf556fc620d74b680515562f0137f25
|
||||
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1438,7 +1444,7 @@ F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf
|
||||
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
|
||||
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
|
||||
F test/tkt-3a77c9714e.test 90e3e8455ee945a4076d4c44062b8845708af24a880355328fe7008f2047c9f0
|
||||
F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
|
||||
F test/tkt-3fe897352e.test 6849fde0a87165ff83f54f5047af7c743d72af26908fadb90174f3294450b3f4
|
||||
F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
|
||||
F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
|
||||
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
|
||||
@@ -1701,7 +1707,7 @@ F test/where9.test 2c554b97bbdb2fdf26c57099f60db8a52bfcf7c147f2c256f9798fa0e267c
|
||||
F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
|
||||
F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
|
||||
F test/whereG.test c9378b285828754377ef47fbece7264018c0a3743e7eb686e89917bb9df10885
|
||||
@@ -1709,7 +1715,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
|
||||
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
|
||||
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/whereL.test 976f100f412ce2f39bf923eb57794cdc39fc0a3fec8fab025d51706a7cc4845b
|
||||
F test/whereL.test e05cedc9389c6f09ad55bd5999a3fddccebec90672fb989433c145dcdaf26996
|
||||
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
|
||||
@@ -1718,25 +1724,25 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test cec56b9a0a2e7ca4bd63b30590c7b049dce9acfd87478e2597e13b67152bd821
|
||||
F test/window1.test ec792f92e63ee457447c5c04de8f8d42f4a94b842b5bac1f403ac38a6d867c22
|
||||
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
|
||||
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
|
||||
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
|
||||
F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb
|
||||
F test/window4.tcl d732df0e81beedc0ba8a563ade68611d322d27303ad0c0c8e4444107c39e84ec
|
||||
F test/window4.test 807f3e6b15f9338e5b9742b87c5c7ca825b42b9657fde6096e890119370848e0
|
||||
F test/window4.tcl 6f85307eb67242b654d051f7da32a996a66aee039a09c5ae358541aa61720742
|
||||
F test/window4.test fbead87f681400ac07ef3555e0488b544a47d35491f8bf09a7474b6f76ce9b4e
|
||||
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
|
||||
F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32
|
||||
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
|
||||
F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
|
||||
F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2
|
||||
F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b
|
||||
F test/window9.test b63f6f74d730547e63e78946f951f5d1a7d4e99f91f6d5906305469043d92a15
|
||||
F test/window9.test c22c25377c820613e1842fe7ad4af7c03df625f6a7caee99e6fdb4fcd52e0a8b
|
||||
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
|
||||
F test/windowB.test 7a983ea1cc1cf72be7f378e4b32f6cb2d73014c5cd8b25aaee825164cd4269e5
|
||||
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
|
||||
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
|
||||
F test/windowfault.test 8e3b69abe0eea9595ba3940afd9c63644e11966ed8815734b67f1479a8e9891a
|
||||
F test/windowfault.test 72375ae71031eabf96bc88d0af128c8628a091ddc99b5a394e848b3df5fc17ad
|
||||
F test/with1.test 584580a5ae79868a91873863f8cb2d00040006dc1e4c332ef1d8642f2815dc6e
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test 13b3336739da648a9e4dfa11bb04e73a920c97620041007c5f75d5d14084c346
|
||||
@@ -1785,17 +1791,17 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
|
||||
F tool/mkkeywordhash.c 27ffc6f6e7e3ecbfc5bca1f1f11a09fc5badf6d67557a5fb2d3b069dbed90617
|
||||
F tool/mkkeywordhash.c 11a3f3af8e787d0c5ca459ed66fe80fd09e661876506e7b978ec08c19477bdc2
|
||||
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl ca12b1c718ececdab2d3aacb437bc3c81ebf68467f19d7974e17f18844a3a48f
|
||||
F tool/mkpragmatab.tcl 62663c65d9191aada624a787e1ee3420f268a3c27999ad0ffb77a6918ddc1e52
|
||||
F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
|
||||
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
|
||||
F tool/mksqlite3c.tcl 5fed3d75069d8f66f202d3b5200b0cea4aa7108481acd06732a06fdd42eb83a2
|
||||
F tool/mksqlite3c.tcl 3ab95bcf7b765f9d6d99cbeb8c4f150b38b0bb1f001ffac688f2ad02ebce2123
|
||||
F tool/mksqlite3h.tcl 080873e3856eceb9d289a08a00c4b30f875ea3feadcbece796bd509b1532792c
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
|
||||
@@ -1814,7 +1820,7 @@ F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a80
|
||||
F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c2a1
|
||||
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
|
||||
F tool/spaceanal.tcl c161d838825d0242317c7cc13b1eb2126f8cec031950ef31114d42732cb2674e
|
||||
F tool/speed-check.sh 2b042d703a9472f08c3b13be27afac658426f8e4fc87cd2d575953fda86f08d1
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
@@ -1857,10 +1863,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 4daf94d83319231e42243625c804d5db2d14f10fa5ea1a1f358c3603c47b955b
|
||||
R 5a98666c879217368b8f21c26d062d92
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.31.0 *
|
||||
P 96dfc71ea599702ef38b60952d03e95dce5a8c534cd943e076e9c76b00e61e65
|
||||
R 8a6312f86dfd0f2dc1b9dbd32625eb27
|
||||
U drh
|
||||
Z 51c630793e0eec473e1274a795f77643
|
||||
Z 054131aab304a488c76322b7f6a162fc
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
f6affdd41608946fcfcea914ece149038a8b25a62bbe719ed2561c649b86d824
|
||||
baa720e4a88f268ed95337daab5f434fd3263b00f09101cddc6424765bf3b722
|
||||
+19
-1
@@ -469,6 +469,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
||||
for(i=0; i<pNew->nCol; i++){
|
||||
Column *pCol = &pNew->aCol[i];
|
||||
pCol->zName = sqlite3DbStrDup(db, pCol->zName);
|
||||
pCol->hName = sqlite3StrIHash(pCol->zName);
|
||||
pCol->zColl = 0;
|
||||
pCol->pDflt = 0;
|
||||
}
|
||||
@@ -697,7 +698,7 @@ void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
|
||||
RenameToken *pNew;
|
||||
assert( pPtr || pParse->db->mallocFailed );
|
||||
renameTokenCheckAll(pParse, pPtr);
|
||||
if( pParse->eParseMode!=PARSE_MODE_UNMAP ){
|
||||
if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){
|
||||
pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
|
||||
if( pNew ){
|
||||
pNew->p = pPtr;
|
||||
@@ -755,6 +756,21 @@ static void renameWalkWith(Walker *pWalker, Select *pSelect){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Unmap all tokens in the IdList object passed as the second argument.
|
||||
*/
|
||||
static void unmapColumnIdlistNames(
|
||||
Parse *pParse,
|
||||
IdList *pIdList
|
||||
){
|
||||
if( pIdList ){
|
||||
int ii;
|
||||
for(ii=0; ii<pIdList->nId; ii++){
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)pIdList->a[ii].zName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Walker callback used by sqlite3RenameExprUnmap().
|
||||
*/
|
||||
@@ -776,6 +792,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
|
||||
if( sqlite3WalkExpr(pWalker, pSrc->a[i].pOn) ) return WRC_Abort;
|
||||
unmapColumnIdlistNames(pParse, pSrc->a[i].pUsing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,6 +1001,7 @@ static void renameColumnIdlistNames(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Parse the SQL statement zSql using Parse object (*p). The Parse object
|
||||
** is initialized by this function before it is used.
|
||||
|
||||
+61
-62
@@ -256,9 +256,9 @@ static void openStatTable(
|
||||
** share an instance of the following structure to hold their state
|
||||
** information.
|
||||
*/
|
||||
typedef struct Stat4Accum Stat4Accum;
|
||||
typedef struct Stat4Sample Stat4Sample;
|
||||
struct Stat4Sample {
|
||||
typedef struct StatAccum StatAccum;
|
||||
typedef struct StatSample StatSample;
|
||||
struct StatSample {
|
||||
tRowcnt *anEq; /* sqlite_stat4.nEq */
|
||||
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
@@ -273,27 +273,29 @@ struct Stat4Sample {
|
||||
u32 iHash; /* Tiebreaker hash */
|
||||
#endif
|
||||
};
|
||||
struct Stat4Accum {
|
||||
struct StatAccum {
|
||||
sqlite3 *db; /* Database connection, for malloc() */
|
||||
tRowcnt nRow; /* Number of rows in the entire table */
|
||||
tRowcnt nPSample; /* How often to do a periodic sample */
|
||||
int nCol; /* Number of columns in index + pk/rowid */
|
||||
int nKeyCol; /* Number of index columns w/o the pk/rowid */
|
||||
StatSample current; /* Current row as a StatSample */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
tRowcnt nPSample; /* How often to do a periodic sample */
|
||||
int mxSample; /* Maximum number of samples to accumulate */
|
||||
Stat4Sample current; /* Current row as a Stat4Sample */
|
||||
u32 iPrn; /* Pseudo-random number used for sampling */
|
||||
Stat4Sample *aBest; /* Array of nCol best samples */
|
||||
StatSample *aBest; /* Array of nCol best samples */
|
||||
int iMin; /* Index in a[] of entry with minimum score */
|
||||
int nSample; /* Current number of samples */
|
||||
int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
|
||||
int iGet; /* Index of current sample accessed by stat_get() */
|
||||
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
|
||||
sqlite3 *db; /* Database connection, for malloc() */
|
||||
StatSample *a; /* Array of mxSample StatSample objects */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Reclaim memory used by a Stat4Sample
|
||||
/* Reclaim memory used by a StatSample
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
static void sampleClear(sqlite3 *db, Stat4Sample *p){
|
||||
static void sampleClear(sqlite3 *db, StatSample *p){
|
||||
assert( db!=0 );
|
||||
if( p->nRowid ){
|
||||
sqlite3DbFree(db, p->u.aRowid);
|
||||
@@ -305,7 +307,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){
|
||||
/* Initialize the BLOB value of a ROWID
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
|
||||
static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){
|
||||
assert( db!=0 );
|
||||
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
|
||||
p->u.aRowid = sqlite3DbMallocRawNN(db, n);
|
||||
@@ -321,7 +323,7 @@ static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
|
||||
/* Initialize the INTEGER value of a ROWID.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
|
||||
static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){
|
||||
assert( db!=0 );
|
||||
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
|
||||
p->nRowid = 0;
|
||||
@@ -334,7 +336,7 @@ static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
|
||||
** Copy the contents of object (*pFrom) into (*pTo).
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
|
||||
static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){
|
||||
pTo->isPSample = pFrom->isPSample;
|
||||
pTo->iCol = pFrom->iCol;
|
||||
pTo->iHash = pFrom->iHash;
|
||||
@@ -350,10 +352,10 @@ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Reclaim all memory of a Stat4Accum structure.
|
||||
** Reclaim all memory of a StatAccum structure.
|
||||
*/
|
||||
static void stat4Destructor(void *pOld){
|
||||
Stat4Accum *p = (Stat4Accum*)pOld;
|
||||
static void statAccumDestructor(void *pOld){
|
||||
StatAccum *p = (StatAccum*)pOld;
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
int i;
|
||||
for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
|
||||
@@ -381,9 +383,9 @@ static void stat4Destructor(void *pOld){
|
||||
** PRIMARY KEY of the table. The covering index that implements the
|
||||
** original WITHOUT ROWID table as N==K as a special case.
|
||||
**
|
||||
** This routine allocates the Stat4Accum object in heap memory. The return
|
||||
** value is a pointer to the Stat4Accum object. The datatype of the
|
||||
** return value is BLOB, but it is really just a pointer to the Stat4Accum
|
||||
** This routine allocates the StatAccum object in heap memory. The return
|
||||
** value is a pointer to the StatAccum object. The datatype of the
|
||||
** return value is BLOB, but it is really just a pointer to the StatAccum
|
||||
** object.
|
||||
*/
|
||||
static void statInit(
|
||||
@@ -391,7 +393,7 @@ static void statInit(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
Stat4Accum *p;
|
||||
StatAccum *p;
|
||||
int nCol; /* Number of columns in index being sampled */
|
||||
int nKeyCol; /* Number of key columns */
|
||||
int nColUp; /* nCol rounded up for alignment */
|
||||
@@ -410,13 +412,13 @@ static void statInit(
|
||||
assert( nKeyCol<=nCol );
|
||||
assert( nKeyCol>0 );
|
||||
|
||||
/* Allocate the space required for the Stat4Accum object */
|
||||
/* Allocate the space required for the StatAccum object */
|
||||
n = sizeof(*p)
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
|
||||
+ sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
|
||||
+ sizeof(tRowcnt)*nColUp /* StatAccum.anDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
|
||||
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
|
||||
+ sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
|
||||
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
|
||||
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
|
||||
#endif
|
||||
;
|
||||
@@ -445,8 +447,8 @@ static void statInit(
|
||||
p->current.anLt = &p->current.anEq[nColUp];
|
||||
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
|
||||
|
||||
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
||||
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
||||
/* Set up the StatAccum.a[] and aBest[] arrays */
|
||||
p->a = (struct StatSample*)&p->current.anLt[nColUp];
|
||||
p->aBest = &p->a[mxSample];
|
||||
pSpace = (u8*)(&p->a[mxSample+nCol]);
|
||||
for(i=0; i<(mxSample+nCol); i++){
|
||||
@@ -466,7 +468,7 @@ static void statInit(
|
||||
** only the pointer (the 2nd parameter) matters. The size of the object
|
||||
** (given by the 3rd parameter) is never used and can be any positive
|
||||
** value. */
|
||||
sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
|
||||
sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
|
||||
}
|
||||
static const FuncDef statInitFuncdef = {
|
||||
2+IsStat4, /* nArg */
|
||||
@@ -493,9 +495,9 @@ static const FuncDef statInitFuncdef = {
|
||||
** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid.
|
||||
*/
|
||||
static int sampleIsBetterPost(
|
||||
Stat4Accum *pAccum,
|
||||
Stat4Sample *pNew,
|
||||
Stat4Sample *pOld
|
||||
StatAccum *pAccum,
|
||||
StatSample *pNew,
|
||||
StatSample *pOld
|
||||
){
|
||||
int nCol = pAccum->nCol;
|
||||
int i;
|
||||
@@ -517,9 +519,9 @@ static int sampleIsBetterPost(
|
||||
** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid.
|
||||
*/
|
||||
static int sampleIsBetter(
|
||||
Stat4Accum *pAccum,
|
||||
Stat4Sample *pNew,
|
||||
Stat4Sample *pOld
|
||||
StatAccum *pAccum,
|
||||
StatSample *pNew,
|
||||
StatSample *pOld
|
||||
){
|
||||
tRowcnt nEqNew = pNew->anEq[pNew->iCol];
|
||||
tRowcnt nEqOld = pOld->anEq[pOld->iCol];
|
||||
@@ -539,21 +541,21 @@ static int sampleIsBetter(
|
||||
** Copy the contents of sample *pNew into the p->a[] array. If necessary,
|
||||
** remove the least desirable sample from p->a[] to make room.
|
||||
*/
|
||||
static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
|
||||
Stat4Sample *pSample = 0;
|
||||
static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){
|
||||
StatSample *pSample = 0;
|
||||
int i;
|
||||
|
||||
assert( IsStat4 || nEqZero==0 );
|
||||
|
||||
/* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
|
||||
** values in the anEq[] array of any sample in Stat4Accum.a[]. In
|
||||
/* StatAccum.nMaxEqZero is set to the maximum number of leading 0
|
||||
** values in the anEq[] array of any sample in StatAccum.a[]. In
|
||||
** other words, if nMaxEqZero is n, then it is guaranteed that there
|
||||
** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
|
||||
** are no samples with StatSample.anEq[m]==0 for (m>=n). */
|
||||
if( nEqZero>p->nMaxEqZero ){
|
||||
p->nMaxEqZero = nEqZero;
|
||||
}
|
||||
if( pNew->isPSample==0 ){
|
||||
Stat4Sample *pUpgrade = 0;
|
||||
StatSample *pUpgrade = 0;
|
||||
assert( pNew->anEq[pNew->iCol]>0 );
|
||||
|
||||
/* This sample is being added because the prefix that ends in column
|
||||
@@ -562,7 +564,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
|
||||
** this one. Instead, upgrade the priority of the highest priority
|
||||
** existing sample that shares this prefix. */
|
||||
for(i=p->nSample-1; i>=0; i--){
|
||||
Stat4Sample *pOld = &p->a[i];
|
||||
StatSample *pOld = &p->a[i];
|
||||
if( pOld->anEq[pNew->iCol]==0 ){
|
||||
if( pOld->isPSample ) return;
|
||||
assert( pOld->iCol>pNew->iCol );
|
||||
@@ -581,7 +583,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
|
||||
|
||||
/* If necessary, remove sample iMin to make room for the new sample. */
|
||||
if( p->nSample>=p->mxSample ){
|
||||
Stat4Sample *pMin = &p->a[p->iMin];
|
||||
StatSample *pMin = &p->a[p->iMin];
|
||||
tRowcnt *anEq = pMin->anEq;
|
||||
tRowcnt *anLt = pMin->anLt;
|
||||
tRowcnt *anDLt = pMin->anDLt;
|
||||
@@ -624,20 +626,20 @@ find_new_min:
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT4 */
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
/*
|
||||
** Field iChng of the index being scanned has changed. So at this point
|
||||
** p->current contains a sample that reflects the previous row of the
|
||||
** index. The value of anEq[iChng] and subsequent anEq[] elements are
|
||||
** correct at this point.
|
||||
*/
|
||||
static void samplePushPrevious(Stat4Accum *p, int iChng){
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
static void samplePushPrevious(StatAccum *p, int iChng){
|
||||
int i;
|
||||
|
||||
/* Check if any samples from the aBest[] array should be pushed
|
||||
** into IndexSample.a[] at this point. */
|
||||
for(i=(p->nCol-2); i>=iChng; i--){
|
||||
Stat4Sample *pBest = &p->aBest[i];
|
||||
StatSample *pBest = &p->aBest[i];
|
||||
pBest->anEq[i] = p->current.anEq[i];
|
||||
if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
|
||||
sampleInsert(p, pBest, i);
|
||||
@@ -661,25 +663,20 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
|
||||
}
|
||||
p->nMaxEqZero = iChng;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_ENABLE_STAT4
|
||||
UNUSED_PARAMETER( p );
|
||||
UNUSED_PARAMETER( iChng );
|
||||
#endif
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT4 */
|
||||
|
||||
/*
|
||||
** Implementation of the stat_push SQL function: stat_push(P,C,R)
|
||||
** Arguments:
|
||||
**
|
||||
** P Pointer to the Stat4Accum object created by stat_init()
|
||||
** P Pointer to the StatAccum object created by stat_init()
|
||||
** C Index of left-most column to differ from previous row
|
||||
** R Rowid for the current row. Might be a key record for
|
||||
** WITHOUT ROWID tables.
|
||||
**
|
||||
** This SQL function always returns NULL. It's purpose it to accumulate
|
||||
** statistical data and/or samples in the Stat4Accum object about the
|
||||
** statistical data and/or samples in the StatAccum object about the
|
||||
** index being analyzed. The stat_get() SQL function will later be used to
|
||||
** extract relevant information for constructing the sqlite_statN tables.
|
||||
**
|
||||
@@ -693,7 +690,7 @@ static void statPush(
|
||||
int i;
|
||||
|
||||
/* The three function arguments */
|
||||
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
|
||||
StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
|
||||
int iChng = sqlite3_value_int(argv[1]);
|
||||
|
||||
UNUSED_PARAMETER( argc );
|
||||
@@ -706,7 +703,9 @@ static void statPush(
|
||||
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
|
||||
}else{
|
||||
/* Second and subsequent calls get processed here */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
samplePushPrevious(p, iChng);
|
||||
#endif
|
||||
|
||||
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
|
||||
** to the current row of the index. */
|
||||
@@ -775,15 +774,15 @@ static const FuncDef statPushFuncdef = {
|
||||
/*
|
||||
** Implementation of the stat_get(P,J) SQL function. This routine is
|
||||
** used to query statistical information that has been gathered into
|
||||
** the Stat4Accum object by prior calls to stat_push(). The P parameter
|
||||
** has type BLOB but it is really just a pointer to the Stat4Accum object.
|
||||
** the StatAccum object by prior calls to stat_push(). The P parameter
|
||||
** has type BLOB but it is really just a pointer to the StatAccum object.
|
||||
** The content to returned is determined by the parameter J
|
||||
** which is one of the STAT_GET_xxxx values defined above.
|
||||
**
|
||||
** The stat_get(P,J) function is not available to generic SQL. It is
|
||||
** inserted as part of a manually constructed bytecode program. (See
|
||||
** the callStatGet() routine below.) It is guaranteed that the P
|
||||
** parameter will always be a poiner to a Stat4Accum object, never a
|
||||
** parameter will always be a pointer to a StatAccum object, never a
|
||||
** NULL.
|
||||
**
|
||||
** If STAT4 is not enabled, then J is always
|
||||
@@ -796,7 +795,7 @@ static void statGet(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
|
||||
StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
/* STAT4 has a parameter on this routine. */
|
||||
int eCall = sqlite3_value_int(argv[1]);
|
||||
@@ -817,7 +816,7 @@ static void statGet(
|
||||
** the index. The first integer in the list is the total number of
|
||||
** entries in the index. There is one additional integer in the list
|
||||
** for each indexed column. This additional integer is an estimate of
|
||||
** the number of rows matched by a stabbing query on the index using
|
||||
** the number of rows matched by a equality query on the index using
|
||||
** a key with the corresponding number of fields. In other words,
|
||||
** if the index is on columns (a,b) and the sqlite_stat1 value is
|
||||
** "100 10 2", then SQLite estimates that:
|
||||
@@ -860,7 +859,7 @@ static void statGet(
|
||||
p->iGet = 0;
|
||||
}
|
||||
if( p->iGet<p->nSample ){
|
||||
Stat4Sample *pS = p->a + p->iGet;
|
||||
StatSample *pS = p->a + p->iGet;
|
||||
if( pS->nRowid==0 ){
|
||||
sqlite3_result_int64(context, pS->u.iRowid);
|
||||
}else{
|
||||
@@ -951,7 +950,7 @@ static void analyzeOneTable(
|
||||
int iDb; /* Index of database containing pTab */
|
||||
u8 needTableCnt = 1; /* True to count the table */
|
||||
int regNewRowid = iMem++; /* Rowid for the inserted record */
|
||||
int regStat4 = iMem++; /* Register to hold Stat4Accum object */
|
||||
int regStat4 = iMem++; /* Register to hold StatAccum object */
|
||||
int regChng = iMem++; /* Index of changed index field */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
|
||||
|
||||
+20
-45
@@ -45,6 +45,17 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zName points to a name that may be used to refer to
|
||||
** database iDb attached to handle db.
|
||||
*/
|
||||
int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){
|
||||
return (
|
||||
sqlite3StrICmp(db->aDb[iDb].zDbSName, zName)==0
|
||||
|| (iDb==0 && sqlite3StrICmp("main", zName)==0)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
** An SQL user-function registered to do the work of an ATTACH statement. The
|
||||
** three arguments to the function come directly from an attach statement:
|
||||
@@ -117,9 +128,8 @@ static void attachFunc(
|
||||
goto attach_error;
|
||||
}
|
||||
for(i=0; i<db->nDb; i++){
|
||||
char *z = db->aDb[i].zDbSName;
|
||||
assert( z && zName );
|
||||
if( sqlite3StrICmp(z, zName)==0 ){
|
||||
assert( zName );
|
||||
if( sqlite3DbIsNamed(db, i, zName) ){
|
||||
zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
|
||||
goto attach_error;
|
||||
}
|
||||
@@ -187,43 +197,7 @@ static void attachFunc(
|
||||
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( rc==SQLITE_OK ){
|
||||
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
|
||||
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
||||
int nKey;
|
||||
char *zKey;
|
||||
int t = sqlite3_value_type(argv[2]);
|
||||
switch( t ){
|
||||
case SQLITE_INTEGER:
|
||||
case SQLITE_FLOAT:
|
||||
zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
|
||||
case SQLITE_TEXT:
|
||||
case SQLITE_BLOB:
|
||||
nKey = sqlite3_value_bytes(argv[2]);
|
||||
zKey = (char *)sqlite3_value_blob(argv[2]);
|
||||
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
|
||||
break;
|
||||
|
||||
case SQLITE_NULL:
|
||||
/* No key specified. Use the key from URI filename, or if none,
|
||||
** use the key from the main database. */
|
||||
if( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
|
||||
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
|
||||
if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
|
||||
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sqlite3_free( zPath );
|
||||
sqlite3_free_filename( zPath );
|
||||
|
||||
/* If the file was opened successfully, read the schema for the new database.
|
||||
** If this fails, or if opening the file failed, then close the file and
|
||||
@@ -308,7 +282,7 @@ static void detachFunc(
|
||||
for(i=0; i<db->nDb; i++){
|
||||
pDb = &db->aDb[i];
|
||||
if( pDb->pBt==0 ) continue;
|
||||
if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break;
|
||||
if( sqlite3DbIsNamed(db, i, zName) ) break;
|
||||
}
|
||||
|
||||
if( i>=db->nDb ){
|
||||
@@ -499,20 +473,21 @@ int sqlite3FixSrcList(
|
||||
SrcList *pList /* The Source list to check and modify */
|
||||
){
|
||||
int i;
|
||||
const char *zDb;
|
||||
struct SrcList_item *pItem;
|
||||
sqlite3 *db = pFix->pParse->db;
|
||||
int iDb = sqlite3FindDbName(db, pFix->zDb);
|
||||
|
||||
if( NEVER(pList==0) ) return 0;
|
||||
zDb = pFix->zDb;
|
||||
|
||||
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
|
||||
if( pFix->bTemp==0 ){
|
||||
if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
|
||||
if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
|
||||
sqlite3ErrorMsg(pFix->pParse,
|
||||
"%s %T cannot reference objects in database %s",
|
||||
pFix->zType, pFix->pName, pItem->zDatabase);
|
||||
return 1;
|
||||
}
|
||||
sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
|
||||
sqlite3DbFree(db, pItem->zDatabase);
|
||||
pItem->zDatabase = 0;
|
||||
pItem->pSchema = pFix->pSchema;
|
||||
pItem->fg.fromDDL = 1;
|
||||
|
||||
@@ -235,13 +235,6 @@ static int backupOnePage(
|
||||
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
|
||||
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
|
||||
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
|
||||
** guaranteed that the shared-mutex is held by this thread, handle
|
||||
** p->pSrc may not actually be the owner. */
|
||||
int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
|
||||
int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
|
||||
#endif
|
||||
int rc = SQLITE_OK;
|
||||
i64 iOff;
|
||||
|
||||
@@ -258,26 +251,6 @@ static int backupOnePage(
|
||||
rc = SQLITE_READONLY;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/* Backup is not possible if the page size of the destination is changing
|
||||
** and a codec is in use.
|
||||
*/
|
||||
if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
|
||||
rc = SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/* Backup is not possible if the number of bytes of reserve space differ
|
||||
** between source and destination. If there is a difference, try to
|
||||
** fix the destination to agree with the source. If that is not possible,
|
||||
** then the backup cannot proceed.
|
||||
*/
|
||||
if( nSrcReserve!=nDestReserve ){
|
||||
u32 newPgsz = nSrcPgsz;
|
||||
rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
|
||||
if( rc==SQLITE_OK && newPgsz!=(u32)nSrcPgsz ) rc = SQLITE_READONLY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This loop runs once for each destination page spanned by the source
|
||||
** page. For each iteration, variable iOff is set to the byte offset
|
||||
** of the destination page.
|
||||
@@ -773,10 +746,6 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
b.pDest = pTo;
|
||||
b.iNext = 1;
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
|
||||
#endif
|
||||
|
||||
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
|
||||
** file. By passing this as the number of pages to copy to
|
||||
** sqlite3_backup_step(), we can guarantee that the copy finishes
|
||||
|
||||
+15
-17
@@ -611,7 +611,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
|
||||
*/
|
||||
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
|
||||
Bitvec *p = pBt->pHasContent;
|
||||
return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
|
||||
return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1449,7 +1449,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
||||
int sz2 = 0;
|
||||
int sz = get2byte(&data[iFree+2]);
|
||||
int top = get2byte(&data[hdr+5]);
|
||||
if( NEVER(top>=iFree) ){
|
||||
if( top>=iFree ){
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
if( iFree2 ){
|
||||
@@ -1780,7 +1780,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
** so just extend the cell content area rather than create another
|
||||
** freelist entry */
|
||||
if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage);
|
||||
if( NEVER(iPtr!=hdr+1) ) return SQLITE_CORRUPT_PAGE(pPage);
|
||||
if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
|
||||
put2byte(&data[hdr+1], iFreeBlk);
|
||||
put2byte(&data[hdr+5], iEnd);
|
||||
}else{
|
||||
@@ -2857,11 +2857,11 @@ int sqlite3BtreeSetPagerFlags(
|
||||
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
|
||||
int rc = SQLITE_OK;
|
||||
BtShared *pBt = p->pBt;
|
||||
assert( nReserve>=-1 && nReserve<=255 );
|
||||
assert( nReserve>=-1 && nReserve<=254 );
|
||||
sqlite3BtreeEnter(p);
|
||||
#if SQLITE_HAS_CODEC
|
||||
if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
|
||||
#endif
|
||||
if( nReserve>=0 ){
|
||||
pBt->nReserveWanted = nReserve + 1;
|
||||
}
|
||||
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
|
||||
sqlite3BtreeLeave(p);
|
||||
return SQLITE_READONLY;
|
||||
@@ -2914,17 +2914,15 @@ int sqlite3BtreeGetReserveNoMutex(Btree *p){
|
||||
** are intentually left unused. This is the "reserved" space that is
|
||||
** sometimes used by extensions.
|
||||
**
|
||||
** If SQLITE_HAS_MUTEX is defined then the number returned is the
|
||||
** greater of the current reserved space and the maximum requested
|
||||
** reserve space.
|
||||
** The value returned is the larger of the current reserve size and
|
||||
** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
|
||||
** The amount of reserve can only grow - never shrink.
|
||||
*/
|
||||
int sqlite3BtreeGetOptimalReserve(Btree *p){
|
||||
int sqlite3BtreeGetRequestedReserve(Btree *p){
|
||||
int n;
|
||||
sqlite3BtreeEnter(p);
|
||||
n = sqlite3BtreeGetReserveNoMutex(p);
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
|
||||
#endif
|
||||
n = ((int)p->pBt->nReserveWanted) - 1;
|
||||
if( n<0 ) n = sqlite3BtreeGetReserveNoMutex(p);
|
||||
sqlite3BtreeLeave(p);
|
||||
return n;
|
||||
}
|
||||
@@ -9536,7 +9534,7 @@ int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
|
||||
/* Unless an error occurs, the following loop runs one iteration for each
|
||||
** page in the B-Tree structure (not including overflow pages).
|
||||
*/
|
||||
while( rc==SQLITE_OK && !db->u1.isInterrupted ){
|
||||
while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
|
||||
int iIdx; /* Index of child node in parent */
|
||||
MemPage *pPage; /* Current page of the b-tree */
|
||||
|
||||
@@ -9662,7 +9660,7 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
|
||||
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
|
||||
return 1;
|
||||
}
|
||||
if( pCheck->db->u1.isInterrupted ) return 1;
|
||||
if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1;
|
||||
setPageReferenced(pCheck, iPage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ int sqlite3BtreeGetPageSize(Btree*);
|
||||
int sqlite3BtreeMaxPageCount(Btree*,int);
|
||||
u32 sqlite3BtreeLastPage(Btree*);
|
||||
int sqlite3BtreeSecureDelete(Btree*,int);
|
||||
int sqlite3BtreeGetOptimalReserve(Btree*);
|
||||
int sqlite3BtreeGetRequestedReserve(Btree*);
|
||||
int sqlite3BtreeGetReserveNoMutex(Btree *p);
|
||||
int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
||||
int sqlite3BtreeGetAutoVacuum(Btree *);
|
||||
|
||||
+1
-3
@@ -417,9 +417,7 @@ struct BtShared {
|
||||
#endif
|
||||
u8 inTransaction; /* Transaction state */
|
||||
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
u8 optimalReserve; /* Desired amount of reserved space per page */
|
||||
#endif
|
||||
u8 nReserveWanted; /* 1 more than desired number of extra bytes per page */
|
||||
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
|
||||
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
||||
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
||||
|
||||
+32
-2
@@ -315,7 +315,7 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
||||
while(1){
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
|
||||
if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
|
||||
if( p ) return p;
|
||||
@@ -437,7 +437,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
Schema *pSchema = db->aDb[j].pSchema;
|
||||
assert( pSchema );
|
||||
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
|
||||
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
p = sqlite3HashFind(&pSchema->idxHash, zName);
|
||||
if( p ) break;
|
||||
@@ -590,6 +590,7 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
|
||||
assert( pTable!=0 );
|
||||
if( (pCol = pTable->aCol)!=0 ){
|
||||
for(i=0; i<pTable->nCol; i++, pCol++){
|
||||
assert( pCol->zName==0 || pCol->hName==sqlite3StrIHash(pCol->zName) );
|
||||
sqlite3DbFree(db, pCol->zName);
|
||||
sqlite3ExprDelete(db, pCol->pDflt);
|
||||
sqlite3DbFree(db, pCol->zColl);
|
||||
@@ -1238,6 +1239,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
|
||||
pCol = &p->aCol[p->nCol];
|
||||
memset(pCol, 0, sizeof(p->aCol[0]));
|
||||
pCol->zName = z;
|
||||
pCol->hName = sqlite3StrIHash(z);
|
||||
sqlite3ColumnPropertiesFromName(p, pCol);
|
||||
|
||||
if( pType->n==0 ){
|
||||
@@ -2157,6 +2159,32 @@ int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
|
||||
}
|
||||
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Mark all nodes of an expression as EP_Immutable, indicating that
|
||||
** they should not be changed. Expressions attached to a table or
|
||||
** index definition are tagged this way to help ensure that we do
|
||||
** not pass them into code generator routines by mistake.
|
||||
*/
|
||||
static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){
|
||||
ExprSetVVAProperty(pExpr, EP_Immutable);
|
||||
return WRC_Continue;
|
||||
}
|
||||
static void markExprListImmutable(ExprList *pList){
|
||||
if( pList ){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = markImmutableExprStep;
|
||||
w.xSelectCallback = sqlite3SelectWalkNoop;
|
||||
w.xSelectCallback2 = 0;
|
||||
sqlite3WalkExprList(&w, pList);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define markExprListImmutable(X) /* no-op */
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
|
||||
/*
|
||||
** This routine is called to report the final ")" that terminates
|
||||
** a CREATE TABLE statement.
|
||||
@@ -2249,6 +2277,8 @@ void sqlite3EndTable(
|
||||
** actually be used if PRAGMA writable_schema=ON is set. */
|
||||
sqlite3ExprListDelete(db, p->pCheck);
|
||||
p->pCheck = 0;
|
||||
}else{
|
||||
markExprListImmutable(p->pCheck);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CHECK) */
|
||||
|
||||
+16
-3
@@ -163,17 +163,30 @@ CollSeq *sqlite3FindCollSeq(
|
||||
int create /* True to create CollSeq if doesn't already exist */
|
||||
){
|
||||
CollSeq *pColl;
|
||||
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
|
||||
if( zName ){
|
||||
pColl = findCollSeqEntry(db, zName, create);
|
||||
if( pColl ) pColl += enc-1;
|
||||
}else{
|
||||
pColl = db->pDfltColl;
|
||||
}
|
||||
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
|
||||
if( pColl ) pColl += enc-1;
|
||||
return pColl;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the text encoding for a database connection. This means that
|
||||
** the pDfltColl must change as well.
|
||||
*/
|
||||
void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
db->enc = enc;
|
||||
/* EVIDENCE-OF: R-08308-17224 The default collating function for all
|
||||
** strings is BINARY.
|
||||
*/
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is responsible for invoking the collation factory callback
|
||||
** or substituting a collation sequence of a different encoding when the
|
||||
|
||||
+3
-3
@@ -193,6 +193,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
"ENABLE_BATCH_ATOMIC_WRITE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_BYTECODE_VTAB
|
||||
"ENABLE_BYTECODE_VTAB",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_CEROD
|
||||
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
|
||||
#endif
|
||||
@@ -355,9 +358,6 @@ static const char * const sqlite3azCompileOpt[] = {
|
||||
#if SQLITE_FTS5_NO_WITHOUT_ROWID
|
||||
"FTS5_NO_WITHOUT_ROWID",
|
||||
#endif
|
||||
#if SQLITE_HAS_CODEC
|
||||
"HAS_CODEC",
|
||||
#endif
|
||||
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
||||
"HAVE_ISNAN",
|
||||
#endif
|
||||
|
||||
+6
-6
@@ -621,12 +621,12 @@ static const struct {
|
||||
double rLimit; /* Maximum NNN value for this transform */
|
||||
double rXform; /* Constant used for this transform */
|
||||
} aXformType[] = {
|
||||
{ 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
|
||||
{ 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
|
||||
{ 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
|
||||
{ 0, 3, "day", 5373485.0, 86400000.0 },
|
||||
{ 1, 5, "month", 176546.0, 30.0*86400000.0 },
|
||||
{ 2, 4, "year", 14713.0, 365.0*86400000.0 },
|
||||
{ 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 },
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+4
-1
@@ -238,6 +238,7 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
i = 0;
|
||||
if( iSchema>=0 ){
|
||||
pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i;
|
||||
pIdxInfo->aConstraintUsage[iSchema].omit = 1;
|
||||
pIdxInfo->idxNum |= 0x01;
|
||||
}
|
||||
if( iName>=0 ){
|
||||
@@ -452,7 +453,9 @@ static int statDecodePage(Btree *pBt, StatPage *p){
|
||||
if( nPayload>(u32)nLocal ){
|
||||
int j;
|
||||
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
|
||||
if( iOff+nLocal>nUsable ) goto statPageIsCorrupt;
|
||||
if( iOff+nLocal>nUsable || nPayload>0x7fffffff ){
|
||||
goto statPageIsCorrupt;
|
||||
}
|
||||
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
|
||||
pCell->nOvfl = nOvfl;
|
||||
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
|
||||
|
||||
+3
-1
@@ -533,7 +533,9 @@ void sqlite3DeleteFrom(
|
||||
iTabCur, aToOpen, &iDataCur, &iIdxCur);
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a loop over the rowids/primary-keys that were found in the
|
||||
|
||||
+132
-83
@@ -42,10 +42,10 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){
|
||||
** SELECT a AS b FROM t1 WHERE b;
|
||||
** SELECT * FROM t1 WHERE (select a from t1);
|
||||
*/
|
||||
char sqlite3ExprAffinity(Expr *pExpr){
|
||||
char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
int op;
|
||||
while( ExprHasProperty(pExpr, EP_Skip) ){
|
||||
assert( pExpr->op==TK_COLLATE );
|
||||
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
||||
pExpr = pExpr->pLeft;
|
||||
assert( pExpr!=0 );
|
||||
}
|
||||
@@ -112,7 +112,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
||||
*/
|
||||
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
||||
assert( pExpr->op==TK_COLLATE );
|
||||
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
return pExpr;
|
||||
@@ -131,7 +131,7 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
}else{
|
||||
assert( pExpr->op==TK_COLLATE );
|
||||
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
}
|
||||
@@ -152,10 +152,10 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
||||
** COLLATE operators take first precedence. Left operands take
|
||||
** precedence over right operands.
|
||||
*/
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
sqlite3 *db = pParse->db;
|
||||
CollSeq *pColl = 0;
|
||||
Expr *p = pExpr;
|
||||
const Expr *p = pExpr;
|
||||
while( p ){
|
||||
int op = p->op;
|
||||
if( op==TK_REGISTER ) op = p->op2;
|
||||
@@ -224,7 +224,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
** The sqlite3ExprCollSeq() routine works the same except that it
|
||||
** returns NULL if there is no defined collation.
|
||||
*/
|
||||
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
|
||||
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
|
||||
if( p==0 ) p = pParse->db->pDfltColl;
|
||||
assert( p!=0 );
|
||||
@@ -234,7 +234,7 @@ CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
|
||||
/*
|
||||
** Return TRUE if the two expressions have equivalent collating sequences.
|
||||
*/
|
||||
int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
|
||||
int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
|
||||
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
|
||||
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
|
||||
return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
|
||||
@@ -245,7 +245,7 @@ int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
|
||||
** type affinity of the other operand. This routine returns the
|
||||
** type affinity that should be used for the comparison operator.
|
||||
*/
|
||||
char sqlite3CompareAffinity(Expr *pExpr, char aff2){
|
||||
char sqlite3CompareAffinity(const Expr *pExpr, char aff2){
|
||||
char aff1 = sqlite3ExprAffinity(pExpr);
|
||||
if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){
|
||||
/* Both sides of the comparison are columns. If one has numeric
|
||||
@@ -267,7 +267,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
|
||||
** pExpr is a comparison operator. Return the type affinity that should
|
||||
** be applied to both operands prior to doing the comparison.
|
||||
*/
|
||||
static char comparisonAffinity(Expr *pExpr){
|
||||
static char comparisonAffinity(const Expr *pExpr){
|
||||
char aff;
|
||||
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
|
||||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
|
||||
@@ -290,7 +290,7 @@ static char comparisonAffinity(Expr *pExpr){
|
||||
** if the index with affinity idx_affinity may be used to implement
|
||||
** the comparison in pExpr.
|
||||
*/
|
||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
||||
int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){
|
||||
char aff = comparisonAffinity(pExpr);
|
||||
if( aff<SQLITE_AFF_TEXT ){
|
||||
return 1;
|
||||
@@ -305,7 +305,11 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
||||
** Return the P5 value that should be used for a binary comparison
|
||||
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
|
||||
*/
|
||||
static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
static u8 binaryCompareP5(
|
||||
const Expr *pExpr1, /* Left operand */
|
||||
const Expr *pExpr2, /* Right operand */
|
||||
int jumpIfNull /* Extra flags added to P5 */
|
||||
){
|
||||
u8 aff = (char)sqlite3ExprAffinity(pExpr2);
|
||||
aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
|
||||
return aff;
|
||||
@@ -325,8 +329,8 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
*/
|
||||
CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
Parse *pParse,
|
||||
Expr *pLeft,
|
||||
Expr *pRight
|
||||
const Expr *pLeft,
|
||||
const Expr *pRight
|
||||
){
|
||||
CollSeq *pColl;
|
||||
assert( pLeft );
|
||||
@@ -351,7 +355,7 @@ CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
|
||||
** correct collating sequence is found.
|
||||
*/
|
||||
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, Expr *p){
|
||||
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){
|
||||
if( ExprHasProperty(p, EP_Commuted) ){
|
||||
return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
|
||||
}else{
|
||||
@@ -594,6 +598,7 @@ static void codeVectorCompare(
|
||||
int addrDone = sqlite3VdbeMakeLabel(pParse);
|
||||
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
|
||||
|
||||
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
||||
if( pParse->nErr ) return;
|
||||
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
|
||||
sqlite3ErrorMsg(pParse, "row value misused");
|
||||
@@ -1206,7 +1211,7 @@ static int dupedExprStructSize(Expr *p, int flags){
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(p, EP_FromJoin) );
|
||||
assert( !ExprHasProperty(p, EP_MemToken) );
|
||||
assert( !ExprHasProperty(p, EP_NoReduce) );
|
||||
assert( !ExprHasVVAProperty(p, EP_NoReduce) );
|
||||
if( p->pLeft || p->x.pList ){
|
||||
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
||||
}else{
|
||||
@@ -1311,6 +1316,10 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
|
||||
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
|
||||
pNew->flags |= staticFlag;
|
||||
ExprClearVVAProperties(pNew);
|
||||
if( dupFlags ){
|
||||
ExprSetVVAProperty(pNew, EP_Immutable);
|
||||
}
|
||||
|
||||
/* Copy the p->u.zToken string, if any. */
|
||||
if( nToken ){
|
||||
@@ -1778,6 +1787,7 @@ void sqlite3ExprListSetName(
|
||||
int dequote /* True to cause the name to be dequoted */
|
||||
){
|
||||
assert( pList!=0 || pParse->db->mallocFailed!=0 );
|
||||
assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 );
|
||||
if( pList ){
|
||||
struct ExprList_item *pItem;
|
||||
assert( pList->nExpr>0 );
|
||||
@@ -1785,9 +1795,14 @@ void sqlite3ExprListSetName(
|
||||
assert( pItem->zEName==0 );
|
||||
assert( pItem->eEName==ENAME_NAME );
|
||||
pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
|
||||
if( dequote ) sqlite3Dequote(pItem->zEName);
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
|
||||
if( dequote ){
|
||||
/* If dequote==0, then pName->z does not point to part of a DDL
|
||||
** statement handled by the parser. And so no token need be added
|
||||
** to the token-map. */
|
||||
sqlite3Dequote(pItem->zEName);
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2087,7 +2102,7 @@ int sqlite3ExprIsConstant(Expr *p){
|
||||
**
|
||||
** When this routine returns true, it indicates that the expression
|
||||
** can be added to the pParse->pConstExpr list and evaluated once when
|
||||
** the prepared statement starts up. See sqlite3ExprCodeAtInit().
|
||||
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
||||
*/
|
||||
int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
return exprIsConst(p, 2, 0);
|
||||
@@ -2850,6 +2865,7 @@ void sqlite3CodeRhsOfIN(
|
||||
|
||||
/* Begin coding the subroutine */
|
||||
ExprSetProperty(pExpr, EP_Subrtn);
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
pExpr->y.sub.regReturn = ++pParse->nMem;
|
||||
pExpr->y.sub.iAddr =
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
|
||||
@@ -2931,6 +2947,8 @@ void sqlite3CodeRhsOfIN(
|
||||
affinity = sqlite3ExprAffinity(pLeft);
|
||||
if( affinity<=SQLITE_AFF_NONE ){
|
||||
affinity = SQLITE_AFF_BLOB;
|
||||
}else if( affinity==SQLITE_AFF_REAL ){
|
||||
affinity = SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
if( pKeyInfo ){
|
||||
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
||||
@@ -3169,7 +3187,9 @@ static void sqlite3ExprCodeIN(
|
||||
int destNotNull; /* Jump here if a comparison is not true in step 6 */
|
||||
int addrTop; /* Top of the step-6 loop */
|
||||
int iTab = 0; /* Index to use */
|
||||
u8 okConstFactor = pParse->okConstFactor;
|
||||
|
||||
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
||||
pLeft = pExpr->pLeft;
|
||||
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
|
||||
zAff = exprINAffinity(pParse, pExpr);
|
||||
@@ -3212,8 +3232,14 @@ static void sqlite3ExprCodeIN(
|
||||
** so that the fields are in the same order as an existing index. The
|
||||
** aiMap[] array contains a mapping from the original LHS field order to
|
||||
** the field order that matches the RHS index.
|
||||
*/
|
||||
**
|
||||
** Avoid factoring the LHS of the IN(...) expression out of the loop,
|
||||
** even if it is constant, as OP_Affinity may be used on the register
|
||||
** by code generated below. */
|
||||
assert( pParse->okConstFactor==okConstFactor );
|
||||
pParse->okConstFactor = 0;
|
||||
rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
|
||||
pParse->okConstFactor = okConstFactor;
|
||||
for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
|
||||
if( i==nVector ){
|
||||
/* LHS fields are not reordered */
|
||||
@@ -3239,21 +3265,13 @@ static void sqlite3ExprCodeIN(
|
||||
int r2, regToFree;
|
||||
int regCkNull = 0;
|
||||
int ii;
|
||||
int bLhsReal; /* True if the LHS of the IN has REAL affinity */
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
if( destIfNull!=destIfFalse ){
|
||||
regCkNull = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
|
||||
}
|
||||
bLhsReal = sqlite3ExprAffinity(pExpr->pLeft)==SQLITE_AFF_REAL;
|
||||
for(ii=0; ii<pList->nExpr; ii++){
|
||||
if( bLhsReal ){
|
||||
r2 = regToFree = sqlite3GetTempReg(pParse);
|
||||
sqlite3ExprCode(pParse, pList->a[ii].pExpr, r2);
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, r2, 1, 0, "E", P4_STATIC);
|
||||
}else{
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree);
|
||||
}
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree);
|
||||
if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
|
||||
sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
|
||||
}
|
||||
@@ -3496,7 +3514,7 @@ void sqlite3ExprCodeGeneratedColumn(
|
||||
}else{
|
||||
iAddr = 0;
|
||||
}
|
||||
sqlite3ExprCode(pParse, pCol->pDflt, regOut);
|
||||
sqlite3ExprCodeCopy(pParse, pCol->pDflt, regOut);
|
||||
if( pCol->affinity>=SQLITE_AFF_TEXT ){
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
|
||||
}
|
||||
@@ -3637,6 +3655,16 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
|
||||
return iResult;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5)
|
||||
** so that a subsequent copy will not be merged into this one.
|
||||
*/
|
||||
static void setDoNotMergeFlagOnCopy(Vdbe *v){
|
||||
if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){
|
||||
sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code to implement special SQL functions that are implemented
|
||||
** in-line rather than by using the usual callbacks.
|
||||
@@ -3668,9 +3696,7 @@ static int exprCodeInlineFunction(
|
||||
VdbeCoverage(v);
|
||||
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
||||
}
|
||||
if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){
|
||||
sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */
|
||||
}
|
||||
setDoNotMergeFlagOnCopy(v);
|
||||
sqlite3VdbeResolveLabel(v, endCoalesce);
|
||||
break;
|
||||
}
|
||||
@@ -3772,6 +3798,7 @@ expr_code_doover:
|
||||
if( pExpr==0 ){
|
||||
op = TK_NULL;
|
||||
}else{
|
||||
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
||||
op = pExpr->op;
|
||||
}
|
||||
switch( op ){
|
||||
@@ -3782,8 +3809,17 @@ expr_code_doover:
|
||||
assert( pCol->iMem>0 );
|
||||
return pCol->iMem;
|
||||
}else if( pAggInfo->useSortingIdx ){
|
||||
Table *pTab = pCol->pTab;
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
|
||||
pCol->iSorterColumn, target);
|
||||
if( pCol->iColumn<0 ){
|
||||
VdbeComment((v,"%s.rowid",pTab->zName));
|
||||
}else{
|
||||
VdbeComment((v,"%s.%s",pTab->zName,pTab->aCol[pCol->iColumn].zName));
|
||||
if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
/* Otherwise, fall thru into the TK_COLUMN case */
|
||||
@@ -3809,10 +3845,6 @@ expr_code_doover:
|
||||
static const char zAff[] = "B\000C\000D\000E";
|
||||
assert( SQLITE_AFF_BLOB=='A' );
|
||||
assert( SQLITE_AFF_TEXT=='B' );
|
||||
if( iReg!=target ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target);
|
||||
iReg = target;
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0,
|
||||
&zAff[(aff-'B')*2], P4_STATIC);
|
||||
}
|
||||
@@ -4026,6 +4058,7 @@ expr_code_doover:
|
||||
tempX.op = TK_INTEGER;
|
||||
tempX.flags = EP_IntValue|EP_TokenOnly;
|
||||
tempX.u.iValue = 0;
|
||||
ExprClearVVAProperties(&tempX);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2);
|
||||
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
|
||||
@@ -4097,16 +4130,13 @@ expr_code_doover:
|
||||
#endif
|
||||
|
||||
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
||||
/* SQL functions can be expensive. So try to move constant functions
|
||||
** out of the inner loop, even if that means an extra OP_Copy. */
|
||||
return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
|
||||
/* SQL functions can be expensive. So try to avoid running them
|
||||
** multiple times if we know they always give the same result */
|
||||
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
||||
pFarg = 0;
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
|
||||
pFarg = pExpr->x.pList;
|
||||
nFarg = pFarg ? pFarg->nExpr : 0;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
zId = pExpr->u.zToken;
|
||||
@@ -4441,6 +4471,7 @@ expr_code_doover:
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
||||
}
|
||||
sqlite3ExprDelete(db, pDel);
|
||||
setDoNotMergeFlagOnCopy(v);
|
||||
sqlite3VdbeResolveLabel(v, endLabel);
|
||||
break;
|
||||
}
|
||||
@@ -4479,15 +4510,23 @@ expr_code_doover:
|
||||
}
|
||||
|
||||
/*
|
||||
** Factor out the code of the given expression to initialization time.
|
||||
** Generate code that will evaluate expression pExpr just one time
|
||||
** per prepared statement execution.
|
||||
**
|
||||
** If the expression uses functions (that might throw an exception) then
|
||||
** guard them with an OP_Once opcode to ensure that the code is only executed
|
||||
** once. If no functions are involved, then factor the code out and put it at
|
||||
** the end of the prepared statement in the initialization section.
|
||||
**
|
||||
** If regDest>=0 then the result is always stored in that register and the
|
||||
** result is not reusable. If regDest<0 then this routine is free to
|
||||
** store the value whereever it wants. The register where the expression
|
||||
** is stored is returned. When regDest<0, two identical expressions will
|
||||
** code to the same register.
|
||||
** is stored is returned. When regDest<0, two identical expressions might
|
||||
** code to the same register, if they do not contain function calls and hence
|
||||
** are factored out into the initialization section at the end of the
|
||||
** prepared statement.
|
||||
*/
|
||||
int sqlite3ExprCodeAtInit(
|
||||
int sqlite3ExprCodeRunJustOnce(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Expr *pExpr, /* The expression to code when the VDBE initializes */
|
||||
int regDest /* Store the value in this register */
|
||||
@@ -4505,14 +4544,29 @@ int sqlite3ExprCodeAtInit(
|
||||
}
|
||||
}
|
||||
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
|
||||
p = sqlite3ExprListAppend(pParse, p, pExpr);
|
||||
if( p ){
|
||||
struct ExprList_item *pItem = &p->a[p->nExpr-1];
|
||||
pItem->reusable = regDest<0;
|
||||
if( regDest<0 ) regDest = ++pParse->nMem;
|
||||
pItem->u.iConstExprReg = regDest;
|
||||
if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int addr;
|
||||
assert( v );
|
||||
addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
pParse->okConstFactor = 0;
|
||||
if( !pParse->db->mallocFailed ){
|
||||
if( regDest<0 ) regDest = ++pParse->nMem;
|
||||
sqlite3ExprCode(pParse, pExpr, regDest);
|
||||
}
|
||||
pParse->okConstFactor = 1;
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}else{
|
||||
p = sqlite3ExprListAppend(pParse, p, pExpr);
|
||||
if( p ){
|
||||
struct ExprList_item *pItem = &p->a[p->nExpr-1];
|
||||
pItem->reusable = regDest<0;
|
||||
if( regDest<0 ) regDest = ++pParse->nMem;
|
||||
pItem->u.iConstExprReg = regDest;
|
||||
}
|
||||
pParse->pConstExpr = p;
|
||||
}
|
||||
pParse->pConstExpr = p;
|
||||
return regDest;
|
||||
}
|
||||
|
||||
@@ -4537,7 +4591,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
||||
){
|
||||
*pReg = 0;
|
||||
r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
|
||||
r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||
}else{
|
||||
int r1 = sqlite3GetTempReg(pParse);
|
||||
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
|
||||
@@ -4559,6 +4613,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
||||
void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
||||
int inReg;
|
||||
|
||||
assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
||||
assert( target>0 && target<=pParse->nMem );
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
|
||||
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
|
||||
@@ -4593,9 +4648,9 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
|
||||
*/
|
||||
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
||||
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
||||
sqlite3ExprCodeAtInit(pParse, pExpr, target);
|
||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, pExpr, target);
|
||||
sqlite3ExprCodeCopy(pParse, pExpr, target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4653,7 +4708,7 @@ int sqlite3ExprCodeExprList(
|
||||
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
|
||||
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
||||
){
|
||||
sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
|
||||
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
|
||||
}else{
|
||||
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
|
||||
if( inReg!=target+i ){
|
||||
@@ -4776,6 +4831,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
||||
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
||||
if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
||||
assert( !ExprHasVVAProperty(pExpr, EP_Immutable) );
|
||||
op = pExpr->op;
|
||||
switch( op ){
|
||||
case TK_AND:
|
||||
@@ -4917,6 +4973,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
||||
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
||||
if( pExpr==0 ) return;
|
||||
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
||||
|
||||
/* The value of pExpr->op and op are related as follows:
|
||||
**
|
||||
@@ -5200,7 +5257,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
}
|
||||
if( (pA->flags & (EP_Distinct|EP_Commuted))
|
||||
!= (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
|
||||
if( (combinedFlags & EP_TokenOnly)==0 ){
|
||||
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
|
||||
if( combinedFlags & EP_xIsSelect ) return 2;
|
||||
if( (combinedFlags & EP_FixedCol)==0
|
||||
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
@@ -5208,24 +5265,10 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( pA->op!=TK_STRING
|
||||
&& pA->op!=TK_TRUEFALSE
|
||||
&& (combinedFlags & EP_Reduced)==0
|
||||
&& ALWAYS((combinedFlags & EP_Reduced)==0)
|
||||
){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
if( pA->op2!=pB->op2 ){
|
||||
if( pA->op==TK_TRUTH ) return 2;
|
||||
if( pA->op==TK_FUNCTION && iTab<0 ){
|
||||
/* Ex: CREATE TABLE t1(a CHECK( a<julianday('now') ));
|
||||
** INSERT INTO t1(a) VALUES(julianday('now')+10);
|
||||
** Without this test, sqlite3ExprCodeAtInit() will run on the
|
||||
** the julianday() of INSERT first, and remember that expression.
|
||||
** Then sqlite3ExprCodeInit() will see the julianday() in the CHECK
|
||||
** constraint as redundant, reusing the one from the INSERT, even
|
||||
** though the julianday() in INSERT lacks the critical NC_IsCheck
|
||||
** flag. See ticket [830277d9db6c3ba1] (2019-10-30)
|
||||
*/
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if( pA->op2!=pB->op2 && pA->op==TK_TRUTH ) return 2;
|
||||
if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){
|
||||
return 2;
|
||||
}
|
||||
@@ -5463,19 +5506,25 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
||||
case TK_LT:
|
||||
case TK_LE:
|
||||
case TK_GT:
|
||||
case TK_GE:
|
||||
case TK_GE: {
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
testcase( pExpr->op==TK_EQ );
|
||||
testcase( pExpr->op==TK_NE );
|
||||
testcase( pExpr->op==TK_LT );
|
||||
testcase( pExpr->op==TK_LE );
|
||||
testcase( pExpr->op==TK_GT );
|
||||
testcase( pExpr->op==TK_GE );
|
||||
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
|
||||
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
|
||||
/* The y.pTab=0 assignment in wherecode.c always happens after the
|
||||
** impliesNotNullRow() test */
|
||||
if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0)
|
||||
&& IsVirtual(pLeft->y.pTab))
|
||||
|| (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0)
|
||||
&& IsVirtual(pRight->y.pTab))
|
||||
){
|
||||
return WRC_Prune;
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
+1
-1
@@ -658,7 +658,7 @@ static void fkScanChildren(
|
||||
/* Clean up the WHERE clause constructed above. */
|
||||
sqlite3ExprDelete(db, pWhere);
|
||||
if( iFkIfZero ){
|
||||
sqlite3VdbeJumpHere(v, iFkIfZero);
|
||||
sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-10
@@ -853,6 +853,7 @@ static void likeFunc(
|
||||
int nPat;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
struct compareInfo *pInfo = sqlite3_user_data(context);
|
||||
struct compareInfo backupInfo;
|
||||
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
|
||||
@@ -888,6 +889,12 @@ static void likeFunc(
|
||||
return;
|
||||
}
|
||||
escape = sqlite3Utf8Read(&zEsc);
|
||||
if( escape==pInfo->matchAll || escape==pInfo->matchOne ){
|
||||
memcpy(&backupInfo, pInfo, sizeof(backupInfo));
|
||||
pInfo = &backupInfo;
|
||||
if( escape==pInfo->matchAll ) pInfo->matchAll = 0;
|
||||
if( escape==pInfo->matchOne ) pInfo->matchOne = 0;
|
||||
}
|
||||
}else{
|
||||
escape = pInfo->matchSet;
|
||||
}
|
||||
@@ -1864,19 +1871,12 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
nExpr = pExpr->x.pList->nExpr;
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
||||
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
if( pDef==0 ) return 0;
|
||||
#endif
|
||||
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
|
||||
return 0;
|
||||
}
|
||||
if( nExpr<3 ){
|
||||
aWc[3] = 0;
|
||||
}else{
|
||||
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
|
||||
char *zEscape;
|
||||
if( pEscape->op!=TK_STRING ) return 0;
|
||||
zEscape = pEscape->u.zToken;
|
||||
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
|
||||
aWc[3] = zEscape[0];
|
||||
}
|
||||
|
||||
/* The memcpy() statement assumes that the wildcard characters are
|
||||
** the first three statements in the compareInfo structure. The
|
||||
@@ -1886,6 +1886,20 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
|
||||
assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
|
||||
assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
|
||||
|
||||
if( nExpr<3 ){
|
||||
aWc[3] = 0;
|
||||
}else{
|
||||
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
|
||||
char *zEscape;
|
||||
if( pEscape->op!=TK_STRING ) return 0;
|
||||
zEscape = pEscape->u.zToken;
|
||||
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
|
||||
if( zEscape[0]==aWc[0] ) return 0;
|
||||
if( zEscape[0]==aWc[1] ) return 0;
|
||||
aWc[3] = zEscape[0];
|
||||
}
|
||||
|
||||
*pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+1
-8
@@ -135,16 +135,9 @@ const unsigned char sqlite3CtypeMap[256] = {
|
||||
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
|
||||
** disabled. The default value may be changed by compiling with the
|
||||
** SQLITE_USE_URI symbol defined.
|
||||
**
|
||||
** URI filenames are enabled by default if SQLITE_HAS_CODEC is
|
||||
** enabled.
|
||||
*/
|
||||
#ifndef SQLITE_USE_URI
|
||||
# ifdef SQLITE_HAS_CODEC
|
||||
# define SQLITE_USE_URI 1
|
||||
# else
|
||||
# define SQLITE_USE_URI 0
|
||||
# endif
|
||||
# define SQLITE_USE_URI 0
|
||||
#endif
|
||||
|
||||
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
|
||||
|
||||
+18
-9
@@ -1606,7 +1606,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
VdbeCoverage(v);
|
||||
assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
|
||||
nSeenReplace++;
|
||||
sqlite3ExprCode(pParse, pCol->pDflt, iReg);
|
||||
sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
break;
|
||||
}
|
||||
@@ -1661,6 +1661,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
|
||||
for(i=0; i<pCheck->nExpr; i++){
|
||||
int allOk;
|
||||
Expr *pCopy;
|
||||
Expr *pExpr = pCheck->a[i].pExpr;
|
||||
if( aiChng
|
||||
&& !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
|
||||
@@ -1669,9 +1670,17 @@ void sqlite3GenerateConstraintChecks(
|
||||
** updated so there is no point it verifying the check constraint */
|
||||
continue;
|
||||
}
|
||||
if( bAffinityDone==0 ){
|
||||
sqlite3TableAffinity(v, pTab, regNewData+1);
|
||||
bAffinityDone = 1;
|
||||
}
|
||||
allOk = sqlite3VdbeMakeLabel(pParse);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
|
||||
pCopy = sqlite3ExprDup(db, pExpr, 0);
|
||||
if( !db->mallocFailed ){
|
||||
sqlite3ExprIfTrue(pParse, pCopy, allOk, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
sqlite3ExprDelete(db, pCopy);
|
||||
if( onError==OE_Ignore ){
|
||||
sqlite3VdbeGoto(v, ignoreDest);
|
||||
}else{
|
||||
@@ -2170,12 +2179,14 @@ void sqlite3GenerateConstraintChecks(
|
||||
x = *sqlite3VdbeGetOp(v, addrConflictCk);
|
||||
if( x.opcode!=OP_IdxRowid ){
|
||||
int p2; /* New P2 value for copied conflict check opcode */
|
||||
const char *zP4;
|
||||
if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
|
||||
p2 = lblRecheckOk;
|
||||
}else{
|
||||
p2 = x.p2;
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, x.p4.z, x.p4type);
|
||||
zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z;
|
||||
sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type);
|
||||
sqlite3VdbeChangeP5(v, x.p5);
|
||||
VdbeCoverageIf(v, p2!=x.p2);
|
||||
}
|
||||
@@ -2783,14 +2794,13 @@ static int xferOptimization(
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
|
||||
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
||||
if( db->mDbFlags & DBFLAG_Vacuum ){
|
||||
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
|
||||
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
|
||||
OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
|
||||
insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
|
||||
}else{
|
||||
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
|
||||
(char*)pDest, P4_TABLE);
|
||||
sqlite3VdbeChangeP5(v, insFlags);
|
||||
@@ -2815,7 +2825,6 @@ static int xferOptimization(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
|
||||
VdbeComment((v, "%s", pDestIdx->zName));
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
||||
if( db->mDbFlags & DBFLAG_Vacuum ){
|
||||
/* This INSERT command is part of a VACUUM operation, which guarantees
|
||||
** that the destination table is empty. If all indexed columns use
|
||||
@@ -2839,10 +2848,10 @@ static int xferOptimization(
|
||||
idxInsFlags = OPFLAG_USESEEKRESULT;
|
||||
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
|
||||
}
|
||||
}
|
||||
if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
|
||||
}else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
|
||||
idxInsFlags |= OPFLAG_NCHANGE;
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
|
||||
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
|
||||
|
||||
+13
-1
@@ -474,8 +474,20 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_filename_database,
|
||||
sqlite3_filename_journal,
|
||||
sqlite3_filename_wal,
|
||||
/* Version 3.32.0 and later */
|
||||
sqlite3_create_filename,
|
||||
sqlite3_free_filename,
|
||||
sqlite3_database_file_object,
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
*/
|
||||
#if SQLITE_OS_WIN
|
||||
# define DirSep(X) ((X)=='/'||(X)=='\\')
|
||||
#else
|
||||
# define DirSep(X) ((X)=='/')
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Attempt to load an SQLite extension library contained in the file
|
||||
** zFile. The entry point is zProc. zProc may be 0 in which case a
|
||||
@@ -577,7 +589,7 @@ static int sqlite3LoadExtension(
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
memcpy(zAltEntry, "sqlite3_", 8);
|
||||
for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
|
||||
for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
|
||||
iFile++;
|
||||
if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
|
||||
for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
|
||||
|
||||
+162
-101
@@ -161,7 +161,10 @@ int sqlite3_initialize(void){
|
||||
** must be complete. So isInit must not be set until the very end
|
||||
** of this routine.
|
||||
*/
|
||||
if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
|
||||
if( sqlite3GlobalConfig.isInit ){
|
||||
sqlite3MemoryBarrier();
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Make sure the mutex subsystem is initialized. If unable to
|
||||
** initialize the mutex subsystem, return early with the error.
|
||||
@@ -1566,9 +1569,21 @@ static int sqliteDefaultBusyCallback(
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
|
||||
if( count ){
|
||||
tmout = 0;
|
||||
sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
|
||||
return 0;
|
||||
/* If this is the second or later invocation of the busy-handler,
|
||||
** but tmout==0, then code in wal.c must have disabled the blocking
|
||||
** lock before the SQLITE_BUSY error was hit. In this case, no delay
|
||||
** occurred while waiting for the lock, so fall through to the xSleep()
|
||||
** code below to delay a while before retrying the lock.
|
||||
**
|
||||
** Alternatively, if tmout!=0, then SQLite has already waited
|
||||
** sqlite3.busyTimeout ms for a lock. In this case, return 0 to
|
||||
** indicate that the lock should not be retried and the SQLITE_BUSY
|
||||
** error returned to the application. */
|
||||
if( tmout ){
|
||||
tmout = 0;
|
||||
sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
@@ -1718,7 +1733,7 @@ void sqlite3_interrupt(sqlite3 *db){
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
db->u1.isInterrupted = 1;
|
||||
AtomicStore(&db->u1.isInterrupted, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2340,7 +2355,7 @@ int sqlite3_wal_checkpoint_v2(
|
||||
/* If there are no active statements, clear the interrupt flag at this
|
||||
** point. */
|
||||
if( db->nVdbeActive==0 ){
|
||||
db->u1.isInterrupted = 0;
|
||||
AtomicStore(&db->u1.isInterrupted, 0);
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@@ -2750,9 +2765,11 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
|
||||
** the VFS that should be used to open the database file. *pzFile is set to
|
||||
** point to a buffer containing the name of the file to open. It is the
|
||||
** responsibility of the caller to eventually call sqlite3_free() to release
|
||||
** this buffer.
|
||||
** point to a buffer containing the name of the file to open. The value
|
||||
** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter()
|
||||
** and is in the same format as names created using sqlite3_create_filename().
|
||||
** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on
|
||||
** the value returned in *pzFile to avoid a memory leak.
|
||||
**
|
||||
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
|
||||
** may be set to point to a buffer containing an English language error
|
||||
@@ -2784,7 +2801,7 @@ int sqlite3ParseUri(
|
||||
int eState; /* Parser state when parsing URI */
|
||||
int iIn; /* Input character index */
|
||||
int iOut = 0; /* Output character index */
|
||||
u64 nByte = nUri+2; /* Bytes of space to allocate */
|
||||
u64 nByte = nUri+8; /* Bytes of space to allocate */
|
||||
|
||||
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
|
||||
** method that there may be extra parameters following the file-name. */
|
||||
@@ -2794,6 +2811,9 @@ int sqlite3ParseUri(
|
||||
zFile = sqlite3_malloc64(nByte);
|
||||
if( !zFile ) return SQLITE_NOMEM_BKPT;
|
||||
|
||||
memset(zFile, 0, 4); /* 4-byte of 0x00 is the start of DB name marker */
|
||||
zFile += 4;
|
||||
|
||||
iIn = 5;
|
||||
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
||||
if( strncmp(zUri+5, "///", 3)==0 ){
|
||||
@@ -2883,8 +2903,7 @@ int sqlite3ParseUri(
|
||||
zFile[iOut++] = c;
|
||||
}
|
||||
if( eState==1 ) zFile[iOut++] = '\0';
|
||||
zFile[iOut++] = '\0';
|
||||
zFile[iOut++] = '\0';
|
||||
memset(zFile+iOut, 0, 4); /* end-of-options + empty journal filenames */
|
||||
|
||||
/* Check if there were any options specified that should be interpreted
|
||||
** here. Options that are interpreted here include "vfs" and those that
|
||||
@@ -2964,13 +2983,14 @@ int sqlite3ParseUri(
|
||||
}
|
||||
|
||||
}else{
|
||||
zFile = sqlite3_malloc64(nUri+2);
|
||||
zFile = sqlite3_malloc64(nUri+8);
|
||||
if( !zFile ) return SQLITE_NOMEM_BKPT;
|
||||
memset(zFile, 0, 4);
|
||||
zFile += 4;
|
||||
if( nUri ){
|
||||
memcpy(zFile, zUri, nUri);
|
||||
}
|
||||
zFile[nUri] = '\0';
|
||||
zFile[nUri+1] = '\0';
|
||||
memset(zFile+nUri, 0, 4);
|
||||
flags &= ~SQLITE_OPEN_URI;
|
||||
}
|
||||
|
||||
@@ -2981,7 +3001,7 @@ int sqlite3ParseUri(
|
||||
}
|
||||
parse_uri_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zFile);
|
||||
sqlite3_free_filename(zFile);
|
||||
zFile = 0;
|
||||
}
|
||||
*pFlags = flags;
|
||||
@@ -2989,39 +3009,21 @@ int sqlite3ParseUri(
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
/*
|
||||
** Process URI filename query parameters relevant to the SQLite Encryption
|
||||
** Extension. Return true if any of the relevant query parameters are
|
||||
** seen and return false if not.
|
||||
** This routine does the core work of extracting URI parameters from a
|
||||
** database filename for the sqlite3_uri_parameter() interface.
|
||||
*/
|
||||
int sqlite3CodecQueryParameters(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zDb, /* Which schema is being created/attached */
|
||||
const char *zUri /* URI filename */
|
||||
){
|
||||
const char *zKey;
|
||||
if( (zKey = sqlite3_uri_parameter(zUri, "hexkey"))!=0 && zKey[0] ){
|
||||
u8 iByte;
|
||||
int i;
|
||||
char zDecoded[40];
|
||||
for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
|
||||
iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
|
||||
if( (i&1)!=0 ) zDecoded[i/2] = iByte;
|
||||
}
|
||||
sqlite3_key_v2(db, zDb, zDecoded, i/2);
|
||||
return 1;
|
||||
}else if( (zKey = sqlite3_uri_parameter(zUri, "key"))!=0 ){
|
||||
sqlite3_key_v2(db, zDb, zKey, sqlite3Strlen30(zKey));
|
||||
return 1;
|
||||
}else if( (zKey = sqlite3_uri_parameter(zUri, "textkey"))!=0 ){
|
||||
sqlite3_key_v2(db, zDb, zKey, -1);
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
static const char *uriParameter(const char *zFilename, const char *zParam){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
int x = strcmp(zFilename, zParam);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
if( x==0 ) return zFilename;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -3209,11 +3211,6 @@ static int openDatabase(
|
||||
if( db->mallocFailed ){
|
||||
goto opendb_out;
|
||||
}
|
||||
/* EVIDENCE-OF: R-08308-17224 The default collating function for all
|
||||
** strings is BINARY.
|
||||
*/
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
|
||||
assert( db->pDfltColl!=0 );
|
||||
|
||||
/* Parse the filename/URI argument
|
||||
**
|
||||
@@ -3258,7 +3255,9 @@ static int openDatabase(
|
||||
}
|
||||
sqlite3BtreeEnter(db->aDb[0].pBt);
|
||||
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
|
||||
if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
|
||||
if( !db->mallocFailed ){
|
||||
sqlite3SetTextEncoding(db, SCHEMA_ENC(db));
|
||||
}
|
||||
sqlite3BtreeLeave(db->aDb[0].pBt);
|
||||
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
|
||||
|
||||
@@ -3359,6 +3358,12 @@ static int openDatabase(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
if( !db->mallocFailed && rc==SQLITE_OK){
|
||||
rc = sqlite3VdbeBytecodeVtabInit(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
|
||||
/* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
|
||||
** option gives access to internal functions by default.
|
||||
@@ -3406,10 +3411,7 @@ opendb_out:
|
||||
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen);
|
||||
#endif
|
||||
sqlite3_free(zOpen);
|
||||
sqlite3_free_filename(zOpen);
|
||||
return rc & 0xff;
|
||||
}
|
||||
|
||||
@@ -3636,13 +3638,15 @@ int sqlite3CantopenError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file");
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
|
||||
int sqlite3CorruptPgnoError(int lineno, Pgno pgno){
|
||||
char zMsg[100];
|
||||
sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno);
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3NomemError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM");
|
||||
@@ -3845,6 +3849,13 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
|
||||
}else if( op==SQLITE_FCNTL_DATA_VERSION ){
|
||||
*(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
|
||||
rc = SQLITE_OK;
|
||||
}else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
|
||||
int iNew = *(int*)pArg;
|
||||
*(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
|
||||
if( iNew>=0 && iNew<=254 ){
|
||||
sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
|
||||
}
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = sqlite3OsFileControl(fd, op, pArg);
|
||||
}
|
||||
@@ -4061,20 +4072,6 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
|
||||
**
|
||||
** Set the nReserve size to N for the main database on the database
|
||||
** connection db.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_RESERVE: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
int x = va_arg(ap,int);
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
|
||||
**
|
||||
** Enable or disable various optimizations for testing purposes. The
|
||||
@@ -4243,6 +4240,83 @@ int sqlite3_test_control(int op, ...){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The Pager stores the Database filename, Journal filename, and WAL filename
|
||||
** consecutively in memory, in that order. The database filename is prefixed
|
||||
** by four zero bytes. Locate the start of the database filename by searching
|
||||
** backwards for the first byte following four consecutive zero bytes.
|
||||
**
|
||||
** This only works if the filename passed in was obtained from the Pager.
|
||||
*/
|
||||
static const char *databaseName(const char *zName){
|
||||
while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
|
||||
zName--;
|
||||
}
|
||||
return zName;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append text z[] to the end of p[]. Return a pointer to the first
|
||||
** character after then zero terminator on the new text in p[].
|
||||
*/
|
||||
static char *appendText(char *p, const char *z){
|
||||
size_t n = strlen(z);
|
||||
memcpy(p, z, n+1);
|
||||
return p+n+1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate memory to hold names for a database, journal file, WAL file,
|
||||
** and query parameters. The pointer returned is valid for use by
|
||||
** sqlite3_filename_database() and sqlite3_uri_parameter() and related
|
||||
** functions.
|
||||
**
|
||||
** Memory layout must be compatible with that generated by the pager
|
||||
** and expected by sqlite3_uri_parameter() and databaseName().
|
||||
*/
|
||||
char *sqlite3_create_filename(
|
||||
const char *zDatabase,
|
||||
const char *zJournal,
|
||||
const char *zWal,
|
||||
int nParam,
|
||||
const char **azParam
|
||||
){
|
||||
sqlite3_int64 nByte;
|
||||
int i;
|
||||
char *pResult, *p;
|
||||
nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10;
|
||||
for(i=0; i<nParam*2; i++){
|
||||
nByte += strlen(azParam[i])+1;
|
||||
}
|
||||
pResult = p = sqlite3_malloc64( nByte );
|
||||
if( p==0 ) return 0;
|
||||
memset(p, 0, 4);
|
||||
p += 4;
|
||||
p = appendText(p, zDatabase);
|
||||
for(i=0; i<nParam*2; i++){
|
||||
p = appendText(p, azParam[i]);
|
||||
}
|
||||
*(p++) = 0;
|
||||
p = appendText(p, zJournal);
|
||||
p = appendText(p, zWal);
|
||||
*(p++) = 0;
|
||||
*(p++) = 0;
|
||||
assert( (sqlite3_int64)(p - pResult)==nByte );
|
||||
return pResult + 4;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free memory obtained from sqlite3_create_filename(). It is a severe
|
||||
** error to call this routine with any parameter other than a pointer
|
||||
** previously obtained from sqlite3_create_filename() or a NULL pointer.
|
||||
*/
|
||||
void sqlite3_free_filename(char *p){
|
||||
if( p==0 ) return;
|
||||
p = (char*)databaseName(p);
|
||||
sqlite3_free(p - 4);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This is a utility routine, useful to VFS implementations, that checks
|
||||
** to see if a database file was a URI that contained a specific query
|
||||
@@ -4256,14 +4330,8 @@ int sqlite3_test_control(int op, ...){
|
||||
*/
|
||||
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
if( zFilename==0 || zParam==0 ) return 0;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
int x = strcmp(zFilename, zParam);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
if( x==0 ) return zFilename;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
return 0;
|
||||
zFilename = databaseName(zFilename);
|
||||
return uriParameter(zFilename, zParam);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4271,6 +4339,7 @@ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
*/
|
||||
const char *sqlite3_uri_key(const char *zFilename, int N){
|
||||
if( zFilename==0 || N<0 ) return 0;
|
||||
zFilename = databaseName(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] && (N--)>0 ){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
@@ -4304,25 +4373,6 @@ sqlite3_int64 sqlite3_uri_int64(
|
||||
return bDflt;
|
||||
}
|
||||
|
||||
/*
|
||||
** The Pager stores the Journal filename, WAL filename, and Database filename
|
||||
** consecutively in memory, in that order, with prefixes \000\001\000,
|
||||
** \002\000, and \003\000, in that order. Thus the three names look like query
|
||||
** parameters if you start at the first prefix.
|
||||
**
|
||||
** This routine backs up a filename to the start of the first prefix.
|
||||
**
|
||||
** This only works if the filenamed passed in was obtained from the Pager.
|
||||
*/
|
||||
static const char *startOfNameList(const char *zName){
|
||||
while( zName[0]!='\001' || zName[1]!=0 ){
|
||||
zName -= 3;
|
||||
while( zName[0]!='\000' ){ zName--; }
|
||||
zName++;
|
||||
}
|
||||
return zName-1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Translate a filename that was handed to a VFS routine into the corresponding
|
||||
** database, journal, or WAL file.
|
||||
@@ -4334,14 +4384,25 @@ static const char *startOfNameList(const char *zName){
|
||||
** corruption.
|
||||
*/
|
||||
const char *sqlite3_filename_database(const char *zFilename){
|
||||
return sqlite3_uri_parameter(zFilename - 3, "\003");
|
||||
return databaseName(zFilename);
|
||||
}
|
||||
const char *sqlite3_filename_journal(const char *zFilename){
|
||||
const char *z = sqlite3_uri_parameter(startOfNameList(zFilename), "\001");
|
||||
return ALWAYS(z) && z[0] ? z : 0;
|
||||
zFilename = databaseName(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
return zFilename + 1;
|
||||
}
|
||||
const char *sqlite3_filename_wal(const char *zFilename){
|
||||
return sqlite3_uri_parameter(startOfNameList(zFilename), "\002");
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
return 0;
|
||||
#else
|
||||
zFilename = sqlite3_filename_journal(zFilename);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
return zFilename;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+6
-6
@@ -111,7 +111,7 @@ sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
|
||||
}
|
||||
mem0.alarmThreshold = n;
|
||||
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
mem0.nearlyFull = (n>0 && n<=nUsed);
|
||||
AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
excess = sqlite3_memory_used() - n;
|
||||
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
|
||||
@@ -179,7 +179,7 @@ int sqlite3MallocInit(void){
|
||||
** sqlite3_soft_heap_limit().
|
||||
*/
|
||||
int sqlite3HeapNearlyFull(void){
|
||||
return mem0.nearlyFull;
|
||||
return AtomicLoad(&mem0.nearlyFull);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -243,7 +243,7 @@ static void mallocWithAlarm(int n, void **pp){
|
||||
if( mem0.alarmThreshold>0 ){
|
||||
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
AtomicStore(&mem0.nearlyFull, 1);
|
||||
sqlite3MallocAlarm(nFull);
|
||||
if( mem0.hardLimit ){
|
||||
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
@@ -253,7 +253,7 @@ static void mallocWithAlarm(int n, void **pp){
|
||||
}
|
||||
}
|
||||
}else{
|
||||
mem0.nearlyFull = 0;
|
||||
AtomicStore(&mem0.nearlyFull, 0);
|
||||
}
|
||||
}
|
||||
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
||||
@@ -760,7 +760,7 @@ void sqlite3OomFault(sqlite3 *db){
|
||||
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
|
||||
db->mallocFailed = 1;
|
||||
if( db->nVdbeExec>0 ){
|
||||
db->u1.isInterrupted = 1;
|
||||
AtomicStore(&db->u1.isInterrupted, 1);
|
||||
}
|
||||
DisableLookaside;
|
||||
if( db->pParse ){
|
||||
@@ -779,7 +779,7 @@ void sqlite3OomFault(sqlite3 *db){
|
||||
void sqlite3OomClear(sqlite3 *db){
|
||||
if( db->mallocFailed && db->nVdbeExec==0 ){
|
||||
db->mallocFailed = 0;
|
||||
db->u1.isInterrupted = 0;
|
||||
AtomicStore(&db->u1.isInterrupted, 0);
|
||||
assert( db->lookaside.bDisable>0 );
|
||||
EnableLookaside;
|
||||
}
|
||||
|
||||
@@ -254,6 +254,7 @@ int sqlite3MutexInit(void){
|
||||
GLOBAL(int, mutexIsInit) = 1;
|
||||
#endif
|
||||
|
||||
sqlite3MemoryBarrier();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+22
-2
@@ -689,7 +689,7 @@ static int robust_open(const char *z, int f, mode_t m){
|
||||
sqlite3_log(SQLITE_WARNING,
|
||||
"attempt to open \"%s\" as file descriptor %d", z, fd);
|
||||
fd = -1;
|
||||
if( osOpen("/dev/null", f, m)<0 ) break;
|
||||
if( osOpen("/dev/null", O_RDONLY, m)<0 ) break;
|
||||
}
|
||||
if( fd>=0 ){
|
||||
if( m!=0 ){
|
||||
@@ -3685,7 +3685,7 @@ static int openDirectory(const char *zFilename, int *pFd){
|
||||
if( zDirname[0]!='/' ) zDirname[0] = '.';
|
||||
zDirname[1] = 0;
|
||||
}
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY|O_NOFOLLOW, 0);
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
||||
if( fd>=0 ){
|
||||
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
||||
}
|
||||
@@ -3995,7 +3995,9 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
case SQLITE_FCNTL_LOCK_TIMEOUT: {
|
||||
int iOld = pFile->iBusyTimeout;
|
||||
pFile->iBusyTimeout = *(int*)pArg;
|
||||
*(int*)pArg = iOld;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -4817,6 +4819,24 @@ static int unixShmLock(
|
||||
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
|
||||
/* Check that, if this to be a blocking lock, that locks have been
|
||||
** obtained in the following order.
|
||||
**
|
||||
** 1. Checkpointer lock (ofst==1).
|
||||
** 2. Recover lock (ofst==2).
|
||||
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
|
||||
** 4. Write lock (ofst==0).
|
||||
**
|
||||
** In other words, if this is a blocking lock, none of the locks that
|
||||
** occur later in the above list than the lock being obtained may be
|
||||
** held. */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
assert( pDbFd->iBusyTimeout==0
|
||||
|| (flags & SQLITE_SHM_UNLOCK) || ofst==0
|
||||
|| ((p->exclMask|p->sharedMask)&~((1<<ofst)-2))==0
|
||||
);
|
||||
#endif
|
||||
|
||||
mask = (1<<(ofst+n)) - (1<<ofst);
|
||||
assert( n>1 || mask==(1<<ofst) );
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
|
||||
+75
-183
@@ -406,20 +406,6 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
||||
*/
|
||||
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
|
||||
|
||||
/*
|
||||
** A macro used for invoking the codec if there is one
|
||||
*/
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
# define CODEC1(P,D,N,X,E) \
|
||||
if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
|
||||
# define CODEC2(P,D,N,X,E,O) \
|
||||
if( P->xCodec==0 ){ O=(char*)D; }else \
|
||||
if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
|
||||
#else
|
||||
# define CODEC1(P,D,N,X,E) /* NO-OP */
|
||||
# define CODEC2(P,D,N,X,E,O) O=(char*)D
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum allowed sector size. 64KiB. If the xSectorsize() method
|
||||
** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
|
||||
@@ -705,12 +691,6 @@ struct Pager {
|
||||
#endif
|
||||
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
|
||||
int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
|
||||
void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
|
||||
void (*xCodecFree)(void*); /* Destructor for the codec */
|
||||
void *pCodec; /* First argument to xCodec... methods */
|
||||
#endif
|
||||
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
|
||||
PCache *pPCache; /* Pointer to page cache object */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
@@ -837,9 +817,6 @@ static const unsigned char aJournalMagic[] = {
|
||||
int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
|
||||
if( pPager->fd->pMethods==0 ) return 0;
|
||||
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( pPager->xCodec!=0 ) return 0;
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
if( pPager->pWal ){
|
||||
u32 iRead = 0;
|
||||
@@ -1073,11 +1050,7 @@ static void setGetterMethod(Pager *pPager){
|
||||
if( pPager->errCode ){
|
||||
pPager->xGet = getPageError;
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
}else if( USEFETCH(pPager)
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
&& pPager->xCodec==0
|
||||
#endif
|
||||
){
|
||||
}else if( USEFETCH(pPager) ){
|
||||
pPager->xGet = getPageMMap;
|
||||
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
||||
}else{
|
||||
@@ -2225,35 +2198,6 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
|
||||
return cksum;
|
||||
}
|
||||
|
||||
/*
|
||||
** Report the current page size and number of reserved bytes back
|
||||
** to the codec.
|
||||
*/
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
static void pagerReportSize(Pager *pPager){
|
||||
if( pPager->xCodecSizeChng ){
|
||||
pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
|
||||
(int)pPager->nReserve);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define pagerReportSize(X) /* No-op if we do not support a codec */
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/*
|
||||
** Make sure the number of reserved bits is the same in the destination
|
||||
** pager as it is in the source. This comes up when a VACUUM changes the
|
||||
** number of reserved bits to the "optimal" amount.
|
||||
*/
|
||||
void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
|
||||
if( pDest->nReserve!=pSrc->nReserve ){
|
||||
pDest->nReserve = pSrc->nReserve;
|
||||
pagerReportSize(pDest);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Read a single page from either the journal file (if isMainJrnl==1) or
|
||||
** from the sub-journal (if isMainJrnl==0) and playback that page.
|
||||
@@ -2305,11 +2249,6 @@ static int pager_playback_one_page(
|
||||
char *aData; /* Temporary storage for the page */
|
||||
sqlite3_file *jfd; /* The file descriptor for the journal file */
|
||||
int isSynced; /* True if journal page is synced */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/* The jrnlEnc flag is true if Journal pages should be passed through
|
||||
** the codec. It is false for pure in-memory journals. */
|
||||
const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
|
||||
#endif
|
||||
|
||||
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
|
||||
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
|
||||
@@ -2372,7 +2311,6 @@ static int pager_playback_one_page(
|
||||
*/
|
||||
if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
|
||||
pPager->nReserve = ((u8*)aData)[20];
|
||||
pagerReportSize(pPager);
|
||||
}
|
||||
|
||||
/* If the pager is in CACHEMOD state, then there must be a copy of this
|
||||
@@ -2440,26 +2378,12 @@ static int pager_playback_one_page(
|
||||
** is if the data was just read from an in-memory sub-journal. In that
|
||||
** case it must be encrypted here before it is copied into the database
|
||||
** file. */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( !jrnlEnc ){
|
||||
CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
|
||||
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
|
||||
CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
|
||||
}else
|
||||
#endif
|
||||
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
|
||||
|
||||
if( pgno>pPager->dbFileSize ){
|
||||
pPager->dbFileSize = pgno;
|
||||
}
|
||||
if( pPager->pBackup ){
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( jrnlEnc ){
|
||||
CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
|
||||
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
||||
CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
|
||||
}else
|
||||
#endif
|
||||
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
||||
}
|
||||
}else if( !isMainJrnl && pPg==0 ){
|
||||
@@ -2510,11 +2434,6 @@ static int pager_playback_one_page(
|
||||
if( pgno==1 ){
|
||||
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
|
||||
}
|
||||
|
||||
/* Decode the page just read from disk */
|
||||
#if SQLITE_HAS_CODEC
|
||||
if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
|
||||
#endif
|
||||
sqlite3PcacheRelease(pPg);
|
||||
}
|
||||
return rc;
|
||||
@@ -2617,9 +2536,12 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
/* One of the journals pointed to by the master journal exists.
|
||||
** Open it and check if it points at the master journal. If
|
||||
** so, return without deleting the master journal file.
|
||||
** NB: zJournal is really a MAIN_JOURNAL. But call it a
|
||||
** MASTER_JOURNAL here so that the VFS will not send the zJournal
|
||||
** name into sqlite3_database_file_object().
|
||||
*/
|
||||
int c;
|
||||
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
|
||||
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
|
||||
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto delmaster_out;
|
||||
@@ -3074,8 +2996,6 @@ static int readDbPage(PgHdr *pPg){
|
||||
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
|
||||
}
|
||||
}
|
||||
CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
|
||||
|
||||
PAGER_INCR(sqlite3_pager_readdb_count);
|
||||
PAGER_INCR(pPager->nRead);
|
||||
IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
|
||||
@@ -3819,7 +3739,6 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
|
||||
if( nReserve<0 ) nReserve = pPager->nReserve;
|
||||
assert( nReserve>=0 && nReserve<1000 );
|
||||
pPager->nReserve = (i16)nReserve;
|
||||
pagerReportSize(pPager);
|
||||
pagerFixMaplimit(pPager);
|
||||
}
|
||||
return rc;
|
||||
@@ -4215,11 +4134,6 @@ int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
|
||||
sqlite3OsClose(pPager->fd);
|
||||
sqlite3PageFree(pTmp);
|
||||
sqlite3PcacheClose(pPager->pPCache);
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
|
||||
#endif
|
||||
|
||||
assert( !pPager->aSavepoint && !pPager->pInJournal );
|
||||
assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
|
||||
|
||||
@@ -4470,8 +4384,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
|
||||
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
|
||||
if( pList->pgno==1 ) pager_write_changecounter(pList);
|
||||
|
||||
/* Encode the database */
|
||||
CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData);
|
||||
pData = pList->pData;
|
||||
|
||||
/* Write out the page data. */
|
||||
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
|
||||
@@ -4560,12 +4473,6 @@ static int subjournalPage(PgHdr *pPg){
|
||||
void *pData = pPg->pData;
|
||||
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
|
||||
char *pData2;
|
||||
|
||||
#if SQLITE_HAS_CODEC
|
||||
if( !pPager->subjInMemory ){
|
||||
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
|
||||
}else
|
||||
#endif
|
||||
pData2 = pData;
|
||||
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
|
||||
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
|
||||
@@ -4838,30 +4745,55 @@ int sqlite3PagerOpen(
|
||||
** Database file handle (pVfs->szOsFile bytes)
|
||||
** Sub-journal file handle (journalFileSize bytes)
|
||||
** Main journal file handle (journalFileSize bytes)
|
||||
** \0\1\0 journal prefix (3 bytes)
|
||||
** Journal filename (nPathname+8+1 bytes)
|
||||
** \2\0 WAL prefix (2 bytes)
|
||||
** WAL filename (nPathname+4+1 bytes)
|
||||
** \3\0 database prefix (2 bytes)
|
||||
** Ptr back to the Pager (sizeof(Pager*) bytes)
|
||||
** \0\0\0\0 database prefix (4 bytes)
|
||||
** Database file name (nPathname+1 bytes)
|
||||
** URI query parameters (nUriByte bytes)
|
||||
** \0\0 terminator (2 bytes)
|
||||
** Journal filename (nPathname+8+1 bytes)
|
||||
** WAL filename (nPathname+4+1 bytes)
|
||||
** \0\0\0 terminator (3 bytes)
|
||||
**
|
||||
** Some 3rd-party software, over which we have no control, depends on
|
||||
** the specific order of the filenames and the \0 separators between them
|
||||
** so that it can (for example) find the database filename given the WAL
|
||||
** filename without using the sqlite3_filename_database() API. This is a
|
||||
** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
|
||||
** software is in widespread use, so we try to avoid changing the filename
|
||||
** order and formatting if possible. In particular, the details of the
|
||||
** filename format expected by 3rd-party software should be as follows:
|
||||
**
|
||||
** - Main Database Path
|
||||
** - \0
|
||||
** - Multiple URI components consisting of:
|
||||
** - Key
|
||||
** - \0
|
||||
** - Value
|
||||
** - \0
|
||||
** - \0
|
||||
** - Journal Path
|
||||
** - \0
|
||||
** - WAL Path (zWALName)
|
||||
** - \0
|
||||
**
|
||||
** The sqlite3_create_filename() interface and the databaseFilename() utility
|
||||
** that is used by sqlite3_filename_database() and kin also depend on the
|
||||
** specific formatting and order of the various filenames, so if the format
|
||||
** changes here, be sure to change it there as well.
|
||||
*/
|
||||
pPtr = (u8 *)sqlite3MallocZero(
|
||||
ROUND8(sizeof(*pPager)) + /* Pager structure */
|
||||
ROUND8(pcacheSize) + /* PCache object */
|
||||
ROUND8(pVfs->szOsFile) + /* The main db file */
|
||||
journalFileSize * 2 + /* The two journal files */
|
||||
3 + /* Journal prefix */
|
||||
nPathname + 8 + 1 + /* Journal filename */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
2 + /* WAL prefix */
|
||||
nPathname + 4 + 1 + /* WAL filename */
|
||||
#endif
|
||||
2 + /* Database prefix */
|
||||
sizeof(pPager) + /* Space to hold a pointer */
|
||||
4 + /* Database prefix */
|
||||
nPathname + 1 + /* database filename */
|
||||
nUriByte + /* query parameters */
|
||||
2 /* Terminator */
|
||||
nPathname + 8 + 1 + /* Journal filename */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
nPathname + 4 + 1 + /* WAL filename */
|
||||
#endif
|
||||
3 /* Terminator */
|
||||
);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
|
||||
if( !pPtr ){
|
||||
@@ -4874,10 +4806,22 @@ int sqlite3PagerOpen(
|
||||
pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
||||
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
|
||||
memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
|
||||
|
||||
/* Fill in the Pager.zFilename and pPager.zQueryParam fields */
|
||||
pPtr += 4; /* Skip zero prefix */
|
||||
pPager->zFilename = (char*)pPtr;
|
||||
if( nPathname>0 ){
|
||||
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
|
||||
if( zUri ){
|
||||
memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte;
|
||||
}else{
|
||||
pPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Fill in Pager.zJournal */
|
||||
pPtr[1] = '\001'; pPtr += 3;
|
||||
if( nPathname>0 ){
|
||||
pPager->zJournal = (char*)pPtr;
|
||||
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
|
||||
@@ -4888,12 +4832,10 @@ int sqlite3PagerOpen(
|
||||
#endif
|
||||
}else{
|
||||
pPager->zJournal = 0;
|
||||
pPtr++;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/* Fill in Pager.zWal */
|
||||
pPtr[0] = '\002'; pPtr[1] = 0; pPtr += 2;
|
||||
if( nPathname>0 ){
|
||||
pPager->zWal = (char*)pPtr;
|
||||
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
|
||||
@@ -4904,21 +4846,9 @@ int sqlite3PagerOpen(
|
||||
#endif
|
||||
}else{
|
||||
pPager->zWal = 0;
|
||||
pPtr++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill in the Pager.zFilename and pPager.zQueryParam fields */
|
||||
pPtr[0] = '\003'; pPtr[1] = 0; pPtr += 2;
|
||||
pPager->zFilename = (char*)pPtr;
|
||||
if( nPathname>0 ){
|
||||
memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
|
||||
if( zUri ){
|
||||
memcpy(pPtr, zUri, nUriByte); /* pPtr += nUriByte; // not needed */
|
||||
}
|
||||
/* Double-zero terminator implied by the sqlite3MallocZero */
|
||||
}
|
||||
|
||||
if( nPathname ) sqlite3DbFree(0, zPathname);
|
||||
pPager->pVfs = pVfs;
|
||||
pPager->vfsFlags = vfsFlags;
|
||||
@@ -5077,6 +5007,19 @@ act_like_temp_file:
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the sqlite3_file for the main database given the name
|
||||
** of the corresonding WAL or Journal name as passed into
|
||||
** xOpen.
|
||||
*/
|
||||
sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
Pager *pPager;
|
||||
while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
|
||||
zName--;
|
||||
}
|
||||
pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
|
||||
return pPager->fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -5632,9 +5575,6 @@ static int getPageMMap(
|
||||
);
|
||||
|
||||
assert( USEFETCH(pPager) );
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
assert( pPager->xCodec==0 );
|
||||
#endif
|
||||
|
||||
/* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
|
||||
** allows the compiler optimizer to reuse the results of the "pgno>1"
|
||||
@@ -5963,7 +5903,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
|
||||
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
|
||||
|
||||
assert( pPager->journalHdr<=pPager->journalOff );
|
||||
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
|
||||
pData2 = pPg->pData;
|
||||
cksum = pager_cksum(pPager, (u8*)pData2);
|
||||
|
||||
/* Even if an IO or diskfull error occurs while journalling the
|
||||
@@ -6328,7 +6268,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
||||
if( DIRECT_MODE ){
|
||||
const void *zBuf;
|
||||
assert( pPager->dbFileSize>0 );
|
||||
CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf);
|
||||
zBuf = pPgHdr->pData;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
|
||||
pPager->aStat[PAGER_STAT_WRITE]++;
|
||||
@@ -7038,8 +6978,8 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
|
||||
** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
|
||||
*/
|
||||
const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
|
||||
static const char zFake[] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
|
||||
return (nullIfMemDb && pPager->memDb) ? &zFake[3] : pPager->zFilename;
|
||||
static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -7087,54 +7027,6 @@ const char *sqlite3PagerJournalname(Pager *pPager){
|
||||
return pPager->zJournal;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/*
|
||||
** Set or retrieve the codec for this pager
|
||||
*/
|
||||
void sqlite3PagerSetCodec(
|
||||
Pager *pPager,
|
||||
void *(*xCodec)(void*,void*,Pgno,int),
|
||||
void (*xCodecSizeChng)(void*,int,int),
|
||||
void (*xCodecFree)(void*),
|
||||
void *pCodec
|
||||
){
|
||||
if( pPager->xCodecFree ){
|
||||
pPager->xCodecFree(pPager->pCodec);
|
||||
}else{
|
||||
pager_reset(pPager);
|
||||
}
|
||||
pPager->xCodec = pPager->memDb ? 0 : xCodec;
|
||||
pPager->xCodecSizeChng = xCodecSizeChng;
|
||||
pPager->xCodecFree = xCodecFree;
|
||||
pPager->pCodec = pCodec;
|
||||
setGetterMethod(pPager);
|
||||
pagerReportSize(pPager);
|
||||
}
|
||||
void *sqlite3PagerGetCodec(Pager *pPager){
|
||||
return pPager->pCodec;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called by the wal module when writing page content
|
||||
** into the log file.
|
||||
**
|
||||
** This function returns a pointer to a buffer containing the encrypted
|
||||
** page content. If a malloc fails, this function may return NULL.
|
||||
*/
|
||||
void *sqlite3PagerCodec(PgHdr *pPg){
|
||||
void *aData = 0;
|
||||
CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
|
||||
return aData;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current pager state
|
||||
*/
|
||||
int sqlite3PagerState(Pager *pPager){
|
||||
return pPager->eState;
|
||||
}
|
||||
#endif /* SQLITE_HAS_CODEC */
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
/*
|
||||
** Move the page pPg to location pgno in the file.
|
||||
|
||||
@@ -128,9 +128,6 @@ int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
|
||||
/* Functions used to configure a Pager object. */
|
||||
void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
|
||||
int sqlite3PagerSetPagesize(Pager*, u32*, int);
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
void sqlite3PagerAlignReserve(Pager*,Pager*);
|
||||
#endif
|
||||
int sqlite3PagerMaxPageCount(Pager*, int);
|
||||
void sqlite3PagerSetCachesize(Pager*, int);
|
||||
int sqlite3PagerSetSpillsize(Pager*, int);
|
||||
@@ -224,10 +221,6 @@ void sqlite3PagerTruncateImage(Pager*,Pgno);
|
||||
|
||||
void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
||||
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
|
||||
void *sqlite3PagerCodec(DbPage *);
|
||||
#endif
|
||||
|
||||
/* Functions to support testing and debugging. */
|
||||
#if !defined(NDEBUG) || defined(SQLITE_TEST)
|
||||
Pgno sqlite3PagerPagenumber(DbPage*);
|
||||
|
||||
@@ -965,6 +965,7 @@ idlist(A) ::= nm(Y).
|
||||
p->op = (u8)op;
|
||||
p->affExpr = 0;
|
||||
p->flags = EP_Leaf;
|
||||
ExprClearVVAProperties(p);
|
||||
p->iAgg = -1;
|
||||
p->pLeft = p->pRight = 0;
|
||||
p->x.pList = 0;
|
||||
@@ -1193,6 +1194,13 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
*/
|
||||
sqlite3ExprUnmapAndDelete(pParse, A);
|
||||
A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0");
|
||||
}else if( Y->nExpr==1 && sqlite3ExprIsConstant(Y->a[0].pExpr) ){
|
||||
Expr *pRHS = Y->a[0].pExpr;
|
||||
Y->a[0].pExpr = 0;
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
|
||||
A = sqlite3PExpr(pParse, TK_EQ, A, pRHS);
|
||||
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
|
||||
}else{
|
||||
A = sqlite3PExpr(pParse, TK_IN, A, 0);
|
||||
if( A ){
|
||||
|
||||
+5
-62
@@ -1824,21 +1824,12 @@ void sqlite3Pragma(
|
||||
** will be overwritten when the schema is next loaded. If it does not
|
||||
** already exists, it will be created to use the new encoding value.
|
||||
*/
|
||||
int canChangeEnc = 1; /* True if allowed to change the encoding */
|
||||
int i; /* For looping over all attached databases */
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( db->aDb[i].pBt!=0
|
||||
&& DbHasProperty(db,i,DB_SchemaLoaded)
|
||||
&& !DbHasProperty(db,i,DB_Empty)
|
||||
){
|
||||
canChangeEnc = 0;
|
||||
}
|
||||
}
|
||||
if( canChangeEnc ){
|
||||
if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
|
||||
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
|
||||
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
|
||||
SCHEMA_ENC(db) = ENC(db) =
|
||||
pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
||||
u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
||||
SCHEMA_ENC(db) = enc;
|
||||
sqlite3SetTextEncoding(db, enc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2215,59 +2206,11 @@ void sqlite3Pragma(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/* Pragma iArg
|
||||
** ---------- ------
|
||||
** key 0
|
||||
** rekey 1
|
||||
** hexkey 2
|
||||
** hexrekey 3
|
||||
** textkey 4
|
||||
** textrekey 5
|
||||
*/
|
||||
case PragTyp_KEY: {
|
||||
if( zRight ){
|
||||
char zBuf[40];
|
||||
const char *zKey = zRight;
|
||||
int n;
|
||||
if( pPragma->iArg==2 || pPragma->iArg==3 ){
|
||||
u8 iByte;
|
||||
int i;
|
||||
for(i=0, iByte=0; i<sizeof(zBuf)*2 && sqlite3Isxdigit(zRight[i]); i++){
|
||||
iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
|
||||
if( (i&1)!=0 ) zBuf[i/2] = iByte;
|
||||
}
|
||||
zKey = zBuf;
|
||||
n = i/2;
|
||||
}else{
|
||||
n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1;
|
||||
}
|
||||
if( (pPragma->iArg & 1)==0 ){
|
||||
rc = sqlite3_key_v2(db, zDb, zKey, n);
|
||||
}else{
|
||||
rc = sqlite3_rekey_v2(db, zDb, zKey, n);
|
||||
}
|
||||
if( rc==SQLITE_OK && n!=0 ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "ok", SQLITE_STATIC);
|
||||
returnSingleText(v, "ok");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
||||
#if defined(SQLITE_ENABLE_CEROD)
|
||||
case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
|
||||
sqlite3_activate_see(&zRight[4]);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
|
||||
sqlite3_activate_cerod(&zRight[6]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
+46
-87
@@ -5,51 +5,50 @@
|
||||
*/
|
||||
|
||||
/* The various pragma types */
|
||||
#define PragTyp_HEADER_VALUE 0
|
||||
#define PragTyp_AUTO_VACUUM 1
|
||||
#define PragTyp_FLAG 2
|
||||
#define PragTyp_BUSY_TIMEOUT 3
|
||||
#define PragTyp_CACHE_SIZE 4
|
||||
#define PragTyp_CACHE_SPILL 5
|
||||
#define PragTyp_CASE_SENSITIVE_LIKE 6
|
||||
#define PragTyp_COLLATION_LIST 7
|
||||
#define PragTyp_COMPILE_OPTIONS 8
|
||||
#define PragTyp_DATA_STORE_DIRECTORY 9
|
||||
#define PragTyp_DATABASE_LIST 10
|
||||
#define PragTyp_DEFAULT_CACHE_SIZE 11
|
||||
#define PragTyp_ENCODING 12
|
||||
#define PragTyp_FOREIGN_KEY_CHECK 13
|
||||
#define PragTyp_FOREIGN_KEY_LIST 14
|
||||
#define PragTyp_FUNCTION_LIST 15
|
||||
#define PragTyp_HARD_HEAP_LIMIT 16
|
||||
#define PragTyp_INCREMENTAL_VACUUM 17
|
||||
#define PragTyp_INDEX_INFO 18
|
||||
#define PragTyp_INDEX_LIST 19
|
||||
#define PragTyp_INTEGRITY_CHECK 20
|
||||
#define PragTyp_JOURNAL_MODE 21
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 22
|
||||
#define PragTyp_LOCK_PROXY_FILE 23
|
||||
#define PragTyp_LOCKING_MODE 24
|
||||
#define PragTyp_PAGE_COUNT 25
|
||||
#define PragTyp_MMAP_SIZE 26
|
||||
#define PragTyp_MODULE_LIST 27
|
||||
#define PragTyp_OPTIMIZE 28
|
||||
#define PragTyp_PAGE_SIZE 29
|
||||
#define PragTyp_PRAGMA_LIST 30
|
||||
#define PragTyp_SECURE_DELETE 31
|
||||
#define PragTyp_SHRINK_MEMORY 32
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 33
|
||||
#define PragTyp_SYNCHRONOUS 34
|
||||
#define PragTyp_TABLE_INFO 35
|
||||
#define PragTyp_TEMP_STORE 36
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 37
|
||||
#define PragTyp_THREADS 38
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 39
|
||||
#define PragTyp_WAL_CHECKPOINT 40
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 41
|
||||
#define PragTyp_KEY 42
|
||||
#define PragTyp_LOCK_STATUS 43
|
||||
#define PragTyp_STATS 44
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 0
|
||||
#define PragTyp_HEADER_VALUE 1
|
||||
#define PragTyp_AUTO_VACUUM 2
|
||||
#define PragTyp_FLAG 3
|
||||
#define PragTyp_BUSY_TIMEOUT 4
|
||||
#define PragTyp_CACHE_SIZE 5
|
||||
#define PragTyp_CACHE_SPILL 6
|
||||
#define PragTyp_CASE_SENSITIVE_LIKE 7
|
||||
#define PragTyp_COLLATION_LIST 8
|
||||
#define PragTyp_COMPILE_OPTIONS 9
|
||||
#define PragTyp_DATA_STORE_DIRECTORY 10
|
||||
#define PragTyp_DATABASE_LIST 11
|
||||
#define PragTyp_DEFAULT_CACHE_SIZE 12
|
||||
#define PragTyp_ENCODING 13
|
||||
#define PragTyp_FOREIGN_KEY_CHECK 14
|
||||
#define PragTyp_FOREIGN_KEY_LIST 15
|
||||
#define PragTyp_FUNCTION_LIST 16
|
||||
#define PragTyp_HARD_HEAP_LIMIT 17
|
||||
#define PragTyp_INCREMENTAL_VACUUM 18
|
||||
#define PragTyp_INDEX_INFO 19
|
||||
#define PragTyp_INDEX_LIST 20
|
||||
#define PragTyp_INTEGRITY_CHECK 21
|
||||
#define PragTyp_JOURNAL_MODE 22
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 23
|
||||
#define PragTyp_LOCK_PROXY_FILE 24
|
||||
#define PragTyp_LOCKING_MODE 25
|
||||
#define PragTyp_PAGE_COUNT 26
|
||||
#define PragTyp_MMAP_SIZE 27
|
||||
#define PragTyp_MODULE_LIST 28
|
||||
#define PragTyp_OPTIMIZE 29
|
||||
#define PragTyp_PAGE_SIZE 30
|
||||
#define PragTyp_PRAGMA_LIST 31
|
||||
#define PragTyp_SECURE_DELETE 32
|
||||
#define PragTyp_SHRINK_MEMORY 33
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 34
|
||||
#define PragTyp_SYNCHRONOUS 35
|
||||
#define PragTyp_TABLE_INFO 36
|
||||
#define PragTyp_TEMP_STORE 37
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 38
|
||||
#define PragTyp_THREADS 39
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 40
|
||||
#define PragTyp_WAL_CHECKPOINT 41
|
||||
#define PragTyp_LOCK_STATUS 42
|
||||
#define PragTyp_STATS 43
|
||||
|
||||
/* Property flags associated with various pragma. */
|
||||
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
|
||||
@@ -133,7 +132,7 @@ typedef struct PragmaName {
|
||||
u64 iArg; /* Extra argument */
|
||||
} PragmaName;
|
||||
static const PragmaName aPragmaName[] = {
|
||||
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
||||
#if defined(SQLITE_ENABLE_CEROD)
|
||||
{/* zName: */ "activate_extensions",
|
||||
/* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
|
||||
/* ePragFlg: */ 0,
|
||||
@@ -329,18 +328,6 @@ static const PragmaName aPragmaName[] = {
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
{/* zName: */ "hexkey",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 2 },
|
||||
{/* zName: */ "hexrekey",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 3 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
#if !defined(SQLITE_OMIT_CHECK)
|
||||
{/* zName: */ "ignore_check_constraints",
|
||||
@@ -393,13 +380,6 @@ static const PragmaName aPragmaName[] = {
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
{/* zName: */ "key",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
{/* zName: */ "legacy_alter_table",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
@@ -507,15 +487,6 @@ static const PragmaName aPragmaName[] = {
|
||||
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ SQLITE_RecTriggers },
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
{/* zName: */ "rekey",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 1 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
{/* zName: */ "reverse_unordered_selects",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
||||
@@ -599,18 +570,6 @@ static const PragmaName aPragmaName[] = {
|
||||
/* ePragFlg: */ PragFlg_NoColumns1,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
{/* zName: */ "textkey",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 4 },
|
||||
{/* zName: */ "textrekey",
|
||||
/* ePragTyp: */ PragTyp_KEY,
|
||||
/* ePragFlg: */ 0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 5 },
|
||||
#endif
|
||||
{/* zName: */ "threads",
|
||||
/* ePragTyp: */ PragTyp_THREADS,
|
||||
@@ -680,4 +639,4 @@ static const PragmaName aPragmaName[] = {
|
||||
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 66 on by default, 82 total. */
|
||||
/* Number of pragmas: 66 on by default, 76 total. */
|
||||
|
||||
+9
-10
@@ -91,7 +91,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
assert( argc==5 );
|
||||
UNUSED_PARAMETER2(NotUsed, argc);
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
DbClearProperty(db, iDb, DB_Empty);
|
||||
db->mDbFlags |= DBFLAG_EncodingFixed;
|
||||
pData->nInitRow++;
|
||||
if( db->mallocFailed ){
|
||||
corruptSchema(pData, argv[1], 0);
|
||||
@@ -179,6 +179,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
InitData initData;
|
||||
const char *zMasterName;
|
||||
int openedTransaction = 0;
|
||||
int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed);
|
||||
|
||||
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
@@ -207,6 +208,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
initData.mInitFlags = mFlags;
|
||||
initData.nInitRow = 0;
|
||||
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
|
||||
db->mDbFlags &= mask;
|
||||
if( initData.rc ){
|
||||
rc = initData.rc;
|
||||
goto error_out;
|
||||
@@ -266,27 +268,25 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
** as sqlite3.enc.
|
||||
*/
|
||||
if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
|
||||
if( iDb==0 ){
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
|
||||
u8 encoding;
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/* If opening the main database, set ENC(db). */
|
||||
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
|
||||
if( encoding==0 ) encoding = SQLITE_UTF8;
|
||||
ENC(db) = encoding;
|
||||
#else
|
||||
ENC(db) = SQLITE_UTF8;
|
||||
encoding = SQLITE_UTF8;
|
||||
#endif
|
||||
sqlite3SetTextEncoding(db, encoding);
|
||||
}else{
|
||||
/* If opening an attached database, the encoding much match ENC(db) */
|
||||
if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
|
||||
if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
|
||||
sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
|
||||
" text encoding as main database");
|
||||
rc = SQLITE_ERROR;
|
||||
goto initone_error_out;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
DbSetProperty(db, iDb, DB_Empty);
|
||||
}
|
||||
pDb->pSchema->enc = ENC(db);
|
||||
|
||||
@@ -398,8 +398,7 @@ error_out:
|
||||
** error occurs, write an error message into *pzErrMsg.
|
||||
**
|
||||
** After a database is initialized, the DB_SchemaLoaded bit is set
|
||||
** bit is set in the flags field of the Db structure. If the database
|
||||
** file was of zero-length, then the DB_Empty flag is also set.
|
||||
** bit is set in the flags field of the Db structure.
|
||||
*/
|
||||
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
int i, rc;
|
||||
|
||||
+73
-24
@@ -140,7 +140,7 @@ int sqlite3MatchEName(
|
||||
){
|
||||
int n;
|
||||
const char *zSpan;
|
||||
if( NEVER(pItem->eEName!=ENAME_TAB) ) return 0;
|
||||
if( pItem->eEName!=ENAME_TAB ) return 0;
|
||||
zSpan = pItem->zEName;
|
||||
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
||||
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
|
||||
@@ -175,6 +175,31 @@ static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is guaranteed to be a non-NULL Expr node of type TK_COLUMN.
|
||||
** return the appropriate colUsed mask.
|
||||
*/
|
||||
Bitmask sqlite3ExprColUsed(Expr *pExpr){
|
||||
int n;
|
||||
Table *pExTab;
|
||||
|
||||
n = pExpr->iColumn;
|
||||
pExTab = pExpr->y.pTab;
|
||||
assert( pExTab!=0 );
|
||||
if( (pExTab->tabFlags & TF_HasGenerated)!=0
|
||||
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
|
||||
){
|
||||
testcase( pExTab->nCol==BMS-1 );
|
||||
testcase( pExTab->nCol==BMS );
|
||||
return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
|
||||
}else{
|
||||
testcase( n==BMS-1 );
|
||||
testcase( n==BMS );
|
||||
if( n>=BMS ) n = BMS-1;
|
||||
return ((Bitmask)1)<<n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
|
||||
** that name in the set of source tables in pSrcList and make the pExpr
|
||||
@@ -252,6 +277,12 @@ static int lookupName(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i==db->nDb && sqlite3StrICmp("main", zDb)==0 ){
|
||||
/* This branch is taken when the main database has been renamed
|
||||
** using SQLITE_DBCONFIG_MAINDBNAME. */
|
||||
pSchema = db->aDb[0].pSchema;
|
||||
zDb = db->aDb[0].zDbSName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +294,7 @@ static int lookupName(
|
||||
|
||||
if( pSrcList ){
|
||||
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
|
||||
u8 hCol;
|
||||
pTab = pItem->pTab;
|
||||
assert( pTab!=0 && pTab->zName!=0 );
|
||||
assert( pTab->nCol>0 );
|
||||
@@ -296,8 +328,9 @@ static int lookupName(
|
||||
if( 0==(cntTab++) ){
|
||||
pMatch = pItem;
|
||||
}
|
||||
hCol = sqlite3StrIHash(zCol);
|
||||
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
/* If there has been exactly one prior match and this match
|
||||
** is for the right-hand table of a NATURAL JOIN or is in a
|
||||
** USING clause, then skip this match.
|
||||
@@ -358,10 +391,11 @@ static int lookupName(
|
||||
|
||||
if( pTab ){
|
||||
int iCol;
|
||||
u8 hCol = sqlite3StrIHash(zCol);
|
||||
pSchema = pTab->pSchema;
|
||||
cntTab++;
|
||||
for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
if( iCol==pTab->iPKey ){
|
||||
iCol = -1;
|
||||
}
|
||||
@@ -571,22 +605,7 @@ static int lookupName(
|
||||
** of the table.
|
||||
*/
|
||||
if( pExpr->iColumn>=0 && pMatch!=0 ){
|
||||
int n = pExpr->iColumn;
|
||||
Table *pExTab = pExpr->y.pTab;
|
||||
assert( pExTab!=0 );
|
||||
assert( pMatch->iCursor==pExpr->iTable );
|
||||
if( (pExTab->tabFlags & TF_HasGenerated)!=0
|
||||
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
|
||||
){
|
||||
testcase( pExTab->nCol==BMS-1 );
|
||||
testcase( pExTab->nCol==BMS );
|
||||
pMatch->colUsed = pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
|
||||
}else{
|
||||
testcase( n==BMS-1 );
|
||||
testcase( n==BMS );
|
||||
if( n>=BMS ) n = BMS-1;
|
||||
pMatch->colUsed |= ((Bitmask)1)<<n;
|
||||
}
|
||||
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
|
||||
}
|
||||
|
||||
/* Clean up and return
|
||||
@@ -1051,7 +1070,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
assert( !ExprHasProperty(pExpr, EP_Reduced) );
|
||||
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
|
||||
** and "x IS NOT FALSE". */
|
||||
if( pRight->op==TK_ID ){
|
||||
if( pRight && pRight->op==TK_ID ){
|
||||
int rc = resolveExprStep(pWalker, pRight);
|
||||
if( rc==WRC_Abort ) return WRC_Abort;
|
||||
if( pRight->op==TK_TRUEFALSE ){
|
||||
@@ -1177,7 +1196,7 @@ static int resolveOrderByTermToExprList(
|
||||
nc.nErr = 0;
|
||||
db = pParse->db;
|
||||
savedSuppErr = db->suppressErr;
|
||||
db->suppressErr = 1;
|
||||
if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
|
||||
rc = sqlite3ResolveExprNames(&nc, pE);
|
||||
db->suppressErr = savedSuppErr;
|
||||
if( rc ) return 0;
|
||||
@@ -1812,11 +1831,41 @@ int sqlite3ResolveExprListNames(
|
||||
ExprList *pList /* The expression list to be analyzed. */
|
||||
){
|
||||
int i;
|
||||
if( pList ){
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
|
||||
int savedHasAgg = 0;
|
||||
Walker w;
|
||||
if( pList==0 ) return WRC_Continue;
|
||||
w.pParse = pNC->pParse;
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
w.xSelectCallback2 = 0;
|
||||
w.u.pNC = pNC;
|
||||
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
Expr *pExpr = pList->a[i].pExpr;
|
||||
if( pExpr==0 ) continue;
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
w.pParse->nHeight += pExpr->nHeight;
|
||||
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
#endif
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
w.pParse->nHeight -= pExpr->nHeight;
|
||||
#endif
|
||||
assert( EP_Agg==NC_HasAgg );
|
||||
assert( EP_Win==NC_HasWin );
|
||||
testcase( pNC->ncFlags & NC_HasAgg );
|
||||
testcase( pNC->ncFlags & NC_HasWin );
|
||||
if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
|
||||
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
|
||||
savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
||||
}
|
||||
if( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
|
||||
}
|
||||
pNC->ncFlags |= savedHasAgg;
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -177,7 +177,7 @@ void sqlite3RowSetDelete(void *pArg){
|
||||
/*
|
||||
** Allocate a new RowSetEntry object that is associated with the
|
||||
** given RowSet. Return a pointer to the new and completely uninitialized
|
||||
** objected.
|
||||
** object.
|
||||
**
|
||||
** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
|
||||
** routine returns NULL.
|
||||
@@ -453,7 +453,7 @@ int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
|
||||
if( p ){
|
||||
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
|
||||
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
/* Only sort the current set of entiries if they need it */
|
||||
/* Only sort the current set of entries if they need it */
|
||||
p = rowSetEntrySort(p);
|
||||
}
|
||||
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
|
||||
|
||||
+54
-12
@@ -103,7 +103,6 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
|
||||
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
|
||||
sqlite3WindowListDelete(db, p->pWinDefn);
|
||||
}
|
||||
assert( p->pWin==0 );
|
||||
#endif
|
||||
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
|
||||
if( bFree ) sqlite3DbFreeNN(db, p);
|
||||
@@ -2024,6 +2023,7 @@ int sqlite3ColumnsFromExprList(
|
||||
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
|
||||
}
|
||||
pCol->zName = zName;
|
||||
pCol->hName = sqlite3StrIHash(zName);
|
||||
sqlite3ColumnPropertiesFromName(0, pCol);
|
||||
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
|
||||
sqlite3OomFault(db);
|
||||
@@ -2806,6 +2806,7 @@ static int multiSelect(
|
||||
/* Generate code to take the intersection of the two temporary
|
||||
** tables.
|
||||
*/
|
||||
if( rc ) break;
|
||||
assert( p->pEList );
|
||||
iBreak = sqlite3VdbeMakeLabel(pParse);
|
||||
iCont = sqlite3VdbeMakeLabel(pParse);
|
||||
@@ -3476,7 +3477,10 @@ static Expr *substExpr(
|
||||
){
|
||||
pExpr->iRightJoinTable = pSubst->iNewTable;
|
||||
}
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
|
||||
if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iTable==pSubst->iTable
|
||||
&& !ExprHasProperty(pExpr, EP_FixedCol)
|
||||
){
|
||||
if( pExpr->iColumn<0 ){
|
||||
pExpr->op = TK_NULL;
|
||||
}else{
|
||||
@@ -3494,6 +3498,7 @@ static Expr *substExpr(
|
||||
ifNullRow.op = TK_IF_NULL_ROW;
|
||||
ifNullRow.pLeft = pCopy;
|
||||
ifNullRow.iTable = pSubst->iNewTable;
|
||||
ifNullRow.flags = EP_Skip;
|
||||
pCopy = &ifNullRow;
|
||||
}
|
||||
testcase( ExprHasProperty(pCopy, EP_Subquery) );
|
||||
@@ -3580,6 +3585,38 @@ static void substSelect(
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
/*
|
||||
** pSelect is a SELECT statement and pSrcItem is one item in the FROM
|
||||
** clause of that SELECT.
|
||||
**
|
||||
** This routine scans the entire SELECT statement and recomputes the
|
||||
** pSrcItem->colUsed mask.
|
||||
*/
|
||||
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
|
||||
struct SrcList_item *pItem;
|
||||
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
|
||||
pItem = pWalker->u.pSrcItem;
|
||||
if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
|
||||
if( pExpr->iColumn<0 ) return WRC_Continue;
|
||||
pItem->colUsed |= sqlite3ExprColUsed(pExpr);
|
||||
return WRC_Continue;
|
||||
}
|
||||
static void recomputeColumnsUsed(
|
||||
Select *pSelect, /* The complete SELECT statement */
|
||||
struct SrcList_item *pSrcItem /* Which FROM clause item to recompute */
|
||||
){
|
||||
Walker w;
|
||||
if( NEVER(pSrcItem->pTab==0) ) return;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = recomputeColumnsUsedExpr;
|
||||
w.xSelectCallback = sqlite3SelectWalkNoop;
|
||||
w.u.pSrcItem = pSrcItem;
|
||||
pSrcItem->colUsed = 0;
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
/*
|
||||
** This routine attempts to flatten subqueries as a performance optimization.
|
||||
@@ -4118,6 +4155,12 @@ static int flattenSubquery(
|
||||
pParent->pLimit = pSub->pLimit;
|
||||
pSub->pLimit = 0;
|
||||
}
|
||||
|
||||
/* Recompute the SrcList_item.colUsed masks for the flattened
|
||||
** tables. */
|
||||
for(i=0; i<nSubSrc; i++){
|
||||
recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finially, delete what is left of the subquery and return
|
||||
@@ -4166,9 +4209,8 @@ static void constInsert(
|
||||
assert( pColumn->op==TK_COLUMN );
|
||||
assert( sqlite3ExprIsConstant(pValue) );
|
||||
|
||||
if( !ExprHasProperty(pValue, EP_FixedCol) && sqlite3ExprAffinity(pValue)!=0 ){
|
||||
return;
|
||||
}
|
||||
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
|
||||
if( sqlite3ExprAffinity(pValue)!=0 ) return;
|
||||
if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
|
||||
return;
|
||||
}
|
||||
@@ -4191,9 +4233,6 @@ static void constInsert(
|
||||
if( pConst->apExpr==0 ){
|
||||
pConst->nConst = 0;
|
||||
}else{
|
||||
if( ExprHasProperty(pValue, EP_FixedCol) ){
|
||||
pValue = pValue->pLeft;
|
||||
}
|
||||
pConst->apExpr[pConst->nConst*2-2] = pColumn;
|
||||
pConst->apExpr[pConst->nConst*2-1] = pValue;
|
||||
}
|
||||
@@ -4469,7 +4508,7 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
|
||||
ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
|
||||
const char *zFunc; /* Name of aggregate function pFunc */
|
||||
ExprList *pOrderBy;
|
||||
u8 sortFlags;
|
||||
u8 sortFlags = 0;
|
||||
|
||||
assert( *ppMinMax==0 );
|
||||
assert( pFunc->op==TK_AGG_FUNCTION );
|
||||
@@ -4480,7 +4519,9 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
|
||||
zFunc = pFunc->u.zToken;
|
||||
if( sqlite3StrICmp(zFunc, "min")==0 ){
|
||||
eRet = WHERE_ORDERBY_MIN;
|
||||
sortFlags = KEYINFO_ORDER_BIGNULL;
|
||||
if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){
|
||||
sortFlags = KEYINFO_ORDER_BIGNULL;
|
||||
}
|
||||
}else if( sqlite3StrICmp(zFunc, "max")==0 ){
|
||||
eRet = WHERE_ORDERBY_MAX;
|
||||
sortFlags = KEYINFO_ORDER_DESC;
|
||||
@@ -5148,7 +5189,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
|
||||
sqlite3TokenInit(&sColname, zColname);
|
||||
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
|
||||
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
|
||||
if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
|
||||
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
|
||||
sqlite3DbFree(db, pX->zEName);
|
||||
if( pSub ){
|
||||
@@ -5352,6 +5393,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
struct AggInfo_func *pFunc;
|
||||
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
|
||||
if( nReg==0 ) return;
|
||||
if( pParse->nErr ) return;
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Verify that all AggInfo registers are within the range specified by
|
||||
** AggInfo.mnReg..AggInfo.mxReg */
|
||||
@@ -5493,7 +5535,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
|
||||
|
||||
pAggInfo->directMode = 0;
|
||||
if( addrHitTest ){
|
||||
sqlite3VdbeJumpHere(v, addrHitTest);
|
||||
sqlite3VdbeJumpHereOrPopInst(v, addrHitTest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+414
-147
@@ -17,6 +17,14 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WinRT, which provides only a subset of
|
||||
** the full Win32 API.
|
||||
*/
|
||||
#if !defined(SQLITE_OS_WINRT)
|
||||
# define SQLITE_OS_WINRT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Warning pragmas copied from msvc.h in the core.
|
||||
*/
|
||||
@@ -129,22 +137,26 @@ typedef unsigned char u8;
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# define isatty(h) _isatty(h)
|
||||
# ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
# if SQLITE_OS_WINRT
|
||||
# define SQLITE_OMIT_POPEN 1
|
||||
# else
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# define isatty(h) _isatty(h)
|
||||
# ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
# endif
|
||||
# ifndef unlink
|
||||
# define unlink _unlink
|
||||
# endif
|
||||
# ifndef strdup
|
||||
# define strdup _strdup
|
||||
# endif
|
||||
# undef popen
|
||||
# define popen _popen
|
||||
# undef pclose
|
||||
# define pclose _pclose
|
||||
# endif
|
||||
# ifndef unlink
|
||||
# define unlink _unlink
|
||||
# endif
|
||||
# ifndef strdup
|
||||
# define strdup _strdup
|
||||
# endif
|
||||
# undef popen
|
||||
# define popen _popen
|
||||
# undef pclose
|
||||
# define pclose _pclose
|
||||
#else
|
||||
/* Make sure isatty() has a prototype. */
|
||||
extern int isatty(int);
|
||||
@@ -173,6 +185,9 @@ typedef unsigned char u8;
|
||||
#define ToLower(X) (char)tolower((unsigned char)X)
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
#if SQLITE_OS_WINRT
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
/* string conversion routines only needed on Win32 */
|
||||
@@ -188,7 +203,7 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
|
||||
** rendering quoted strings that contain \n characters). The following
|
||||
** routines take care of that.
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
||||
static void setBinaryMode(FILE *file, int isOutput){
|
||||
if( isOutput ) fflush(file);
|
||||
_setmode(_fileno(file), _O_BINARY);
|
||||
@@ -292,6 +307,7 @@ static int hasTimer(void){
|
||||
if( getProcessTimesAddr ){
|
||||
return 1;
|
||||
} else {
|
||||
#if !SQLITE_OS_WINRT
|
||||
/* GetProcessTimes() isn't supported in WIN95 and some other Windows
|
||||
** versions. See if the version we are running on has it, and if it
|
||||
** does, save off a pointer to it and the current process handle.
|
||||
@@ -308,6 +324,7 @@ static int hasTimer(void){
|
||||
FreeLibrary(hinstLib);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -397,6 +414,15 @@ static sqlite3 *globalDb = 0;
|
||||
*/
|
||||
static volatile int seenInterrupt = 0;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Out-of-memory simulator variables
|
||||
*/
|
||||
static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */
|
||||
static unsigned int oomRepeat = 0; /* Number of OOMs in a row */
|
||||
static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** This is the name of our program. It is set in main(), used
|
||||
** in a number of other places, mostly for error messages.
|
||||
@@ -448,6 +474,49 @@ static void shell_out_of_memory(void){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* This routine is called when a simulated OOM occurs. It is broken
|
||||
** out as a separate routine to make it easy to set a breakpoint on
|
||||
** the OOM
|
||||
*/
|
||||
void shellOomFault(void){
|
||||
if( oomRepeat>0 ){
|
||||
oomRepeat--;
|
||||
}else{
|
||||
oomCounter--;
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* This routine is a replacement malloc() that is used to simulate
|
||||
** Out-Of-Memory (OOM) errors for testing purposes.
|
||||
*/
|
||||
static void *oomMalloc(int nByte){
|
||||
if( oomCounter ){
|
||||
if( oomCounter==1 ){
|
||||
shellOomFault();
|
||||
return 0;
|
||||
}else{
|
||||
oomCounter--;
|
||||
}
|
||||
}
|
||||
return defaultMalloc(nByte);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Register the OOM simulator. This must occur before any memory
|
||||
** allocations */
|
||||
static void registerOomSimulator(void){
|
||||
sqlite3_mem_methods mem;
|
||||
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
|
||||
defaultMalloc = mem.xMalloc;
|
||||
mem.xMalloc = oomMalloc;
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Write I/O traces to the following stream.
|
||||
*/
|
||||
@@ -941,6 +1010,7 @@ INCLUDE ../ext/misc/fileio.c
|
||||
INCLUDE ../ext/misc/completion.c
|
||||
INCLUDE ../ext/misc/appendvfs.c
|
||||
INCLUDE ../ext/misc/memtrace.c
|
||||
INCLUDE ../ext/misc/uint.c
|
||||
#ifdef SQLITE_HAVE_ZLIB
|
||||
INCLUDE ../ext/misc/zipfile.c
|
||||
INCLUDE ../ext/misc/sqlar.c
|
||||
@@ -1037,6 +1107,7 @@ struct ShellState {
|
||||
unsigned mxProgress; /* Maximum progress callbacks before failing */
|
||||
unsigned flgProgress; /* Flags for the progress callback */
|
||||
unsigned shellFlgs; /* Various flags */
|
||||
unsigned priorShFlgs; /* Saved copy of flags */
|
||||
sqlite3_int64 szMax; /* --maxsize argument to .open */
|
||||
char *zDestTable; /* Name of destination table when MODE_Insert */
|
||||
char *zTempFile; /* Temporary file that might need deleting */
|
||||
@@ -1337,11 +1408,13 @@ edit_func_end:
|
||||
*/
|
||||
static void outputModePush(ShellState *p){
|
||||
p->modePrior = p->mode;
|
||||
p->priorShFlgs = p->shellFlgs;
|
||||
memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
|
||||
memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
|
||||
}
|
||||
static void outputModePop(ShellState *p){
|
||||
p->mode = p->modePrior;
|
||||
p->shellFlgs = p->priorShFlgs;
|
||||
memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
|
||||
memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
|
||||
}
|
||||
@@ -2306,8 +2379,7 @@ static void set_table_name(ShellState *p, const char *zName){
|
||||
*/
|
||||
static int run_table_dump_query(
|
||||
ShellState *p, /* Query context */
|
||||
const char *zSelect, /* SELECT statement to extract content */
|
||||
const char *zFirstRow /* Print before first row, if not NULL */
|
||||
const char *zSelect /* SELECT statement to extract content */
|
||||
){
|
||||
sqlite3_stmt *pSelect;
|
||||
int rc;
|
||||
@@ -2324,10 +2396,6 @@ static int run_table_dump_query(
|
||||
rc = sqlite3_step(pSelect);
|
||||
nResult = sqlite3_column_count(pSelect);
|
||||
while( rc==SQLITE_ROW ){
|
||||
if( zFirstRow ){
|
||||
utf8_printf(p->out, "%s", zFirstRow);
|
||||
zFirstRow = 0;
|
||||
}
|
||||
z = (const char*)sqlite3_column_text(pSelect, 0);
|
||||
utf8_printf(p->out, "%s", z);
|
||||
for(i=1; i<nResult; i++){
|
||||
@@ -2784,9 +2852,9 @@ static void bind_table_init(ShellState *p){
|
||||
** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
|
||||
** WITHOUT ROWID;
|
||||
**
|
||||
** No bindings occur if this table does not exist. The special character '$'
|
||||
** is included in the table name to help prevent collisions with actual tables.
|
||||
** The table must be in the TEMP schema.
|
||||
** No bindings occur if this table does not exist. The name of the table
|
||||
** begins with "sqlite_" so that it will not collide with ordinary application
|
||||
** tables. The table must be in the TEMP schema.
|
||||
*/
|
||||
static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
|
||||
int nVar;
|
||||
@@ -3090,6 +3158,7 @@ static int shell_exec(
|
||||
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
|
||||
int iEqpId = sqlite3_column_int(pExplain, 0);
|
||||
int iParentId = sqlite3_column_int(pExplain, 1);
|
||||
if( zEQPLine==0 ) zEQPLine = "";
|
||||
if( zEQPLine[0]=='-' ) eqp_render(pArg);
|
||||
eqp_append(pArg, iEqpId, iParentId, zEQPLine);
|
||||
}
|
||||
@@ -3500,11 +3569,12 @@ static const char *(azHelp[]) = {
|
||||
".databases List names and files of attached databases",
|
||||
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
|
||||
".dbinfo ?DB? Show status information about the database",
|
||||
".dump ?TABLE? ... Render all database content as SQL",
|
||||
".dump ?TABLE? Render database content as SQL",
|
||||
" Options:",
|
||||
" --preserve-rowids Include ROWID values in the output",
|
||||
" --newlines Allow unescaped newline characters in output",
|
||||
" TABLE is a LIKE pattern for the tables to dump",
|
||||
" Additional LIKE patterns can be given in subsequent arguments",
|
||||
".echo on|off Turn command echo on or off",
|
||||
".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
|
||||
" Other Modes:",
|
||||
@@ -3514,15 +3584,29 @@ static const char *(azHelp[]) = {
|
||||
#endif
|
||||
" trigger Like \"full\" but also show trigger bytecode",
|
||||
".excel Display the output of next command in spreadsheet",
|
||||
" --bom Put a UTF8 byte-order mark on intermediate file",
|
||||
".exit ?CODE? Exit this program with return-code CODE",
|
||||
".expert EXPERIMENTAL. Suggest indexes for queries",
|
||||
".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
|
||||
".filectrl CMD ... Run various sqlite3_file_control() operations",
|
||||
" Run \".filectrl\" with no arguments for details",
|
||||
" --schema SCHEMA Use SCHEMA instead of \"main\"",
|
||||
" --help Show CMD details",
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
|
||||
".headers on|off Turn display of headers on or off",
|
||||
".help ?-all? ?PATTERN? Show help text for PATTERN",
|
||||
".import FILE TABLE Import data from FILE into TABLE",
|
||||
" Options:",
|
||||
" --ascii Use \\037 and \\036 as column and row separators",
|
||||
" --csv Use , and \\n as column and row separators",
|
||||
" --skip N Skip the first N rows of input",
|
||||
" -v \"Verbose\" - increase auxiliary output",
|
||||
" Notes:",
|
||||
" * If TABLE does not exist, it is created. The first row of input",
|
||||
" determines the column names.",
|
||||
" * If neither --csv or --ascii are used, the input mode is derived",
|
||||
" from the \".mode\" output mode",
|
||||
" * If FILE begins with \"|\" then it is a command that generates the",
|
||||
" input text.",
|
||||
#ifndef SQLITE_OMIT_TEST_CONTROL
|
||||
".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
|
||||
#endif
|
||||
@@ -3553,11 +3637,14 @@ static const char *(azHelp[]) = {
|
||||
" tabs Tab-separated values",
|
||||
" tcl TCL list elements",
|
||||
".nullvalue STRING Use STRING in place of NULL values",
|
||||
".once (-e|-x|FILE) Output for the next SQL command only to FILE",
|
||||
".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
|
||||
" If FILE begins with '|' then open as a pipe",
|
||||
" Other options:",
|
||||
" -e Invoke system text editor",
|
||||
" -x Open in a spreadsheet",
|
||||
" --bom Put a UTF8 byte-order mark at the beginning",
|
||||
" -e Send output to the system text editor",
|
||||
" -x Send output as CSV to a spreadsheet (same as \".excel\")",
|
||||
#ifdef SQLITE_DEBUG
|
||||
".oom [--repeat M] [N] Simulate an OOM error on the N-th allocation",
|
||||
#endif
|
||||
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
|
||||
" Options:",
|
||||
" --append Use appendvfs to append database to the end of FILE",
|
||||
@@ -3571,7 +3658,11 @@ static const char *(azHelp[]) = {
|
||||
" --readonly Open FILE readonly",
|
||||
" --zip FILE is a ZIP archive",
|
||||
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
|
||||
" If FILE begins with '|' then open it as a pipe.",
|
||||
" If FILE begins with '|' then open it as a pipe.",
|
||||
" Options:",
|
||||
" --bom Prefix output with a UTF8 byte-order mark",
|
||||
" -e Send output to the system text editor",
|
||||
" -x Send output as CSV to a spreadsheet",
|
||||
".parameter CMD ... Manage SQL parameter bindings",
|
||||
" clear Erase all bindings",
|
||||
" init Initialize the TEMP table that holds bindings",
|
||||
@@ -3691,6 +3782,7 @@ static int showHelp(FILE *out, const char *zPattern){
|
||||
|| zPattern[0]=='0'
|
||||
|| strcmp(zPattern,"-a")==0
|
||||
|| strcmp(zPattern,"-all")==0
|
||||
|| strcmp(zPattern,"--all")==0
|
||||
){
|
||||
/* Show all commands, but only one line per command */
|
||||
if( zPattern==0 ) zPattern = "";
|
||||
@@ -4172,6 +4264,7 @@ static void open_db(ShellState *p, int openFlags){
|
||||
sqlite3_fileio_init(p->db, 0, 0);
|
||||
sqlite3_shathree_init(p->db, 0, 0);
|
||||
sqlite3_completion_init(p->db, 0, 0);
|
||||
sqlite3_uint_init(p->db, 0, 0);
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||
sqlite3_dbdata_init(p->db, 0, 0);
|
||||
#endif
|
||||
@@ -4508,6 +4601,8 @@ struct ImportCtx {
|
||||
int n; /* Number of bytes in z */
|
||||
int nAlloc; /* Space allocated for z[] */
|
||||
int nLine; /* Current line number */
|
||||
int nRow; /* Number of rows imported */
|
||||
int nErr; /* Number of errors encountered */
|
||||
int bNotFirst; /* True if one or more bytes already read */
|
||||
int cTerm; /* Character that terminated the most recent field */
|
||||
int cColSep; /* The column separator character. (Usually ",") */
|
||||
@@ -4889,11 +4984,15 @@ static void output_reset(ShellState *p){
|
||||
zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
|
||||
if( system(zCmd) ){
|
||||
utf8_printf(stderr, "Failed: [%s]\n", zCmd);
|
||||
}else{
|
||||
/* Give the start/open/xdg-open command some time to get
|
||||
** going before we continue, and potential delete the
|
||||
** p->zTempFile data file out from under it */
|
||||
sqlite3_sleep(2000);
|
||||
}
|
||||
sqlite3_free(zCmd);
|
||||
outputModePop(p);
|
||||
p->doXdgOpen = 0;
|
||||
sqlite3_sleep(100);
|
||||
}
|
||||
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
|
||||
}
|
||||
@@ -4969,12 +5068,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
|
||||
-1, &pStmt, 0);
|
||||
if( rc ){
|
||||
if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
|
||||
utf8_printf(stderr, "the \".dbinfo\" command requires the "
|
||||
"-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
|
||||
}else{
|
||||
utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
|
||||
}
|
||||
utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
|
||||
sqlite3_finalize(pStmt);
|
||||
return 1;
|
||||
}
|
||||
@@ -5183,9 +5277,21 @@ static void newTempFile(ShellState *p, const char *zSuffix){
|
||||
sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
|
||||
}
|
||||
if( p->zTempFile==0 ){
|
||||
/* If p->db is an in-memory database then the TEMPFILENAME file-control
|
||||
** will not work and we will need to fallback to guessing */
|
||||
char *zTemp;
|
||||
sqlite3_uint64 r;
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
|
||||
zTemp = getenv("TEMP");
|
||||
if( zTemp==0 ) zTemp = getenv("TMP");
|
||||
if( zTemp==0 ){
|
||||
#ifdef _WIN32
|
||||
zTemp = "\\tmp";
|
||||
#else
|
||||
zTemp = "/tmp";
|
||||
#endif
|
||||
}
|
||||
p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
|
||||
}else{
|
||||
p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
|
||||
}
|
||||
@@ -7209,7 +7315,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
|
||||
|
||||
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
|
||||
const char *zLike = 0;
|
||||
char *zLike = 0;
|
||||
char *zSql;
|
||||
int i;
|
||||
int savedShowHeader = p->showHeader;
|
||||
int savedShellFlags = p->shellFlgs;
|
||||
@@ -7237,12 +7344,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}else if( zLike ){
|
||||
raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
|
||||
"?--newlines? ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
|
||||
zLike, azArg[i]);
|
||||
}else{
|
||||
zLike = azArg[i];
|
||||
zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7260,35 +7365,25 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
** corrupt. */
|
||||
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
|
||||
p->nErr = 0;
|
||||
if( zLike==0 ){
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
|
||||
);
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE name=='sqlite_sequence'"
|
||||
);
|
||||
run_table_dump_query(p,
|
||||
"SELECT sql FROM sqlite_master "
|
||||
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
|
||||
);
|
||||
}else{
|
||||
char *zSql;
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE tbl_name LIKE %Q AND type=='table'"
|
||||
" AND sql NOT NULL", zLike);
|
||||
run_schema_dump_query(p,zSql);
|
||||
sqlite3_free(zSql);
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT sql FROM sqlite_master "
|
||||
"WHERE sql NOT NULL"
|
||||
" AND type IN ('index','trigger','view')"
|
||||
" AND tbl_name LIKE %Q", zLike);
|
||||
run_table_dump_query(p, zSql, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( zLike==0 ) zLike = sqlite3_mprintf("true");
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE (%s) AND type=='table'"
|
||||
" AND sql NOT NULL"
|
||||
" ORDER BY tbl_name='sqlite_sequence', rowid",
|
||||
zLike
|
||||
);
|
||||
run_schema_dump_query(p,zSql);
|
||||
sqlite3_free(zSql);
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT sql FROM sqlite_master "
|
||||
"WHERE (%s) AND sql NOT NULL"
|
||||
" AND type IN ('index','trigger','view')",
|
||||
zLike
|
||||
);
|
||||
run_table_dump_query(p, zSql);
|
||||
sqlite3_free(zSql);
|
||||
sqlite3_free(zLike);
|
||||
if( p->writableSchema ){
|
||||
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
|
||||
p->writableSchema = 0;
|
||||
@@ -7391,6 +7486,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
|
||||
{ "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
|
||||
{ "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
|
||||
{ "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
|
||||
};
|
||||
int filectrl = -1;
|
||||
int iCtrl = -1;
|
||||
@@ -7398,10 +7494,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int isOk = 0; /* 0: usage 1: %lld 2: no-result */
|
||||
int n2, i;
|
||||
const char *zCmd = 0;
|
||||
const char *zSchema = 0;
|
||||
|
||||
open_db(p, 0);
|
||||
zCmd = nArg>=2 ? azArg[1] : "help";
|
||||
|
||||
if( zCmd[0]=='-'
|
||||
&& (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
|
||||
&& nArg>=4
|
||||
){
|
||||
zSchema = azArg[2];
|
||||
for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
|
||||
nArg -= 2;
|
||||
zCmd = azArg[1];
|
||||
}
|
||||
|
||||
/* The argument can optionally begin with "-" or "--" */
|
||||
if( zCmd[0]=='-' && zCmd[1] ){
|
||||
zCmd++;
|
||||
@@ -7443,7 +7550,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_FCNTL_SIZE_LIMIT: {
|
||||
if( nArg!=2 && nArg!=3 ) break;
|
||||
iRes = nArg==3 ? integerValue(azArg[2]) : -1;
|
||||
sqlite3_file_control(p->db, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
|
||||
sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
|
||||
isOk = 1;
|
||||
break;
|
||||
}
|
||||
@@ -7452,7 +7559,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int x;
|
||||
if( nArg!=3 ) break;
|
||||
x = (int)integerValue(azArg[2]);
|
||||
sqlite3_file_control(p->db, 0, filectrl, &x);
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
||||
isOk = 2;
|
||||
break;
|
||||
}
|
||||
@@ -7461,7 +7568,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int x;
|
||||
if( nArg!=2 && nArg!=3 ) break;
|
||||
x = nArg==3 ? booleanValue(azArg[2]) : -1;
|
||||
sqlite3_file_control(p->db, 0, filectrl, &x);
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
||||
iRes = x;
|
||||
isOk = 1;
|
||||
break;
|
||||
@@ -7469,7 +7576,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_FCNTL_HAS_MOVED: {
|
||||
int x;
|
||||
if( nArg!=2 ) break;
|
||||
sqlite3_file_control(p->db, 0, filectrl, &x);
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
||||
iRes = x;
|
||||
isOk = 1;
|
||||
break;
|
||||
@@ -7477,7 +7584,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
case SQLITE_FCNTL_TEMPFILENAME: {
|
||||
char *z = 0;
|
||||
if( nArg!=2 ) break;
|
||||
sqlite3_file_control(p->db, 0, filectrl, &z);
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &z);
|
||||
if( z ){
|
||||
utf8_printf(p->out, "%s\n", z);
|
||||
sqlite3_free(z);
|
||||
@@ -7485,6 +7592,18 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
isOk = 2;
|
||||
break;
|
||||
}
|
||||
case SQLITE_FCNTL_RESERVE_BYTES: {
|
||||
int x;
|
||||
if( nArg>=3 ){
|
||||
x = atoi(azArg[2]);
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
||||
}
|
||||
x = -1;
|
||||
sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
||||
utf8_printf(p->out,"%d\n", x);
|
||||
isOk = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( isOk==0 && iCtrl>=0 ){
|
||||
@@ -7568,8 +7687,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
|
||||
char *zTable; /* Insert data into this table */
|
||||
char *zFile; /* Name of file to extra content from */
|
||||
char *zTable = 0; /* Insert data into this table */
|
||||
char *zFile = 0; /* Name of file to extra content from */
|
||||
sqlite3_stmt *pStmt = NULL; /* A statement */
|
||||
int nCol; /* Number of columns in the table */
|
||||
int nByte; /* Number of bytes in an SQL string */
|
||||
@@ -7580,51 +7699,108 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
ImportCtx sCtx; /* Reader context */
|
||||
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
|
||||
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
|
||||
int eVerbose = 0; /* Larger for more console output */
|
||||
int nSkip = 0; /* Initial lines to skip */
|
||||
int useOutputMode = 1; /* Use output mode to determine separators */
|
||||
|
||||
if( nArg!=3 ){
|
||||
raw_printf(stderr, "Usage: .import FILE TABLE\n");
|
||||
memset(&sCtx, 0, sizeof(sCtx));
|
||||
if( p->mode==MODE_Ascii ){
|
||||
xRead = ascii_read_one_field;
|
||||
}else{
|
||||
xRead = csv_read_one_field;
|
||||
}
|
||||
for(i=1; i<nArg; i++){
|
||||
char *z = azArg[i];
|
||||
if( z[0]=='-' && z[1]=='-' ) z++;
|
||||
if( z[0]!='-' ){
|
||||
if( zFile==0 ){
|
||||
zFile = z;
|
||||
}else if( zTable==0 ){
|
||||
zTable = z;
|
||||
}else{
|
||||
utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
|
||||
showHelp(p->out, "import");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}else if( strcmp(z,"-v")==0 ){
|
||||
eVerbose++;
|
||||
}else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
|
||||
nSkip = integerValue(azArg[++i]);
|
||||
}else if( strcmp(z,"-ascii")==0 ){
|
||||
sCtx.cColSep = SEP_Unit[0];
|
||||
sCtx.cRowSep = SEP_Record[0];
|
||||
xRead = ascii_read_one_field;
|
||||
useOutputMode = 0;
|
||||
}else if( strcmp(z,"-csv")==0 ){
|
||||
sCtx.cColSep = ',';
|
||||
sCtx.cRowSep = '\n';
|
||||
xRead = csv_read_one_field;
|
||||
useOutputMode = 0;
|
||||
}else{
|
||||
utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
|
||||
showHelp(p->out, "import");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}
|
||||
if( zTable==0 ){
|
||||
utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
|
||||
zFile==0 ? "FILE" : "TABLE");
|
||||
showHelp(p->out, "import");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zFile = azArg[1];
|
||||
zTable = azArg[2];
|
||||
seenInterrupt = 0;
|
||||
memset(&sCtx, 0, sizeof(sCtx));
|
||||
open_db(p, 0);
|
||||
nSep = strlen30(p->colSeparator);
|
||||
if( nSep==0 ){
|
||||
raw_printf(stderr,
|
||||
"Error: non-null column separator required for import\n");
|
||||
return 1;
|
||||
}
|
||||
if( nSep>1 ){
|
||||
raw_printf(stderr, "Error: multi-character column separators not allowed"
|
||||
" for import\n");
|
||||
return 1;
|
||||
}
|
||||
nSep = strlen30(p->rowSeparator);
|
||||
if( nSep==0 ){
|
||||
raw_printf(stderr, "Error: non-null row separator required for import\n");
|
||||
return 1;
|
||||
}
|
||||
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
|
||||
/* When importing CSV (only), if the row separator is set to the
|
||||
** default output row separator, change it to the default input
|
||||
** row separator. This avoids having to maintain different input
|
||||
** and output row separators. */
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
if( useOutputMode ){
|
||||
/* If neither the --csv or --ascii options are specified, then set
|
||||
** the column and row separator characters from the output mode. */
|
||||
nSep = strlen30(p->colSeparator);
|
||||
if( nSep==0 ){
|
||||
raw_printf(stderr,
|
||||
"Error: non-null column separator required for import\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( nSep>1 ){
|
||||
raw_printf(stderr,
|
||||
"Error: multi-character column separators not allowed"
|
||||
" for import\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
nSep = strlen30(p->rowSeparator);
|
||||
}
|
||||
if( nSep>1 ){
|
||||
raw_printf(stderr, "Error: multi-character row separators not allowed"
|
||||
" for import\n");
|
||||
return 1;
|
||||
if( nSep==0 ){
|
||||
raw_printf(stderr,
|
||||
"Error: non-null row separator required for import\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
|
||||
/* When importing CSV (only), if the row separator is set to the
|
||||
** default output row separator, change it to the default input
|
||||
** row separator. This avoids having to maintain different input
|
||||
** and output row separators. */
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
nSep = strlen30(p->rowSeparator);
|
||||
}
|
||||
if( nSep>1 ){
|
||||
raw_printf(stderr, "Error: multi-character row separators not allowed"
|
||||
" for import\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
sCtx.cColSep = p->colSeparator[0];
|
||||
sCtx.cRowSep = p->rowSeparator[0];
|
||||
}
|
||||
sCtx.zFile = zFile;
|
||||
sCtx.nLine = 1;
|
||||
if( sCtx.zFile[0]=='|' ){
|
||||
#ifdef SQLITE_OMIT_POPEN
|
||||
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
#else
|
||||
sCtx.in = popen(sCtx.zFile+1, "r");
|
||||
sCtx.zFile = "<pipe>";
|
||||
@@ -7634,17 +7810,26 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sCtx.in = fopen(sCtx.zFile, "rb");
|
||||
xCloser = fclose;
|
||||
}
|
||||
if( p->mode==MODE_Ascii ){
|
||||
xRead = ascii_read_one_field;
|
||||
}else{
|
||||
xRead = csv_read_one_field;
|
||||
}
|
||||
if( sCtx.in==0 ){
|
||||
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
|
||||
char zSep[2];
|
||||
zSep[1] = 0;
|
||||
zSep[0] = sCtx.cColSep;
|
||||
utf8_printf(p->out, "Column separator ");
|
||||
output_c_string(p->out, zSep);
|
||||
utf8_printf(p->out, ", row separator ");
|
||||
zSep[0] = sCtx.cRowSep;
|
||||
output_c_string(p->out, zSep);
|
||||
utf8_printf(p->out, "\n");
|
||||
}
|
||||
while( (nSkip--)>0 ){
|
||||
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
||||
sCtx.nLine++;
|
||||
}
|
||||
sCtx.cColSep = p->colSeparator[0];
|
||||
sCtx.cRowSep = p->rowSeparator[0];
|
||||
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
|
||||
if( zSql==0 ){
|
||||
xCloser(sCtx.in);
|
||||
@@ -7666,9 +7851,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(sCtx.z);
|
||||
xCloser(sCtx.in);
|
||||
utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zCreate = sqlite3_mprintf("%z\n)", zCreate);
|
||||
if( eVerbose>=1 ){
|
||||
utf8_printf(p->out, "%s\n", zCreate);
|
||||
}
|
||||
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
|
||||
sqlite3_free(zCreate);
|
||||
if( rc ){
|
||||
@@ -7676,7 +7865,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_errmsg(p->db));
|
||||
sqlite3_free(sCtx.z);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
}
|
||||
@@ -7685,7 +7875,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
nCol = sqlite3_column_count(pStmt);
|
||||
sqlite3_finalize(pStmt);
|
||||
@@ -7704,13 +7895,17 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
zSql[j++] = ')';
|
||||
zSql[j] = 0;
|
||||
if( eVerbose>=2 ){
|
||||
utf8_printf(p->out, "Insert using: %s\n", zSql);
|
||||
}
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
needCommit = sqlite3_get_autocommit(p->db);
|
||||
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
|
||||
@@ -7753,6 +7948,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( rc!=SQLITE_OK ){
|
||||
utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
|
||||
startLine, sqlite3_errmsg(p->db));
|
||||
sCtx.nErr++;
|
||||
}else{
|
||||
sCtx.nRow++;
|
||||
}
|
||||
}
|
||||
}while( sCtx.cTerm!=EOF );
|
||||
@@ -7761,6 +7959,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(sCtx.z);
|
||||
sqlite3_finalize(pStmt);
|
||||
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
|
||||
if( eVerbose>0 ){
|
||||
utf8_printf(p->out,
|
||||
"Added %d rows with %d errors using %d lines of input\n",
|
||||
sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
|
||||
}
|
||||
}else
|
||||
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
@@ -8039,6 +8242,34 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( c=='o' && strcmp(azArg[0],"oom")==0 ){
|
||||
int i;
|
||||
for(i=1; i<nArg; i++){
|
||||
const char *z = azArg[i];
|
||||
if( z[0]=='-' && z[1]=='-' ) z++;
|
||||
if( strcmp(z,"-repeat")==0 ){
|
||||
if( i==nArg-1 ){
|
||||
raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
|
||||
rc = 1;
|
||||
}else{
|
||||
oomRepeat = (int)integerValue(azArg[++i]);
|
||||
}
|
||||
}else if( IsDigit(z[0]) ){
|
||||
oomCounter = (int)integerValue(azArg[i]);
|
||||
}else{
|
||||
raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
|
||||
raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
if( rc==0 ){
|
||||
raw_printf(p->out, "oomCounter = %d\n", oomCounter);
|
||||
raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
|
||||
char *zNewFilename; /* Name of the database file to open */
|
||||
int iName = 1; /* Index in azArg[] of the filename */
|
||||
@@ -8106,42 +8337,66 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
&& (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
|
||||
|| (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
|
||||
){
|
||||
const char *zFile = nArg>=2 ? azArg[1] : "stdout";
|
||||
const char *zFile = 0;
|
||||
int bTxtMode = 0;
|
||||
if( azArg[0][0]=='e' ){
|
||||
/* Transform the ".excel" command into ".once -x" */
|
||||
nArg = 2;
|
||||
azArg[0] = "once";
|
||||
zFile = azArg[1] = "-x";
|
||||
n = 4;
|
||||
int i;
|
||||
int eMode = 0;
|
||||
int bBOM = 0;
|
||||
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
|
||||
|
||||
if( c=='e' ){
|
||||
eMode = 'x';
|
||||
bOnce = 2;
|
||||
}else if( strncmp(azArg[0],"once",n)==0 ){
|
||||
bOnce = 1;
|
||||
}
|
||||
if( nArg>2 ){
|
||||
utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( n>1 && strncmp(azArg[0], "once", n)==0 ){
|
||||
if( nArg<2 ){
|
||||
raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
|
||||
for(i=1; i<nArg; i++){
|
||||
char *z = azArg[i];
|
||||
if( z[0]=='-' ){
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z,"-bom")==0 ){
|
||||
bBOM = 1;
|
||||
}else if( c!='e' && strcmp(z,"-x")==0 ){
|
||||
eMode = 'x'; /* spreadsheet */
|
||||
}else if( c!='e' && strcmp(z,"-e")==0 ){
|
||||
eMode = 'e'; /* text editor */
|
||||
}else{
|
||||
utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
|
||||
azArg[i]);
|
||||
showHelp(p->out, azArg[0]);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}else if( zFile==0 ){
|
||||
zFile = z;
|
||||
}else{
|
||||
utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
|
||||
azArg[i]);
|
||||
showHelp(p->out, azArg[0]);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}
|
||||
if( zFile==0 ) zFile = "stdout";
|
||||
if( bOnce ){
|
||||
p->outCount = 2;
|
||||
}else{
|
||||
p->outCount = 0;
|
||||
}
|
||||
output_reset(p);
|
||||
if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
|
||||
if( eMode=='e' || eMode=='x' ){
|
||||
p->doXdgOpen = 1;
|
||||
outputModePush(p);
|
||||
if( zFile[1]=='x' ){
|
||||
if( eMode=='x' ){
|
||||
/* spreadsheet mode. Output as CSV. */
|
||||
newTempFile(p, "csv");
|
||||
ShellClearFlag(p, SHFLG_Echo);
|
||||
p->mode = MODE_Csv;
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
|
||||
}else{
|
||||
/* text editor mode */
|
||||
newTempFile(p, "txt");
|
||||
bTxtMode = 1;
|
||||
}
|
||||
@@ -8160,6 +8415,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
p->out = stdout;
|
||||
rc = 1;
|
||||
}else{
|
||||
if( bBOM ) fprintf(p->out,"\357\273\277");
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
||||
}
|
||||
#endif
|
||||
@@ -8172,6 +8428,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
p->out = stdout;
|
||||
rc = 1;
|
||||
} else {
|
||||
if( bBOM ) fprintf(p->out,"\357\273\277");
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
||||
}
|
||||
}
|
||||
@@ -9235,7 +9492,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
|
||||
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
|
||||
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
|
||||
{ "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE"},
|
||||
};
|
||||
int testctrl = -1;
|
||||
int iCtrl = -1;
|
||||
@@ -9288,7 +9544,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
|
||||
/* sqlite3_test_control(int, db, int) */
|
||||
case SQLITE_TESTCTRL_OPTIMIZATIONS:
|
||||
case SQLITE_TESTCTRL_RESERVE:
|
||||
if( nArg==3 ){
|
||||
int opt = (int)strtol(azArg[2], 0, 0);
|
||||
rc2 = sqlite3_test_control(testctrl, p->db, opt);
|
||||
@@ -10060,14 +10315,18 @@ static void main_init(ShellState *data) {
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
static void printBold(const char *zText){
|
||||
#if !SQLITE_OS_WINRT
|
||||
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
|
||||
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
|
||||
SetConsoleTextAttribute(out,
|
||||
FOREGROUND_RED|FOREGROUND_INTENSITY
|
||||
);
|
||||
#endif
|
||||
printf("%s", zText);
|
||||
#if !SQLITE_OS_WINRT
|
||||
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void printBold(const char *zText){
|
||||
@@ -10122,6 +10381,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
stdin_is_interactive = isatty(0);
|
||||
stdout_is_console = isatty(1);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
registerOomSimulator();
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
if( getenv("SQLITE_DEBUG_BREAK") ){
|
||||
if( isatty(0) && isatty(2) ){
|
||||
@@ -10131,7 +10394,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
fgetc(stdin);
|
||||
}else{
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
#if SQLITE_OS_WINRT
|
||||
__debugbreak();
|
||||
#else
|
||||
DebugBreak();
|
||||
#endif
|
||||
#elif defined(SIGTRAP)
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
|
||||
+151
-75
@@ -299,26 +299,22 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
** the [sqlite3] object is successfully destroyed and all associated
|
||||
** resources are deallocated.
|
||||
**
|
||||
** ^If the database connection is associated with unfinalized prepared
|
||||
** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
||||
** will leave the database connection open and return [SQLITE_BUSY].
|
||||
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
||||
** and/or unfinished sqlite3_backups, then the database connection becomes
|
||||
** an unusable "zombie" which will automatically be deallocated when the
|
||||
** last prepared statement is finalized or the last sqlite3_backup is
|
||||
** finished. The sqlite3_close_v2() interface is intended for use with
|
||||
** host languages that are garbage collected, and where the order in which
|
||||
** destructors are called is arbitrary.
|
||||
**
|
||||
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
|
||||
** [sqlite3_blob_close | close] all [BLOB handles], and
|
||||
** Ideally, applications should [sqlite3_finalize | finalize] all
|
||||
** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
|
||||
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
|
||||
** with the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** sqlite3_close_v2() is called on a [database connection] that still has
|
||||
** outstanding [prepared statements], [BLOB handles], and/or
|
||||
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
||||
** of resources is deferred until all [prepared statements], [BLOB handles],
|
||||
** and [sqlite3_backup] objects are also destroyed.
|
||||
** with the [sqlite3] object prior to attempting to close the object.
|
||||
** ^If the database connection is associated with unfinalized prepared
|
||||
** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
|
||||
** sqlite3_close() will leave the database connection open and return
|
||||
** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
|
||||
** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
|
||||
** it returns [SQLITE_OK] regardless, but instead of deallocating the database
|
||||
** connection immediately, it marks the database connection as an unusable
|
||||
** "zombie" and makes arrangements to automatically deallocate the database
|
||||
** connection after all prepared statements are finalized, all BLOB handles
|
||||
** are closed, and all backups have finished. The sqlite3_close_v2() interface
|
||||
** is intended for use with host languages that are garbage collected, and
|
||||
** where the order in which destructors are called is arbitrary.
|
||||
**
|
||||
** ^If an [sqlite3] object is destroyed while a transaction is open,
|
||||
** the transaction is automatically rolled back.
|
||||
@@ -507,6 +503,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
|
||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
@@ -1087,10 +1084,12 @@ struct sqlite3_io_methods {
|
||||
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
|
||||
** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
|
||||
** a file lock using the xLock or xShmLock methods of the VFS to wait
|
||||
** for up to M milliseconds before failing, where M is the single
|
||||
** unsigned integer parameter.
|
||||
** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS
|
||||
** to block for up to M milliseconds before failing when attempting to
|
||||
** obtain a file lock using the xLock or xShmLock methods of the VFS.
|
||||
** The parameter is a pointer to a 32-bit signed integer that contains
|
||||
** the value that M is to be set to. Before returning, the 32-bit signed
|
||||
** integer is overwritten with the previous value of M.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
|
||||
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
|
||||
@@ -1155,6 +1154,7 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_DATA_VERSION 35
|
||||
#define SQLITE_FCNTL_SIZE_LIMIT 36
|
||||
#define SQLITE_FCNTL_CKPT_DONE 37
|
||||
#define SQLITE_FCNTL_RESERVE_BYTES 38
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -3533,8 +3533,19 @@ int sqlite3_open_v2(
|
||||
** that check if a database file was a URI that contained a specific query
|
||||
** parameter, and if so obtains the value of that query parameter.
|
||||
**
|
||||
** If F is the database filename pointer passed into the xOpen() method of
|
||||
** a VFS implementation or it is the return value of [sqlite3_db_filename()]
|
||||
** The first parameter to these interfaces (hereafter referred to
|
||||
** as F) must be one of:
|
||||
** <ul>
|
||||
** <li> A database filename pointer created by the SQLite core and
|
||||
** passed into the xOpen() method of a VFS implemention, or
|
||||
** <li> A filename obtained from [sqlite3_db_filename()], or
|
||||
** <li> A new filename constructed using [sqlite3_create_filename()].
|
||||
** </ul>
|
||||
** If the F parameter is not one of the above, then the behavior is
|
||||
** undefined and probably undesirable. Older versions of SQLite were
|
||||
** more tolerant of invalid F parameters than newer versions.
|
||||
**
|
||||
** If F is a suitable filename (as described in the previous paragraph)
|
||||
** and if P is the name of the query parameter, then
|
||||
** sqlite3_uri_parameter(F,P) returns the value of the P
|
||||
** parameter if it exists or a NULL pointer if P does not appear as a
|
||||
@@ -3617,6 +3628,78 @@ const char *sqlite3_filename_database(const char*);
|
||||
const char *sqlite3_filename_journal(const char*);
|
||||
const char *sqlite3_filename_wal(const char*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database File Corresponding To A Journal
|
||||
**
|
||||
** ^If X is the name of a rollback or WAL-mode journal file that is
|
||||
** passed into the xOpen method of [sqlite3_vfs], then
|
||||
** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
|
||||
** object that represents the main database file.
|
||||
**
|
||||
** This routine is intended for use in custom [VFS] implementations
|
||||
** only. It is not a general-purpose interface.
|
||||
** The argument sqlite3_file_object(X) must be a filename pointer that
|
||||
** has been passed into [sqlite3_vfs].xOpen method where the
|
||||
** flags parameter to xOpen contains one of the bits
|
||||
** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
|
||||
** of this routine results in undefined and probably undesirable
|
||||
** behavior.
|
||||
*/
|
||||
sqlite3_file *sqlite3_database_file_object(const char*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create and Destroy VFS Filenames
|
||||
**
|
||||
** These interfces are provided for use by [VFS shim] implementations and
|
||||
** are not useful outside of that context.
|
||||
**
|
||||
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
||||
** database filename D with corresponding journal file J and WAL file W and
|
||||
** with N URI parameters key/values pairs in the array P. The result from
|
||||
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
|
||||
** is safe to pass to routines like:
|
||||
** <ul>
|
||||
** <li> [sqlite3_uri_parameter()],
|
||||
** <li> [sqlite3_uri_boolean()],
|
||||
** <li> [sqlite3_uri_int64()],
|
||||
** <li> [sqlite3_uri_key()],
|
||||
** <li> [sqlite3_filename_database()],
|
||||
** <li> [sqlite3_filename_journal()], or
|
||||
** <li> [sqlite3_filename_wal()].
|
||||
** </ul>
|
||||
** If a memory allocation error occurs, sqlite3_create_filename() might
|
||||
** return a NULL pointer. The memory obtained from sqlite3_create_filename(X)
|
||||
** must be released by a corresponding call to sqlite3_free_filename(Y).
|
||||
**
|
||||
** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array
|
||||
** of 2*N pointers to strings. Each pair of pointers in this array corresponds
|
||||
** to a key and value for a query parameter. The P parameter may be a NULL
|
||||
** pointer if N is zero. None of the 2*N pointers in the P array may be
|
||||
** NULL pointers and key pointers should not be empty strings.
|
||||
** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
|
||||
** be NULL pointers, though they can be empty strings.
|
||||
**
|
||||
** The sqlite3_free_filename(Y) routine releases a memory allocation
|
||||
** previously obtained from sqlite3_create_filename(). Invoking
|
||||
** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
|
||||
**
|
||||
** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
||||
** than a NULL pointer or a pointer previously acquired from
|
||||
** sqlite3_create_filename(), then bad things such as heap
|
||||
** corruption or segfaults may occur. The value Y should be
|
||||
** used again after sqlite3_free_filename(Y) has been called. This means
|
||||
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
||||
** then the corresponding [sqlite3_module.xClose() method should also be
|
||||
** invoked prior to calling sqlite3_free_filename(Y).
|
||||
*/
|
||||
char *sqlite3_create_filename(
|
||||
const char *zDatabase,
|
||||
const char *zJournal,
|
||||
const char *zWal,
|
||||
int nParam,
|
||||
const char **azParam
|
||||
);
|
||||
void sqlite3_free_filename(char*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Codes And Messages
|
||||
@@ -4199,12 +4282,30 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** [sqlite3_bind_parameter_index()] API if desired. ^The index
|
||||
** for "?NNN" parameters is the value of NNN.
|
||||
** ^The NNN value must be between 1 and the [sqlite3_limit()]
|
||||
** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
|
||||
** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
|
||||
**
|
||||
** ^The third argument is the value to bind to the parameter.
|
||||
** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
||||
** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
|
||||
** is ignored and the end result is the same as sqlite3_bind_null().
|
||||
** ^If the third parameter to sqlite3_bind_text() is not NULL, then
|
||||
** it should be a pointer to well-formed UTF8 text.
|
||||
** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
|
||||
** it should be a pointer to well-formed UTF16 text.
|
||||
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
|
||||
** it should be a pointer to a well-formed unicode string that is
|
||||
** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
|
||||
** otherwise.
|
||||
**
|
||||
** [[byte-order determination rules]] ^The byte-order of
|
||||
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
|
||||
** found in first character, which is removed, or in the absence of a BOM
|
||||
** the byte order is the native byte order of the host
|
||||
** machine for sqlite3_bind_text16() or the byte order specified in
|
||||
** the 6th parameter for sqlite3_bind_text64().)^
|
||||
** ^If UTF16 input text contains invalid unicode
|
||||
** characters, then SQLite might change those invalid characters
|
||||
** into the unicode replacement character: U+FFFD.
|
||||
**
|
||||
** ^(In those routines that have a fourth argument, its value is the
|
||||
** number of bytes in the parameter. To be clear: the value is the
|
||||
@@ -4218,7 +4319,7 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
|
||||
** that parameter must be the byte offset
|
||||
** where the NUL terminator would occur assuming the string were NUL
|
||||
** terminated. If any NUL characters occur at byte offsets less than
|
||||
** terminated. If any NUL characters occurs at byte offsets less than
|
||||
** the value of the fourth parameter then the resulting string value will
|
||||
** contain embedded NULs. The result of expressions involving strings
|
||||
** with embedded NULs is undefined.
|
||||
@@ -5543,8 +5644,9 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
|
||||
** as the text of an error message. ^SQLite interprets the error
|
||||
** message string from sqlite3_result_error() as UTF-8. ^SQLite
|
||||
** interprets the string from sqlite3_result_error16() as UTF-16 in native
|
||||
** byte order. ^If the third parameter to sqlite3_result_error()
|
||||
** interprets the string from sqlite3_result_error16() as UTF-16 using
|
||||
** the same [byte-order determination rules] as [sqlite3_bind_text16()].
|
||||
** ^If the third parameter to sqlite3_result_error()
|
||||
** or sqlite3_result_error16() is negative then SQLite takes as the error
|
||||
** message all text up through the first zero character.
|
||||
** ^If the third parameter to sqlite3_result_error() or
|
||||
@@ -5612,6 +5714,25 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** then SQLite makes a copy of the result into space obtained
|
||||
** from [sqlite3_malloc()] before it returns.
|
||||
**
|
||||
** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
|
||||
** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
|
||||
** when the encoding is not UTF8, if the input UTF16 begins with a
|
||||
** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
|
||||
** string and the rest of the string is interpreted according to the
|
||||
** byte-order specified by the BOM. ^The byte-order specified by
|
||||
** the BOM at the beginning of the text overrides the byte-order
|
||||
** specified by the interface procedure. ^So, for example, if
|
||||
** sqlite3_result_text16le() is invoked with text that begins
|
||||
** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
|
||||
** first two bytes of input are skipped and the remaining input
|
||||
** is interpreted as UTF16BE text.
|
||||
**
|
||||
** ^For UTF16 input text to the sqlite3_result_text16(),
|
||||
** sqlite3_result_text16be(), sqlite3_result_text16le(), and
|
||||
** sqlite3_result_text64() routines, if the text contains invalid
|
||||
** UTF16 characters, the invalid characters might be converted
|
||||
** into the unicode replacement character, U+FFFD.
|
||||
**
|
||||
** ^The sqlite3_result_value() interface sets the result of
|
||||
** the application-defined function to be a copy of the
|
||||
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
|
||||
@@ -5817,51 +5938,6 @@ int sqlite3_collation_needed16(
|
||||
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
||||
);
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/*
|
||||
** Specify the key for an encrypted database. This routine should be
|
||||
** called right after sqlite3_open().
|
||||
**
|
||||
** The code to implement this API is not available in the public release
|
||||
** of SQLite.
|
||||
*/
|
||||
int sqlite3_key(
|
||||
sqlite3 *db, /* Database to be rekeyed */
|
||||
const void *pKey, int nKey /* The key */
|
||||
);
|
||||
int sqlite3_key_v2(
|
||||
sqlite3 *db, /* Database to be rekeyed */
|
||||
const char *zDbName, /* Name of the database */
|
||||
const void *pKey, int nKey /* The key */
|
||||
);
|
||||
|
||||
/*
|
||||
** Change the key on an open database. If the current database is not
|
||||
** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
|
||||
** database is decrypted.
|
||||
**
|
||||
** The code to implement this API is not available in the public release
|
||||
** of SQLite.
|
||||
*/
|
||||
int sqlite3_rekey(
|
||||
sqlite3 *db, /* Database to be rekeyed */
|
||||
const void *pKey, int nKey /* The new key */
|
||||
);
|
||||
int sqlite3_rekey_v2(
|
||||
sqlite3 *db, /* Database to be rekeyed */
|
||||
const char *zDbName, /* Name of the database */
|
||||
const void *pKey, int nKey /* The new key */
|
||||
);
|
||||
|
||||
/*
|
||||
** Specify the activation key for a SEE database. Unless
|
||||
** activated, none of the SEE routines will work.
|
||||
*/
|
||||
void sqlite3_activate_see(
|
||||
const char *zPassPhrase /* Activation phrase */
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
/*
|
||||
** Specify the activation key for a CEROD database. Unless
|
||||
@@ -7604,7 +7680,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PENDING_BYTE 11
|
||||
#define SQLITE_TESTCTRL_ASSERT 12
|
||||
#define SQLITE_TESTCTRL_ALWAYS 13
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
|
||||
+12
-3
@@ -330,6 +330,11 @@ struct sqlite3_api_routines {
|
||||
const char *(*filename_database)(const char*);
|
||||
const char *(*filename_journal)(const char*);
|
||||
const char *(*filename_wal)(const char*);
|
||||
/* Version 3.32.0 and later */
|
||||
char *(*create_filename)(const char*,const char*,const char*,
|
||||
int,const char**);
|
||||
void (*free_filename)(char*);
|
||||
sqlite3_file *(*database_file_object)(const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -620,16 +625,20 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.26.0 and later */
|
||||
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
||||
/* Version 3.28.0 and later */
|
||||
#define sqlite3_stmt_isexplain sqlite3_api->isexplain
|
||||
#define sqlite3_value_frombind sqlite3_api->frombind
|
||||
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
||||
#define sqlite3_value_frombind sqlite3_api->value_frombind
|
||||
/* Version 3.30.0 and later */
|
||||
#define sqlite3_drop_modules sqlite3_api->drop_modules
|
||||
/* Version 3.31.0 andn later */
|
||||
/* Version 3.31.0 and later */
|
||||
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
||||
#define sqlite3_uri_key sqlite3_api->uri_key
|
||||
#define sqlite3_filename_database sqlite3_api->filename_database
|
||||
#define sqlite3_filename_journal sqlite3_api->filename_journal
|
||||
#define sqlite3_filename_wal sqlite3_api->filename_wal
|
||||
/* Version 3.32.0 and later */
|
||||
#define sqlite3_create_filename sqlite3_api->create_filename
|
||||
#define sqlite3_free_filename sqlite3_api->free_filename
|
||||
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+61
-22
@@ -186,6 +186,21 @@
|
||||
#pragma warn -spa /* Suspicious pointer arithmetic */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
|
||||
** places. The following macros try to make this explicit.
|
||||
*/
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0 /* compatibility with non-clang compilers */
|
||||
#endif
|
||||
#if GCC_VERSION>=4007000 || __has_feature(c_atomic)
|
||||
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
|
||||
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
|
||||
#else
|
||||
# define AtomicLoad(PTR) (*(PTR))
|
||||
# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Include standard header files as necessary
|
||||
*/
|
||||
@@ -1264,7 +1279,6 @@ struct Schema {
|
||||
*/
|
||||
#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
|
||||
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
|
||||
#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
|
||||
#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
|
||||
|
||||
/*
|
||||
@@ -1422,7 +1436,7 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
|
||||
struct sqlite3 {
|
||||
sqlite3_vfs *pVfs; /* OS Interface */
|
||||
struct Vdbe *pVdbe; /* List of active virtual machines */
|
||||
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
|
||||
CollSeq *pDfltColl; /* BINARY collseq for the database encoding */
|
||||
sqlite3_mutex *mutex; /* Connection mutex */
|
||||
Db *aDb; /* All backends */
|
||||
int nDb; /* Number of backends currently in use */
|
||||
@@ -1631,6 +1645,7 @@ struct sqlite3 {
|
||||
#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */
|
||||
#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */
|
||||
#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
|
||||
#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
|
||||
|
||||
/*
|
||||
** Bits of the sqlite3.dbOptFlags field that are used by the
|
||||
@@ -1934,6 +1949,7 @@ struct Column {
|
||||
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
|
||||
char affinity; /* One of the SQLITE_AFF_... values */
|
||||
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
|
||||
u8 hName; /* Column name hash for faster lookup */
|
||||
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
||||
};
|
||||
|
||||
@@ -2153,8 +2169,11 @@ struct Table {
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define IsVirtual(X) ((X)->nModuleArg)
|
||||
# define ExprIsVtab(X) \
|
||||
((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
|
||||
#else
|
||||
# define IsVirtual(X) 0
|
||||
# define ExprIsVtab(X) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2512,10 +2531,10 @@ struct AggInfo {
|
||||
** it uses less memory in the Expr object, which is a big memory user
|
||||
** in systems with lots of prepared statements. And few applications
|
||||
** need more than about 10 or 20 variables. But some extreme users want
|
||||
** to have prepared statements with over 32767 variables, and for them
|
||||
** to have prepared statements with over 32766 variables, and for them
|
||||
** the option is available (at compile-time).
|
||||
*/
|
||||
#if SQLITE_MAX_VARIABLE_NUMBER<=32767
|
||||
#if SQLITE_MAX_VARIABLE_NUMBER<32767
|
||||
typedef i16 ynVar;
|
||||
#else
|
||||
typedef int ynVar;
|
||||
@@ -2591,6 +2610,9 @@ struct Expr {
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth
|
||||
** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 vvaFlags; /* Verification flags. */
|
||||
#endif
|
||||
u32 flags; /* Various flags. EP_* See below */
|
||||
union {
|
||||
char *zToken; /* Token value. Zero terminated and dequoted */
|
||||
@@ -2665,7 +2687,7 @@ struct Expr {
|
||||
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Win 0x008000 /* Contains window functions */
|
||||
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
|
||||
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
/* 0x020000 // available for reuse */
|
||||
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
||||
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
|
||||
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
||||
@@ -2679,6 +2701,7 @@ struct Expr {
|
||||
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
|
||||
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
|
||||
#define EP_FromDDL 0x40000000 /* Originates from sqlite_master */
|
||||
/* 0x80000000 // Available */
|
||||
|
||||
/*
|
||||
** The EP_Propagate mask is a set of properties that automatically propagate
|
||||
@@ -2697,14 +2720,24 @@ struct Expr {
|
||||
#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
|
||||
#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
|
||||
|
||||
|
||||
/* Flags for use with Expr.vvaFlags
|
||||
*/
|
||||
#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_Immutable 0x02 /* Do not change this Expr node */
|
||||
|
||||
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
|
||||
** and Accreditation only. It works like ExprSetProperty() during VVA
|
||||
** processes but is a no-op for delivery.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
|
||||
# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P)
|
||||
# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0)
|
||||
# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
|
||||
#else
|
||||
# define ExprSetVVAProperty(E,P)
|
||||
# define ExprHasVVAProperty(E,P) 0
|
||||
# define ExprClearVVAProperties(E)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -3678,6 +3711,7 @@ struct Walker {
|
||||
struct WhereConst *pConst; /* WHERE clause constants */
|
||||
struct RenameCtx *pRename; /* RENAME COLUMN context */
|
||||
struct Table *pTab; /* Table of generated column */
|
||||
struct SrcList_item *pSrcItem; /* A single FROM clause item */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -3834,13 +3868,16 @@ int sqlite3CantopenError(int);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3NomemError(int);
|
||||
int sqlite3IoerrnomemError(int);
|
||||
int sqlite3CorruptPgnoError(int,Pgno);
|
||||
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
|
||||
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
|
||||
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
|
||||
#else
|
||||
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
|
||||
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
|
||||
int sqlite3CorruptPgnoError(int,Pgno);
|
||||
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
|
||||
#else
|
||||
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
|
||||
#endif
|
||||
|
||||
@@ -4110,11 +4147,7 @@ void sqlite3AddGenerated(Parse*,Expr*,Token*);
|
||||
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
|
||||
int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
||||
sqlite3_vfs**,char**,char **);
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*);
|
||||
#else
|
||||
# define sqlite3CodecQueryParameters(A,B,C) 0
|
||||
#endif
|
||||
#define sqlite3CodecQueryParameters(A,B,C) 0
|
||||
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
||||
|
||||
#ifdef SQLITE_UNTESTABLE
|
||||
@@ -4223,7 +4256,7 @@ void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
|
||||
#endif
|
||||
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
||||
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
|
||||
@@ -4378,6 +4411,7 @@ void sqlite3DeferForeignKey(Parse*, int);
|
||||
# define sqlite3AuthContextPush(a,b,c)
|
||||
# define sqlite3AuthContextPop(a) ((void)(a))
|
||||
#endif
|
||||
int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName);
|
||||
void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
|
||||
void sqlite3Detach(Parse*, Expr*);
|
||||
void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
|
||||
@@ -4426,6 +4460,8 @@ int sqlite3VarintLen(u64 v);
|
||||
*/
|
||||
#define getVarint32(A,B) \
|
||||
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
|
||||
#define getVarint32NR(A,B) \
|
||||
B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B))
|
||||
#define putVarint32(A,B) \
|
||||
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
|
||||
sqlite3PutVarint((A),(B)))
|
||||
@@ -4435,10 +4471,10 @@ int sqlite3VarintLen(u64 v);
|
||||
|
||||
const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
|
||||
void sqlite3TableAffinity(Vdbe*, Table*, int);
|
||||
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||
char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
|
||||
int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
|
||||
char sqlite3TableColumnAffinity(Table*,int);
|
||||
char sqlite3ExprAffinity(Expr *pExpr);
|
||||
char sqlite3ExprAffinity(const Expr *pExpr);
|
||||
int sqlite3Atoi64(const char*, i64*, int, u8);
|
||||
int sqlite3DecOrHexToI64(const char*, i64*);
|
||||
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
||||
@@ -4461,9 +4497,10 @@ int sqlite3ReadSchema(Parse *pParse);
|
||||
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
|
||||
int sqlite3IsBinary(const CollSeq*);
|
||||
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
|
||||
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
|
||||
int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
|
||||
void sqlite3SetTextEncoding(sqlite3 *db, u8);
|
||||
CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
|
||||
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
|
||||
int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
|
||||
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
|
||||
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
|
||||
Expr *sqlite3ExprSkipCollate(Expr*);
|
||||
@@ -4530,6 +4567,8 @@ int sqlite3MatchEName(
|
||||
const char*,
|
||||
const char*
|
||||
);
|
||||
Bitmask sqlite3ExprColUsed(Expr*);
|
||||
u8 sqlite3StrIHash(const char*);
|
||||
int sqlite3ResolveExprNames(NameContext*, Expr*);
|
||||
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
|
||||
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
||||
@@ -4694,8 +4733,8 @@ char *sqlite3Normalize(Vdbe*, const char*);
|
||||
#endif
|
||||
int sqlite3Reprepare(Vdbe*);
|
||||
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
||||
CollSeq *sqlite3ExprCompareCollSeq(Parse*,Expr*);
|
||||
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
|
||||
CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
|
||||
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
|
||||
int sqlite3TempInMemory(const sqlite3*);
|
||||
const char *sqlite3JournalModename(int);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
|
||||
+4
-1
@@ -131,9 +131,12 @@
|
||||
|
||||
/*
|
||||
** The maximum value of a ?nnn wildcard that the parser will accept.
|
||||
** If the value exceeds 32767 then extra space is required for the Expr
|
||||
** structure. But otherwise, we believe that the number can be as large
|
||||
** as a signed 32-bit integer can hold.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_VARIABLE_NUMBER
|
||||
# define SQLITE_MAX_VARIABLE_NUMBER 999
|
||||
# define SQLITE_MAX_VARIABLE_NUMBER 32766
|
||||
#endif
|
||||
|
||||
/* Maximum page size. The upper bound on this value is 65536. This a limit
|
||||
|
||||
+1
-31
@@ -3094,22 +3094,10 @@ deserialize_error:
|
||||
** Change the encryption key on the currently open database.
|
||||
*/
|
||||
case DB_REKEY: {
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
int nKey;
|
||||
void *pKey;
|
||||
#endif
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "KEY");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
||||
rc = sqlite3_rekey(pDb->db, pKey, nKey);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
|
||||
rc = TCL_ERROR;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3678,9 +3666,6 @@ static int sqliteCmdUsage(
|
||||
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
||||
" ?-nofollow BOOLEAN?"
|
||||
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
" ?-key CODECKEY?"
|
||||
#endif
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3715,10 +3700,6 @@ static int SQLITE_TCLAPI DbMain(
|
||||
const char *zVfs = 0;
|
||||
int flags;
|
||||
Tcl_DString translatedFilename;
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
void *pKey = 0;
|
||||
int nKey = 0;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
/* In normal use, each TCL interpreter runs in a single thread. So
|
||||
@@ -3745,11 +3726,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
return TCL_OK;
|
||||
}
|
||||
if( strcmp(zArg,"-has-codec")==0 ){
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
Tcl_AppendResult(interp,"1",(char*)0);
|
||||
#else
|
||||
Tcl_AppendResult(interp,"0",(char*)0);
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
|
||||
@@ -3764,9 +3741,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
|
||||
i++;
|
||||
if( strcmp(zArg,"-key")==0 ){
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey);
|
||||
#endif
|
||||
/* no-op */
|
||||
}else if( strcmp(zArg, "-vfs")==0 ){
|
||||
zVfs = Tcl_GetString(objv[i]);
|
||||
}else if( strcmp(zArg, "-readonly")==0 ){
|
||||
@@ -3842,11 +3817,6 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}else{
|
||||
zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
|
||||
}
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
if( p->db ){
|
||||
sqlite3_key(p->db, pKey, nKey);
|
||||
}
|
||||
#endif
|
||||
if( p->db==0 ){
|
||||
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
|
||||
Tcl_Free((char*)p);
|
||||
|
||||
-28
@@ -655,20 +655,6 @@ static int SQLITE_TCLAPI test_key(
|
||||
int argc, /* Number of arguments */
|
||||
char **argv /* Text of each argument */
|
||||
){
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
sqlite3 *db;
|
||||
const char *zKey;
|
||||
int nKey;
|
||||
if( argc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" FILENAME\"", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
zKey = argv[2];
|
||||
nKey = strlen(zKey);
|
||||
sqlite3_key(db, zKey, nKey);
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -683,20 +669,6 @@ static int SQLITE_TCLAPI test_rekey(
|
||||
int argc, /* Number of arguments */
|
||||
char **argv /* Text of each argument */
|
||||
){
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
sqlite3 *db;
|
||||
const char *zKey;
|
||||
int nKey;
|
||||
if( argc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" FILENAME\"", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
zKey = argv[2];
|
||||
nKey = strlen(zKey);
|
||||
sqlite3_rekey(db, zKey, nKey);
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,11 +226,7 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
Tcl_SetVar2(interp, "sqlite_options", "has_codec", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "has_codec", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "0", TCL_GLOBAL_ONLY);
|
||||
|
||||
@@ -267,11 +267,14 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
|
||||
if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
|
||||
char *z;
|
||||
int n = pGroup->nName;
|
||||
pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
|
||||
z = sqlite3_malloc64( n+5 );
|
||||
if( z==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
|
||||
pGroup->aReal[iChunk].z = sqlite3_create_filename(z,"","",0,0);
|
||||
sqlite3_free(z);
|
||||
if( pGroup->aReal[iChunk].z==0 ) return SQLITE_NOMEM;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -438,7 +441,7 @@ static void multiplexSubClose(
|
||||
}
|
||||
sqlite3_free(pGroup->aReal[iChunk].p);
|
||||
}
|
||||
sqlite3_free(pGroup->aReal[iChunk].z);
|
||||
sqlite3_free_filename(pGroup->aReal[iChunk].z);
|
||||
memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
|
||||
}
|
||||
|
||||
@@ -530,7 +533,7 @@ static int multiplexOpen(
|
||||
pGroup->szChunk += 65536;
|
||||
}
|
||||
}
|
||||
pGroup->flags = flags;
|
||||
pGroup->flags = (flags & ~SQLITE_OPEN_URI);
|
||||
rc = multiplexSubFilename(pGroup, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
|
||||
|
||||
@@ -287,22 +287,6 @@ static int SQLITE_TCLAPI sqlthread_open(
|
||||
|
||||
zFilename = Tcl_GetString(objv[2]);
|
||||
sqlite3_open(zFilename, &db);
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( db && objc>=4 ){
|
||||
const char *zKey;
|
||||
int nKey;
|
||||
int rc;
|
||||
zKey = Tcl_GetStringFromObj(objv[3], &nKey);
|
||||
rc = sqlite3_key(db, zKey, nKey);
|
||||
if( rc!=SQLITE_OK ){
|
||||
char *zErrMsg = sqlite3_mprintf("error %d: %s", rc, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
Tcl_AppendResult(interp, zErrMsg, (char*)0);
|
||||
sqlite3_free(zErrMsg);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Md5_Register(db, 0, 0);
|
||||
sqlite3_busy_handler(db, xBusy, 0);
|
||||
|
||||
|
||||
+2
-2
@@ -568,7 +568,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
assert( zSql!=0 );
|
||||
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
|
||||
if( db->nVdbeActive==0 ){
|
||||
db->u1.isInterrupted = 0;
|
||||
AtomicStore(&db->u1.isInterrupted, 0);
|
||||
}
|
||||
pParse->rc = SQLITE_OK;
|
||||
pParse->zTail = zSql;
|
||||
@@ -613,7 +613,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
if( tokenType>=TK_SPACE ){
|
||||
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
if( db->u1.isInterrupted ){
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
pParse->rc = SQLITE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
+8
-4
@@ -138,8 +138,8 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
|
||||
sqlite3_str_appendf(&x, " %s", pItem->zName);
|
||||
}
|
||||
if( pItem->pTab ){
|
||||
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p",
|
||||
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab);
|
||||
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
|
||||
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
|
||||
}
|
||||
if( pItem->zAlias ){
|
||||
sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
|
||||
@@ -398,14 +398,14 @@ void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
|
||||
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
const char *zBinOp = 0; /* Binary operator */
|
||||
const char *zUniOp = 0; /* Unary operator */
|
||||
char zFlgs[60];
|
||||
char zFlgs[200];
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
if( pExpr==0 ){
|
||||
sqlite3TreeViewLine(pView, "nil");
|
||||
sqlite3TreeViewPop(pView);
|
||||
return;
|
||||
}
|
||||
if( pExpr->flags || pExpr->affExpr ){
|
||||
if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
|
||||
StrAccum x;
|
||||
sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
|
||||
sqlite3_str_appendf(&x, " fg.af=%x.%c",
|
||||
@@ -416,6 +416,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
if( ExprHasProperty(pExpr, EP_FromDDL) ){
|
||||
sqlite3_str_appendf(&x, " DDL");
|
||||
}
|
||||
if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
|
||||
sqlite3_str_appendf(&x, " IMMUTABLE");
|
||||
}
|
||||
sqlite3StrAccumFinish(&x);
|
||||
}else{
|
||||
zFlgs[0] = 0;
|
||||
@@ -522,6 +525,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
||||
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
||||
case TK_DOT: zBinOp = "DOT"; break;
|
||||
case TK_LIMIT: zBinOp = "LIMIT"; break;
|
||||
|
||||
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
||||
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
||||
|
||||
+1
-1
@@ -580,7 +580,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
|
||||
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue;
|
||||
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
|
||||
if( pTrigger ) break;
|
||||
|
||||
+3
-1
@@ -616,7 +616,9 @@ void sqlite3Update(
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
|
||||
aToOpen, 0, 0);
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
if( addrOnce ){
|
||||
sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
|
||||
}
|
||||
}
|
||||
|
||||
/* Top of the update loop */
|
||||
|
||||
@@ -105,26 +105,6 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UTF16LE(zIn, TERM, c){ \
|
||||
c = (*zIn++); \
|
||||
c += ((*zIn++)<<8); \
|
||||
if( c>=0xD800 && c<0xE000 && TERM ){ \
|
||||
int c2 = (*zIn++); \
|
||||
c2 += ((*zIn++)<<8); \
|
||||
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UTF16BE(zIn, TERM, c){ \
|
||||
c = ((*zIn++)<<8); \
|
||||
c += (*zIn++); \
|
||||
if( c>=0xD800 && c<0xE000 && TERM ){ \
|
||||
int c2 = ((*zIn++)<<8); \
|
||||
c2 += (*zIn++); \
|
||||
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
** Translate a single UTF-8 character. Return the unicode value.
|
||||
**
|
||||
@@ -301,13 +281,43 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
|
||||
if( pMem->enc==SQLITE_UTF16LE ){
|
||||
/* UTF-16 Little-endian -> UTF-8 */
|
||||
while( zIn<zTerm ){
|
||||
READ_UTF16LE(zIn, zIn<zTerm, c);
|
||||
c = *(zIn++);
|
||||
c += (*(zIn++))<<8;
|
||||
if( c>=0xd800 && c<0xe000 ){
|
||||
if( c>=0xdc00 || zIn>=zTerm ){
|
||||
c = 0xfffd;
|
||||
}else{
|
||||
int c2 = *(zIn++);
|
||||
c2 += (*(zIn++))<<8;
|
||||
if( c2<0xdc00 || c2>=0xe000 ){
|
||||
zIn -= 2;
|
||||
c = 0xfffd;
|
||||
}else{
|
||||
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE_UTF8(z, c);
|
||||
}
|
||||
}else{
|
||||
/* UTF-16 Big-endian -> UTF-8 */
|
||||
while( zIn<zTerm ){
|
||||
READ_UTF16BE(zIn, zIn<zTerm, c);
|
||||
c = (*(zIn++))<<8;
|
||||
c += *(zIn++);
|
||||
if( c>=0xd800 && c<0xe000 ){
|
||||
if( c>=0xdc00 || zIn>=zTerm ){
|
||||
c = 0xfffd;
|
||||
}else{
|
||||
int c2 = (*(zIn++))<<8;
|
||||
c2 += *(zIn++);
|
||||
if( c2<0xdc00 || c2>=0xe000 ){
|
||||
zIn -= 2;
|
||||
c = 0xfffd;
|
||||
}else{
|
||||
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE_UTF8(z, c);
|
||||
}
|
||||
}
|
||||
@@ -466,18 +476,15 @@ int sqlite3Utf16ByteLen(const void *zIn, int nChar){
|
||||
unsigned char const *z = zIn;
|
||||
int n = 0;
|
||||
|
||||
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
|
||||
while( n<nChar ){
|
||||
READ_UTF16BE(z, 1, c);
|
||||
n++;
|
||||
}
|
||||
}else{
|
||||
while( n<nChar ){
|
||||
READ_UTF16LE(z, 1, c);
|
||||
n++;
|
||||
}
|
||||
if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
|
||||
while( n<nChar ){
|
||||
c = z[0];
|
||||
z += 2;
|
||||
if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
|
||||
n++;
|
||||
}
|
||||
return (int)(z-(unsigned char const *)zIn);
|
||||
return (int)(z-(unsigned char const *)zIn)
|
||||
- (SQLITE_UTF16NATIVE==SQLITE_UTF16LE);
|
||||
}
|
||||
|
||||
#if defined(SQLITE_TEST)
|
||||
@@ -507,30 +514,6 @@ void sqlite3UtfSelfTest(void){
|
||||
assert( c==t );
|
||||
assert( (z-zBuf)==n );
|
||||
}
|
||||
for(i=0; i<0x00110000; i++){
|
||||
if( i>=0xD800 && i<0xE000 ) continue;
|
||||
z = zBuf;
|
||||
WRITE_UTF16LE(z, i);
|
||||
n = (int)(z-zBuf);
|
||||
assert( n>0 && n<=4 );
|
||||
z[0] = 0;
|
||||
z = zBuf;
|
||||
READ_UTF16LE(z, 1, c);
|
||||
assert( c==i );
|
||||
assert( (z-zBuf)==n );
|
||||
}
|
||||
for(i=0; i<0x00110000; i++){
|
||||
if( i>=0xD800 && i<0xE000 ) continue;
|
||||
z = zBuf;
|
||||
WRITE_UTF16BE(z, i);
|
||||
n = (int)(z-zBuf);
|
||||
assert( n>0 && n<=4 );
|
||||
z[0] = 0;
|
||||
z = zBuf;
|
||||
READ_UTF16BE(z, 1, c);
|
||||
assert( c==i );
|
||||
assert( (z-zBuf)==n );
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_TEST */
|
||||
#endif /* SQLITE_OMIT_UTF16 */
|
||||
|
||||
+15
-2
@@ -317,6 +317,19 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
|
||||
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute an 8-bit hash on a string that is insensitive to case differences
|
||||
*/
|
||||
u8 sqlite3StrIHash(const char *z){
|
||||
u8 h = 0;
|
||||
if( z==0 ) return 0;
|
||||
while( z[0] ){
|
||||
h += UpperToLower[(unsigned char)z[0]];
|
||||
z++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute 10 to the E-th power. Examples: E==1 results in 10.
|
||||
** E==2 results in 100. E==50 results in 1.0e50.
|
||||
@@ -1256,7 +1269,7 @@ u8 sqlite3HexToInt(int h){
|
||||
return (u8)(h & 0xf);
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
|
||||
#if !defined(SQLITE_OMIT_BLOB_LITERAL)
|
||||
/*
|
||||
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
|
||||
** value. Return a pointer to its binary value. Space to hold the
|
||||
@@ -1277,7 +1290,7 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
|
||||
}
|
||||
return zBlob;
|
||||
}
|
||||
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
|
||||
#endif /* !SQLITE_OMIT_BLOB_LITERAL */
|
||||
|
||||
/*
|
||||
** Log an error that is an API call on a connection pointer that should
|
||||
|
||||
+1
-12
@@ -233,18 +233,7 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
}
|
||||
db->mDbFlags |= DBFLAG_VacuumInto;
|
||||
}
|
||||
nRes = sqlite3BtreeGetOptimalReserve(pMain);
|
||||
|
||||
/* A VACUUM cannot change the pagesize of an encrypted database. */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( db->nextPagesize ){
|
||||
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
||||
int nKey;
|
||||
char *zKey;
|
||||
sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
|
||||
if( nKey ) db->nextPagesize = 0;
|
||||
}
|
||||
#endif
|
||||
nRes = sqlite3BtreeGetRequestedReserve(pMain);
|
||||
|
||||
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
|
||||
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
|
||||
|
||||
+71
-54
@@ -707,7 +707,7 @@ int sqlite3VdbeExec(
|
||||
assert( p->explain==0 );
|
||||
p->pResultSet = 0;
|
||||
db->busyHandler.nBusy = 0;
|
||||
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
|
||||
sqlite3VdbeIOTraceSql(p);
|
||||
#ifdef SQLITE_DEBUG
|
||||
sqlite3BeginBenignMalloc();
|
||||
@@ -891,7 +891,7 @@ jump_to_p2_and_check_for_interrupt:
|
||||
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
|
||||
** faster according to "valgrind --tool=cachegrind" */
|
||||
check_for_interrupt:
|
||||
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
/* Call the progress callback if it is configured and the required number
|
||||
** of VDBE ops have been executed (either since this invocation of
|
||||
@@ -1544,7 +1544,6 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
pOut = &aMem[pOp->p3];
|
||||
testcase( pIn1==pIn2 );
|
||||
testcase( pOut==pIn2 );
|
||||
assert( pIn1!=pOut );
|
||||
flags1 = pIn1->flags;
|
||||
@@ -2075,7 +2074,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
if( (flags1 | flags3)&MEM_Str ){
|
||||
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn1,0);
|
||||
testcase( flags3!=pIn3->flags );
|
||||
assert( flags3==pIn3->flags );
|
||||
flags3 = pIn3->flags;
|
||||
}
|
||||
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
@@ -2098,7 +2097,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( pIn1==pIn3 ) flags3 = flags1 | MEM_Str;
|
||||
if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
|
||||
}
|
||||
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
||||
testcase( pIn3->flags & MEM_Int );
|
||||
@@ -2713,7 +2712,7 @@ case OP_Column: {
|
||||
/* Make sure zData points to enough of the record to cover the header. */
|
||||
if( pC->aRow==0 ){
|
||||
memset(&sMem, 0, sizeof(sMem));
|
||||
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
|
||||
rc = sqlite3VdbeMemFromBtreeZeroOffset(pC->uc.pCursor,aOffset[0],&sMem);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
zData = (u8*)sMem.z;
|
||||
}else{
|
||||
@@ -3665,7 +3664,7 @@ case OP_SetCookie: {
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** of OP_SeekLE/OP_IdxLT)
|
||||
** </ul>
|
||||
**
|
||||
** The P4 value may be either an integer (P4_INT32) or a pointer to
|
||||
@@ -3695,7 +3694,7 @@ case OP_SetCookie: {
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** of OP_SeekLE/OP_IdxLT)
|
||||
** </ul>
|
||||
**
|
||||
** See also: OP_OpenRead, OP_OpenWrite
|
||||
@@ -3719,7 +3718,7 @@ case OP_SetCookie: {
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** of OP_SeekLE/OP_IdxLT)
|
||||
** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
|
||||
** and subsequently delete entries in an index btree. This is a
|
||||
** hint to the storage engine that the storage engine is allowed to
|
||||
@@ -3831,9 +3830,7 @@ open_cursor_set_hints:
|
||||
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
||||
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
|
||||
testcase( pOp->p5 & OPFLAG_BULKCSR );
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
testcase( pOp->p2 & OPFLAG_SEEKEQ );
|
||||
#endif
|
||||
sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
|
||||
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
|
||||
if( rc ) goto abort_due_to_error;
|
||||
@@ -4089,11 +4086,13 @@ case OP_ColumnsUsed: {
|
||||
** greater than or equal to the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
||||
** opcode will always land on a record that equally equals the key, or
|
||||
** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
||||
** opcode must be followed by an IdxLE opcode with the same arguments.
|
||||
** The IdxLE opcode will be skipped if this opcode succeeds, but the
|
||||
** IdxLE opcode will be used on subsequent loop iterations.
|
||||
** opcode will either land on a record that exactly matches the key, or
|
||||
** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
|
||||
** this opcode must be followed by an IdxLE opcode with the same arguments.
|
||||
** The IdxGT opcode will be skipped if this opcode succeeds, but the
|
||||
** IdxGT opcode will be used on subsequent loop iterations. The
|
||||
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
|
||||
** is an equality search.
|
||||
**
|
||||
** This opcode leaves the cursor configured to move in forward order,
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
@@ -4109,7 +4108,7 @@ case OP_ColumnsUsed: {
|
||||
** to an SQL index, then P3 is the first in an array of P4 registers
|
||||
** that are used as an unpacked index key.
|
||||
**
|
||||
** Reposition cursor P1 so that it points to the smallest entry that
|
||||
** Reposition cursor P1 so that it points to the smallest entry that
|
||||
** is greater than the key value. If there are no records greater than
|
||||
** the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
@@ -4154,11 +4153,13 @@ case OP_ColumnsUsed: {
|
||||
** configured to use Prev, not Next.
|
||||
**
|
||||
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
||||
** opcode will always land on a record that equally equals the key, or
|
||||
** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
||||
** opcode must be followed by an IdxGE opcode with the same arguments.
|
||||
** opcode will either land on a record that exactly matches the key, or
|
||||
** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
|
||||
** this opcode must be followed by an IdxLE opcode with the same arguments.
|
||||
** The IdxGE opcode will be skipped if this opcode succeeds, but the
|
||||
** IdxGE opcode will be used on subsequent loop iterations.
|
||||
** IdxGE opcode will be used on subsequent loop iterations. The
|
||||
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
|
||||
** is an equality search.
|
||||
**
|
||||
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
||||
*/
|
||||
@@ -4195,7 +4196,7 @@ case OP_SeekGT: { /* jump, in3, group */
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
if( pC->isTable ){
|
||||
u16 flags3, newType;
|
||||
/* The BTREE_SEEK_EQ flag is only set on index cursors */
|
||||
/* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */
|
||||
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
|
||||
|| CORRUPT_DB );
|
||||
|
||||
@@ -4254,14 +4255,17 @@ case OP_SeekGT: { /* jump, in3, group */
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}else{
|
||||
/* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
|
||||
** OP_SeekLE opcodes are allowed, and these must be immediately followed
|
||||
** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
|
||||
/* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the
|
||||
** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be
|
||||
** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively,
|
||||
** with the same key.
|
||||
*/
|
||||
if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
|
||||
eqOnly = 1;
|
||||
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
|
||||
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
||||
assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT );
|
||||
assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT );
|
||||
assert( pOp[1].p1==pOp[0].p1 );
|
||||
assert( pOp[1].p2==pOp[0].p2 );
|
||||
assert( pOp[1].p3==pOp[0].p3 );
|
||||
@@ -5209,7 +5213,7 @@ case OP_RowData: {
|
||||
goto too_big;
|
||||
}
|
||||
testcase( n==0 );
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
|
||||
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( !pOp->p3 ) Deephemeralize(pOut);
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
@@ -5587,14 +5591,6 @@ next_tail:
|
||||
** This instruction only works for indices. The equivalent instruction
|
||||
** for tables is OP_Insert.
|
||||
*/
|
||||
/* Opcode: SorterInsert P1 P2 * * *
|
||||
** Synopsis: key=r[P2]
|
||||
**
|
||||
** Register P2 holds an SQL index key made using the
|
||||
** MakeRecord instructions. This opcode writes that key
|
||||
** into the sorter P1. Data for the entry is nil.
|
||||
*/
|
||||
case OP_SorterInsert: /* in2 */
|
||||
case OP_IdxInsert: { /* in2 */
|
||||
VdbeCursor *pC;
|
||||
BtreePayload x;
|
||||
@@ -5603,28 +5599,49 @@ case OP_IdxInsert: { /* in2 */
|
||||
pC = p->apCsr[pOp->p1];
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
assert( pC!=0 );
|
||||
assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
|
||||
assert( !isSorter(pC) );
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
assert( pIn2->flags & MEM_Blob );
|
||||
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
||||
assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pC->isTable==0 );
|
||||
rc = ExpandBlob(pIn2);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( pOp->opcode==OP_SorterInsert ){
|
||||
rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
||||
}else{
|
||||
x.nKey = pIn2->n;
|
||||
x.pKey = pIn2->z;
|
||||
x.aMem = aMem + pOp->p3;
|
||||
x.nMem = (u16)pOp->p4.i;
|
||||
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
|
||||
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
|
||||
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
||||
);
|
||||
assert( pC->deferredMoveto==0 );
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
x.nKey = pIn2->n;
|
||||
x.pKey = pIn2->z;
|
||||
x.aMem = aMem + pOp->p3;
|
||||
x.nMem = (u16)pOp->p4.i;
|
||||
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
|
||||
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
|
||||
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
||||
);
|
||||
assert( pC->deferredMoveto==0 );
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
if( rc) goto abort_due_to_error;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SorterInsert P1 P2 * * *
|
||||
** Synopsis: key=r[P2]
|
||||
**
|
||||
** Register P2 holds an SQL index key made using the
|
||||
** MakeRecord instructions. This opcode writes that key
|
||||
** into the sorter P1. Data for the entry is nil.
|
||||
*/
|
||||
case OP_SorterInsert: { /* in2 */
|
||||
VdbeCursor *pC;
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
assert( pC!=0 );
|
||||
assert( isSorter(pC) );
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
assert( pIn2->flags & MEM_Blob );
|
||||
assert( pC->isTable==0 );
|
||||
rc = ExpandBlob(pIn2);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
||||
if( rc) goto abort_due_to_error;
|
||||
break;
|
||||
}
|
||||
@@ -6463,7 +6480,7 @@ case OP_Program: { /* jump */
|
||||
int i;
|
||||
for(i=0; i<p->nMem; i++){
|
||||
aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */
|
||||
aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
|
||||
MemSetTypeFlag(&aMem[i], MEM_Undefined); /* Fault if this reg is reused */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -7574,7 +7591,7 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
#endif
|
||||
|
||||
/* Opcode: Function P1 P2 P3 P4 *
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
** Synopsis: r[P3]=func(r[P2@NP])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
||||
** contains a pointer to the function to be run) with arguments taken
|
||||
@@ -7593,7 +7610,7 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
** See also: AggStep, AggFinal, PureFunc
|
||||
*/
|
||||
/* Opcode: PureFunc P1 P2 P3 P4 *
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
** Synopsis: r[P3]=func(r[P2@NP])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
||||
** contains a pointer to the function to be run) with arguments taken
|
||||
@@ -7982,7 +7999,7 @@ no_mem:
|
||||
** flag.
|
||||
*/
|
||||
abort_due_to_interrupt:
|
||||
assert( db->u1.isInterrupted );
|
||||
assert( AtomicLoad(&db->u1.isInterrupted) );
|
||||
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
||||
p->rc = rc;
|
||||
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
|
||||
|
||||
@@ -230,6 +230,7 @@ void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
|
||||
void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
|
||||
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
|
||||
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
||||
void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
|
||||
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -289,6 +290,9 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
||||
int sqlite3VdbeHasSubProgram(Vdbe*);
|
||||
|
||||
int sqlite3NotPureFunc(sqlite3_context*);
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
int sqlite3VdbeBytecodeVtabInit(sqlite3*);
|
||||
#endif
|
||||
|
||||
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
|
||||
** each VDBE opcode.
|
||||
|
||||
+13
-4
@@ -31,7 +31,8 @@
|
||||
** "explain" P4 display logic is enabled.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|
||||
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
||||
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
|
||||
|| defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
||||
# define VDBE_DISPLAY_P4 1
|
||||
#else
|
||||
# define VDBE_DISPLAY_P4 0
|
||||
@@ -418,9 +419,9 @@ struct Vdbe {
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||
u8 doingRerun; /* True if rerunning after an auto-reprepare */
|
||||
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
|
||||
bft explain:2; /* True if EXPLAIN present on SQL command */
|
||||
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
|
||||
bft changeCntOn:1; /* True to update the change-counter */
|
||||
bft runOnlyOnce:1; /* Automatically expire on reset */
|
||||
bft usesStmtJournal:1; /* True if uses a statement journal */
|
||||
@@ -496,7 +497,14 @@ int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||
int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
|
||||
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
|
||||
int sqlite3VdbeExec(Vdbe*);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
||||
int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
|
||||
char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
|
||||
char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN)
|
||||
int sqlite3VdbeList(Vdbe*);
|
||||
#endif
|
||||
int sqlite3VdbeHalt(Vdbe*);
|
||||
@@ -532,12 +540,13 @@ int sqlite3VdbeMemRealify(Mem*);
|
||||
int sqlite3VdbeMemNumerify(Mem*);
|
||||
int sqlite3VdbeMemCast(Mem*,u8,u8);
|
||||
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
|
||||
int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
|
||||
void sqlite3VdbeMemRelease(Mem *p);
|
||||
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
||||
const char *sqlite3OpcodeName(int);
|
||||
#endif
|
||||
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
|
||||
|
||||
+1
-1
@@ -663,7 +663,7 @@ static int sqlite3Step(Vdbe *p){
|
||||
** from interrupting a statement that has not yet started.
|
||||
*/
|
||||
if( db->nVdbeActive==0 ){
|
||||
db->u1.isInterrupted = 0;
|
||||
AtomicStore(&db->u1.isInterrupted, 0);
|
||||
}
|
||||
|
||||
assert( db->nVdbeWrite>0 || db->autoCommit==0
|
||||
|
||||
+260
-200
@@ -424,7 +424,7 @@ void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Add a new OP_ opcode.
|
||||
** Add a new OP_Explain opcode.
|
||||
**
|
||||
** If the bPush flag is true, then make this opcode the parent for
|
||||
** subsequent Explains until sqlite3VdbeExplainPop() is called.
|
||||
@@ -1065,6 +1065,34 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
||||
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the P2 operand of the jump instruction at addr so that
|
||||
** the jump lands on the next opcode. Or if the jump instruction was
|
||||
** the previous opcode (and is thus a no-op) then simply back up
|
||||
** the next instruction counter by one slot so that the jump is
|
||||
** overwritten by the next inserted opcode.
|
||||
**
|
||||
** This routine is an optimization of sqlite3VdbeJumpHere() that
|
||||
** strives to omit useless byte-code like this:
|
||||
**
|
||||
** 7 Once 0 8 0
|
||||
** 8 ...
|
||||
*/
|
||||
void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
|
||||
if( addr==p->nOp-1 ){
|
||||
assert( p->aOp[addr].opcode==OP_Once
|
||||
|| p->aOp[addr].opcode==OP_If
|
||||
|| p->aOp[addr].opcode==OP_FkIfZero );
|
||||
assert( p->aOp[addr].p4type==0 );
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
sqlite3VdbeGetOp(p,-1)->iSrcLine = 0; /* Erase VdbeCoverage() macros */
|
||||
#endif
|
||||
p->nOp--;
|
||||
}else{
|
||||
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the input FuncDef structure is ephemeral, then free it. If
|
||||
@@ -1436,17 +1464,19 @@ static int translateP(char c, const Op *pOp){
|
||||
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
|
||||
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
|
||||
*/
|
||||
static int displayComment(
|
||||
char *sqlite3VdbeDisplayComment(
|
||||
sqlite3 *db, /* Optional - Oom error reporting only */
|
||||
const Op *pOp, /* The opcode to be commented */
|
||||
const char *zP4, /* Previously obtained value for P4 */
|
||||
char *zTemp, /* Write result here */
|
||||
int nTemp /* Space available in zTemp[] */
|
||||
const char *zP4 /* Previously obtained value for P4 */
|
||||
){
|
||||
const char *zOpName;
|
||||
const char *zSynopsis;
|
||||
int nOpName;
|
||||
int ii, jj;
|
||||
int ii;
|
||||
char zAlt[50];
|
||||
StrAccum x;
|
||||
|
||||
sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
|
||||
zOpName = sqlite3OpcodeName(pOp->opcode);
|
||||
nOpName = sqlite3Strlen30(zOpName);
|
||||
if( zOpName[nOpName+1] ){
|
||||
@@ -1461,53 +1491,64 @@ static int displayComment(
|
||||
}
|
||||
zSynopsis = zAlt;
|
||||
}
|
||||
for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
|
||||
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
|
||||
if( c=='P' ){
|
||||
c = zSynopsis[++ii];
|
||||
if( c=='4' ){
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
|
||||
sqlite3_str_appendall(&x, zP4);
|
||||
}else if( c=='X' ){
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
|
||||
sqlite3_str_appendall(&x, pOp->zComment);
|
||||
seenCom = 1;
|
||||
}else{
|
||||
int v1 = translateP(c, pOp);
|
||||
int v2;
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
|
||||
if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
|
||||
ii += 3;
|
||||
jj += sqlite3Strlen30(zTemp+jj);
|
||||
v2 = translateP(zSynopsis[ii], pOp);
|
||||
if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
|
||||
ii += 2;
|
||||
v2++;
|
||||
}
|
||||
if( v2>1 ){
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
|
||||
if( v2<2 ){
|
||||
sqlite3_str_appendf(&x, "%d", v1);
|
||||
}else{
|
||||
sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1);
|
||||
}
|
||||
}else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){
|
||||
sqlite3_context *pCtx = pOp->p4.pCtx;
|
||||
if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){
|
||||
sqlite3_str_appendf(&x, "%d", v1);
|
||||
}else if( pCtx->argc>1 ){
|
||||
sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
|
||||
}else{
|
||||
assert( x.nChar>2 );
|
||||
x.nChar -= 2;
|
||||
ii++;
|
||||
}
|
||||
ii += 3;
|
||||
}else{
|
||||
sqlite3_str_appendf(&x, "%d", v1);
|
||||
if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
||||
ii += 4;
|
||||
}
|
||||
}else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
||||
ii += 4;
|
||||
}
|
||||
}
|
||||
jj += sqlite3Strlen30(zTemp+jj);
|
||||
}else{
|
||||
zTemp[jj++] = c;
|
||||
sqlite3_str_appendchar(&x, 1, c);
|
||||
}
|
||||
}
|
||||
if( !seenCom && jj<nTemp-5 && pOp->zComment ){
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
|
||||
jj += sqlite3Strlen30(zTemp+jj);
|
||||
if( !seenCom && pOp->zComment ){
|
||||
sqlite3_str_appendf(&x, "; %s", pOp->zComment);
|
||||
}
|
||||
if( jj<nTemp ) zTemp[jj] = 0;
|
||||
}else if( pOp->zComment ){
|
||||
sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
|
||||
jj = sqlite3Strlen30(zTemp);
|
||||
}else{
|
||||
zTemp[0] = 0;
|
||||
jj = 0;
|
||||
sqlite3_str_appendall(&x, pOp->zComment);
|
||||
}
|
||||
return jj;
|
||||
if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
|
||||
sqlite3OomFault(db);
|
||||
}
|
||||
return sqlite3StrAccumFinish(&x);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */
|
||||
|
||||
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
|
||||
/*
|
||||
@@ -1588,11 +1629,11 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
** Compute a string that describes the P4 parameter for an opcode.
|
||||
** Use zTemp for any required temporary buffer space.
|
||||
*/
|
||||
static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
char *zP4 = zTemp;
|
||||
char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
|
||||
char *zP4 = 0;
|
||||
StrAccum x;
|
||||
assert( nTemp>=20 );
|
||||
sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
|
||||
|
||||
sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
|
||||
switch( pOp->p4type ){
|
||||
case P4_KEYINFO: {
|
||||
int j;
|
||||
@@ -1618,8 +1659,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
}
|
||||
#endif
|
||||
case P4_COLLSEQ: {
|
||||
static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
|
||||
CollSeq *pColl = pOp->p4.pColl;
|
||||
sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
|
||||
assert( pColl->enc>=0 && pColl->enc<4 );
|
||||
sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
|
||||
encnames[pColl->enc]);
|
||||
break;
|
||||
}
|
||||
case P4_FUNCDEF: {
|
||||
@@ -1673,36 +1717,32 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
int n = ai[0]; /* The first element of an INTARRAY is always the
|
||||
** count of the number of elements to follow */
|
||||
for(i=1; i<=n; i++){
|
||||
sqlite3_str_appendf(&x, ",%d", ai[i]);
|
||||
sqlite3_str_appendf(&x, "%c%d", (i==1 ? '[' : ','), ai[i]);
|
||||
}
|
||||
zTemp[0] = '[';
|
||||
sqlite3_str_append(&x, "]", 1);
|
||||
break;
|
||||
}
|
||||
case P4_SUBPROGRAM: {
|
||||
sqlite3_str_appendf(&x, "program");
|
||||
zP4 = "program";
|
||||
break;
|
||||
}
|
||||
case P4_DYNBLOB:
|
||||
case P4_ADVANCE: {
|
||||
zTemp[0] = 0;
|
||||
break;
|
||||
}
|
||||
case P4_TABLE: {
|
||||
sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
|
||||
zP4 = pOp->p4.pTab->zName;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
zP4 = pOp->p4.z;
|
||||
if( zP4==0 ){
|
||||
zP4 = zTemp;
|
||||
zTemp[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3StrAccumFinish(&x);
|
||||
assert( zP4!=0 );
|
||||
return zP4;
|
||||
if( zP4 ) sqlite3_str_appendall(&x, zP4);
|
||||
if( (x.accError & SQLITE_NOMEM)!=0 ){
|
||||
sqlite3OomFault(db);
|
||||
}
|
||||
return sqlite3StrAccumFinish(&x);
|
||||
}
|
||||
#endif /* VDBE_DISPLAY_P4 */
|
||||
|
||||
@@ -1792,24 +1832,28 @@ void sqlite3VdbeLeave(Vdbe *p){
|
||||
*/
|
||||
void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
|
||||
char *zP4;
|
||||
char zPtr[50];
|
||||
char zCom[100];
|
||||
char *zCom;
|
||||
sqlite3 dummyDb;
|
||||
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
|
||||
if( pOut==0 ) pOut = stdout;
|
||||
zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
|
||||
dummyDb.mallocFailed = 1;
|
||||
zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
displayComment(pOp, zP4, zCom, sizeof(zCom));
|
||||
zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
|
||||
#else
|
||||
zCom[0] = 0;
|
||||
zCom = 0;
|
||||
#endif
|
||||
/* NB: The sqlite3OpcodeName() function is implemented by code created
|
||||
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
|
||||
** information from the vdbe.c source text */
|
||||
fprintf(pOut, zFormat1, pc,
|
||||
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
|
||||
zCom
|
||||
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3,
|
||||
zP4 ? zP4 : "", pOp->p5,
|
||||
zCom ? zCom : ""
|
||||
);
|
||||
fflush(pOut);
|
||||
sqlite3_free(zP4);
|
||||
sqlite3_free(zCom);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1900,6 +1944,121 @@ void sqlite3VdbeFrameMemDel(void *pArg){
|
||||
pFrame->v->pDelFrame = pFrame;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
|
||||
/*
|
||||
** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
|
||||
** QUERY PLAN output.
|
||||
**
|
||||
** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
|
||||
** more opcodes to be displayed.
|
||||
*/
|
||||
int sqlite3VdbeNextOpcode(
|
||||
Vdbe *p, /* The statement being explained */
|
||||
Mem *pSub, /* Storage for keeping track of subprogram nesting */
|
||||
int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */
|
||||
int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
|
||||
int *piAddr, /* OUT: Write index into (*paOp)[] here */
|
||||
Op **paOp /* OUT: Write the opcode array here */
|
||||
){
|
||||
int nRow; /* Stop when row count reaches this */
|
||||
int nSub = 0; /* Number of sub-vdbes seen so far */
|
||||
SubProgram **apSub = 0; /* Array of sub-vdbes */
|
||||
int i; /* Next instruction address */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
Op *aOp = 0; /* Opcode array */
|
||||
int iPc; /* Rowid. Copy of value in *piPc */
|
||||
|
||||
/* When the number of output rows reaches nRow, that means the
|
||||
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
||||
** nRow is the sum of the number of rows in the main program, plus
|
||||
** the sum of the number of rows in all trigger subprograms encountered
|
||||
** so far. The nRow value will increase as new trigger subprograms are
|
||||
** encountered, but p->pc will eventually catch up to nRow.
|
||||
*/
|
||||
nRow = p->nOp;
|
||||
if( pSub!=0 ){
|
||||
if( pSub->flags&MEM_Blob ){
|
||||
/* pSub is initiallly NULL. It is initialized to a BLOB by
|
||||
** the P4_SUBPROGRAM processing logic below */
|
||||
nSub = pSub->n/sizeof(Vdbe*);
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
}
|
||||
for(i=0; i<nSub; i++){
|
||||
nRow += apSub[i]->nOp;
|
||||
}
|
||||
}
|
||||
iPc = *piPc;
|
||||
while(1){ /* Loop exits via break */
|
||||
i = iPc++;
|
||||
if( i>=nRow ){
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_DONE;
|
||||
break;
|
||||
}
|
||||
if( i<p->nOp ){
|
||||
/* The rowid is small enough that we are still in the
|
||||
** main program. */
|
||||
aOp = p->aOp;
|
||||
}else{
|
||||
/* We are currently listing subprograms. Figure out which one and
|
||||
** pick up the appropriate opcode. */
|
||||
int j;
|
||||
i -= p->nOp;
|
||||
assert( apSub!=0 );
|
||||
assert( nSub>0 );
|
||||
for(j=0; i>=apSub[j]->nOp; j++){
|
||||
i -= apSub[j]->nOp;
|
||||
assert( i<apSub[j]->nOp || j+1<nSub );
|
||||
}
|
||||
aOp = apSub[j]->aOp;
|
||||
}
|
||||
|
||||
/* When an OP_Program opcode is encounter (the only opcode that has
|
||||
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
||||
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
||||
** has not already been seen.
|
||||
*/
|
||||
if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
|
||||
int nByte = (nSub+1)*sizeof(SubProgram*);
|
||||
int j;
|
||||
for(j=0; j<nSub; j++){
|
||||
if( apSub[j]==aOp[i].p4.pProgram ) break;
|
||||
}
|
||||
if( j==nSub ){
|
||||
p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
apSub[nSub++] = aOp[i].p4.pProgram;
|
||||
MemSetTypeFlag(pSub, MEM_Blob);
|
||||
pSub->n = nSub*sizeof(SubProgram*);
|
||||
nRow += aOp[i].p4.pProgram->nOp;
|
||||
}
|
||||
}
|
||||
if( eMode==0 ) break;
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
if( eMode==2 ){
|
||||
Op *pOp = aOp + i;
|
||||
if( pOp->opcode==OP_OpenRead ) break;
|
||||
if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
|
||||
if( pOp->opcode==OP_ReopenIdx ) break;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
assert( eMode==1 );
|
||||
if( aOp[i].opcode==OP_Explain ) break;
|
||||
if( aOp[i].opcode==OP_Init && iPc>1 ) break;
|
||||
}
|
||||
}
|
||||
*piPc = iPc;
|
||||
*piAddr = i;
|
||||
*paOp = aOp;
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */
|
||||
|
||||
|
||||
/*
|
||||
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
||||
@@ -1940,16 +2099,14 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
||||
int sqlite3VdbeList(
|
||||
Vdbe *p /* The VDBE */
|
||||
){
|
||||
int nRow; /* Stop when row count reaches this */
|
||||
int nSub = 0; /* Number of sub-vdbes seen so far */
|
||||
SubProgram **apSub = 0; /* Array of sub-vdbes */
|
||||
Mem *pSub = 0; /* Memory cell hold array of subprogs */
|
||||
sqlite3 *db = p->db; /* The database connection */
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
|
||||
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
|
||||
Op *pOp = 0;
|
||||
Op *aOp; /* Array of opcodes */
|
||||
Op *pOp; /* Current opcode */
|
||||
|
||||
assert( p->explain );
|
||||
assert( p->magic==VDBE_MAGIC_RUN );
|
||||
@@ -1969,14 +2126,6 @@ int sqlite3VdbeList(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* When the number of output rows reaches nRow, that means the
|
||||
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
||||
** nRow is the sum of the number of rows in the main program, plus
|
||||
** the sum of the number of rows in all trigger subprograms encountered
|
||||
** so far. The nRow value will increase as new trigger subprograms are
|
||||
** encountered, but p->pc will eventually catch up to nRow.
|
||||
*/
|
||||
nRow = p->nOp;
|
||||
if( bListSubprogs ){
|
||||
/* The first 8 memory cells are used for the result set. So we will
|
||||
** commandeer the 9th cell to use as storage for an array of pointers
|
||||
@@ -1984,147 +2133,55 @@ int sqlite3VdbeList(
|
||||
** cells. */
|
||||
assert( p->nMem>9 );
|
||||
pSub = &p->aMem[9];
|
||||
if( pSub->flags&MEM_Blob ){
|
||||
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
||||
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
||||
nSub = pSub->n/sizeof(Vdbe*);
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
}
|
||||
for(i=0; i<nSub; i++){
|
||||
nRow += apSub[i]->nOp;
|
||||
}
|
||||
}else{
|
||||
pSub = 0;
|
||||
}
|
||||
|
||||
while(1){ /* Loop exits via break */
|
||||
i = p->pc++;
|
||||
if( i>=nRow ){
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_DONE;
|
||||
break;
|
||||
}
|
||||
if( i<p->nOp ){
|
||||
/* The output line number is small enough that we are still in the
|
||||
** main program. */
|
||||
pOp = &p->aOp[i];
|
||||
}else{
|
||||
/* We are currently listing subprograms. Figure out which one and
|
||||
** pick up the appropriate opcode. */
|
||||
int j;
|
||||
i -= p->nOp;
|
||||
assert( apSub!=0 );
|
||||
assert( nSub>0 );
|
||||
for(j=0; i>=apSub[j]->nOp; j++){
|
||||
i -= apSub[j]->nOp;
|
||||
assert( i<apSub[j]->nOp || j+1<nSub );
|
||||
}
|
||||
pOp = &apSub[j]->aOp[i];
|
||||
}
|
||||
|
||||
/* When an OP_Program opcode is encounter (the only opcode that has
|
||||
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
||||
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
||||
** has not already been seen.
|
||||
*/
|
||||
if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
|
||||
int nByte = (nSub+1)*sizeof(SubProgram*);
|
||||
int j;
|
||||
for(j=0; j<nSub; j++){
|
||||
if( apSub[j]==pOp->p4.pProgram ) break;
|
||||
}
|
||||
if( j==nSub ){
|
||||
p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
apSub[nSub++] = pOp->p4.pProgram;
|
||||
pSub->flags |= MEM_Blob;
|
||||
pSub->n = nSub*sizeof(SubProgram*);
|
||||
nRow += pOp->p4.pProgram->nOp;
|
||||
}
|
||||
}
|
||||
if( p->explain<2 ) break;
|
||||
if( pOp->opcode==OP_Explain ) break;
|
||||
if( pOp->opcode==OP_Init && p->pc>1 ) break;
|
||||
}
|
||||
/* Figure out which opcode is next to display */
|
||||
rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( db->u1.isInterrupted ){
|
||||
pOp = aOp + i;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
p->rc = SQLITE_INTERRUPT;
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
|
||||
}else{
|
||||
char *zP4;
|
||||
if( p->explain==1 ){
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = i; /* Program counter */
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
|
||||
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
|
||||
assert( pMem->z!=0 );
|
||||
pMem->n = sqlite3Strlen30(pMem->z);
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem++;
|
||||
}
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p1; /* P1 */
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p2; /* P2 */
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p3; /* P3 */
|
||||
pMem++;
|
||||
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
|
||||
if( zP4!=pMem->z ){
|
||||
pMem->n = 0;
|
||||
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
||||
char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
|
||||
if( p->explain==2 ){
|
||||
sqlite3VdbeMemSetInt64(pMem, pOp->p1);
|
||||
sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
|
||||
sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
|
||||
sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
|
||||
p->nResColumn = 4;
|
||||
}else{
|
||||
assert( pMem->z!=0 );
|
||||
pMem->n = sqlite3Strlen30(pMem->z);
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
}
|
||||
pMem++;
|
||||
|
||||
if( p->explain==1 ){
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = 2;
|
||||
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem++;
|
||||
|
||||
sqlite3VdbeMemSetInt64(pMem+0, i);
|
||||
sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
|
||||
-1, SQLITE_UTF8, SQLITE_STATIC);
|
||||
sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
|
||||
sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
|
||||
sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
|
||||
/* pMem+5 for p4 is done last */
|
||||
sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
{
|
||||
char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
|
||||
sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
|
||||
}
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
#else
|
||||
pMem->flags = MEM_Null; /* Comment */
|
||||
sqlite3VdbeMemSetNull(pMem+7);
|
||||
#endif
|
||||
sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
|
||||
p->nResColumn = 8;
|
||||
}
|
||||
p->pResultSet = pMem;
|
||||
if( db->mallocFailed ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_ROW;
|
||||
}
|
||||
|
||||
p->nResColumn = 8 - 4*(p->explain-1);
|
||||
p->pResultSet = &p->aMem[1];
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_ROW;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -2332,6 +2389,7 @@ void sqlite3VdbeMakeReady(
|
||||
};
|
||||
int iFirst, mx, i;
|
||||
if( nMem<10 ) nMem = 10;
|
||||
p->explain = pParse->explain;
|
||||
if( pParse->explain==2 ){
|
||||
sqlite3VdbeSetNumCols(p, 4);
|
||||
iFirst = 8;
|
||||
@@ -2382,7 +2440,6 @@ void sqlite3VdbeMakeReady(
|
||||
|
||||
p->pVList = pParse->pVList;
|
||||
pParse->pVList = 0;
|
||||
p->explain = pParse->explain;
|
||||
if( db->mallocFailed ){
|
||||
p->nVar = 0;
|
||||
p->nCursor = 0;
|
||||
@@ -3500,7 +3557,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
|
||||
assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
|
||||
if( p->deferredMoveto ){
|
||||
int iMap;
|
||||
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
|
||||
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
|
||||
*pp = p->pAltCursor;
|
||||
*piCol = iMap - 1;
|
||||
return SQLITE_OK;
|
||||
@@ -4503,7 +4560,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
|
||||
/* RHS is a string */
|
||||
else if( pRhs->flags & MEM_Str ){
|
||||
getVarint32(&aKey1[idx1], serial_type);
|
||||
getVarint32NR(&aKey1[idx1], serial_type);
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type<12 ){
|
||||
rc = -1;
|
||||
@@ -4537,7 +4594,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
/* RHS is a blob */
|
||||
else if( pRhs->flags & MEM_Blob ){
|
||||
assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
|
||||
getVarint32(&aKey1[idx1], serial_type);
|
||||
getVarint32NR(&aKey1[idx1], serial_type);
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type<12 || (serial_type & 0x01) ){
|
||||
rc = -1;
|
||||
@@ -4726,7 +4783,10 @@ static int vdbeRecordCompareString(
|
||||
|
||||
assert( pPKey2->aMem[0].flags & MEM_Str );
|
||||
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
|
||||
getVarint32(&aKey1[1], serial_type);
|
||||
serial_type = (u8)(aKey1[1]);
|
||||
if( serial_type >= 0x80 ){
|
||||
sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
|
||||
}
|
||||
if( serial_type<12 ){
|
||||
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
|
||||
}else if( !(serial_type & 0x01) ){
|
||||
@@ -4847,13 +4907,13 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
|
||||
|
||||
/* Read in the complete content of the index entry */
|
||||
sqlite3VdbeMemInit(&m, db, 0);
|
||||
rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
|
||||
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The index entry must begin with a header size */
|
||||
(void)getVarint32((u8*)m.z, szHdr);
|
||||
getVarint32NR((u8*)m.z, szHdr);
|
||||
testcase( szHdr==3 );
|
||||
testcase( szHdr==m.n );
|
||||
testcase( szHdr>0x7fffffff );
|
||||
@@ -4864,7 +4924,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
|
||||
|
||||
/* The last field of the index should be an integer - the ROWID.
|
||||
** Verify that the last entry really is an integer. */
|
||||
(void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
|
||||
getVarint32NR((u8*)&m.z[szHdr-1], typeRowid);
|
||||
testcase( typeRowid==1 );
|
||||
testcase( typeRowid==2 );
|
||||
testcase( typeRowid==3 );
|
||||
@@ -4929,7 +4989,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
sqlite3VdbeMemInit(&m, db, 0);
|
||||
rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
|
||||
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
+7
-15
@@ -961,7 +961,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
||||
sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
|
||||
(int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
|
||||
}
|
||||
/* If pX is marked as a shallow copy of pMem, then verify that
|
||||
/* If pX is marked as a shallow copy of pMem, then try to verify that
|
||||
** no significant changes have been made to pX since the OP_SCopy.
|
||||
** A significant change would indicated a missed call to this
|
||||
** function for pX. Minor changes, such as adding or removing a
|
||||
@@ -969,11 +969,6 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
||||
** same. */
|
||||
mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
|
||||
assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
|
||||
/* assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r ); */
|
||||
/* ^^ */
|
||||
/* Cannot reliably compare doubles for equality */
|
||||
assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) );
|
||||
assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 );
|
||||
|
||||
/* pMem is the register that is changing. But also mark pX as
|
||||
** undefined so that we can quickly detect the shallow-copy error */
|
||||
@@ -1169,7 +1164,7 @@ int sqlite3VdbeMemSetStr(
|
||||
** If this routine fails for any reason (malloc returns NULL or unable
|
||||
** to read from the disk) then the pMem is left in an inconsistent state.
|
||||
*/
|
||||
static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
|
||||
int sqlite3VdbeMemFromBtree(
|
||||
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
||||
u32 offset, /* Offset from the start of data to return bytes from. */
|
||||
u32 amt, /* Number of bytes to return. */
|
||||
@@ -1192,13 +1187,11 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3VdbeMemFromBtree(
|
||||
int sqlite3VdbeMemFromBtreeZeroOffset(
|
||||
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
||||
u32 offset, /* Offset from the start of data to return bytes from. */
|
||||
u32 amt, /* Number of bytes to return. */
|
||||
Mem *pMem /* OUT: Return data in this Mem structure. */
|
||||
){
|
||||
char *zData; /* Data from the btree layer */
|
||||
u32 available = 0; /* Number of bytes available on the local btree page */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
@@ -1208,15 +1201,14 @@ int sqlite3VdbeMemFromBtree(
|
||||
/* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
|
||||
** that both the BtShared and database handle mutexes are held. */
|
||||
assert( !sqlite3VdbeMemIsRowSet(pMem) );
|
||||
zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
|
||||
assert( zData!=0 );
|
||||
pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available);
|
||||
assert( pMem->z!=0 );
|
||||
|
||||
if( offset+amt<=available ){
|
||||
pMem->z = &zData[offset];
|
||||
if( amt<=available ){
|
||||
pMem->flags = MEM_Blob|MEM_Ephem;
|
||||
pMem->n = (int)amt;
|
||||
}else{
|
||||
rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
|
||||
rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
+3
-3
@@ -815,8 +815,8 @@ static int vdbeSorterCompareText(
|
||||
int n2;
|
||||
int res;
|
||||
|
||||
getVarint32(&p1[1], n1);
|
||||
getVarint32(&p2[1], n2);
|
||||
getVarint32NR(&p1[1], n1);
|
||||
getVarint32NR(&p2[1], n2);
|
||||
res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
|
||||
if( res==0 ){
|
||||
res = n1 - n2;
|
||||
@@ -1773,7 +1773,7 @@ int sqlite3VdbeSorterWrite(
|
||||
|
||||
assert( pCsr->eCurType==CURTYPE_SORTER );
|
||||
pSorter = pCsr->uc.pSorter;
|
||||
getVarint32((const u8*)&pVal->z[1], t);
|
||||
getVarint32NR((const u8*)&pVal->z[1], t);
|
||||
if( t>0 && t<10 && t!=7 ){
|
||||
pSorter->typeMask &= SORTER_TYPE_INTEGER;
|
||||
}else if( t>10 && (t & 0x01) ){
|
||||
|
||||
+422
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
** 2020-03-23
|
||||
**
|
||||
** 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 virtual-tables for examining the bytecode content
|
||||
** of a prepared statement.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
|
||||
/* An instance of the bytecode() table-valued function.
|
||||
*/
|
||||
typedef struct bytecodevtab bytecodevtab;
|
||||
struct bytecodevtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection */
|
||||
int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */
|
||||
};
|
||||
|
||||
/* A cursor for scanning through the bytecode
|
||||
*/
|
||||
typedef struct bytecodevtab_cursor bytecodevtab_cursor;
|
||||
struct bytecodevtab_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */
|
||||
int iRowid; /* The rowid of the output table */
|
||||
int iAddr; /* Address */
|
||||
int needFinalize; /* Cursors owns pStmt and must finalize it */
|
||||
int showSubprograms; /* Provide a listing of subprograms */
|
||||
Op *aOp; /* Operand array */
|
||||
char *zP4; /* Rendered P4 value */
|
||||
const char *zType; /* tables_used.type */
|
||||
const char *zSchema; /* tables_used.schema */
|
||||
const char *zName; /* tables_used.name */
|
||||
Mem sub; /* Subprograms */
|
||||
};
|
||||
|
||||
/*
|
||||
** Create a new bytecode() table-valued function.
|
||||
*/
|
||||
static int bytecodevtabConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
bytecodevtab *pNew;
|
||||
int rc;
|
||||
int isTabUsed = pAux!=0;
|
||||
const char *azSchema[2] = {
|
||||
/* bytecode() schema */
|
||||
"CREATE TABLE x("
|
||||
"addr INT,"
|
||||
"opcode TEXT,"
|
||||
"p1 INT,"
|
||||
"p2 INT,"
|
||||
"p3 INT,"
|
||||
"p4 TEXT,"
|
||||
"p5 INT,"
|
||||
"comment TEXT,"
|
||||
"subprog TEXT,"
|
||||
"stmt HIDDEN"
|
||||
");",
|
||||
|
||||
/* Tables_used() schema */
|
||||
"CREATE TABLE x("
|
||||
"type TEXT,"
|
||||
"schema TEXT,"
|
||||
"name TEXT,"
|
||||
"wr INT,"
|
||||
"subprog TEXT,"
|
||||
"stmt HIDDEN"
|
||||
");"
|
||||
};
|
||||
|
||||
rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->db = db;
|
||||
pNew->bTablesUsed = isTabUsed*2;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for bytecodevtab objects.
|
||||
*/
|
||||
static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
|
||||
bytecodevtab *p = (bytecodevtab*)pVtab;
|
||||
sqlite3_free(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new bytecodevtab_cursor object.
|
||||
*/
|
||||
static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
bytecodevtab *pVTab = (bytecodevtab*)p;
|
||||
bytecodevtab_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear all internal content from a bytecodevtab cursor.
|
||||
*/
|
||||
static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
|
||||
sqlite3_free(pCur->zP4);
|
||||
pCur->zP4 = 0;
|
||||
sqlite3VdbeMemRelease(&pCur->sub);
|
||||
sqlite3VdbeMemSetNull(&pCur->sub);
|
||||
if( pCur->needFinalize ){
|
||||
sqlite3_finalize(pCur->pStmt);
|
||||
}
|
||||
pCur->pStmt = 0;
|
||||
pCur->needFinalize = 0;
|
||||
pCur->zType = 0;
|
||||
pCur->zSchema = 0;
|
||||
pCur->zName = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a bytecodevtab_cursor.
|
||||
*/
|
||||
static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
||||
bytecodevtabCursorClear(pCur);
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance a bytecodevtab_cursor to its next row of output.
|
||||
*/
|
||||
static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
||||
bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
|
||||
int rc;
|
||||
if( pCur->zP4 ){
|
||||
sqlite3_free(pCur->zP4);
|
||||
pCur->zP4 = 0;
|
||||
}
|
||||
if( pCur->zName ){
|
||||
pCur->zName = 0;
|
||||
pCur->zType = 0;
|
||||
pCur->zSchema = 0;
|
||||
}
|
||||
rc = sqlite3VdbeNextOpcode(
|
||||
(Vdbe*)pCur->pStmt,
|
||||
pCur->showSubprograms ? &pCur->sub : 0,
|
||||
pTab->bTablesUsed,
|
||||
&pCur->iRowid,
|
||||
&pCur->iAddr,
|
||||
&pCur->aOp);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3VdbeMemSetNull(&pCur->sub);
|
||||
pCur->aOp = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
||||
return pCur->aOp==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the bytecodevtab_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int bytecodevtabColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int i /* Which column to return */
|
||||
){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
||||
bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
|
||||
Op *pOp = pCur->aOp + pCur->iAddr;
|
||||
if( pVTab->bTablesUsed ){
|
||||
if( i==4 ){
|
||||
i = 8;
|
||||
}else{
|
||||
if( i<=2 && pCur->zType==0 ){
|
||||
Schema *pSchema;
|
||||
HashElem *k;
|
||||
int iDb = pOp->p3;
|
||||
int iRoot = pOp->p2;
|
||||
sqlite3 *db = pVTab->db;
|
||||
pSchema = db->aDb[iDb].pSchema;
|
||||
pCur->zSchema = db->aDb[iDb].zDbSName;
|
||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
Table *pTab = (Table*)sqliteHashData(k);
|
||||
if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
|
||||
pCur->zName = pTab->zName;
|
||||
pCur->zType = "table";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pCur->zName==0 ){
|
||||
for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
|
||||
Index *pIdx = (Index*)sqliteHashData(k);
|
||||
if( pIdx->tnum==iRoot ){
|
||||
pCur->zName = pIdx->zName;
|
||||
pCur->zType = "index";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 10;
|
||||
}
|
||||
}
|
||||
switch( i ){
|
||||
case 0: /* addr */
|
||||
sqlite3_result_int(ctx, pCur->iAddr);
|
||||
break;
|
||||
case 1: /* opcode */
|
||||
sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
|
||||
-1, SQLITE_STATIC);
|
||||
break;
|
||||
case 2: /* p1 */
|
||||
sqlite3_result_int(ctx, pOp->p1);
|
||||
break;
|
||||
case 3: /* p2 */
|
||||
sqlite3_result_int(ctx, pOp->p2);
|
||||
break;
|
||||
case 4: /* p3 */
|
||||
sqlite3_result_int(ctx, pOp->p3);
|
||||
break;
|
||||
case 5: /* p4 */
|
||||
case 7: /* comment */
|
||||
if( pCur->zP4==0 ){
|
||||
pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
|
||||
}
|
||||
if( i==5 ){
|
||||
sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
|
||||
sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 6: /* p5 */
|
||||
sqlite3_result_int(ctx, pOp->p5);
|
||||
break;
|
||||
case 8: { /* subprog */
|
||||
Op *aOp = pCur->aOp;
|
||||
assert( aOp[0].opcode==OP_Init );
|
||||
assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
|
||||
if( pCur->iRowid==pCur->iAddr+1 ){
|
||||
break; /* Result is NULL for the main program */
|
||||
}else if( aOp[0].p4.z!=0 ){
|
||||
sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
|
||||
}else{
|
||||
sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: /* tables_used.type */
|
||||
sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
|
||||
break;
|
||||
case 11: /* tables_used.schema */
|
||||
sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
|
||||
break;
|
||||
case 12: /* tables_used.name */
|
||||
sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
|
||||
break;
|
||||
case 13: /* tables_used.wr */
|
||||
sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
|
||||
break;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the rowid for the current row. In this implementation, the
|
||||
** rowid is the same as the output value.
|
||||
*/
|
||||
static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize a cursor.
|
||||
**
|
||||
** idxNum==0 means show all subprograms
|
||||
** idxNum==1 means show only the main bytecode and omit subprograms.
|
||||
*/
|
||||
static int bytecodevtabFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
|
||||
bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
bytecodevtabCursorClear(pCur);
|
||||
pCur->iRowid = 0;
|
||||
pCur->iAddr = 0;
|
||||
pCur->showSubprograms = idxNum==0;
|
||||
assert( argc==1 );
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
|
||||
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
|
||||
pCur->needFinalize = 1;
|
||||
}
|
||||
}else{
|
||||
pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
|
||||
}
|
||||
if( pCur->pStmt==0 ){
|
||||
pVTab->base.zErrMsg = sqlite3_mprintf(
|
||||
"argument to %s() is not a valid SQL statement",
|
||||
pVTab->bTablesUsed ? "tables_used" : "bytecode"
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
bytecodevtabNext(pVtabCursor);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** We must have a single stmt=? constraint that will be passed through
|
||||
** into the xFilter method. If there is no valid stmt=? constraint,
|
||||
** then return an SQLITE_CONSTRAINT error.
|
||||
*/
|
||||
static int bytecodevtabBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i;
|
||||
int rc = SQLITE_CONSTRAINT;
|
||||
struct sqlite3_index_constraint *p;
|
||||
bytecodevtab *pVTab = (bytecodevtab*)tab;
|
||||
int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
|
||||
pIdxInfo->estimatedCost = (double)100;
|
||||
pIdxInfo->estimatedRows = 100;
|
||||
pIdxInfo->idxNum = 0;
|
||||
for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
|
||||
if( p->usable==0 ) continue;
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
|
||||
rc = SQLITE_OK;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
||||
}
|
||||
if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
pIdxInfo->idxNum = 1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** virtual table.
|
||||
*/
|
||||
static sqlite3_module bytecodevtabModule = {
|
||||
/* iVersion */ 0,
|
||||
/* xCreate */ 0,
|
||||
/* xConnect */ bytecodevtabConnect,
|
||||
/* xBestIndex */ bytecodevtabBestIndex,
|
||||
/* xDisconnect */ bytecodevtabDisconnect,
|
||||
/* xDestroy */ 0,
|
||||
/* xOpen */ bytecodevtabOpen,
|
||||
/* xClose */ bytecodevtabClose,
|
||||
/* xFilter */ bytecodevtabFilter,
|
||||
/* xNext */ bytecodevtabNext,
|
||||
/* xEof */ bytecodevtabEof,
|
||||
/* xColumn */ bytecodevtabColumn,
|
||||
/* xRowid */ bytecodevtabRowid,
|
||||
/* xUpdate */ 0,
|
||||
/* xBegin */ 0,
|
||||
/* xSync */ 0,
|
||||
/* xCommit */ 0,
|
||||
/* xRollback */ 0,
|
||||
/* xFindMethod */ 0,
|
||||
/* xRename */ 0,
|
||||
/* xSavepoint */ 0,
|
||||
/* xRelease */ 0,
|
||||
/* xRollbackTo */ 0,
|
||||
/* xShadowName */ 0
|
||||
};
|
||||
|
||||
|
||||
int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
|
||||
int rc;
|
||||
rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_BYTECODE_VTAB */
|
||||
@@ -258,18 +258,6 @@ int sqlite3WalTrace = 0;
|
||||
# define WALTRACE(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
|
||||
** places. The following macros try to make this explicit.
|
||||
*/
|
||||
#if GCC_VESRION>=5004000
|
||||
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
|
||||
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
|
||||
#else
|
||||
# define AtomicLoad(PTR) (*(PTR))
|
||||
# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum (and only) versions of the wal and wal-index formats
|
||||
** that may be interpreted by this version of SQLite.
|
||||
@@ -1140,6 +1128,11 @@ static int walIndexRecover(Wal *pWal){
|
||||
u32 aFrameCksum[2] = {0, 0};
|
||||
int iLock; /* Lock offset to lock for checkpoint */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int tmout = 0;
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
|
||||
#endif
|
||||
|
||||
/* Obtain an exclusive lock on all byte in the locking range not already
|
||||
** locked by the caller. The caller is guaranteed to have locked the
|
||||
** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
|
||||
@@ -1886,7 +1879,7 @@ static int walCheckpoint(
|
||||
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
||||
i64 iOffset;
|
||||
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
||||
if( db->u1.isInterrupted ){
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
@@ -2599,7 +2592,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame);
|
||||
AtomicStore(pInfo->aReadMark+i,mxFrame);
|
||||
mxReadMark = mxFrame;
|
||||
mxI = i;
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
break;
|
||||
@@ -2758,6 +2752,9 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
|
||||
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
int rc; /* Return code */
|
||||
int cnt = 0; /* Number of TryBeginRead attempts */
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
int tmout = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int bChanged = 0;
|
||||
@@ -2767,6 +2764,12 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
/* Disable blocking locks. They are not useful when trying to open a
|
||||
** read-transaction, and blocking may cause deadlock anyway. */
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
|
||||
#endif
|
||||
|
||||
do{
|
||||
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
|
||||
}while( rc==WAL_RETRY );
|
||||
@@ -2775,6 +2778,16 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
testcase( rc==SQLITE_PROTOCOL );
|
||||
testcase( rc==SQLITE_OK );
|
||||
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
/* If they were disabled earlier and the read-transaction has been
|
||||
** successfully opened, re-enable blocking locks. This is because the
|
||||
** connection may attempt to upgrade to a write-transaction, which does
|
||||
** benefit from using blocking locks. */
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
|
||||
@@ -3253,11 +3266,7 @@ static int walWriteOneFrame(
|
||||
int rc; /* Result code from subfunctions */
|
||||
void *pData; /* Data actually written */
|
||||
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
|
||||
#else
|
||||
pData = pPage->pData;
|
||||
#endif
|
||||
walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
|
||||
rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
|
||||
if( rc ) return rc;
|
||||
@@ -3440,11 +3449,7 @@ int sqlite3WalFrames(
|
||||
if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
|
||||
pWal->iReCksum = iWrite;
|
||||
}
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
|
||||
#else
|
||||
pData = p->pData;
|
||||
#endif
|
||||
rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff);
|
||||
if( rc ) return rc;
|
||||
p->flags &= ~PGHDR_WAL_APPEND;
|
||||
|
||||
+10
-9
@@ -156,15 +156,16 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
struct SrcList_item *pItem;
|
||||
|
||||
pSrc = p->pSrc;
|
||||
assert( pSrc!=0 );
|
||||
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
||||
if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( pItem->fg.isTabFunc
|
||||
&& sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
||||
){
|
||||
return WRC_Abort;
|
||||
if( pSrc ){
|
||||
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
||||
if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( pItem->fg.isTabFunc
|
||||
&& sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
|
||||
+88
-26
@@ -2298,7 +2298,9 @@ static void whereLoopOutputAdjust(
|
||||
/* In the absence of explicit truth probabilities, use heuristics to
|
||||
** guess a reasonable truth probability. */
|
||||
pLoop->nOut--;
|
||||
if( pTerm->eOperator&(WO_EQ|WO_IS) ){
|
||||
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
|
||||
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
|
||||
){
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
int k = 0;
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
@@ -2307,7 +2309,10 @@ static void whereLoopOutputAdjust(
|
||||
}else{
|
||||
k = 20;
|
||||
}
|
||||
if( iReduce<k ) iReduce = k;
|
||||
if( iReduce<k ){
|
||||
pTerm->wtFlags |= TERM_HEURTRUTH;
|
||||
iReduce = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2489,9 +2494,9 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
|
||||
if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
|
||||
pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
|
||||
pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE;
|
||||
}else{
|
||||
pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
|
||||
pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED;
|
||||
}
|
||||
pNew->wsFlags = saved_wsFlags;
|
||||
pNew->u.btree.nEq = saved_nEq;
|
||||
@@ -2656,6 +2661,27 @@ static int whereLoopAddBtreeIndex(
|
||||
if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
|
||||
if( nOut ){
|
||||
pNew->nOut = sqlite3LogEst(nOut);
|
||||
if( nEq==1
|
||||
/* TUNING: Mark terms as "low selectivity" if they seem likely
|
||||
** to be true for half or more of the rows in the table.
|
||||
** See tag-202002240-1 */
|
||||
&& pNew->nOut+10 > pProbe->aiRowLogEst[0]
|
||||
){
|
||||
#if WHERETRACE_ENABLED /* 0x01 */
|
||||
if( sqlite3WhereTrace & 0x01 ){
|
||||
sqlite3DebugPrintf(
|
||||
"STAT4 determines term has low selectivity:\n");
|
||||
sqlite3WhereTermPrint(pTerm, 999);
|
||||
}
|
||||
#endif
|
||||
pTerm->wtFlags |= TERM_HIGHTRUTH;
|
||||
if( pTerm->wtFlags & TERM_HEURTRUTH ){
|
||||
/* If the term has previously been used with an assumption of
|
||||
** higher selectivity, then set the flag to rerun the
|
||||
** loop computations. */
|
||||
pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS;
|
||||
}
|
||||
}
|
||||
if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
|
||||
pNew->nOut -= nIn;
|
||||
}
|
||||
@@ -2732,6 +2758,7 @@ static int whereLoopAddBtreeIndex(
|
||||
&& saved_nEq+1<pProbe->nKeyCol
|
||||
&& saved_nEq==pNew->nLTerm
|
||||
&& pProbe->noSkipScan==0
|
||||
&& pProbe->hasStat1!=0
|
||||
&& OptimizationEnabled(db, SQLITE_SkipScan)
|
||||
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
|
||||
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
|
||||
@@ -3079,9 +3106,9 @@ static int whereLoopAddBtree(
|
||||
}
|
||||
}
|
||||
|
||||
pBuilder->bldFlags = 0;
|
||||
pBuilder->bldFlags1 = 0;
|
||||
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
|
||||
if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
|
||||
if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){
|
||||
/* If a non-unique index is used, or if a prefix of the key for
|
||||
** unique index is used (making the index functionally non-unique)
|
||||
** then the sqlite_stat1 data becomes important for scoring the
|
||||
@@ -3752,8 +3779,11 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
if( j>=pLoop->nLTerm ) continue;
|
||||
}
|
||||
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
|
||||
if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
|
||||
pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
|
||||
Parse *pParse = pWInfo->pParse;
|
||||
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr);
|
||||
CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
|
||||
assert( pColl1 );
|
||||
if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){
|
||||
continue;
|
||||
}
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
@@ -4533,6 +4563,28 @@ static int exprIsDeterministic(Expr *p){
|
||||
return w.eCode;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
/*
|
||||
** Display all WhereLoops in pWInfo
|
||||
*/
|
||||
static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
|
||||
if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */
|
||||
WhereLoop *p;
|
||||
int i;
|
||||
static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
||||
p->cId = zLabel[i%(sizeof(zLabel)-1)];
|
||||
sqlite3WhereLoopPrint(p, pWC);
|
||||
}
|
||||
}
|
||||
}
|
||||
# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C)
|
||||
#else
|
||||
# define WHERETRACE_ALL_LOOPS(W,C)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Generate the beginning of the loop used for WHERE clause processing.
|
||||
** The return value is a pointer to an opaque structure that contains
|
||||
@@ -4834,19 +4886,28 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
|
||||
rc = whereLoopAddAll(&sWLB);
|
||||
if( rc ) goto whereBeginError;
|
||||
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */
|
||||
WhereLoop *p;
|
||||
int i;
|
||||
static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
||||
p->cId = zLabel[i%(sizeof(zLabel)-1)];
|
||||
sqlite3WhereLoopPrint(p, sWLB.pWC);
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
/* If one or more WhereTerm.truthProb values were used in estimating
|
||||
** loop parameters, but then those truthProb values were subsequently
|
||||
** changed based on STAT4 information while computing subsequent loops,
|
||||
** then we need to rerun the whole loop building process so that all
|
||||
** loops will be built using the revised truthProb values. */
|
||||
if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){
|
||||
WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
|
||||
WHERETRACE(0xffff,
|
||||
("**** Redo all loop computations due to"
|
||||
" TERM_HIGHTRUTH changes ****\n"));
|
||||
while( pWInfo->pLoops ){
|
||||
WhereLoop *p = pWInfo->pLoops;
|
||||
pWInfo->pLoops = p->pNextLoop;
|
||||
whereLoopDelete(db, p);
|
||||
}
|
||||
rc = whereLoopAddAll(&sWLB);
|
||||
if( rc ) goto whereBeginError;
|
||||
}
|
||||
#endif
|
||||
WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
|
||||
|
||||
wherePathSolver(pWInfo, 0);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
@@ -5117,7 +5178,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
|
||||
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
|
||||
){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ);
|
||||
}
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
@@ -5275,12 +5336,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
if( pIn->eEndLoopOp!=OP_Noop ){
|
||||
if( pIn->nPrefix ){
|
||||
assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
||||
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2+(pLevel->iLeftJoin!=0),
|
||||
pIn->iBase, pIn->nPrefix);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( pLevel->iLeftJoin ){
|
||||
/* For LEFT JOIN queries, cursor pIn->iCur may not have been
|
||||
** opened yet. This occurs for WHERE clauses such as
|
||||
@@ -5291,10 +5346,17 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** jump over the OP_Next or OP_Prev instruction about to
|
||||
** be coded. */
|
||||
sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
|
||||
sqlite3VdbeCurrentAddr(v) + 2
|
||||
sqlite3VdbeCurrentAddr(v) + 2 +
|
||||
((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0)
|
||||
);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
||||
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2,
|
||||
pIn->iBase, pIn->nPrefix);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
||||
VdbeCoverage(v);
|
||||
|
||||
+12
-3
@@ -291,6 +291,12 @@ struct WhereTerm {
|
||||
#define TERM_LIKE 0x0400 /* The original LIKE operator */
|
||||
#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */
|
||||
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
|
||||
#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
# define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */
|
||||
#else
|
||||
# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** An instance of the WhereScan object is used as an iterator for locating
|
||||
@@ -405,13 +411,16 @@ struct WhereLoopBuilder {
|
||||
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
|
||||
int nRecValid; /* Number of valid fields currently in pRec */
|
||||
#endif
|
||||
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
|
||||
unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */
|
||||
unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */
|
||||
unsigned int iPlanLimit; /* Search limiter */
|
||||
};
|
||||
|
||||
/* Allowed values for WhereLoopBuider.bldFlags */
|
||||
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
|
||||
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
|
||||
#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */
|
||||
#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
|
||||
|
||||
#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */
|
||||
|
||||
/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
|
||||
** index+constraint combinations the query planner will consider for a
|
||||
|
||||
+6
-1
@@ -1432,7 +1432,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
|
||||
if( pRight ){
|
||||
pRight->iTable = iReg+j+2;
|
||||
sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
|
||||
sqlite3ExprIfFalse(
|
||||
pParse, pCompare, pLevel->addrCont, SQLITE_JUMPIFNULL
|
||||
);
|
||||
}
|
||||
pCompare->pLeft = 0;
|
||||
sqlite3ExprDelete(db, pCompare);
|
||||
@@ -1709,6 +1711,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
nExtraReg = 1;
|
||||
bSeekPastNull = 1;
|
||||
pLevel->regBignull = regBignull = ++pParse->nMem;
|
||||
if( pLevel->iLeftJoin ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull);
|
||||
}
|
||||
pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -377,7 +377,8 @@ static int isAuxiliaryVtabOperator(
|
||||
** MATCH(expression,vtab_column)
|
||||
*/
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
||||
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
||||
if( ExprIsVtab(pCol) ){
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
@@ -399,7 +400,8 @@ static int isAuxiliaryVtabOperator(
|
||||
** with function names in an arbitrary case.
|
||||
*/
|
||||
pCol = pList->a[0].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
||||
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
||||
if( ExprIsVtab(pCol) ){
|
||||
sqlite3_vtab *pVtab;
|
||||
sqlite3_module *pMod;
|
||||
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
|
||||
@@ -422,10 +424,12 @@ static int isAuxiliaryVtabOperator(
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
|
||||
testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
|
||||
if( ExprIsVtab(pLeft) ){
|
||||
res++;
|
||||
}
|
||||
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
|
||||
testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
|
||||
if( pRight && ExprIsVtab(pRight) ){
|
||||
res++;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
}
|
||||
|
||||
@@ -933,6 +933,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
Window *pMWin = p->pWin; /* Master window object */
|
||||
Window *pWin; /* Window object iterator */
|
||||
Table *pTab;
|
||||
u32 selFlags = p->selFlags;
|
||||
|
||||
pTab = sqlite3DbMallocZero(db, sizeof(Table));
|
||||
if( pTab==0 ){
|
||||
@@ -1022,6 +1023,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
sqlite3SrcListAssignCursors(pParse, p->pSrc);
|
||||
pSub->selFlags |= SF_Expanded;
|
||||
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
|
||||
pSub->selFlags |= (selFlags & SF_Aggregate);
|
||||
if( pTab2==0 ){
|
||||
/* Might actually be some other kind of error, but in that case
|
||||
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
|
||||
@@ -1910,6 +1912,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
|
||||
Window *pWin;
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
FuncDef *pFunc = pWin->pFunc;
|
||||
assert( pWin->regAccum );
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
|
||||
nArg = MAX(nArg, windowArgCount(pWin));
|
||||
if( pMWin->regStartRowid==0 ){
|
||||
@@ -2288,6 +2291,10 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
|
||||
pNew->eStart = p->eStart;
|
||||
pNew->eExclude = p->eExclude;
|
||||
pNew->regResult = p->regResult;
|
||||
pNew->regAccum = p->regAccum;
|
||||
pNew->iArgCol = p->iArgCol;
|
||||
pNew->iEphCsr = p->iEphCsr;
|
||||
pNew->bExprArgs = p->bExprArgs;
|
||||
pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
|
||||
pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);
|
||||
pNew->pOwner = pOwner;
|
||||
|
||||
+47
-1
@@ -594,7 +594,6 @@ reset_db
|
||||
do_execsql_test 18.1.0 {
|
||||
CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)) WITHOUT ROWID;
|
||||
}
|
||||
breakpoint
|
||||
do_execsql_test 18.1.1 {
|
||||
ALTER TABLE t0 RENAME COLUMN c0 TO c1;
|
||||
}
|
||||
@@ -613,4 +612,51 @@ do_execsql_test 18.2.2 {
|
||||
SELECT sql FROM sqlite_master;
|
||||
} {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1))}}
|
||||
|
||||
# 2020-02-23 ticket f50af3e8a565776b
|
||||
reset_db
|
||||
do_execsql_test 19.100 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE VIEW t2 AS SELECT 1 FROM t1, (t1 AS a0, t1);
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
SELECT sql FROM sqlite_master;
|
||||
} {{CREATE TABLE "t3"(x)} {CREATE VIEW t2 AS SELECT 1 FROM "t3", ("t3" AS a0, "t3")}}
|
||||
do_execsql_test 19.110 {
|
||||
INSERT INTO t3(x) VALUES(123);
|
||||
SELECT * FROM t2;
|
||||
} {1}
|
||||
do_execsql_test 19.120 {
|
||||
INSERT INTO t3(x) VALUES('xyz');
|
||||
SELECT * FROM t2;
|
||||
} {1 1 1 1 1 1 1 1}
|
||||
|
||||
# Ticket 4722bdab08cb14
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE TABLE a(a);
|
||||
CREATE VIEW b AS SELECT(SELECT *FROM c JOIN a USING(d, a, a, a) JOIN a) IN();
|
||||
}
|
||||
do_execsql_test 20.1 {
|
||||
ALTER TABLE a RENAME a TO e;
|
||||
} {}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 21.0 {
|
||||
CREATE TABLE a(b);
|
||||
CREATE VIEW c AS
|
||||
SELECT NULL INTERSECT
|
||||
SELECT NULL ORDER BY
|
||||
likelihood(NULL, (d, (SELECT c)));
|
||||
} {}
|
||||
do_catchsql_test 21.1 {
|
||||
SELECT likelihood(NULL, (d, (SELECT c)));
|
||||
} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}}
|
||||
do_catchsql_test 21.2 {
|
||||
SELECT * FROM c;
|
||||
} {1 {1st ORDER BY term does not match any column in the result set}}
|
||||
|
||||
do_catchsql_test 21.3 {
|
||||
ALTER TABLE a RENAME TO e;
|
||||
} {1 {error in view c: 1st ORDER BY term does not match any column in the result set}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# 2020-02-23
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# Tests for functionality related to ANALYZE.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !stat4 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set testprefix analyzeG
|
||||
|
||||
proc do_scan_order_test {tn sql expect} {
|
||||
uplevel [list do_test $tn [subst -nocommands {
|
||||
set res ""
|
||||
db eval "explain query plan $sql" {
|
||||
lappend res [set detail]
|
||||
}
|
||||
set res
|
||||
}] [list {*}$expect]]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases 1.* seek to verify that even if an index is not used, its
|
||||
# stat4 data may be used by the planner to estimate the number of
|
||||
# rows that match an unindexed constraint on the same column.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA automatic_index = 0;
|
||||
CREATE TABLE t1(a, x);
|
||||
CREATE TABLE t2(b, y);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
|
||||
)
|
||||
INSERT INTO t1 SELECT (i%50), NULL FROM s;
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
|
||||
)
|
||||
INSERT INTO t2 SELECT (CASE WHEN i<95 THEN 44 ELSE i END), NULL FROM s;
|
||||
}
|
||||
|
||||
# Join tables t1 and t2. Both contain 100 rows. (a=44) matches 2 rows
|
||||
# in "t1", (b=44) matches 95 rows in table "t2". But the planner doesn't
|
||||
# know this, so it has no preference as to which order the tables are
|
||||
# scanned in. In practice this means that tables are scanned in the order
|
||||
# they are specified in in the FROM clause.
|
||||
do_scan_order_test 1.1.1 {
|
||||
SELECT * FROM t1, t2 WHERE a=44 AND b=44;
|
||||
} {
|
||||
{SCAN TABLE t1} {SCAN TABLE t2}
|
||||
}
|
||||
do_scan_order_test 1.1.2 {
|
||||
SELECT * FROM t2, t1 WHERE a=44 AND b=44
|
||||
} {
|
||||
{SCAN TABLE t2} {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
CREATE INDEX t2b ON t2(b);
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
# Now, with the ANALYZE data, the planner knows that (b=44) matches a
|
||||
# large number of rows. So it elects to scan table "t1" first, regardless
|
||||
# of the order in which the tables are specified in the FROM clause.
|
||||
do_scan_order_test 1.3.1 {
|
||||
SELECT * FROM t1, t2 WHERE a=44 AND b=44;
|
||||
} {
|
||||
{SCAN TABLE t1} {SCAN TABLE t2}
|
||||
}
|
||||
do_scan_order_test 1.3.2 {
|
||||
SELECT * FROM t2, t1 WHERE a=44 AND b=44
|
||||
} {
|
||||
{SCAN TABLE t1} {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
+5
-8
@@ -148,10 +148,8 @@ do_test attach-1.14 {
|
||||
ATTACH 'test.db' as db9;
|
||||
}
|
||||
} {1 {database db9 is already in use}}
|
||||
do_test attach-1.15 {
|
||||
catchsql {
|
||||
ATTACH 'test.db' as main;
|
||||
}
|
||||
do_catchsql_test attach-1.15 {
|
||||
ATTACH 'test.db' as main;
|
||||
} {1 {database main is already in use}}
|
||||
ifcapable tempdb {
|
||||
do_test attach-1.16 {
|
||||
@@ -160,10 +158,8 @@ ifcapable tempdb {
|
||||
}
|
||||
} {1 {database temp is already in use}}
|
||||
}
|
||||
do_test attach-1.17 {
|
||||
catchsql {
|
||||
ATTACH 'test.db' as MAIN;
|
||||
}
|
||||
do_catchsql_test attach-1.17 {
|
||||
ATTACH 'test.db' as MAIN;
|
||||
} {1 {database MAIN is already in use}}
|
||||
do_test attach-1.18 {
|
||||
catchsql {
|
||||
@@ -231,6 +227,7 @@ do_test attach-1.26 {
|
||||
}
|
||||
} {1 {cannot detach database main}}
|
||||
|
||||
|
||||
ifcapable tempdb {
|
||||
do_test attach-1.27 {
|
||||
catchsql {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# 2020-01-29
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindex7
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
|
||||
proc vtab_command {src method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE xxx(a)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set clist [lindex $args 0]
|
||||
set iCons 0
|
||||
set ret [list]
|
||||
foreach cons $clist {
|
||||
catch { array unset C }
|
||||
array set C $cons
|
||||
if {$C(usable)} {
|
||||
lappend ret use $iCons
|
||||
}
|
||||
incr iCons
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
xFilter {
|
||||
return [list sql "SELECT rowid, x FROM $src"]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(0), (2);
|
||||
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 { select * from vt1 } {0 2}
|
||||
do_execsql_test 1.2 { select * from vt1 WHERE a=0 } {0}
|
||||
do_execsql_test 1.3 { select * from vt1 WHERE a=1 } {}
|
||||
do_execsql_test 1.4 { select * from vt1 WHERE a=1 OR a=0} {0}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
UPDATE t1 SET x=NULL WHERE x=2;
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 { select * from vt1 } {0 {}}
|
||||
do_execsql_test 1.7 { select * from vt1 WHERE a=0 } {0}
|
||||
do_execsql_test 1.8 { select * from vt1 WHERE a=1 } {}
|
||||
do_execsql_test 1.9 { select * from vt1 WHERE a=1 OR a=0} {0}
|
||||
do_execsql_test 1.10 { select * from vt1 WHERE a IN (2) } {}
|
||||
do_execsql_test 1.10 { select * from vt1 WHERE a IN (0,1,2,3) } {0}
|
||||
do_execsql_test 1.11 { select * from vt1 WHERE a IN (0, NULL) } {0}
|
||||
do_execsql_test 1.12 { select * from vt1 WHERE a IN (NULL) } {}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ do_test check-2.6 {
|
||||
catchsql {
|
||||
INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
|
||||
}
|
||||
} {1 {CHECK constraint failed: three}}
|
||||
} {0 {}}
|
||||
|
||||
# Undocumented behavior: The CONSTRAINT name clause can follow a constraint.
|
||||
# Such a clause is ignored. But the parser must accept it for backwards
|
||||
|
||||
@@ -1138,5 +1138,49 @@ do_catchsql_test 13.1 {
|
||||
INSERT INTO t1(b,c) SELECT last_insert_rowid(), x FROM c;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 14.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 512 pagesize 65536 filename clusterfuzz-testcase-minimized-sqlite3_dbfuzz2_fuzzer-4806406219825152
|
||||
| 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: 00 01 02 01 00 40 20 20 00 63 2e 78 00 00 00 07 .....@ .c.x....
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 01 00 35 05 43 00 04 00 00 00 ........5.C.....
|
||||
| 80: 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 0c ................
|
||||
| 96: 00 2e 2c 50 0d 00 00 00 03 00 00 00 01 da 01 b0 ..,P............
|
||||
| 112: 01 56 01 86 01 2a 01 02 00 00 00 00 00 00 00 1c .V...*..........
|
||||
| 128: 00 38 80 b2 e6 0e 00 00 00 00 00 00 00 00 00 10 .8..............
|
||||
| 144: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
|
||||
| 160: 00 00 00 00 00 00 00 00 00 00 00 00 45 20 54 41 ............E TA
|
||||
| 256: 00 00 00 00 00 00 22 07 06 17 11 11 01 35 74 61 .............5ta
|
||||
| 272: 62 6c 00 10 00 00 34 07 43 52 54 45 20 54 41 42 bl....4.CRTE TAB
|
||||
| 288: 4c 45 20 74 33 28 63 2e 78 2c 65 2c 66 15 28 3a LE t3(c.x,e,f.(:
|
||||
| 304: 06 17 11 11 01 65 78 8c cc 87 85 35 05 43 72 45 .....ex....5.CrE
|
||||
| 320: 41 54 48 20 49 4e 44 45 58 20 74 33 78 20 4f 4e ATH INDEX t3x ON
|
||||
| 336: 20 74 33 28 78 39 2e 04 06 17 15 11 01 45 69 6e t3(x9.......Ein
|
||||
| 352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45 dext2cdt2.CREATE
|
||||
| 368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74 INDEX t2cd ON t
|
||||
| 384: 32 28 63 2a 44 29 28 05 fa e8 ee ed 01 3d 74 63 2(c*D)(......=tc
|
||||
| 400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54 blet3t3.CREATE T
|
||||
| 416: 41 42 4c 45 20 74 33 28 63 2e 78 2c 65 2c 66 15 ABLE t3(c.x,e,f.
|
||||
| 432: 28 3a 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74 (:.....=tablet2t
|
||||
| 448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 2.CREATE TABLE t
|
||||
| 464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11 2(c,d,e,f)$.....
|
||||
| 480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .5tablet1t1.CREA
|
||||
| 496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 63 29 TE TABLE t1(a,c)
|
||||
| end clusterfuzz-testcase-minimized-sqlite3_dbfuzz2_fuzzer-4806406219825152
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 14.1 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 14.2 {
|
||||
ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cse
|
||||
|
||||
do_test cse-1.1 {
|
||||
execsql {
|
||||
@@ -157,4 +158,43 @@ for {set i 1} {$i<100} {incr i} {
|
||||
} $answer
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ticket fd1bda016d1a
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a TEXT, b);
|
||||
INSERT INTO t1 VALUES('hello', 0);
|
||||
INSERT INTO t1 VALUES('world', 0);
|
||||
|
||||
CREATE TABLE t2(x TEXT);
|
||||
INSERT INTO t2 VALUES('hello');
|
||||
INSERT INTO t2 VALUES('world');
|
||||
|
||||
CREATE TABLE t3(y);
|
||||
INSERT INTO t3 VALUES(1000);
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT 1000 = y FROM t3
|
||||
} {1}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT 1000 IN (SELECT x FROM t2), 1000 = y FROM t3
|
||||
} {0 1}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SELECT 0 IN (SELECT a), (SELECT a LIMIT 0) FROM t1
|
||||
} {0 {} 0 {}}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT 0 IN (SELECT a) FROM t1 WHERE a = 'hello' OR (SELECT a LIMIT 0);
|
||||
} {0}
|
||||
|
||||
do_execsql_test 3.5 {
|
||||
CREATE TABLE v0(v1 VARCHAR0);
|
||||
INSERT INTO v0 VALUES(2), (3);
|
||||
SELECT 0 IN(SELECT v1) FROM v0 WHERE v1 = 2 OR(SELECT v1 LIMIT 0);
|
||||
} {0}
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user