diff --git a/Makefile.in b/Makefile.in
index 4d14084e03..e4dcbcd90c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -432,7 +432,7 @@ TESTSRC = \
$(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/session/test_session.c \
- $(TOP)/ext/rbu/test_rbu.c
+ $(TOP)/ext/rbu/test_rbu.c
# Statically linked extensions
#
@@ -522,7 +522,8 @@ TESTSRC2 = \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/misc/stmt.c
+ $(TOP)/ext/misc/stmt.c \
+ fts5.c
# Header files used by all library source files.
#
@@ -616,12 +617,10 @@ 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
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
@@ -695,7 +694,6 @@ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -1235,7 +1233,6 @@ 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_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
@@ -1431,6 +1428,9 @@ threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
threadtest: threadtest3$(TEXE)
./threadtest3$(TEXE)
+threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
+ $(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS)
+
releasetest:
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
@@ -1484,6 +1484,7 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f dbhash dbhash.exe
rm -f fts5.* fts5parse.*
+ rm -f threadtest5
distclean: clean
rm -f config.h config.log config.status libtool Makefile sqlite3.pc
diff --git a/Makefile.msc b/Makefile.msc
index f9d4016a65..ff6618e30b 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -367,7 +367,6 @@ 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
!ENDIF
@@ -1552,7 +1551,7 @@ TESTSRC = \
$(TOP)\ext\fts3\fts3_term.c \
$(TOP)\ext\fts3\fts3_test.c \
$(TOP)\ext\rbu\test_rbu.c \
- $(TOP)\ext\session\test_session.c
+ $(TOP)\ext\session\test_session.c
# Statically linked extensions.
#
@@ -1586,7 +1585,8 @@ TESTEXT = \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\unionvtab.c \
- $(TOP)\ext\misc\wholenumber.c
+ $(TOP)\ext\misc\wholenumber.c \
+ fts5.c
# If use of zlib is enabled, add the "zipfile.c" source file.
#
@@ -1689,7 +1689,6 @@ FUZZDATA = \
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
# <>
@@ -1698,7 +1697,6 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
@@ -2392,7 +2390,6 @@ 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) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
diff --git a/README.md b/README.md
index c12b77c1b9..fb72ae8c28 100644
--- a/README.md
+++ b/README.md
@@ -55,11 +55,11 @@ a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.)
Then run commands like this:
- mkdir ~/sqlite
+ mkdir -p ~/sqlite ~/Fossils
cd ~/sqlite
- fossil clone https://www.sqlite.org/src sqlite.fossil
- fossil open sqlite.fossil
-
+ fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
+ fossil open ~/Fossils/sqlite.fossil
+
After setting up a repository using the steps above, you can always
update to the lastest version using:
diff --git a/VERSION b/VERSION
index 9775ea7450..0b477b458f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.35.3
+3.36.0
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index 1f177557a2..40d0e8113d 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -290,7 +290,6 @@ 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
!ENDIF
@@ -960,7 +959,6 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
diff --git a/configure b/configure
index eb21344ce5..5df1386305 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.35.3.
+# Generated by GNU Autoconf 2.69 for sqlite 3.36.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.35.3'
-PACKAGE_STRING='sqlite 3.35.3'
+PACKAGE_VERSION='3.36.0'
+PACKAGE_STRING='sqlite 3.36.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.35.3 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.36.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.35.3:";;
+ short | recursive ) echo "Configuration of sqlite 3.36.0:";;
esac
cat <<\_ACEOF
@@ -1660,7 +1660,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.35.3
+sqlite configure 3.36.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2079,7 +2079,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.35.3, which was
+It was created by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12378,7 +12378,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.35.3, which was
+This file was extended by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12444,7 +12444,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.35.3
+sqlite config.status 3.36.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/doc/lemon.html b/doc/lemon.html
index 457004627e..324b3f3319 100644
--- a/doc/lemon.html
+++ b/doc/lemon.html
@@ -697,6 +697,7 @@ other than that, the order of directives in Lemon is arbitrary.
%token_prefix
@@ -1079,14 +1080,37 @@ can choose a different start symbol using the
See Error Processing.
+
+4.4.20 The %token directive
+
+Tokens are normally created automatically, the first time they are used.
+Any identifier that begins with an upper-case letter is a token.
+
+
Sometimes it is useful to declare tokens in advance, however. The
+integer values assigned to each token determined by the order in which
+the tokens are seen. So by declaring tokens in advance, it is possible to
+cause some tokens to have low-numbered values, which might be desirable in
+some grammers, or to have sequential values assigned to a sequence of
+related tokens. For this reason, the %token directive is provided to
+declare tokens in advance. The syntax is as follows:
+
+
+%token TOKEN TOKEN... .
+
+
+The %token directive is followed by zero or more token symbols and
+terminated by a single ".". Each token named is created if it does not
+already exist. Tokens are created in order.
+
+
-
4.4.20 The %token_class directive
+4.4.21 The %token_class directive
Undocumented. Appears to be related to the MULTITERMINAL concept.
Implementation.
-4.4.21 The %token_destructor directive
+4.4.22 The %token_destructor directive
The %destructor directive assigns a destructor to a non-terminal
symbol. (See the description of the
@@ -1102,7 +1126,7 @@ Other than that, the token destructor works just like the non-terminal
destructors.
-4.4.22 The %token_prefix directive
+4.4.23 The %token_prefix directive
Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
@@ -1129,7 +1153,7 @@ to each of the #defines it generates.
-4.4.23 The %token_type and %type directives
+4.4.24 The %token_type and %type directives
These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
@@ -1166,7 +1190,7 @@ entry parser stack will require 100K of heap space. If you are willing
and able to pay that price, fine. You just need to know.
-4.4.24 The %wildcard directive
+4.4.25 The %wildcard directive
The %wildcard directive is followed by a single token name and a
period. This directive specifies that the identified token should
diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test
index 0e6fc82604..3987d0c910 100644
--- a/ext/expert/expert1.test
+++ b/ext/expert/expert1.test
@@ -103,7 +103,7 @@ do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
SELECT * FROM t1
} {
(no new indexes)
- SCAN TABLE t1
+ SCAN t1
}
do_setup_rec_test $tn.2 {
@@ -112,7 +112,7 @@ do_setup_rec_test $tn.2 {
SELECT * FROM t1 WHERE b>?;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
- SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
+ SEARCH t1 USING INDEX t1_idx_00000062 (b>?)
}
do_setup_rec_test $tn.3 {
@@ -121,7 +121,7 @@ do_setup_rec_test $tn.3 {
SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
} {
CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
- SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b)
+ SEARCH t1 USING INDEX t1_idx_3e094c27 (b>? AND b)
}
do_setup_rec_test $tn.4 {
@@ -130,7 +130,7 @@ do_setup_rec_test $tn.4 {
SELECT a FROM t1 ORDER BY b;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
- SCAN TABLE t1 USING INDEX t1_idx_00000062
+ SCAN t1 USING INDEX t1_idx_00000062
}
do_setup_rec_test $tn.5 {
@@ -139,7 +139,7 @@ do_setup_rec_test $tn.5 {
SELECT a FROM t1 WHERE a=? ORDER BY b;
} {
CREATE INDEX t1_idx_000123a7 ON t1(a, b);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
+ SEARCH t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
}
if 0 {
@@ -149,7 +149,7 @@ do_setup_rec_test $tn.6 {
SELECT min(a) FROM t1
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
+ SEARCH t1 USING COVERING INDEX t1_idx_00000061
}
}
@@ -159,7 +159,7 @@ do_setup_rec_test $tn.7 {
SELECT * FROM t1 ORDER BY a, b, c;
} {
CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
+ SCAN t1 USING COVERING INDEX t1_idx_033e95fe
}
#do_setup_rec_test $tn.1.8 {
@@ -168,7 +168,7 @@ do_setup_rec_test $tn.7 {
# SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
#} {
# CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
-# 0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
+# 0|0|0|SCAN t1 USING COVERING INDEX t1_idx_5be6e222
#}
do_setup_rec_test $tn.8.1 {
@@ -177,7 +177,7 @@ do_setup_rec_test $tn.8.1 {
SELECT * FROM t1 WHERE a=?
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
+ SEARCH t1 USING INDEX t1_idx_00000061 (a=?)
}
do_setup_rec_test $tn.8.2 {
CREATE TABLE t1(a, b COLLATE nocase, c);
@@ -185,7 +185,7 @@ do_setup_rec_test $tn.8.2 {
SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
} {
CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
+ SCAN t1 USING COVERING INDEX t1_idx_5cb97285
}
@@ -197,7 +197,7 @@ do_setup_rec_test $tn.9.1 {
SELECT * FROM "t t" WHERE a=?
} {
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
- SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
+ SEARCH t t USING INDEX t t_idx_00000061 (a=?)
}
do_setup_rec_test $tn.9.2 {
@@ -206,7 +206,7 @@ do_setup_rec_test $tn.9.2 {
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
} {
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
- SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b)
+ SEARCH t t USING INDEX t t_idx_00000062 (b>? AND b)
}
# Columns with names that require quotes.
@@ -217,7 +217,7 @@ do_setup_rec_test $tn.10.1 {
SELECT * FROM t3 WHERE "b b" = ?
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
+ SEARCH t3 USING INDEX t3_idx_00050c52 (b b=?)
}
do_setup_rec_test $tn.10.2 {
@@ -226,7 +226,7 @@ do_setup_rec_test $tn.10.2 {
SELECT * FROM t3 ORDER BY "b b"
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SCAN TABLE t3 USING INDEX t3_idx_00050c52
+ SCAN t3 USING INDEX t3_idx_00050c52
}
# Transitive constraints
@@ -239,8 +239,8 @@ do_setup_rec_test $tn.11.1 {
} {
CREATE INDEX t5_idx_000123a7 ON t5(a, b);
CREATE INDEX t6_idx_00000063 ON t6(c);
- SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
- SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
+ SEARCH t6 USING INDEX t6_idx_00000063 (c=?)
+ SEARCH t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
}
# OR terms.
@@ -254,9 +254,9 @@ do_setup_rec_test $tn.12.1 {
CREATE INDEX t7_idx_00000061 ON t7(a);
MULTI-INDEX OR
INDEX 1
- SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
+ SEARCH t7 USING INDEX t7_idx_00000061 (a=?)
INDEX 2
- SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
+ SEARCH t7 USING INDEX t7_idx_00000062 (b=?)
}
# rowid terms.
@@ -267,7 +267,7 @@ do_setup_rec_test $tn.13.1 {
SELECT * FROM t8 WHERE rowid=?
} {
(no new indexes)
- SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
+ SEARCH t8 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.13.2 {
CREATE TABLE t8(a, b);
@@ -275,7 +275,7 @@ do_setup_rec_test $tn.13.2 {
SELECT * FROM t8 ORDER BY rowid
} {
(no new indexes)
- SCAN TABLE t8
+ SCAN t8
}
do_setup_rec_test $tn.13.3 {
CREATE TABLE t8(a, b);
@@ -283,7 +283,7 @@ do_setup_rec_test $tn.13.3 {
SELECT * FROM t8 WHERE a=? ORDER BY rowid
} {
CREATE INDEX t8_idx_00000061 ON t8(a);
- SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
+ SEARCH t8 USING INDEX t8_idx_00000061 (a=?)
}
# Triggers
@@ -298,7 +298,7 @@ do_setup_rec_test $tn.14 {
INSERT INTO t9 VALUES(?, ?, ?);
} {
CREATE INDEX t10_idx_00000062 ON t10(b);
- SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
+ SEARCH t10 USING INDEX t10_idx_00000062 (b=?)
}
do_setup_rec_test $tn.15 {
@@ -314,8 +314,8 @@ do_setup_rec_test $tn.15 {
SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
} {
CREATE INDEX t2_idx_00000064 ON t2(d);
- SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ SEARCH t2 USING INDEX t2_idx_00000064 (d=?)
+ SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.16 {
@@ -324,7 +324,7 @@ do_setup_rec_test $tn.16 {
SELECT * FROM t1 WHERE b IS NOT NULL;
} {
(no new indexes)
- SCAN TABLE t1
+ SCAN t1
}
do_setup_rec_test $tn.17.1 {
@@ -333,7 +333,7 @@ do_setup_rec_test $tn.17.1 {
SELECT * FROM example WHERE a=?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=?)
}
do_setup_rec_test $tn.17.2 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -341,7 +341,7 @@ do_setup_rec_test $tn.17.2 {
SELECT * FROM example WHERE b=?
} {
CREATE INDEX example_idx_00000042 ON example(B);
- SEARCH TABLE example USING INDEX example_idx_00000042 (B=?)
+ SEARCH example USING INDEX example_idx_00000042 (B=?)
}
do_setup_rec_test $tn.17.3 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -349,7 +349,7 @@ do_setup_rec_test $tn.17.3 {
SELECT * FROM example WHERE a=? AND b=?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
}
do_setup_rec_test $tn.17.4 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -357,7 +357,7 @@ do_setup_rec_test $tn.17.4 {
SELECT * FROM example WHERE a=? AND b>?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
}
do_setup_rec_test $tn.17.5 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -365,7 +365,7 @@ do_setup_rec_test $tn.17.5 {
SELECT * FROM example WHERE a>? AND b=?
} {
CREATE INDEX example_idx_0000cb3f ON example(B, A);
- SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
+ SEARCH example USING INDEX example_idx_0000cb3f (B=? AND A>?)
}
do_setup_rec_test $tn.18.0 {
@@ -377,7 +377,7 @@ do_setup_rec_test $tn.18.0 {
SELECT x FROM SomeObject;
} {
(no new indexes)
- SCAN TABLE SomeObject
+ SCAN SomeObject
}
do_setup_rec_test $tn.18.1 {
CREATE TABLE SomeObject (
@@ -388,7 +388,7 @@ do_setup_rec_test $tn.18.1 {
SELECT * FROM SomeObject WHERE x=?;
} {
CREATE INDEX SomeObject_idx_00000078 ON SomeObject(x);
- SEARCH TABLE SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
+ SEARCH SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
}
}
@@ -455,4 +455,3 @@ do_execsql_test 5.3 {
}
finish_test
-
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index 50fa88db8a..9c5703d3f1 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -326,7 +326,9 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
int sqlite3_fts3_may_be_corrupt = 1;
+#endif
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
@@ -1897,7 +1899,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
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 */
+ u64 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
@@ -1913,8 +1915,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -1967,20 +1969,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
@@ -3586,14 +3588,20 @@ static int fts3SetHasStat(Fts3Table *p){
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
+ int rc;
UNUSED_PARAMETER(pVtab);
assert( p->pSegments==0 );
assert( p->nPendingData==0 );
assert( p->inTransaction!=1 );
- TESTONLY( p->inTransaction = 1 );
- TESTONLY( p->mxSavepoint = -1; );
p->nLeafAdd = 0;
- return fts3SetHasStat(p);
+ rc = fts3SetHasStat(p);
+#ifdef SQLITE_DEBUG
+ if( rc==SQLITE_OK ){
+ p->inTransaction = 1;
+ p->mxSavepoint = -1;
+ }
+#endif
+ return rc;
}
/*
@@ -5122,16 +5130,15 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
- Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
- apOr = (Fts3Expr **)&aTC[nToken];
if( !aTC ){
rc = SQLITE_NOMEM;
}else{
+ Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
int ii;
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index b3e0ec85fb..8c2579166d 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -134,7 +134,7 @@ SQLITE_EXTENSION_INIT3
** is used for assert() conditions that are true only if it can be
** guranteed that the database is not corrupt.
*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+#ifdef SQLITE_DEBUG
extern int sqlite3_fts3_may_be_corrupt;
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
#else
diff --git a/ext/fts3/fts3_aux.c b/ext/fts3/fts3_aux.c
index 08edc00f40..b6e651853b 100644
--- a/ext/fts3/fts3_aux.c
+++ b/ext/fts3/fts3_aux.c
@@ -406,6 +406,7 @@ static int fts3auxFilterMethod(
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->aStat);
+ sqlite3_free(pCsr->zStop);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c
index ebc771fd6a..613d3e5f16 100644
--- a/ext/fts3/fts3_snippet.c
+++ b/ext/fts3/fts3_snippet.c
@@ -17,6 +17,10 @@
#include
#include
+#ifndef SQLITE_AMALGAMATION
+typedef sqlite3_int64 i64;
+#endif
+
/*
** Characters that may appear in the second argument to matchinfo().
*/
@@ -67,9 +71,9 @@ struct SnippetIter {
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
- int iHead; /* Next value in position list */
+ i64 iHead; /* Next value in position list */
char *pHead; /* Position list data following iHead */
- int iTail; /* Next value in trailing position list */
+ i64 iTail; /* Next value in trailing position list */
char *pTail; /* Position list data following iTail */
};
@@ -234,7 +238,7 @@ void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
-static void fts3GetDeltaPosition(char **pp, int *piPos){
+static void fts3GetDeltaPosition(char **pp, i64 *piPos){
int iVal;
*pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
@@ -343,10 +347,10 @@ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
-static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
+static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
- int iIter = *piIter;
+ i64 iIter = *piIter;
while( iIteraPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
- int iCsr = pPhrase->iTail;
+ i64 iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
@@ -475,7 +479,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( pCsr ){
- int iFirst = 0;
+ i64 iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
if( iFirst<0 ){
@@ -1539,8 +1543,8 @@ typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
- int iPos; /* Position just read from pList */
- int iOff; /* Offset of this term from read positions */
+ i64 iPos; /* Position just read from pList */
+ i64 iOff; /* Offset of this term from read positions */
};
struct TermOffsetCtx {
@@ -1559,7 +1563,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
int nTerm; /* Number of tokens in phrase */
int iTerm; /* For looping through nTerm phrase terms */
char *pList; /* Pointer to position list for phrase */
- int iPos = 0; /* First position in position-list */
+ i64 iPos = 0; /* First position in position-list */
int rc;
UNUSED_PARAMETER(iPhrase);
diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c
index fa0f00a6ce..49a8476bf3 100644
--- a/ext/fts3/fts3_test.c
+++ b/ext/fts3/fts3_test.c
@@ -585,6 +585,7 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifdef SQLITE_DEBUG
int bOld = sqlite3_fts3_may_be_corrupt;
if( objc!=2 && objc!=1 ){
@@ -598,6 +599,7 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
+#endif
return TCL_OK;
}
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index bc42fc3d63..544e23addd 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -1807,7 +1807,7 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
if( rc==0 ){
rc = pRhs->iIdx - pLhs->iIdx;
}
- assert( rc!=0 );
+ assert_fts3_nc( rc!=0 );
return rc;
}
diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c
index 6c02d2b35f..32335c9374 100644
--- a/ext/fts5/fts5_config.c
+++ b/ext/fts5/fts5_config.c
@@ -537,7 +537,7 @@ int sqlite3Fts5ConfigParse(
nByte = nArg * (sizeof(char*) + sizeof(u8));
pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
- pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
+ pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0;
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
pRet->bColumnsize = 1;
diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c
index 088d8b8cae..f3cec00be8 100644
--- a/ext/fts5/fts5_expr.c
+++ b/ext/fts5/fts5_expr.c
@@ -2412,6 +2412,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
return pRet;
}
+#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
@@ -2778,12 +2779,14 @@ static void fts5ExprFold(
sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
}
}
+#endif /* ifdef SQLITE_TEST */
/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
+#ifdef SQLITE_TEST
struct Fts5ExprFunc {
const char *z;
void (*x)(sqlite3_context*,int,sqlite3_value**);
@@ -2801,6 +2804,10 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
+#else
+ int rc = SQLITE_OK;
+ UNUSED_PARAM2(pGlobal,db);
+#endif
/* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
** sqlite3Fts5ParserFallback() are unused */
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 7a9ad5d713..b66e9bece4 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -431,7 +431,7 @@ struct Fts5SegIter {
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
- int iLeafOffset; /* Byte offset within current leaf */
+ i64 iLeafOffset; /* Byte offset within current leaf */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
@@ -1611,7 +1611,7 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset;
+ i64 iOff = pIter->iLeafOffset;
ASSERT_SZLEAF_OK(pIter->pLeaf);
if( iOff>=pIter->pLeaf->szLeaf ){
@@ -1644,7 +1644,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset; /* Offset to read at */
+ i64 iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
@@ -2072,7 +2072,6 @@ static void fts5SegIterNext(
** this block is particularly performance critical, so equivalent
** code is inlined. */
int nSz;
- assert( p->rc==SQLITE_OK );
assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
@@ -4541,14 +4540,14 @@ static void fts5FlushOneHash(Fts5Index *p){
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
}else{
i64 iRowid = 0;
- i64 iDelta = 0;
+ u64 iDelta = 0;
int iOff = 0;
/* The entire doclist will not fit on this leaf. The following
** loop iterates through the poslists that make up the current
** doclist. */
while( p->rc==SQLITE_OK && iOffiter.nPoslist - pHead->iOff;
/* WRITEPOSLISTSIZE */
- assert( tmp.n+nTail<=nTmp );
+ assert_nc( tmp.n+nTail<=nTmp );
+ assert( tmp.n+nTail<=nTmp+nMerge*10 );
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
break;
@@ -6226,6 +6226,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
** function only.
*/
+#ifdef SQLITE_TEST
/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
@@ -6248,7 +6249,9 @@ static void fts5DecodeRowid(
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -6266,7 +6269,9 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugStructure(
int *pRc, /* IN/OUT: error code */
Fts5Buffer *pBuf,
@@ -6288,7 +6293,9 @@ static void fts5DebugStructure(
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -6313,7 +6320,9 @@ static void fts5DecodeStructure(
fts5DebugStructure(pRc, pBuf, p);
fts5StructureRelease(p);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -6336,7 +6345,9 @@ static void fts5DecodeAverages(
zSpace = " ";
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
@@ -6353,7 +6364,9 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
}
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
@@ -6386,7 +6399,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is
** only ever used with detail=none tables.
@@ -6427,7 +6442,9 @@ static void fts5DecodeRowidList(
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_decode().
*/
@@ -6636,7 +6653,9 @@ static void fts5DecodeFunction(
}
fts5BufferFree(&s);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
@@ -6670,6 +6689,7 @@ static void fts5RowidFunction(
}
}
}
+#endif /* SQLITE_TEST */
/*
** This is called as part of registering the FTS5 module with database
@@ -6680,6 +6700,7 @@ static void fts5RowidFunction(
** SQLite error code is returned instead.
*/
int sqlite3Fts5IndexInit(sqlite3 *db){
+#ifdef SQLITE_TEST
int rc = sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
@@ -6697,6 +6718,10 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
);
}
return rc;
+#else
+ return SQLITE_OK;
+ UNUSED_PARAM(db);
+#endif
}
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 8a7af1894a..2dcdad9f87 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -22,7 +22,9 @@
** assert() conditions in the fts5 code are activated - conditions that are
** only true if it is guaranteed that the fts5 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
int sqlite3_fts5_may_be_corrupt = 1;
+#endif
typedef struct Fts5Auxdata Fts5Auxdata;
diff --git a/ext/fts5/fts5_tcl.c b/ext/fts5/fts5_tcl.c
index f33dcae033..80c600dbb1 100644
--- a/ext/fts5/fts5_tcl.c
+++ b/ext/fts5/fts5_tcl.c
@@ -29,7 +29,9 @@
#include
#include
+#ifdef SQLITE_DEBUG
extern int sqlite3_fts5_may_be_corrupt;
+#endif
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*);
@@ -1011,6 +1013,7 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifdef SQLITE_DEBUG
int bOld = sqlite3_fts5_may_be_corrupt;
if( objc!=2 && objc!=1 ){
@@ -1024,6 +1027,7 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
+#endif
return TCL_OK;
}
diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test
index 9b43f3e069..4796f2c489 100644
--- a/ext/fts5/test/fts5corrupt3.test
+++ b/ext/fts5/test/fts5corrupt3.test
@@ -14591,6 +14591,336 @@ do_catchsql_test 74.1 {
SELECT rowid, quote(matchinfo(t1,'p�xyb t1.x
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
- `--SCAN TABLE t1
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:
+ `--SCAN t1
}
do_eqp_test 1.3 {
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:M1
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -54,12 +54,12 @@ do_eqp_test 1.4 {
SELECT * FROM f1 ORDER BY rank
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 1.5 {
SELECT * FROM f1 WHERE rank MATCH ?
-} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
+} {SCAN f1 VIRTUAL TABLE INDEX 0:r}
finish_test
diff --git a/ext/fts5/test/fts5trigram.test b/ext/fts5/test/fts5trigram.test
index 26eb7ba8de..fb66efed68 100644
--- a/ext/fts5/test/fts5trigram.test
+++ b/ext/fts5/test/fts5trigram.test
@@ -192,10 +192,9 @@ do_eqp_test 6.2 {
} {VIRTUAL TABLE INDEX 0:G0}
do_eqp_test 6.3 {
SELECT * FROM ci1 WHERE x LIKE ?
-} {{SCAN TABLE ci1 VIRTUAL TABLE INDEX 0:}}
+} {{SCAN ci1 VIRTUAL TABLE INDEX 0:}}
do_eqp_test 6.4 {
SELECT * FROM ci1 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}
finish_test
-
diff --git a/ext/misc/appendvfs.c b/ext/misc/appendvfs.c
index 4ea5b1c2cb..ba6cc2c0b8 100644
--- a/ext/misc/appendvfs.c
+++ b/ext/misc/appendvfs.c
@@ -530,9 +530,11 @@ static int apndOpen(
rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
if( rc==SQLITE_OK ){
rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
+ if( rc ){
+ pBaseFile->pMethods->xClose(pBaseFile);
+ }
}
if( rc ){
- pBaseFile->pMethods->xClose(pBaseFile);
pFile->pMethods = 0;
return rc;
}
diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c
index 0f6b00f436..6994dc7760 100644
--- a/ext/misc/cksumvfs.c
+++ b/ext/misc/cksumvfs.c
@@ -579,6 +579,18 @@ static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( op==SQLITE_FCNTL_CKPT_START || op==SQLITE_FCNTL_CKPT_DONE ){
p->inCkpt = op==SQLITE_FCNTL_CKPT_START;
if( p->pPartner ) p->pPartner->inCkpt = p->inCkpt;
+ }else if( op==SQLITE_FCNTL_CKSM_FILE ){
+ /* This VFS needs to obtain a pointer to the corresponding database
+ ** file handle from within xOpen() calls to open wal files. To do this,
+ ** it uses the sqlite3_database_file_object() API to obtain a pointer
+ ** to the file-handle used by SQLite to access the db file. This is
+ ** fine if cksmvfs happens to be the top-level VFS, but not if there
+ ** are one or more wrapper VFS. To handle this case, this file-control
+ ** is used to extract the cksmvfs file-handle from any wrapper file
+ ** handle. */
+ sqlite3_file **ppFile = (sqlite3_file**)pArg;
+ *ppFile = (sqlite3_file*)p;
+ return SQLITE_OK;
}
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
@@ -688,6 +700,8 @@ static int cksmOpen(
if( rc ) goto cksm_open_done;
if( flags & SQLITE_OPEN_WAL ){
sqlite3_file *pDb = sqlite3_database_file_object(zName);
+ rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
+ assert( rc==SQLITE_OK );
p->pPartner = (CksmFile*)pDb;
assert( p->pPartner->pPartner==0 );
p->pPartner->pPartner = p;
diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c
index a8d68ac72f..37c6c2f52c 100644
--- a/ext/misc/decimal.c
+++ b/ext/misc/decimal.c
@@ -459,10 +459,11 @@ static void decimalSubFunc(
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
- if( pB==0 ) return;
- pB->sign = !pB->sign;
- decimal_add(pA, pB);
- decimal_result(context, pA);
+ if( pB ){
+ pB->sign = !pB->sign;
+ decimal_add(pA, pB);
+ decimal_result(context, pA);
+ }
decimal_free(pA);
decimal_free(pB);
}
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 77641064d4..41ff01db49 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -299,7 +299,7 @@ static void jsonAppendSeparator(JsonString *p){
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
+ if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
p->zBuf[p->nUsed++] = '"';
for(i=0; inUsed>1 ){
jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
}
+ pStr->pCtx = ctx;
jsonAppendValue(pStr, argv[0]);
}
}
@@ -1959,11 +1959,7 @@ static void jsonGroupInverse(
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
- for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
- if( i>=pStr->nUsed ){
- pStr->nUsed = 1;
- return;
- }
+ for(i=1; inUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
inStr = !inStr;
}else if( c=='\\' ){
@@ -1973,8 +1969,13 @@ static void jsonGroupInverse(
if( c=='}' || c==']' ) nNest--;
}
}
- pStr->nUsed -= i;
- memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ if( inUsed ){
+ pStr->nUsed -= i;
+ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ z[pStr->nUsed] = 0;
+ }else{
+ pStr->nUsed = 1;
+ }
}
#else
# define jsonGroupInverse 0
diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c
index f9fbcfc0bd..86f7ba0f94 100644
--- a/ext/misc/zipfile.c
+++ b/ext/misc/zipfile.c
@@ -36,10 +36,24 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_AMALGAMATION
+#ifndef UINT32_TYPE
+# ifdef HAVE_UINT32_T
+# define UINT32_TYPE uint32_t
+# else
+# define UINT32_TYPE unsigned int
+# endif
+#endif
+#ifndef UINT16_TYPE
+# ifdef HAVE_UINT16_T
+# define UINT16_TYPE uint16_t
+# else
+# define UINT16_TYPE unsigned short int
+# endif
+#endif
typedef sqlite3_int64 i64;
typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned long u32;
+typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
+typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
@@ -706,34 +720,24 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/
static u32 zipfileMtime(ZipfileCDS *pCDS){
- int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
- int M = ((pCDS->mDate >> 5) & 0x0F);
- int D = (pCDS->mDate & 0x1F);
- int B = -13;
-
- int sec = (pCDS->mTime & 0x1F)*2;
- int min = (pCDS->mTime >> 5) & 0x3F;
- int hr = (pCDS->mTime >> 11) & 0x1F;
- i64 JD;
-
- /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
-
- /* Calculate the JD in seconds for noon on the day in question */
- if( M<3 ){
- Y = Y-1;
- M = M+12;
+ int Y,M,D,X1,X2,A,B,sec,min,hr;
+ i64 JDsec;
+ Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
+ M = ((pCDS->mDate >> 5) & 0x0F);
+ D = (pCDS->mDate & 0x1F);
+ sec = (pCDS->mTime & 0x1F)*2;
+ min = (pCDS->mTime >> 5) & 0x3F;
+ hr = (pCDS->mTime >> 11) & 0x1F;
+ if( M<=2 ){
+ Y--;
+ M += 12;
}
- JD = (i64)(24*60*60) * (
- (int)(365.25 * (Y + 4716))
- + (int)(30.6001 * (M + 1))
- + D + B - 1524
- );
-
- /* Correct the JD for the time within the day */
- JD += (hr-12) * 3600 + min * 60 + sec;
-
- /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
- return (u32)(JD - (i64)(24405875) * 24*60*6);
+ X1 = 36525*(Y+4716)/100;
+ X2 = 306001*(M+1)/10000;
+ A = Y/100;
+ B = 2 - A + (A/4);
+ JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
+ return (u32)(JDsec - (i64)24405875*(i64)8640);
}
/*
@@ -2170,6 +2174,10 @@ static int zipfileRegister(sqlite3 *db){
zipfileStep, zipfileFinal
);
}
+ assert( sizeof(i64)==8 );
+ assert( sizeof(u32)==4 );
+ assert( sizeof(u16)==2 );
+ assert( sizeof(u8)==1 );
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test
index 7ec075b7e0..9237dbcea7 100644
--- a/ext/rbu/rbu1.test
+++ b/ext/rbu/rbu1.test
@@ -132,6 +132,11 @@ foreach {tn3 create_vfs destroy_vfs} {
} {
sqlite3rbu_destroy_vfs myrbu
}
+ 3 {
+ sqlite3_register_cksumvfs
+ } {
+ sqlite3_unregister_cksumvfs
+ }
} {
eval $create_vfs
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index c5f809848d..1a13b6c4ad 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -1620,7 +1620,9 @@ char *rbuVacuumIndexStart(
zSep = "";
for(iCol=0; iColnCol; iCol++){
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
- if( zQuoted[0]=='N' ){
+ if( zQuoted==0 ){
+ p->rc = SQLITE_NOMEM;
+ }else if( zQuoted[0]=='N' ){
bFailed = 1;
break;
}
@@ -4992,28 +4994,14 @@ static int rbuVfsOpen(
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- /* This call is to open a *-wal file. Intead, open the *-oal. This
- ** code ensures that the string passed to xOpen() is terminated by a
- ** pair of '\0' bytes in case the VFS attempts to extract a URI
- ** parameter from it. */
- const char *zBase = zName;
- size_t nCopy;
- char *zCopy;
+ /* This call is to open a *-wal file. Intead, open the *-oal. */
+ size_t nOpen;
if( rbuIsVacuum(pDb->pRbu) ){
- zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = sqlite3_filename_wal(zBase);
- }
- nCopy = strlen(zBase);
- zCopy = sqlite3_malloc64(nCopy+2);
- if( zCopy ){
- memcpy(zCopy, zBase, nCopy);
- zCopy[nCopy-3] = 'o';
- zCopy[nCopy] = '\0';
- zCopy[nCopy+1] = '\0';
- zOpen = (const char*)(pFd->zDel = zCopy);
- }else{
- rc = SQLITE_NOMEM;
+ zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
+ zOpen = sqlite3_filename_wal(zOpen);
}
+ nOpen = strlen(zOpen);
+ ((char*)zOpen)[nOpen-3] = 'o';
pFd->pRbu = pDb->pRbu;
}
pDb->pWalFd = pFd;
diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c
index b1cff38edf..b7759bbb51 100644
--- a/ext/rtree/geopoly.c
+++ b/ext/rtree/geopoly.c
@@ -310,6 +310,10 @@ static GeoPoly *geopolyFuncParam(
){
const unsigned char *a = sqlite3_value_blob(pVal);
int nVertex;
+ if( a==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ return 0;
+ }
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
if( (a[0]==0 || a[0]==1)
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
@@ -683,7 +687,7 @@ static GeoPoly *geopolyBBox(
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
- }else{
+ }else if( aCoord ){
memset(aCoord, 0, sizeof(RtreeCoord)*4);
}
return pOut;
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index f5b57a5e23..2151d5af04 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -3890,11 +3890,16 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
+
){
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
- sqlite3_result_int(ctx, readInt16(zBlob));
+ if( zBlob ){
+ sqlite3_result_int(ctx, readInt16(zBlob));
+ }else{
+ sqlite3_result_error_nomem(ctx);
+ }
}
}
diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test
index bc9ff84298..b6dfe992a6 100644
--- a/ext/rtree/rtree6.test
+++ b/ext/rtree/rtree6.test
@@ -79,47 +79,47 @@ do_eqp_test rtree6.2.1 {
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.2 {
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.3 {
SELECT * FROM t1,t2 WHERE k=ii
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.4.1 {
SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
+ `--SEARCH t2 USING AUTOMATIC COVERING INDEX (v=?)
}
do_eqp_test rtree6.2.4.2 {
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
+ `--SEARCH t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
}
do_eqp_test rtree6.2.5 {
SELECT * FROM t1,t2 WHERE k=ii AND x1=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.2 {
@@ -39,8 +39,8 @@ do_eqp_test 1.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.3 {
@@ -48,16 +48,16 @@ do_eqp_test 1.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.5 {
SELECT * FROM t, r_tree
} {
QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
+ |--SCAN r_tree VIRTUAL TABLE INDEX 2:
+ `--SCAN t
}
do_execsql_test 2.0 {
@@ -87,8 +87,8 @@ do_eqp_test 2.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.2 {
@@ -96,8 +96,8 @@ do_eqp_test 2.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.3 {
@@ -105,16 +105,16 @@ do_eqp_test 2.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.5 {
SELECT * FROM t, r_tree
} {
QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
+ |--SCAN r_tree VIRTUAL TABLE INDEX 2:
+ `--SCAN t
}
#-------------------------------------------------------------------------
@@ -128,24 +128,24 @@ do_execsql_test 3.1 {
do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t2
+ |--SCAN t1
+ `--SCAN t2
}
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
QUERY PLAN
- |--SCAN TABLE t2
- `--SCAN TABLE t1
+ |--SCAN t2
+ `--SCAN t1
}
do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
+ |--SCAN t1
+ `--SCAN t3 VIRTUAL TABLE INDEX 2:
}
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
QUERY PLAN
- |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t1
+ |--SCAN t3 VIRTUAL TABLE INDEX 2:
+ `--SCAN t1
}
#--------------------------------------------------------------------
@@ -203,8 +203,8 @@ do_eqp_test 5.2 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
@@ -220,8 +220,8 @@ do_eqp_test 5.4 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
+ |--SCAN rt VIRTUAL TABLE INDEX 2:
+ `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
}
# Delete the ANALYZE data. "t1" should be the outer loop again.
@@ -233,8 +233,8 @@ do_eqp_test 5.6 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
# This time create and attach a database that contains ANALYZE data for
@@ -258,8 +258,8 @@ do_eqp_test 5.8 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
#--------------------------------------------------------------------
@@ -327,9 +327,9 @@ do_eqp_execsql_test 7.1 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE ydir
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
+ |--SCAN xdir
+ |--SCAN ydir
+ `--SCAN rt VIRTUAL TABLE INDEX 2:B2D3B0D1
} {
2 4
}
@@ -340,9 +340,9 @@ do_eqp_execsql_test 7.2 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
5 1 2 7 12 14 {}
5 2 2 7 8 12 10
@@ -355,9 +355,9 @@ do_eqp_execsql_test 7.3 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
2 4
}
@@ -368,9 +368,9 @@ do_eqp_execsql_test 7.4 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
2 4
}
diff --git a/ext/rtree/rtreefuzz001.test b/ext/rtree/rtreefuzz001.test
index db9df205af..58fd179ab9 100644
--- a/ext/rtree/rtreefuzz001.test
+++ b/ext/rtree/rtreefuzz001.test
@@ -1045,5 +1045,167 @@ do_test rtreefuzz001-500 {
catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}
+do_test rtreefuzz001-600 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 20480 pagesize 4096 filename crash-7b37d80f000235.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 10 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 05 0e 49 00 0f 99 0f 40 ..........I....@
+| 112: 0e da 0e 8f 0e 49 00 00 00 00 00 00 00 00 00 00 .....I..........
+| 3648: 00 00 00 00 00 00 00 00 00 44 05 06 17 15 15 08 .........D......
+| 3664: 6f 74 61 62 6c 65 67 65 6f 31 67 65 6f 31 43 52 otablegeo1geo1CR
+| 3680: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
+| 3696: 4c 45 20 67 65 6f 31 20 55 53 49 4e 47 20 67 65 LE geo1 USING ge
+| 3712: 6f 70 6f 6c 79 28 74 79 70 65 2c 63 6c 72 29 49 opoly(type,clr)I
+| 3728: 04 06 17 1f 1f 01 63 74 61 62 6c 65 71 75 65 72 ......ctablequer
+| 3744: 79 70 6f 6c 79 71 75 65 72 79 70 6f 6c 79 05 43 ypolyquerypoly.C
+| 3760: 52 45 41 54 45 20 54 41 42 4c 45 20 71 75 65 72 REATE TABLE quer
+| 3776: 79 70 6f 6c 79 28 70 6f 6c 79 20 4a 53 4f 4e 2c ypoly(poly JSON,
+| 3792: 20 63 6c 72 20 54 45 58 54 29 64 03 07 17 23 23 clr TEXT)d...##
+| 3808: 01 81 0f 74 61 62 6c 65 67 65 6f 31 5f 70 61 72 ...tablegeo1_par
+| 3824: 65 6e 74 67 65 6f 31 5f 70 61 72 65 6e 74 04 43 entgeo1_parent.C
+| 3840: 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 6f REATE TABLE .geo
+| 3856: 31 5f 70 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 1_parent.(nodeno
+| 3872: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
+| 3888: 20 4b 45 59 2c 70 61 72 65 6e 74 6e 6f 64 85 29 KEY,parentnod.)
+| 3904: 57 02 06 17 1f 1f 01 7f 74 61 62 6c 65 67 65 6f W.......tablegeo
+| 3920: 31 5f 6e 6f 64 65 67 65 6f 31 5f 6e 6f 64 65 03 1_nodegeo1_node.
+| 3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 CREATE TABLE .ge
+| 3952: 6f 31 5f 6e 6f 64 65 22 28 6e 6f 64 65 6e 6f 20 o1_node.(nodeno
+| 3968: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3984: 4b 45 59 2c 64 61 74 61 29 65 01 07 17 21 21 01 KEY,data)e...!!.
+| 4000: 81 15 74 61 62 6c 65 67 65 6f 31 5f 72 6f 77 69 ..tablegeo1_rowi
+| 4016: 64 67 65 6f 31 5f 72 6f 77 69 64 02 43 52 45 41 dgeo1_rowid.CREA
+| 4032: 54 45 20 54 41 42 4c 45 20 22 67 65 6f 31 5f 72 TE TABLE .geo1_r
+| 4048: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 4064: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 4080: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 2c 61 32 29 nodeno,a0,a1,a2)
+| page 2 offset 4096
+| 0: 0d 00 00 00 0a 0d ab 00 0f c9 0f 88 0f 48 0f 00 .............H..
+| 3488: 00 00 00 00 00 00 00 00 00 00 00 45 82 0a 06 00 ...........E....
+| 3504: 09 74 1d 13 01 00 00 06 00 80 b5 43 00 80 ac 43 .t.........C...C
+| 3520: 00 00 bd 43 8f 82 9f 43 71 fd c9 43 8f 02 a7 43 ...C...Cq..C...C
+| 3536: 71 fd c8 43 e4 bd a8 43 64 bb bd 43 f4 3d a2 43 q..C...Cd..C.=.C
+| 3552: 64 3b b7 43 00 80 ad 43 61 6e 67 6c 65 2d 33 30 d;.C...Cangle-30
+| 3568: 72 65 64 32 81 4e 06 00 09 44 23 17 01 00 00 03 red2.N...D#.....
+| 3584: 00 40 3f 44 00 c0 20 44 00 c0 46 44 00 c0 20 44 .@?D.. D..FD.. D
+| 3600: 00 00 43 44 00 40 28 44 74 72 69 61 6e 67 6c 65 ..CD.@(Dtriangle
+| 3616: 2d 33 30 62 6c 61 63 6b 35 82 3e 06 00 09 54 1d -30black5.>...T.
+| 3632: 13 01 00 00 04 00 40 54 44 00 80 1d 44 9a c9 5c ......@TD...D...
+| 3648: 44 66 36 1b 44 33 13 5f 44 00 c0 23 44 9a 89 5b Df6.D3._D..#D..[
+| 3664: 44 a4 60 1d 44 61 72 72 6f 77 2d 35 30 72 65 64 D.`.Darrow-50red
+| 3680: 36 74 06 00 09 54 1b 17 01 00 00 04 00 80 0d 44 6t...T.........D
+| 3696: 00 00 f2 42 0a d7 04 44 00 00 ca 42 0a 77 05 44 ...B...D...B.w.D
+| 3712: 0a 57 c1 42 00 20 0e 44 0a 57 e9 42 6c 69 6e 65 .W.B. .D.W.Bline
+| 3728: 2d 34 30 67 72 65 65 6e 36 72 06 00 09 54 1b 17 -40green6r...T..
+| 3744: 01 00 00 04 00 00 7b 43 00 00 ea 42 29 5c 58 43 .......C...B).XC
+| 3760: 00 00 c2 42 29 dc 5a 43 0a 57 b9 42 00 80 7d 43 ...B).ZC.W.B...C
+| 3776: 0a 57 e1 42 6c 69 6e 65 2d 34 30 67 72 65 65 6e .W.Bline-40green
+| 3792: 36 54 06 00 09 54 1b 17 01 00 00 04 00 00 a2 43 6T...T.........C
+| 3808: 00 00 24 44 00 00 b6 43 00 00 24 44 00 00 b6 43 ..$D...C..$D...C
+| 3824: 00 40 25 44 00 00 a2 43 00 40 25 44 6c 69 6e 65 .@%D...C.@%Dline
+| 3840: 2d 34 30 62 6c 61 63 6b 3e 37 06 00 09 64 1d 15 -40black>7...d..
+| 3856: 01 00 00 05 00 80 f0 43 00 00 54 43 66 16 01 44 .......C..TCf..D
+| 3872: 66 a6 30 43 cd ec 09 44 00 00 54 43 8f 0a 09 44 f.0C...D..TC...D
+| 3888: a4 d0 73 43 66 16 01 44 9a 59 77 43 68 6f 75 73 ..sCf..D.YwChous
+| 3904: 65 2d 37 30 62 6c 75 65 3e 35 06 00 09 64 1d 15 e-70blue>5...d..
+| 3920: 01 00 00 05 00 00 a2 43 00 00 5a 43 cd ac b3 43 .......C..ZC...C
+| 3936: 66 a6 36 43 9a 59 c5 43 00 00 5a 43 1f 95 c3 43 f.6C.Y.C..ZC...C
+| 3952: a4 d0 79 43 cd ac b3 43 9a 59 7d 43 68 6f 75 73 ..yC...C.Y.Chous
+| 3968: 65 2d 37 30 62 6c 75 65 3f 2c 06 00 09 64 1d 17 e-70blue?,...d..
+| 3984: 01 00 00 05 00 00 f5 43 00 00 2f 43 00 00 07 44 .......C../C...D
+| 4000: 00 00 2f 43 00 00 07 44 00 00 61 43 00 c0 00 44 ../C...D..aC...D
+| 4016: 00 00 75 43 00 00 f5 43 00 00 61 43 68 6f 75 73 ..uC...C..aChous
+| 4032: 65 2d 37 30 62 6c 61 63 6b 35 1f 06 10 09 54 19 e-70black5....T.
+| 4048: 17 01 00 00 04 00 00 9b 43 00 00 67 43 0a 57 92 ........C..gC.W.
+| 4064: 43 00 00 5d 43 0a 57 97 43 14 ae 4b 42 ff ff a0 C..]C.W.C..KB...
+| 4080: 43 14 ae 55 43 62 6f 78 2d 32 30 67 72 65 65 6e C..UCbox-20green
+| page 3 offset 8192
+| 0: 0d 00 00 00 01 0b 2d 00 0b 2e 00 00 00 00 00 00 ......-.........
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 ...............P
+| 2864: 01 04 00 93 24 00 00 00 0a 00 00 00 00 00 00 01 ....$...........
+| 2880: 0a 43 b5 80 00 43 c9 fd 71 43 9f 82 8f 43 ad 80 .C...C..qC...C..
+| 2896: 00 00 00 00 00 00 00 00 72 43 58 5c 29 43 7d 80 ........rCX.)C..
+| 2912: 00 42 b9 57 0a 42 ea 00 00 00 00 00 00 00 00 00 .B.W.B..........
+| 2928: 35 43 a2 00 00 43 c5 59 9a 43 36 a6 66 43 7d 59 5C...C.Y.C6.fC.Y
+| 2944: 9a 00 00 00 00 00 00 00 1f 43 92 57 0a 43 a0 00 .........C.W.C..
+| 2960: 00 43 4b ae 14 43 67 00 00 00 00 00 00 00 00 00 .CK..Cg.........
+| 2976: 37 43 f0 80 00 44 09 ec cd 43 30 a6 66 43 77 59 7C...D...C0.fCwY
+| 2992: 9a 00 00 00 00 00 00 00 2c 43 f5 00 00 44 07 00 ........,C...D..
+| 3008: 00 43 2f 00 00 43 75 00 00 00 00 00 00 00 00 00 .C/..Cu.........
+| 3024: 74 44 04 d7 0a 44 0e 20 00 42 c1 57 0a 42 f2 00 tD...D. .B.W.B..
+| 3040: 00 00 00 00 00 00 00 00 ce 44 3f 40 00 44 46 c0 .........D?@.DF.
+| 3056: 00 44 20 c0 00 44 28 40 00 00 00 00 00 00 00 00 .D ..D(@........
+| 3072: be 44 54 40 00 44 5f 13 33 44 1b 36 66 44 23 c0 .DT@.D_.3D.6fD#.
+| 3088: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3104: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3120: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3136: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3152: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3168: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3184: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3200: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3216: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3232: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3248: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3264: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3280: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3296: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3312: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3328: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3344: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 01 .D$..D%@........
+| 3360: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3376: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3392: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3408: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3424: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3440: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3456: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3472: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3488: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3504: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3520: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3536: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3552: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3568: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3584: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3600: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3616: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3632: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3648: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3664: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3680: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3696: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| page 5 offset 16384
+| 0: 0d 00 00 00 01 0f 8f 00 00 00 00 00 00 00 00 00 ................
+| 3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f ...............o
+| 3984: 01 04 81 57 19 5b 5b 33 30 30 2c 33 30 30 5d 2c ...W.[[300,300],
+| 4000: 5b 34 30 30 2c 33 35 30 5d 2c 5b 35 30 30 2c 32 [400,350],[500,2
+| 4016: 35 30 5d 2c 5b 34 38 30 2c 35 30 30 5d 2c 5b 34 50],[480,500],[4
+| 4032: 30 30 2c 34 38 30 5d 2c 5c 33 30 30 2c 35 35 30 00,480],.300,550
+| 4048: 5d 2c 5b 32 38 30 2c 34 35 30 5d 2c 5b 33 32 30 ],[280,450],[320
+| 4064: 2c 34 30 30 5d 2c 5b 32 38 30 2c 33 35 30 5d 2c ,400],[280,350],
+| 4080: 5b 33 30 30 2c 33 30 00 00 00 00 00 00 00 00 00 [300,30.........
+| end crash-7b37d80f000235.db
+}]} {}
+
+ifcapable geopoly {
+
+do_catchsql_test rtreefuzz001-601 {
+ SAVEPOINT one;
+ UPDATE geo1 SET clr=CASE WHEN rowid IN ( SELECT geo1.rowid FROM geo1, querypoly ) THEN 'e' ELSE 'blue' END;
+} {1 {database disk image is malformed}}
+
+do_catchsql_test rtreefuzz001-602 {
+ SELECT geopoly_svg(_shape, printf('j',geo1.clr))
+ FROM geo1, querypoly WHERE geopoly_overlap(_shape, poly);
+} {1 {database disk image is malformed}}
+
+} ;# ifcapable geopoly
finish_test
diff --git a/ext/session/sessionsize.test b/ext/session/sessionsize.test
new file mode 100644
index 0000000000..04d05514db
--- /dev/null
+++ b/ext/session/sessionsize.test
@@ -0,0 +1,131 @@
+# 2021 April 22
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+set testprefix sessionsize
+
+proc do_changeset_size_test {tn sql} {
+ sqlite3session S db main
+ S attach *
+ db eval $sql
+
+ set sz [S changeset_size]
+ set C [S changeset]
+ set szC [string length $C]
+ S delete
+
+ do_test $tn "expr $sz" $szC
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 'abc', 'def');
+ INSERT INTO t1 VALUES(2, 'ghi', 'jkl');
+}
+
+do_changeset_size_test 1.1 {
+ INSERT INTO t1 VALUES(3, 'hello', 'world');
+}
+
+do_changeset_size_test 1.2 {
+ DELETE FROM t1 WHERE a=2;
+}
+
+do_changeset_size_test 1.3 {
+ DELETE FROM t1 WHERE a=3;
+ INSERT INTO t1 VALUES(3, 1, 2);
+}
+
+do_changeset_size_test 1.4 {
+ UPDATE t1 SET c='hello world' WHERE a=3;
+}
+
+#-------------------------------------------------------------------------
+
+do_execsql_test 2.0 {
+ CREATE TABlE t2(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
+ CREATE TABlE t3(a, b, c, d PRIMARY KEY);
+}
+
+do_changeset_size_test 2.1 {
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
+ )
+ INSERT INTO t2 SELECT i, i+1, i+2, i+3 FROM s;
+
+ UPDATE t2 SET c=randomblob(a) WHERE a>10
+}
+
+do_changeset_size_test 2.2 {
+ DELETE FROM t2 WHERE a=1;
+ INSERT INTO t2 VALUES(1, 4, 3, 4);
+}
+
+do_changeset_size_test 2.2 {
+ UPDATE t2 SET b=4 WHERE a=2
+}
+
+do_changeset_size_test 2.3 {
+ INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
+ UPDATE t2 SET c='qwertyuiop' WHERE a='a';
+}
+
+do_changeset_size_test 2.4 {
+ DELETE FROM t2 WHERE a='a';
+ INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
+}
+
+do_changeset_size_test 2.5 {
+ UPDATE t2 SET a='aa', b='bb' WHERE (a, b) = ('a', 'b');
+}
+
+do_changeset_size_test 2.6 {
+ UPDATE t2 SET a='a', b='b' WHERE (a, b) = ('aa', 'bb');
+}
+
+do_changeset_size_test 2.7 {
+ INSERT INTO t3 DEFAULT VALUES;
+ INSERT INTO t3 VALUES(1,2,3,4);
+}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+}
+
+do_test 3.1 {
+ sqlite3session S db main
+ S object_config_size -1
+} 1
+
+do_test 3.2.1 { S object_config_size 0 } 0
+do_test 3.2.2 { S object_config_size -1 } 0
+do_test 3.2.3 { S object_config_size 1 } 1
+do_test 3.2.4 { S object_config_size -1 } 1
+
+do_test 3.3 { S attach t1 } {}
+do_test 3.4 { S object_config_size 1 } {SQLITE_MISUSE}
+do_test 3.4 { S object_config_size -1 } {1}
+
+S delete
+
+finish_test
+
diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c
index f069a42e1f..e2f997393f 100644
--- a/ext/session/sqlite3session.c
+++ b/ext/session/sqlite3session.c
@@ -49,6 +49,7 @@ struct SessionHook {
struct sqlite3_session {
sqlite3 *db; /* Database handle session is attached to */
char *zDb; /* Name of database session is attached to */
+ int bEnableSize; /* True if changeset_size() enabled */
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
@@ -56,6 +57,7 @@ struct sqlite3_session {
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
i64 nMalloc; /* Number of bytes of data allocated */
+ i64 nMaxChangesetSize;
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
@@ -298,8 +300,9 @@ struct SessionTable {
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
- int op; /* One of UPDATE, DELETE, INSERT */
- int bIndirect; /* True if this change is "indirect" */
+ u8 op; /* One of UPDATE, DELETE, INSERT */
+ u8 bIndirect; /* True if this change is "indirect" */
+ int nMaxSize; /* Max size of eventual changeset record */
int nRecord; /* Number of bytes in buffer aRecord[] */
u8 *aRecord; /* Buffer containing old.* record */
SessionChange *pNext; /* For hash-table collisions */
@@ -1128,6 +1131,12 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
pTab->bStat1 = 1;
}
+
+ if( pSession->bEnableSize ){
+ pSession->nMaxChangesetSize += (
+ 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1
+ );
+ }
}
}
return (pSession->rc || pTab->abPK==0);
@@ -1173,6 +1182,103 @@ static int sessionStat1Depth(void *pCtx){
return p->hook.xDepth(p->hook.pCtx);
}
+static int sessionUpdateMaxSize(
+ int op,
+ sqlite3_session *pSession, /* Session object pTab is attached to */
+ SessionTable *pTab, /* Table that change applies to */
+ SessionChange *pC /* Update pC->nMaxSize */
+){
+ i64 nNew = 2;
+ if( pC->op==SQLITE_INSERT ){
+ if( op!=SQLITE_DELETE ){
+ int ii;
+ for(ii=0; iinCol; ii++){
+ sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ sessionSerializeValue(0, p, &nNew);
+ }
+ }
+ }else if( op==SQLITE_DELETE ){
+ nNew += pC->nRecord;
+ if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){
+ nNew += pC->nRecord;
+ }
+ }else{
+ int ii;
+ u8 *pCsr = pC->aRecord;
+ for(ii=0; iinCol; ii++){
+ int bChanged = 1;
+ int nOld = 0;
+ int eType;
+ sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ eType = *pCsr++;
+ switch( eType ){
+ case SQLITE_NULL:
+ bChanged = sqlite3_value_type(p)!=SQLITE_NULL;
+ break;
+
+ case SQLITE_FLOAT:
+ case SQLITE_INTEGER: {
+ if( eType==sqlite3_value_type(p) ){
+ sqlite3_int64 iVal = sessionGetI64(pCsr);
+ if( eType==SQLITE_INTEGER ){
+ bChanged = (iVal!=sqlite3_value_int64(p));
+ }else{
+ double dVal;
+ memcpy(&dVal, &iVal, 8);
+ bChanged = (dVal!=sqlite3_value_double(p));
+ }
+ }
+ nOld = 8;
+ pCsr += 8;
+ break;
+ }
+
+ default: {
+ int nByte;
+ nOld = sessionVarintGet(pCsr, &nByte);
+ pCsr += nOld;
+ nOld += nByte;
+ assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
+ if( eType==sqlite3_value_type(p)
+ && nByte==sqlite3_value_bytes(p)
+ && (nByte==0 || 0==memcmp(pCsr, sqlite3_value_blob(p), nByte))
+ ){
+ bChanged = 0;
+ }
+ pCsr += nByte;
+ break;
+ }
+ }
+
+ if( bChanged && pTab->abPK[ii] ){
+ nNew = pC->nRecord + 2;
+ break;
+ }
+
+ if( bChanged ){
+ nNew += 1 + nOld;
+ sessionSerializeValue(0, p, &nNew);
+ }else if( pTab->abPK[ii] ){
+ nNew += 2 + nOld;
+ }else{
+ nNew += 2;
+ }
+ }
+ }
+
+ if( nNew>pC->nMaxSize ){
+ int nIncr = nNew - pC->nMaxSize;
+ pC->nMaxSize = nNew;
+ pSession->nMaxChangesetSize += nIncr;
+ }
+ return SQLITE_OK;
+}
/*
** This function is only called from with a pre-update-hook reporting a
@@ -1246,7 +1352,6 @@ static void sessionPreupdateOneChange(
/* Create a new change object containing all the old values (if
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
- SessionChange *pChange; /* New change object */
sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
@@ -1272,13 +1377,13 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
- if( !pChange ){
+ pC = (SessionChange *)sessionMalloc64(pSession, nByte);
+ if( !pC ){
rc = SQLITE_NOMEM;
goto error_out;
}else{
- memset(pChange, 0, sizeof(SessionChange));
- pChange->aRecord = (u8 *)&pChange[1];
+ memset(pC, 0, sizeof(SessionChange));
+ pC->aRecord = (u8 *)&pC[1];
}
/* Populate the change object. None of the preupdate_old(),
@@ -1293,17 +1398,17 @@ static void sessionPreupdateOneChange(
}else if( pTab->abPK[i] ){
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
}
- sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte);
+ sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
}
/* Add the change to the hash-table */
if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
- pChange->bIndirect = 1;
+ pC->bIndirect = 1;
}
- pChange->nRecord = nByte;
- pChange->op = op;
- pChange->pNext = pTab->apChange[iHash];
- pTab->apChange[iHash] = pChange;
+ pC->nRecord = nByte;
+ pC->op = op;
+ pC->pNext = pTab->apChange[iHash];
+ pTab->apChange[iHash] = pC;
}else if( pC->bIndirect ){
/* If the existing change is considered "indirect", but this current
@@ -1314,8 +1419,14 @@ static void sessionPreupdateOneChange(
pC->bIndirect = 0;
}
}
+
+ assert( rc==SQLITE_OK );
+ if( pSession->bEnableSize ){
+ rc = sessionUpdateMaxSize(op, pSession, pTab, pC);
+ }
}
+
/* If an error has occurred, mark the session object as failed. */
error_out:
if( pTab->bStat1 ){
@@ -2527,8 +2638,12 @@ int sqlite3session_changeset(
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
){
- return sessionGenerateChangeset(
+ int rc = sessionGenerateChangeset(
pSession, SESSIONS_CHANGESET, 0, 0, pnChangeset, ppChangeset);
+ assert( rc || pnChangeset==0
+ || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
+ );
+ return rc;
}
/*
@@ -2633,6 +2748,39 @@ sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
return pSession->nMalloc;
}
+/*
+** Configure the session object passed as the first argument.
+*/
+int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){
+ int rc = SQLITE_OK;
+ switch( op ){
+ case SQLITE_SESSION_OBJCONFIG_SIZE: {
+ int iArg = *(int*)pArg;
+ if( iArg>=0 ){
+ if( pSession->pTable ){
+ rc = SQLITE_MISUSE;
+ }else{
+ pSession->bEnableSize = (iArg!=0);
+ }
+ }
+ *(int*)pArg = pSession->bEnableSize;
+ break;
+ }
+
+ default:
+ rc = SQLITE_MISUSE;
+ }
+
+ return rc;
+}
+
+/*
+** Return the maximum size of sqlite3session_changeset() output.
+*/
+sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession){
+ return pSession->nMaxChangesetSize;
+}
+
/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h
index 107bcfb6a9..0090f67d76 100644
--- a/ext/session/sqlite3session.h
+++ b/ext/session/sqlite3session.h
@@ -79,6 +79,38 @@ int sqlite3session_create(
*/
void sqlite3session_delete(sqlite3_session *pSession);
+/*
+** CAPIREF: Conigure a Session Object
+** METHOD: sqlite3_session
+**
+** This method is used to configure a session object after it has been
+** created. At present the only valid value for the second parameter is
+** [SQLITE_SESSION_OBJCONFIG_SIZE].
+**
+** Arguments for sqlite3session_object_config()
+**
+** The following values may passed as the the 4th parameter to
+** sqlite3session_object_config().
+**
+** SQLITE_SESSION_OBJCONFIG_SIZE
+** This option is used to set, clear or query the flag that enables
+** the [sqlite3session_changeset_size()] API. Because it imposes some
+** computational overhead, this API is disabled by default. Argument
+** pArg must point to a value of type (int). If the value is initially
+** 0, then the sqlite3session_changeset_size() API is disabled. If it
+** is greater than 0, then the same API is enabled. Or, if the initial
+** value is less than zero, no change is made. In all cases the (int)
+** variable is set to 1 if the sqlite3session_changeset_size() API is
+** enabled following the current call, or 0 otherwise.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
+
+/*
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -349,6 +381,22 @@ int sqlite3session_fullchangeset(
void **ppChangeset /* OUT: Buffer containing changeset */
);
+/*
+** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
+** METHOD: sqlite3_session
+**
+** By default, this function always returns 0. For it to return
+** a useful result, the sqlite3_session object must have been configured
+** to enable this API using sqlite3session_object_config() with the
+** SQLITE_SESSION_OBJCONFIG_SIZE verb.
+**
+** When enabled, this function returns an upper limit, in bytes, for the size
+** of the changeset that might be produced if sqlite3session_changeset() were
+** called. The final changeset size might be equal to or smaller than the
+** size in bytes returned by this function.
+*/
+sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
+
/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session
diff --git a/ext/session/test_session.c b/ext/session/test_session.c
index d968699e02..009f2990d0 100644
--- a/ext/session/test_session.c
+++ b/ext/session/test_session.c
@@ -247,6 +247,8 @@ static int SQLITE_TCLAPI test_session_cmd(
{ "diff", 2, "FROMDB TBL" }, /* 8 */
{ "fullchangeset",0, "" }, /* 9 */
{ "memory_used", 0, "", }, /* 10 */
+ { "changeset_size", 0, "", }, /* 11 */
+ { "object_config_size", 1, "INTEGER", }, /* 12 */
{ 0 }
};
int iSub;
@@ -362,6 +364,29 @@ static int SQLITE_TCLAPI test_session_cmd(
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nMalloc));
break;
}
+
+ case 11: {
+ sqlite3_int64 nSize = sqlite3session_changeset_size(pSession);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
+ break;
+ }
+ case 12: {
+ int rc;
+ int iArg;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iArg) ){
+ return TCL_ERROR;
+ }
+ rc = sqlite3session_object_config(
+ pSession, SQLITE_SESSION_OBJCONFIG_SIZE, &iArg
+ );
+ if( rc!=SQLITE_OK ){
+ extern const char *sqlite3ErrName(int);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ }else{
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iArg));
+ }
+ break;
+ }
}
return TCL_OK;
@@ -387,6 +412,7 @@ static int SQLITE_TCLAPI test_sqlite3session(
Tcl_CmdInfo info;
int rc; /* sqlite3session_create() return code */
TestSession *p; /* New wrapper object */
+ int iArg = -1;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME");
@@ -407,6 +433,13 @@ static int SQLITE_TCLAPI test_sqlite3session(
return test_session_error(interp, rc, 0);
}
+ /* Query the SQLITE_SESSION_OBJCONFIG_SIZE option to ensure that it
+ ** is clear by default. Then set it. */
+ sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);
+ assert( iArg==0 );
+ iArg = 1;
+ sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);
+
Tcl_CreateObjCommand(
interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p,
test_session_del
diff --git a/main.mk b/main.mk
index 1aabb4d965..2a085a3163 100644
--- a/main.mk
+++ b/main.mk
@@ -441,7 +441,8 @@ TESTSRC2 = \
$(TOP)/ext/misc/stmt.c \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/sqlite3changebatch.c \
- $(TOP)/ext/session/test_session.c
+ $(TOP)/ext/session/test_session.c \
+ fts5.c
# Header files used by all library source files.
#
@@ -540,7 +541,6 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
@@ -593,7 +593,6 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -1085,6 +1084,9 @@ rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)
+threadtest5: $(TOP)/test/threadtest5.c libsqlite3.a
+ $(TCC) $(TOP)/test/threadtest5.c libsqlite3.a -o threadtest5 $(THREADLIB)
+
# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
@@ -1147,3 +1149,4 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c
+ rm -f threadtest5
diff --git a/manifest b/manifest
index 801dddf141..c04ab4523f 100644
--- a/manifest
+++ b/manifest
@@ -1,13 +1,13 @@
-C Merge\sup\sall\sthe\s3.35.3\schanges\sinto\sthe\sbegin-concurrent-pnu-wal2\sbranch.
-D 2021-03-26T14:04:34.993
+C Merge\slatest\schanges\sfrom\swal2\sinto\sthis\sbranch.
+D 2021-05-21T17:31:04.357
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 39bea9c761b58790b94369abfb9257baa459e74fb226c5a44176a62d265944a5
+F Makefile.in 5d28a7a46c2700c518469b9c5720b22d386293ecdd44f148a9a6c69d191e7c3e
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc 670a8d12f5ddf61c38217a011e63065cbb2ae4585c0b5844137e9c3d384dedb0
-F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
-F VERSION 75575cade3e93b31a84ffcb0d40de856a49bd3e4c1028dff52432bfae9806adb
+F Makefile.msc 264c5fe9c681611178d163e61d38f98cea592914e92d0b98b5538c617199243a
+F README.md 2a71913f398ecac5f3e10945fcf438aed425c2e9ed9874de561156ba77fb7023
+F VERSION 8c392f6d70d82e513a0eac622bdf23c43df3e084cb630288beba8cef3012c812
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc ebe7e66edbb2f453593cbde186d1a0fa0dcd8cae9977febcae27aef1dab5678d
+F autoconf/Makefile.msc d146a08ebbdf7f881ba600a49cd8dce40c4c807addcdb4b9b6a507e4b40ce837
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79
@@ -34,12 +34,12 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure 174eed3b99edc1c897fe32638c5b4068d4abfb282dc545ccc3ee92a472f73d7a x
+F configure c658869fc056a2460a2212fb2960e410cd24e3fb9c55640fbc78d15b48810936 x
F configure.ac 4e4b58b32f88c8da9914a2f2c3158f80e69907eccc019fcc7e3ba14ffd91c640
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/begin_concurrent.md 4bee2c3990d1eb800f1ce3726a911292a8e4b889300b2ffd4b08d357370db299
-F doc/lemon.html 1bb72ece6271df0d901d233551dd985f2c6ba30d09382cf2d321ed951ab57491
+F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
@@ -52,7 +52,7 @@ F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test 63d778d964e55ef2d1a723043d91c59e7dc6ef1649d91c78c0bef00f9c6f1427
+F ext/expert/expert1.test 6703fd74711daf8230240680b0a348d0720e28819b602701adfbd32457fdcddd
F ext/expert/sqlite3expert.c de51b187c629a4c4264d5de0b77862641e11426f7a963a92abf2d4077085fc8c
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
@@ -86,25 +86,25 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 7b449348226a91cc851fe969f5c1932d4f00c359a32fd17f2afea92bf875147b
+F ext/fts3/fts3.c 95f55e24550c01c2a325d09c9ea8fdff61e923a4675f8545b28bf3c470e57dfb
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 045179f538c478ced266ca14327269cde8ad8d573c5be902230a5ebaa5636c59
-F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
+F ext/fts3/fts3Int.h bde280294d56ff50ee29d03e5140f0b6953b44d1c969bb5831e8ae85e3e76715
+F ext/fts3/fts3_aux.c 1af58af8f2b00a49f4fb1c2602f8da2054ad60076f46c8ebf85c5410eccccb65
F ext/fts3/fts3_expr.c 5853cd7a35a79d193614add9b4c461b2d56f465d90899ca4309f05d9d1536558
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
-F ext/fts3/fts3_snippet.c 86e7e947a176f0f005720b3ca17631aca2fd2f9daa6729d4adbf2d16ab1b9613
+F ext/fts3/fts3_snippet.c 57e1965906f3ecfcb5251a14aea98ac2d2dd1868a123bcd5a569601719ab9ead
F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
-F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39
+F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
F ext/fts3/fts3_tokenize_vtab.c 8d15b148e7d88a4280389a200b26e8d52abda4c4ec2e9a35e9d7a1fa50e5aa03
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 de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
-F ext/fts3/fts3_write.c a5159accfd88f85fd3fc2298286d7a9427a02d1ea9a52b7c79730cff7a0bc03f
+F ext/fts3/fts3_write.c aa751c4559a0d1b885206c5f4421c5b34a8ec7ea3d3d04127b7747a5a83a2f4e
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
@@ -118,13 +118,13 @@ F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca
F ext/fts5/fts5Int.h 26c74dd5776f798436fbf604a0bf0e8de263b35b5060b05c15f9085845d9fda2
F ext/fts5/fts5_aux.c f558e1fb9f0f86a4f7489e258c162e1f947de5ff2709087fbb465fddb7092f98
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
-F ext/fts5/fts5_config.c be54f44fca491e96c6923a4b9a736f2da2b13811600eb6e38d1bcc91c4ea2e61
-F ext/fts5/fts5_expr.c 016bd06030679bd31b0f07ef87d62c42031e5da25cb3174a84e5b0f6ef4b47b0
+F ext/fts5/fts5_config.c 8336d0ff6db0933f63cfec8ae0ab76e68393259cbccc0b46e1f79f7fa1842ff3
+F ext/fts5/fts5_expr.c 9462249a3bb82d0e49b163500f9d2197c2e4cd95bf440a9bbfc3906b22ea1e1b
F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
-F ext/fts5/fts5_index.c df5e18b705ac601e826576298a5ce23ef1e5d417fbfdb3feb5f702f89e5f6f41
-F ext/fts5/fts5_main.c d77648a52b8d73d13887306149912e420f7e0b2d7b3d7da2f54152bfa140ac02
+F ext/fts5/fts5_index.c 222b5e56f51139ca5400985e26ea9971165901c7a45a2c17499bd2be3695c697
+F ext/fts5/fts5_main.c f497ca97cb2802311ec93733b595762dc5b044ce3c6c8ce5fb3e871dd3fccd5d
F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
-F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
+F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c a2bed8edb25f6432e8cdb62aad5916935c19dba8dac2b8324950cfff397e25ff
F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
@@ -162,13 +162,13 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test 1cad09897fc69084a904c921dee7f777e1c866964ee2ec2cc7a8a69cc3f1ab68
+F ext/fts5/test/fts5corrupt3.test 7748c28d0a0c8f00e7741a097df7c76eed207b5443908621dd1ce1dd23b84a07
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
-F ext/fts5/test/fts5doclist.test e39a6001495f1dc68e20323586ac965787986c2bf6f515b9b0285627b089d9e6
+F ext/fts5/test/fts5doclist.test faa9e9cc3c0645fa6203667cb5f007c359447c6ee66753f71a58175c2497cacd
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
F ext/fts5/test/fts5eb.test 239bb2f02571f8cccfc7018d08f502df1cd8cc6a69b65ed1dde5f6a070e3f669
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
@@ -202,7 +202,7 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
-F ext/fts5/test/fts5plan.test 79d35b5e83bbdcba48d946a7f008df161f6b0ede1a966892d0aa6c8dd0b6e773
+F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
@@ -221,7 +221,7 @@ F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947e
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
-F ext/fts5/test/fts5trigram.test e2ce256fd0ccd6707e740aa3596206aedb0d5834b100c0cb49e344dcd1d8463c
+F ext/fts5/test/fts5trigram.test 5b4feb53a4d5aca70c841f6919c8719b5a9c805474727dda99285fccdd2e9cce
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
@@ -288,27 +288,27 @@ F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f607
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/appendvfs.c bdc9de0a0e61c21327e975da178b4fd6f57de9c46123044aa6ee3a20798c5db2
+F ext/misc/appendvfs.c 500fef0736caafc629ca1dbae348a121367eaa4ed8c385c291cb9ad65ea790fb
F ext/misc/bgckpt.c 49ae19aa03e6da393db5d17da256374d4c4d36889fdd89d6e4bc93aca2b752e6
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
-F ext/misc/cksumvfs.c 8dc4e1b718e374bed3a9b5c0a08da2922438002e33267311697768e06217b983
+F ext/misc/cksumvfs.c 2c6b07714f3be6c1200671c53aa781a86d2c472c0fcb2fff520375362eb94303
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
-F ext/misc/decimal.c 3ddbf8162015be4d5ec2395dee4538f1e638bb517174bb148274b132df6e1d08
+F ext/misc/decimal.c 09f967dcf4a1ee35a76309829308ec278d3648168733f4a1147820e11ebefd12
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
F ext/misc/fileio.c 9b69e25da3b51d4a1d905a464ccb96709792ad627a742ba09215bc0d1447e7bd
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
F ext/misc/ieee754.c cd6ab89f85fda8a020559b3f4d03001a8a62dd856beda5af3f558621d12be913
-F ext/misc/json1.c f31e89171f932d1821c91f10d2cb4979fc0447030030a8bce70420cd43d074c0
+F ext/misc/json1.c 2c5c0dbc7fa303f0213f008e5878db9f0e5875fe8ff59a7c2d9f235b18e323a7
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
@@ -340,10 +340,10 @@ F ext/misc/vfsstat.c 389ea13983d3af926504c314f06a83cc858d5adc24b40af74aaed1fece0
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
-F ext/misc/zipfile.c e35e035bc2765b1ccdcb15f9815c2112843fcbc8f36aa071f0e5935df7072228
+F ext/misc/zipfile.c acbad31bd9c9ec3540fa72b2e3fcd6f757eb33117d51528c0e13d0da5c836908
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c b880ca5cb857d6d6f52e72eb7397813058ef48c78c5402cd04ff2b6b5437f622
-F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
+F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc
@@ -382,7 +382,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
-F ext/rbu/sqlite3rbu.c e6531884442b72f9e0ba47036fb5c4641ea817ff659a642b3984c10b8535b0fd
+F ext/rbu/sqlite3rbu.c badb52388467f58e67ef104c5276d1ac68b316a30f8ccb2f74eac733625ae236
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -395,21 +395,21 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c 1b1ddecb79877b12331d35de9f393b80bbb731e0bf6db6c572f23191987ea803
-F ext/rtree/rtree.c 60f6f1675134201974be4189dbd219494c13e1ed30e80bd92ae0dcc86df1b035
+F ext/rtree/geopoly.c 98d45533989e908bf65b43f36ff6eaad95a9ffe6f3b6b8658fbd47d45c58b10b
+F ext/rtree/rtree.c f1ce6a86f7cbff634900653bec2dfeba732dd4450eec921c0ac3851d41f462b9
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
-F ext/rtree/rtree6.test 1252a0439da01d2f1f5cbbdeeb80455a2d68b9bae2a9787937b167a5e3957828
+F ext/rtree/rtree6.test 9ce3691c1aac43070a9f194f0ebf54372db346c5a82241fd11b525ed53ce9f3f
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
-F ext/rtree/rtreeC.test 6aa87eba4d9a3003b941a1ba77db259c5cabc3fd92fc5a6360f5369520eb9a4d
+F ext/rtree/rtreeC.test c4bfa9a61c6788c03e4a9ce40ab2cfc6100982559effd9842d1b658e1d47aa5f
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
@@ -421,7 +421,7 @@ F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b5879
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
-F ext/rtree/rtreefuzz001.test eef1ed593bb15886cd5d5367a2f2492f81e315848896cdf7afb6e21454978827
+F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
@@ -458,20 +458,21 @@ F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
+F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a347ea9820a002dd8
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3changebatch.c d5553b79e012ee2cb06c0a96bdf9dfe19e66354390ea0036cc46c4953142d517
F ext/session/sqlite3changebatch.h e72016998c9a22d439ddfd547b69e1ebac810c24
-F ext/session/sqlite3session.c 5eb3a3cb490912376c5720d24eb256753e4a29a2a62f39ac708a084d854b4fea
-F ext/session/sqlite3session.h cae11f96e40915220076acf4d7b3e4eb26f817d92064bd5983d47f9fe7f31ec6
-F ext/session/test_session.c 18372dfe254a219705f89bc95c5ef26744236c4dbac5cdfbe71959290afc928d
+F ext/session/sqlite3session.c 381b2437cd5607193b5bf4c07b7f6026adfd7a3258435af1ee8f833eaf935b99
+F ext/session/sqlite3session.h 01807bb8c8f531c23052032e9d531eec49af79b7394f8213cf5a49784325b6a8
+F ext/session/test_session.c 226461035031632255c8098f3bcfa4ea27f0b051efd88857a2a36bcea5c294b9
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 884bf69d5658fdb71862a7e4bab17bdd7fd3c6782992f6879d2ea95d7c024af5
+F main.mk 026b21dfd84fccc01479857995685246ddabc6f7d28e9079cdd5ca89874912cd
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -483,44 +484,44 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 2d631213818b654faaf08755f26e934134c4769757ae9286981401cd6b571081
+F src/alter.c df53c39fd4f32528fc7ad8188b3bf2b506e1a8b3bb975b14f16a1bc6e901950f
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
-F src/attach.c 9cbe761e464025694df8e6f6ee4d9f41432c3a255ca9443ccbb4130eeb87cf72
+F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 8433d9e98dd6f2ea3286e0d2fe5d65de1bfc18a706486eb2026b01be066b5806
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 0ee2ae302a6e6985f655f3ebcf0e7fc61d0963da66c512780b0bf0709372d8e6
+F src/btree.c 8869176dd073fef60c2fab8074ea84fafd3edfdec21a60cbe3e91832e0d4dde0
F src/btree.h ccdc64bd1eee7ba79d4c0b2af22b6df1e5ededdbf9606f45f4fca4738dd6fa0b
F src/btreeInt.h 1e9f10107a4ec5d2940ae5b859242ae83b81402986724bed08b8491a5ea64a4d
-F src/build.c 9f06854962aad6b5d465c38f9f6e8c307028fbb4efa9fccb0531f0874bd088df
+F src/build.c b470cd22b984fcb9c35ae24855b2a167a83098f56fbad744291df421570ec5cc
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c 2a322b9a3d75771fb4d99e0702851f4f68dda982507a0f798eefb0712969a410
+F src/ctime.c 3052b6b05ed9ef547a3dd66b8e01bfa9d582e78752ad6ed327da84652641e038
F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
F src/delete.c 73f57a9a183532c344a3135cf8f2a5589376e39183e0b5f562d6b61b2af0f4d8
-F src/expr.c d681f0b48b1e16173ad8e1e8f7323cda120a0c517cb7a3d5b329c4e2c57f18bd
+F src/expr.c c56c74d40d1ca5359177f1425d2eb2aa050c30da0b49e014da1f109aa38ece0f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
-F src/func.c e701e9a1cbc2e1814d381ce781925c2e8776cdf994e7c17f53578ec3cc7af40a
-F src/global.c ed55af196a9b66e198aaeda3f5454c3aa7d7d050c6c938181fd044b70d180a81
+F src/func.c 0e97ea309f882c4045a73d25219d816e60d2baf3c60068bb5d74f801a46355a9
+F src/global.c 25ba4d58476f6be29bba9d9d14f7f146b78476d3a4d75ebb8c3b736328afe0f9
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 e36be69e3810902eaf7e171260c885bc9547b1d41616c868f1cc46e6a0a3b7fd
+F src/insert.c 2189e0e596010a0dc5405d9f14f78db1ee2fa71138c931f5b6ea96610b95bfc1
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
-F src/main.c 5becd80bb8369fe73cea609ac830dd43453d0a356c56ef361fd74698988484a0
+F src/main.c 28f45be66f575edf05465a2bc91ec50ebff6bb49099ef884f4dd506d83fd7769
F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c ab0632d42407e866d2b616bd19d4211ac0ad1b430f04c4e187d60005b8700b98
+F src/memdb.c f6ce717b26cd51a24cda62fce611b4b72b3db367113374aa498e489a69470715
F src/memjournal.c 431c70a111223a8a6e2e7e9f014afc6c88d818d357d866afc563195f2277d50e
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
@@ -529,44 +530,44 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f956d
F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
-F src/os.c 2d6e646370b1aa78942c68d7edf124e518963adf4a90bce87f365a5a5495529a
+F src/os.c 6e94cd64b134c9317e52ad534117578e3df66ec180d70dbf4b1d7eb1db8e5a5d
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c f0d42250fcded6615ff81af94c7b3005dc2a52d67467b4d7ca2b29427019e2b1
+F src/os_unix.c 430266b3c1fcd3868c2db04a504a78b9a71de82092fc511e968919a0d661f7eb
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 964ebfc5105bdfe1b85fcdcd8b79fc3b971c994d2eaffa8a9dde288d3091e356
+F src/pager.c 08f6583f5463ea4e0d1a584455a321bbf66475fa33e740ea5731751558e77ae2
F src/pager.h 034a193e53d6649bdb641aa996e38094dbb7cbe365d8c10eba871a38a0f5ebb3
-F src/parse.y 3a7f2156485e377a637b4217b797001cf2ed9228e501f8d34fd06a9f46a40a73
+F src/parse.y 68f3bdc6ab07f5660944cde812318eab6007416fd1ea008422a96f1675c75ff2
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
F src/pragma.c 4577091a839722cd74e5492f10dc238a93751f4bcc0c8c9ee572d7592f3936be
F src/pragma.h b93fd693bd38cefeaf8e2c7e8c929717f7799a9770104cdd2bae8df2a84e2da7
-F src/prepare.c e21b54489b5c73b06ada15e6fc79b5c6f64b06701924a6ca98944ae59e06256f
-F src/printf.c 2b03a80d7c11bb422115dca175a18bf430e9c9dbaa0eee63b758f0c022f8f34f
+F src/prepare.c d778af9986f3b0107c5b255dcfe2696e8e99e00fb77c5115bbfea4e92c3302e7
+F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
F src/random.c f27af4099afaea7284ade5c206224dcfdb2334cfd119d018b470d46356b3f27d
-F src/resolve.c dd47248c2c914feb0d4428c27d782e2723971d32cfa5536f49306d080df4d45a
+F src/resolve.c 40e216d9a72e52841a9c8e0aec7d367bade8e2df17b804653b539b20c1ab5660
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c bdcfed8ae9cb311f145fd204be32e3d03f7bf359c796159900d1eec0b557991b
-F src/shell.c.in aa28256887d049badaf93aa30ab5c76a2ec88143a674d685c0e739056702e5c3
-F src/sqlite.h.in 71ba363afc97d615d43ab4d1c6992036e82efb799852fe96106b79c94bb87f7f
+F src/select.c 52ed98f39e1629ccf568b372f29b376ca6007158a46cdd956dbdcf8cab05fc89
+F src/shell.c.in 1b32ba2918ede13b68df47c7b92b72ba0d06e68d384e78bb9d7456527271d400
+F src/sqlite.h.in a5d8462d3c5a45240a258e6ed401b6fc14b7f4d2e00e94b864c31fc019151ce1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h c4fd0becfa9115e307446ed62228c8c6007ddd03d84b9376ab1bba09ea28a9c3
+F src/sqliteInt.h 00259853d647cd714b93834ffef171d242077629e8fa905c9f19de3995c046c8
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
-F src/test1.c 6de6fac373fbf2533e8e772543398cb826d09e6aa38e199a496e09e2a4d1c75d
+F src/tclsqlite.c 97645e4a15dde6a6ad6de8d81057ff9869413b866015a89e208fedacd709493e
+F src/test1.c bb6fe83c5a0e255930c14cc6f0b29414410661839fcdd95015abed823df636b4
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 7fb971777c2c79c734bb52757191d68d4af659b8de9b4a071be3f527a9d19a02
+F src/test8.c 0c856d6ff6b0d2ff6696addc467a15ed17c6910f14475302cd5b3b4e54406161
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
@@ -574,7 +575,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 21aa5fc3e6bb11c60ba7f9a33b73951af8cb7a2042355f07469146b7e5e36765
+F src/test_config.c 7768197f40225aacf0ab4a325b0c30c0dd6ebdf2c64f62da90ad5d4989b42bf5
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -613,34 +614,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 0b9c82fa628b5adce93e2bcaf935a24d43eb83344fb51551f7835526d0693fc4
-F src/treeview.c c6260e1fa5f41c361b2409edc9b0050bcaef5bc4d6abc467fbc45f0d7ccf3d84
-F src/trigger.c 861c3ec2c5b0fc830bdf82470454a9324fad70cbaa96d2e208fb54577c9e8d28
-F src/update.c 254aa78e23a18767a5d55b9d7efb6d808b1fcfd52124c774fa7868546f2ca2af
+F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
+F src/treeview.c e483aeedf6f207000db1f90eb6abd816350493314c30e8749d319bdb9ab3b08c
+F src/trigger.c e0fd347b2571a2d956318cdc6d011ccca7ce862d10a0ca04188a37920ef5440c
+F src/update.c e94570c89b2e339a7ae3e9f7f031ec69487112983e86608d93a8b1171be8b7da
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/vacuum.c 9d6ac090ff36d80f0a2c5bfc63994b714c464bfc44efa5056c457a6a4163dc99
-F src/vdbe.c cb96a5890cab40cf01511296b61c1720df5b421e426ca3e7358d183dad906468
+F src/vdbe.c 52918feb4b91ac67b45990105101818a0c1887a9ba2ad000345f7bdca0fb4bc1
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
-F src/vdbeInt.h 000d9ab1ea4cb55a80de15e28f3f595645b4fddef34bca4347fb3db8031d9041
-F src/vdbeapi.c 4a43e303ec3354c785f453e881521969378e85628278ab74ba4a9df790c0d93b
-F src/vdbeaux.c cf79a11bff51f6b99fc898d10117f4ec289edd92858fae313a3ff8c4f0c60f0f
-F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
-F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
+F src/vdbeInt.h 58980223a32495ad059d10581b83e133abdc77248b1bab85c080cab8a13bd819
+F src/vdbeapi.c d9e99daf59fec928986838b3389a7337e82fec6b3b5de30206cb99fb4661b94e
+F src/vdbeaux.c 708f3479a4b1f895f654e29b4fa597ee4c2927ecde3a27ed07dda964a3a12b3a
+F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193
+F src/vdbemem.c 175c73ced03edbb0f6567a41c8032afaeb83372090fa7bddfc88a67e28da2b8a
F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
-F src/vtab.c 032a0165c147fda16927e6a3230e90c068d4af93f887ce94e26f678fe48e5e4c
+F src/vtab.c b928405ccb66040fc6c3a11eaa93ddb02cbf20f9ab6860b301b222b9b50dc089
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 14561b22781dbf67ec97dddce537e31c1419f94e06d548d2d26cb5c44552ecda
+F src/wal.c 24068dd5d1c25d55d4fb6e362edc2fa680a85ced86a9650d88ab3edaecb1035d
F src/wal.h 7a733af13b966ecb81872ce397e862116b3575ea53245b90b139a2873ee87825
-F src/walker.c d42d6c80ea363ef689a462e65eefcfe87deab924c50de5baa37ecb6af7d7ddaa
-F src/where.c 10d06b16670a1d2a992d52a9f08e49426d38a08fb0a7ae5f7f62fd023d560e1e
-F src/whereInt.h 446e5e8018f83358ef917cf32d8e6a86dc8430113d0b17e720f1839d3faa44c4
-F src/wherecode.c e57a8690311a75d06e723e8d379f9831de04aba300e07174d236e32a7f9c7a13
-F src/whereexpr.c 53452fe2fb07be2f4cb17f55cc721416fae0092c00717f106faf289c990b6494
-F src/window.c 7e89ac4b6cd6bb9b7772234a625d19c39b530f4ac06e43688a8b7e6a1ab512a2
+F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
+F src/where.c 32f41c3c93c6785e0077e3a2cdc669c3ccfe70173787847be77f294c18fc7dc3
+F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
+F src/wherecode.c 110ed13049e0f1dc27e9dd942eb870417b36480cb7819302f5804cbcf9330b0e
+F src/whereexpr.c 5a9c9f5d2dac4bcdcaae3035034b4667523f731df228e0bb1d4efc669efa9da5
+F src/window.c ce5e73ab88a8527d268673906bf89cbe58c61bca8d54d38ed8c33c3220a276ee
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
@@ -651,34 +652,35 @@ F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
F test/alter.test f53d8a4ecd35f051c07e54a36beec5d0a30d30a9d98bc723f6cde6afbfb3c5ca
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
-F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
+F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
-F test/alterauth2.test 794ac5cef251819fe364b4fe20f12f86e9c5d68070513c7fd26c17cb244c89af
-F test/altercol.test 3456f7cc4196ef8f7d82d245d6e91940eb12bc95c36c91ac4b512f6b5c9a4fa9
+F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d
+F test/altercol.test b11fa1b131e80ab5b6ecfb3b725fb0419c14ca6efba5adb57aeabfc9baa0c8f3
F test/altercorrupt.test 584d707a80e106952d6382790c8919bcf9f0db678ed3a1c09fd98b7f9d1d3a10
-F test/alterdropcol.test 596623cb8a72d9570bfb8417b0f302810efe007873796f03c17a9e9ff28dade1
+F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altermalloc3.test 2c7bbd8cf3e9c4a91e28675bb62bcc2ef70f227967fa74349f03d9f4642f0615
-F test/altertab.test 7691872aadfe00a94b459af9086504bcf399dd936336e486da1b182930744b77
+F test/altermalloc3.test 059841a3de6b6780efd9f0b30bf1d9b4443c555f68d39975cbcac2583167b239
+F test/alterqf.test 67568ad152db8c1187b15633b801242cf960f1beafc51261a3d1725d910baeb2
+F test/altertab.test c7966d92e4da535050b911e1e9972ecb3a5befb0b2d22026b132cf5003d43dec
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
-F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49
-F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
+F test/analyze3.test 4440c4932247adb2b4e0c838f657c19dc7af4f56859255436dc4e855f39b9324
+F test/analyze4.test 293ec8ea21525f3435beaf9d6b1efb29e719415f03a0cd2a70589d59098e8464
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
-F test/analyze6.test 6c3f7df2996cb6872f355a6ac1eb6d5de00a5a9288214bad7ef25c97d9cc72dc
-F test/analyze7.test 6ef0b12369f61ddeadc7d8a705c40e6b52cb29f63de3a4c56581b510b46b5783
-F test/analyze8.test 36ce54947710bd44e4f9484e1ad07e725ef01a9d7078b417c1bc884356febe4d
-F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54
-F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46eac710
-F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
-F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
-F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
-F test/analyzeG.test a48c0f324dd14de9a40d52abe5ca2637f682b9a791d2523dd619f6efa14e345b
+F test/analyze6.test 028f5bdfc9e5b5294768fa9a7185b8cd1d019aa7aab5b2f8ee42d7271d9a3b28
+F test/analyze7.test 079d17c495e396bdbd6cc6a083112788a6fbfb3b95c42e760e4270a53c9ead8f
+F test/analyze8.test 29ef237d8a59b39cc31c3310134fefe96a690b195e3deed5ecb652839089f15c
+F test/analyze9.test 162cd40d713310fbe7a63a5ecff5d3a013777d86809618838177d9b2af4dd09c
+F test/analyzeC.test 1111830ad355d29a294a5dda654dd5f6a8622c6a223a4f7b7b3d091df7a7a42b
+F test/analyzeD.test 485f621cfd2ef0a8f8ac79672586651bfa495bd899db50461bb4b558400ab3c1
+F test/analyzeE.test 69d130f9ba78c9853dcd5a18317e81f462a72d704cec0c4c30afb220213acd29
+F test/analyzeF.test 40b5cc3ad7b10e81020d7ca86f1417647ecfae7477cfd88acc5aa7ae1068f949
+F test/analyzeG.test 623be33038c49648872746c8dd8b23b5792c08fef173c55e82f1b12fca259852
F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
@@ -692,18 +694,18 @@ F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
F test/attach.test 54f8e49e88d0de48f6428267a678465863d2b8f72320612f35bd5c02e240bc2f
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
-F test/attach4.test aa05b1d8218b24eba5a7cccf4f224f514ba57ba705c9267f09d2bb63fed0eea1
+F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
F test/auth.test 2154625c05bc79f0e0ea72cb2358395a8041243caa0fd7ce7617d50da4331794
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
-F test/autoindex1.test 96185415f5faacd5b8d7a7f505efddd5abb1f111d58338e9c0b1dc40b87cd3cc
+F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
-F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
+F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
-F test/autoindex5.test a5d72fe8c217cc0ea356dc6fa06a282a8a3fc53aa807709d79dba07a8f248102
+F test/autoindex5.test ee0aa95e3f44190347a29a672c3d4ecf042e3f33c5fa3dc29f0ab6be057bbded
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
@@ -719,17 +721,17 @@ F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
F test/bc_test1.c e0a092579552e066ed4ce7bcdaecfa69c4aacc8d
-F test/bestindex1.test 705b57d7f51d53ee5fd043dd9666236e1fc18f4d59abf51da0ea5ea1b4804947
-F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
-F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b7920b47b84
-F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
+F test/bestindex1.test 2e92e046148b3f8a2be62af9c0f307413547a33677af0df159c0fcc76e5134a2
+F test/bestindex2.test 60266e2854055788459cbfd86cef575601eabe74a2c61faba72601739fea4398
+F test/bestindex3.test e061a6ed0f519beee037ba7e7a4c37f80c8a7e4a303e2559ed1f760e4b0235eb
+F test/bestindex4.test 82250e7dcc6d5b15244edc9d6554b1760583af1b8548c2a255a1c4f28e744c0e
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
-F test/bestindex7.test f36ada201973d3022cf7afffffe08de9e58341996020e7a2df9a1d2f2be20132
-F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802
+F test/bestindex7.test a11348824aed0de2bb9030f092636929000cd72882bdf919adacc3792f67ccbd
+F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
-F test/bigmmap.test e906cf9729d7c362270ffe9fa6471f4c39c28ba83f0f77fb795e1b4d38a22ba0
+F test/bigmmap.test b820c234daa56d24bc3bf006e3ac7aa9d9623c8ac656a38f59063b444a2d65d1
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
@@ -748,7 +750,7 @@ F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1d6cc
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
-F test/busy2.test 0a1633fef7987fc8ea25ed5838f7eef2f08fc6d2a3dcc77d23e6402e53946a7a
+F test/busy2.test dbfb61b3265e7a962d3bcd32cd542bbe3d7801edbda6438d35af5aa707cae981
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -780,7 +782,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
-F test/columncount.test eff33d402a7b0fde0a52a1920d238af200ca573327021e0ce3b7e5688de41449
+F test/columncount.test d86fb6307261186370698962790ad2088ed419e4a4e823512b502f17d443b1b7
F test/concfault.test 500f17c3fcfe7705114422bcc6ddd3c740001a43
F test/concfault2.test 34b3fd258836aa305475d00e804c7450ade92f0de0bf9fa620e701446669bb12
F test/concurrent.test a0248ec6e3e79a5948453649cf86b5b359175cba55ea636b15426d6f0fa6c3da
@@ -798,7 +800,7 @@ F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
F test/corrupt3.test 2520432b1fbf99994841e69804a3c59fb828183f4d09b85a1631bc7adca17e31
-F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
+F test/corrupt4.test b5ae41607e8d17d9c1f3e94fdb572ce061ed3beeebdb46fb3a348181b8c8a097
F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
@@ -815,13 +817,13 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
-F test/corruptL.test 22589f503602cc5984e80f27f46c4de2134f24f1515ba2440513c377cb692258
+F test/corruptL.test df132ba9ffd6fa15038380b4154998b9904ab8f1ea78400d7da53c920cb3b13d
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
-F test/corruptN.test 781c5f26a2d8918f03d45ac4968a738031eeb113a4b153c7588756d9b09c7b04
-F test/cost.test 1d156ce9858780a966c062694687afe0343a0ed12d081d071fb57027e726bafc
-F test/count.test e0699a15712bc2a4679d60e408921c2cce7f6365a30340e790c98e0f334a9c77
+F test/corruptN.test 187d14093c333ddc705ea6c4aef8355febf260d5174d1b7cbc31c1ac8867951d
+F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
+F test/count.test 5364003488249957750a5f15ee42ca1cd7b100b1131c2dc71fff266a1250bf55
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
-F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
+F test/coveridxscan.test f35c7208dedc4f98e471c569df64c0f95a49f6e072d8dc7c8f99bdee2697de1b
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
@@ -845,7 +847,7 @@ F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
-F test/dbfuzz2.c db2a1710c0d30d38e1352ee1b52b717fcb224c8caacc6f10909ef540f73cc9e8
+F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
@@ -860,20 +862,20 @@ F test/descidx1.test edc8adee58d491b06c7157c50364eaf1c3605c9c19f8093cb1ea2b6184f
F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
-F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
+F test/distinct.test 3e4210ef9cd1985aeec44939ad912c4621fbea9bb4a9c565696cebfe184b2ec5
F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1
-F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
+F test/distinctagg.test d76ef2e91fe810630c176d6bd0a58c14d5851c3125f0a1d977db87ba76359639
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
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 7107f5deda2324ea12dbf105044dc9265195401e9dbb3eead6a2c1a3da4bb5b7
+F test/e_createtable.test 7997c0106c181243e0ac7db7ba8b9ae7233d0bfb0188605650322a7a02ea326e
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 6ba7a51ece7b3e7fc145f14f924eed25ebb5a24e7b8596c78f3838d372cf0385
-F test/e_fkey.test a2907f749cccd0b2c30d8576b673002eebdcc1fc9964bae61e5117b1d54733e2
+F test/e_fkey.test 351c7b989e5aefcc339ef5fc78dc4738442bd247a392cd67d81c2881000c369e
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
@@ -893,18 +895,18 @@ F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 84879b63e3110552bf8ce648a3507dc3ceb72109ecec83c2aef0db37a27f6382
+F test/eqp.test bfe979eb1f4b8ab7a3bd7db6d16c2e6c6be0e5a3aada2227716f3fd3a9d76b69
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
-F test/exists2.test 3e5726d6a67ebd4bd3466db58be424c09156c1f276c7594abb260cbf6ad494d3
-F test/existsfault.test 74f7edc713f5a335e7ff47adf503067bf05c6f8630f88b2a19c24f0fa5486ab8
F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
+F test/exprfault.test 497cc0b8fe6a677f49b55cb485e040f709ec2834b84f25912fe9c2dfeeda33db
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
+F test/external_reader.test c7d34694f1b25c32d866f56ac80c1e29edddc42b4ef90cad589263ffac2cde0c
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
@@ -978,7 +980,7 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220
F test/fts3atoken.test dc2078ce464914efe3a8dfc545dd034a0fc14f2ab425c240471d5a5f1c721400
F test/fts3auto.test 649aa4c198d7acc5cd6355e19ee073d051c40d9e88a43fc3d88af46bdf3e99d5
-F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
+F test/fts3aux1.test 1880eaa75c586cd10f53080479a2b819b3915ae7ce55c4e0ba8f1fe05ac0a6a7
F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977bf907f
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
@@ -987,9 +989,9 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6
F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test b71512ec391d39da96d60d01959e4e9f20d4237a964a94abcf5f5a2ad28378c1
+F test/fts3corrupt4.test 2b61991318db59b3c569d630660c4df0f22b0b2fe59f3bfbc111863b3bda6f14
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
-F test/fts3corrupt6.test d5896a8d389bd824457772dc1e2d2023cd5c5cf8e42733607b5d632103018d8b
+F test/fts3corrupt6.test d274f139ec173392002c768631f404fefc007ae02ffa1b03d8cbd096c3fc00f9
F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -1006,7 +1008,7 @@ F test/fts3fault.test 798e45af84be7978ca33d5bdc94246eb44724db24174b5d8e9b1ac46c5
F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11eb18aaf56
-F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
+F test/fts3join.test b285c919559af5b093c51abb2c07ce7ec0156dbc9573f444b78dabd9f3040db2
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
@@ -1015,12 +1017,12 @@ F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
-F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba1654e78f
+F test/fts3query.test 45806a302921b245a9dba5d85c9d51fb98b3f137eea6e6bf6eae4883e041ab72
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
-F test/fts3snippet2.test 2dabb5889eda4c9980aad325e688b470781f97ce7c0fca0db125616fae0a2cdd
+F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
@@ -1047,7 +1049,7 @@ F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d0
F test/fts4rename.test 2e0565ffd92b2c51f1a757df0b8f2ca30537197106fec09e943919801d173692
F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
-F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
+F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
@@ -1063,7 +1065,7 @@ 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 772110a59c6f839f95e49a9fd3e5f855bd9cbb90e9d366a6ccd15cb3616fc631
+F test/fuzzcheck.c c51cdb34e926d0a6551624aa1f04c456c29317b5457855d64391917d9b4c2aff
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1071,7 +1073,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
-F test/fuzzdata8.db c8325de6fbdd24d030cd3a01384a2ff325dda5d5e3ff5d531a26ada3d9d7e010
+F test/fuzzdata8.db 5e616432bbdd9b27014463545cae06797790645021fbc650d28c994b4f02a6f5
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
@@ -1081,7 +1083,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
-F test/hook.test fa54fa8afc842ae375f10c1f9fc0014fa59789052fc30c9eae19811fa3afa009
+F test/hook.test 55b6d605d06dadbb04416eae8ad79889aea3521d119c87f04353c25f9c1450a4
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
@@ -1089,9 +1091,9 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test 64ac9c767ac5af562f066a40163d4202f8fa3be05d264ec65d6258e74606b30c
+F test/in4.test cd08375ba470b248c3dc4ab30fd5dbcb682deafe3862d8249ba0ad6a11dd25ea
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
-F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
+F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1099,7 +1101,7 @@ F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
-F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f97d4a2b
+F test/incrvacuum.test 3fa6145f5e71f603554fd7b8ec3da4290b1341029682313285cb5f9e1893d6ba
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
@@ -1108,13 +1110,13 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
-F test/index6.test f172653b35b20233e59200e8b92a76db61bf7285437bf777b93b306ba26a47e7
-F test/index7.test b8a0ba2110fd517bb48c4e76d26d60f1ab2ed9e257b18d71f820d7e71e9f8570
-F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
+F test/index6.test 880858a65d8686120fe9a8971a4d82b429cc206fe7fd525b8b2b55451c74d82d
+F test/index7.test b238344318e0b4e42126717f6554f0e7dfd0b39cecad4b736039b43e1e3b6eb3
+F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a912a3
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
-F test/indexedby.test a3ca11f0819a9279619099f36b624bcaa315f7a1ed65c3ed2219c2a944683d2c
-F test/indexexpr1.test 284e119999d132cc8bf37735a928c9859b28e8e295d02b7a6a4f93977c7f9ba5
-F test/indexexpr2.test dba11dbb0a58fcba4cd694f46b4004976123b81b0501f525d43c9be59f0207b1
+F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
+F test/indexexpr1.test 7e0e7a33acb4d9b3524398e6ce90cc05c26603fabbaf3062083a036c8874bc12
+F test/indexexpr2.test 2c7abe3c48f8aaa5a448615ab4d13df3662185d28419c00999670834a3f0b484
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
@@ -1128,7 +1130,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
-F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
+F test/intpkey.test aee694afed1a65c86c4e69ad030224b3fc268113d00685234d40079fca16bad3
F test/intreal.test 2a87e85a5949bd55e41ef04c58f5800587c5380bdbc559ff1c79b614b0e6a533
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b
@@ -1139,10 +1141,10 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test 9619a2d77580f676048aaff7a16a0bcfea2b96c6c660dfaded2e53c873418899
F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238
-F test/join2.test 21fc30e54ab35ed66bf51b89cec18729205497f5cc43c83bc042f96a73721593
+F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
+F test/join5.test f418fccdfefa41f1659663463aa517431ddcf3e30ccbb80e64173b7d615a03f4
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
@@ -1160,9 +1162,9 @@ F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
-F test/like.test 0b7b4765ca59d95a1f92dfab9e4d810c9fb8280b5edd6332a01340a20db9e0ed
+F test/like.test 5fe0bc37f307aef0a453ce2de4632bdfc0759448f0421c39f6d53caefe905fac
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
-F test/like3.test 03d1bdf848483b78d2cfd1db283d75c4ec2e37c8b8eccc006813f3978d78fbbd
+F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04
@@ -1197,7 +1199,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
-F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c083707ab
+F test/mallocK.test 25897506da0098cea09b302ff432b0fb6d8002773c1e0fc9732aa8b444bfd455
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
@@ -1205,22 +1207,22 @@ F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0f
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
-F test/memdb1.test 58d92c2bf622cc5f0f41461e1b35cf64f3f787199544c2c1dada37d88753f9d4
+F test/memdb1.test 7b76c3262d63c46dd6b408d18f5721071776f2df4ffeb11e668824e427127594
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
-F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
-F test/minmax2.test 1edf66901ddfab26ae1e04165e8da834c8d3284e2b20aefb26b80ef217962eab
+F test/minmax.test 0015e5cd5e7af48bb3364f26d9f3a9cdbea2a442d4774281c39e2229591b7351
+F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599
-F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
+F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 7b4c88c1d5ea8c8b9d537d212c08a0343d345fdd5c789598692c1c0e60fbda69
-F test/misc8.test 8782708f4c8a459591c3e8fe1215bd2048bffb4024b3df249e9b9ed407dc61ed
+F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
+F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626
@@ -1243,18 +1245,18 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
-F test/notnull2.test 965a893619751255e59c911a8c58504b3174a3788b1458b7c7365b232209711b
-F test/notnullfault.test 6126e31300632070ca6021698393c7fcf61ab4791bc2aa1d6d704242c0fcd4f8
+F test/notnull2.test 131365171d973c57fe694fcc46c1e645f6e24ceb43b230ad5011a0ea2182f215
+F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
-F test/nulls1.test 82c5bc33148405f21205865abf13c786084438d573a4ac4e87e11b6091cde526
+F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
-F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
-F test/orderby1.test 6bf0ce45cbfb1cf4779dd418ac5e8cf66abfa04de2c1d2edf1e0e85f1520d8f3
+F test/optfuzz.c 690430a0bf0ad047d5a168bf52b05b2ee97aedaad8c14337e9eb5050faa64994
+F test/orderby1.test a4bba04b9c60a21e53486fbc173a596b29641a3b3a57a0f26a1cbef1360358e9
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
@@ -1280,7 +1282,7 @@ F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 1f08abeae53780436b5a9c6716e1cb48ebf830cd6b0a9df615d952030c05d84b
+F test/permutations.test 5dc2b65860e54e2fd15d994065035867368c0e29af17053935ec095ecce4cc85
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 50b91bedea9324d3ab48e793f908ee7d2c7dcf84bfa2281e792838be59641ec8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1308,22 +1310,22 @@ F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
-F test/releasetest.tcl fb76d8fcc95ac29d6356cd9e52b726ab9e43a24082897618dfbcb7c2b0049153 x
-F test/releasetest_data.tcl 3d41ddb3f04f474ac9d925485da24ce6576ff0ebc4c7201c8a340bc09846c261
+F test/releasetest.tcl 6f803ef0b896f8f3f4c26eb072c0399963a5987a509a64d45f5dfbc1ebae2951 x
+F test/releasetest_data.tcl f88ed29aa18366ed3956ace36c96ec6868ef5b9ee04cc05d32f4d81031e19e28
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/returning1.test 209b910c132cb2015bb1159f852c7124778004963c09095c42c3d2442110c56c
+F test/returning1.test 52b4ed60f104a4ce85b38417e5319b2078b2b908c71a768d539cee3c0ce8bdc9
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
-F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
+F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab21e
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3
-F test/rowvalue.test 6795850abf6243e96f09ef041919d1ea61713332237b60d01371c0fee73f6379
+F test/rowvalue.test 466efbb7bb93ca9f95d89f69c7c140aa52cc57ac6dfa7efba09ea4a9ab3cd9f0
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
-F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
+F test/rowvalue4.test 441e7e366ac6d939a3a95a574031c56ec2a854077a91d66eee5ff1d86cb5be58
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba
@@ -1340,7 +1342,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test 48a645a7bb3a59a6fcf06a7364cfe5b655c336760de39068f7c241b0fc80d963
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test 874e35011779b07725a47dbf1dd6282b0ca04af7e028fb0b534ee544b571be42
+F test/scanstatus.test 9a0ed37ab6d57b50567282788fffdf832d9b16739ecc41bff9d77a8d767cf317
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
@@ -1353,16 +1355,16 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test 3d23f66bf9ba77570acfe2ca5f1540ece17037cc64ab1a00efec9758ac29c268
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
-F test/select4.test e8a2502e3623f3058871030599a48abb35789d2244d5b380ecf3696873fdd4a4
-F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
+F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
+F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae
F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
-F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
-F test/selectA.test 68de52409e45a3313d00b8461b48bef4fb729faf36ade9067a994eae55cc86f4
+F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
+F test/selectA.test 985df11dfc58dedd6f8124dea32754566346b93e294f26291b5c96d10c8cc889
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test fec14c9015ed4ec941508bbc144f30b42e40ac34a4bb33001450369865dd0b75
-F test/selectD.test fc20452847a01775710090383cfb4423275d2f745fed61f34fbf37573ac0d214
+F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d32189bfb
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
@@ -1395,11 +1397,11 @@ F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
-F test/skipscan1.test ed524bc86f27646b3a297f45d6557b55db338977b6838f8064b196b35848b31b
-F test/skipscan2.test 3eb703ce794f139e7b83567911046298bcde29606116727f9b700ce34f559d2d
+F test/skipscan1.test 1a9972e1dc15ca3887f306d3cd9a29679afb382eca0f3539f3b746f3c2ccaf68
+F test/skipscan2.test c588cb7ed947db724d300f2a0dc537dd2ad292b0f812641d8481bc0b95dd3f49
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
-F test/skipscan5.test 980875ad45d8aacfe7bdec7c288343520cd1d14e84befdcfe50c785f9e6c8709
-F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
+F test/skipscan5.test 0672103fd2c8f96bd114133f356192b35ece45c794fe3677e1d9e5e3104a608e
+F test/skipscan6.test bddbb35dd335e2d21b7791a61e3b2e1f3255dc307ce80aa6fe19cc298e6feb13
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
@@ -1453,7 +1455,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 5ca6d004157a3e886a55a9387b960cc0db41acd88753eb597ff409ec6cfb1be0
+F test/tabfunc01.test acb5be558868c65d8cf3495539fff23093d77139eb1e4e8c4580568099f98645
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1478,6 +1480,7 @@ F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c cfd72c74a40de3eb7576f1ab2da28183390deadb13f2aa5c8d077aacd41eda60
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
+F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-18458b1a.test 6a62cb1ee50fa3c620da59e3a6f531eb38fceaf7e2166203816b724524e6f1d6
@@ -1487,7 +1490,7 @@ F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
-F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1
+F test/tkt-385a5b56b9.test 81d7c8ef2d2a378323ba2190c1f02f91022fdff0d8d0b84c04954d02c85ef374
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3a77c9714e.test 90e3e8455ee945a4076d4c44062b8845708af24a880355328fe7008f2047c9f0
@@ -1502,7 +1505,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
-F test/tkt-78e04e52ea.test cb44d0f5e7940223be740a39913a1b9b9b30d7e4a17ed3349141f893bae1b8f2
+F test/tkt-78e04e52ea.test b731f2ab7d1c2482ac5152097da02ef4805a45147ba9498d3cd9da27072f34d1
F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
@@ -1521,7 +1524,7 @@ F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
-F test/tkt-b75a9ca6b0.test ade89229d853a67a21bbd5e6e1e787a8f9d21f19908d1b7fca6bf3d4d5aa0767
+F test/tkt-b75a9ca6b0.test dc6a853c242f7d0326564ae32e9e5eb462b5e8d2bc5b01ea3b18fd24f8e5894b
F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
@@ -1587,7 +1590,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
-F test/tkt3442.test a1fc47c669e651d16494de3ff349bcb53281456f2ca02c8bc14220b6044bbfe8
+F test/tkt3442.test 6287173de5bb2d43693b1f822426018a209f9df49ce2f454808bac1771852330
F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
@@ -1623,23 +1626,23 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
-F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
+F test/tpch01.test 4479008f85f6f8f25f7ab2cb305d665752b4727fa28a8df3d8e0ad46520c62ff
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047f31
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
-F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
+F test/transitive1.test 06bcfeeb2ed719abf6ae582f9f65a6b07642dd1363fa648ae9a74a35e83a825c
F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
-F test/trigger2.test d15da46f7012832faf3e0c536b47024409d5fb1722d2bb77e29c06d96d704bb1
+F test/trigger2.test 6e35bd7321c49e63d540aee980eb95dec63e1d1caca175224101045bcc80871f
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
F test/trigger7.test e7ce54bfda67a88d778aea42544e151c465547a7e617127b6914c2221a6d53c1
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
-F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
+F test/trigger9.test fd49aff8b724ae1a6238989ecf84320d88c0e8f8d9142a891b93f826dfe37b59
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
@@ -1647,7 +1650,7 @@ F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
-F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
+F test/triggerupfrom.test d1f9e56090408115c522bee626cc33a2f3370f627a5e341d832589d72e3aa271
F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f49edef1494
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_core.c 8cd89ead95410f70e7fb02c79f1e040f9c5ad5cf
@@ -1659,22 +1662,22 @@ F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionall.test 369dac51f4e7b94442b054d3d7f2e6755cd6994274718228878e3bd47c425f6d
-F test/unionall2.test c9a62db63350bcbce3a7bec50dd8c5410f08be33f8af435473756286d4657215
+F test/unionall.test fee6e6adebe5446938475432ae8b042835a286c7e2efdc1b186d2182dfb93ffb
+F test/unionall2.test 71e8fa08d5699d50dc9f9dc0c9799c2e7a6bb7931a330d369307a4df7f157fa1
F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
-F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
+F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
F test/update.test e906ca7cb1dc6f52af1ea243e08f727edfa79f924c2691f2f9e72481f847310d
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
-F test/upfrom1.test d18f69f7c691bc791e7f31bf0e354eeff04cf2f44edc32d6b1928bad71697073
-F test/upfrom2.test 6ebd3be8c3fac984e89a177d823686f04605b512fc167392bce6d8ba2ba63325
-F test/upfrom3.test 7dab379d128e8dd7beb2055b295fb113c7ba93e8c2038f5ddb7a4a10f0ebb348
-F test/upfromfault.test 70ecf8eb85559727a487283f69374e3ae39879e994d8a2437c49d7c05ecb70c9
+F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
+F test/upfrom2.test f92e47bfc35e9410d3e8716ee626384e89ad026c55fd6148508ca9d707521673
+F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
+F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
@@ -1696,7 +1699,8 @@ F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test ea88361d5e9bc8eabf9f573185a16aea73a885be9b6c6a95ae84908913416a80
-F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f
+F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
+F test/vtab1.test 99c0c13b5336ca7f87f137459de144b2f396bb8563fbd602e46bfaa425e3d8cc
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1760,43 +1764,43 @@ F test/walprotocol2.test 7e4bedd5ee83607e2928ac438bf7332a396b980d3e02aa0746509ce
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
F test/walrofault.test 5a25f91c16a68bae65edec7cdef4495e5c6494c8408743fe9b29045fa6665cd0
-F test/walsetlk.test 11f7fe792fdce54cf09874dab824e0627f2eedecfb9f7983e325606ec5184e0c
+F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
F test/walvfs.test bccb3e0d235ef85e276f491d34db32c9ada1ea67be8d9f10aabe7b30319ec656
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
-F test/where.test e713c0c64e3e6b062235e39a2f7e5508c517df16b63d69fd786e26bc7330b1c6
-F test/where2.test 478d2170637b9211f593120648858593bf2445a1
-F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
+F test/where.test 4f7a3939e5190845ef42142031a1819070f65e065e6a840a09adc54dccfef01f
+F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
+F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
+F test/where7.test ab41d53ce8f2a6919ea3d5b13cd1153c1375a8e3ddaa129b81781f9033981383
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test 8e3e0ff42cc17156f52361a1c012281550d0d632912fec92d1d6df74db7a8e6d
+F test/where9.test 1ffb75edc50a8faa6e7bd77f8221d783febb00b44b0bdb32fb48cec6e38eca95
F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
-F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
-F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 77127a4d214bb21da3b5c695cf4106cd9e418c60d9c24471ba55d3772067cd35
+F test/whereE.test 0ac7e61c6225354a980666996539da154991b4325af943a25a9079079c82fb03
+F test/whereF.test 926b65519608e3f2aa28720822b9154fb5c7b13519dd78194f434a511ab3dac5
+F test/whereG.test 8f1a753826d07ed7ae107fbec0d482d348bac6d7edf9db9c5736c06b0b3e9961
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
-F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
-F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
-F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
-F test/whereL.test 1afe47227f093dc0547236491fb37529b7be9724b8575925a321001b80e6a23a
-F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
+F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
+F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
+F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
+F test/whereL.test 50171e3ec00b4c8ad5ec773119a35d9e9642cec45154b44c366d628326479f4d
+F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
-F test/wherelimit.test daa0fd9122c5745cc459ec40b8d3c16ce13ce8382b5b847e7cfff4b871260cbf
+F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
F test/wherelimit2.test 657a3f24aadee62d058c5091ea682dc4af4b95ffe32f137155be49799a58e721
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test e52b81fff0c3cb122a1240f336688eb81bea2967a99c4ddb78969adec7aadc2a
+F test/window1.test 7cb66f49d30d89ca9d28dc20f7f1d85229365651e8e6211f7da1448740866511
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1807,34 +1811,34 @@ F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652
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 4d8c875b73febdbac9b8f2b52ec132b98f48261cdafd6b08db62bc6d8ff913fc
+F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c
+F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
+F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
F test/windowB.test 6e601f8178ba8ba28b2f19e74fe613815084bb4a8d2ad942defc7d42e191e521
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
-F test/windowfault.test d543d46571b32d19f198cb04b6505747fabf3cc369970daae47074ee793612be
-F test/windowpushd.test 5b9c114e8173c3addacf58a0fcd941437b14649f2033700184479a13f188ad00
-F test/with1.test 780be387f01e290e768bdfd1827280f9e37ba37223eb4736aba386864fac5a94
+F test/windowfault.test 21919e601f20b976ea2a73aa401220c89ed0e8d203c4f69476ea55bce3726496
+F test/windowpushd.test d8895d08870b7226f7693665bd292eb177e62ca06799184957b3ca7dc03067df
+F test/with1.test 7bc5abfe4c80c0cef8a90f5a66d60b9982e8ccd7350c8eb70611323a3b8e07ba
F test/with2.test 000fb95f1f29dae868cea0f41505eb5126077d49eb967ff88f9ee46212ad8863
-F test/with3.test 2f1e05aef7aeef9a741cbf36deeb4be73003dc541921c3abc78becbbf5b7852d
+F test/with3.test ad32d13ad50661e6fa305f62a0717649c348792e7b658bf2644976227a9e0373
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
-F test/with6.test 3001b59179cbdc26a8c67ff8f46944e3141fdece9ab064c49bbf08459b67b207
+F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test e4034c0849ccc2e8bb749c69f15bd69bb9fcf8fe77e8d17ce02369604242fe83
+F test/without_rowid1.test 6abc5d497f634520944dac0a89a6c240a48d2ee0f8353356a750eb70dc1db41a
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
-F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e
+F test/without_rowid6.test efbd7add62c59bf5ca97bf8da674e734e6a70ef979234e816166824b4d258f68
F test/without_rowid7.test d7c59a93d726b55812d620f8f284e01904a5b85f9ee9eea8f2f68571a5e8c40e
F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test 429cb81c518487fa1b644b6b04b6e9af704a4fa767bd1a110204c5f03b2e8616
+F test/zipfile.test 0d8758d8c0d63f16644f959689f78969d223789d998964276554039f067b4548
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
@@ -1858,7 +1862,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c d44ba4f03427c9bd34b601f315fe77c2b6d4bd215801a0259aeedbcc4c94a95c
+F tool/lemon.c a5acddd3eec6a388872aae6efc7563336348a9c45e5563642f77e8e3a50e859d
F tool/lempar.c 1d3d075da18681c67ecc66c1f171e7094e18cd2cfba6a8a1bd4f3f639d6656e1
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -1866,11 +1870,11 @@ F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
-F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
+F tool/mkctimec.tcl 06b0d503ee0e6c2d4abe83563b43d4925a12e31ec9fb3249ce39661f53fbd1ce
F tool/mkkeywordhash.c 08b6e4d7a482a7f37a9a0032e7ba968e26624a027b6b2e9ba589be6f5e3d8c2c
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
-F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
+F tool/mkopcodeh.tcl acc798757e2c60e4b6e16745505b9595fca76c206815c8ada576a136cf3608ed
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl d189900fe12be39539f7101222968ac7a5774a63638471f0b6bff9c35006743a
F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
@@ -1882,14 +1886,14 @@ F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
-F tool/omittest.tcl 6616fbf384f0f630113eab27d41d4530435dd94e2883307759988b45f0604a3b
+F tool/omittest.tcl 3d222272b1d840b4e3d67bff0cb743ce3f633faddadb3702b2056b726775db8f
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
-F tool/showdb.c 49e810f5c414c792b5bf38cd5557ca9639713ebfef32aaff32faf7cb7ccce513
+F tool/showdb.c 8c6b1cbb86ee25ca2173497183f8fcd444d4e26923e4cf57ddabe66c633b4dab
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
@@ -1941,7 +1945,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 939b9e75307de5067a11351dd4010046a5400e8126c5c2bafea4fbea97e00f86 a1b8d9d2131830510df291832565311803aa3e047fe07ba979fc69bb0ff329b0
-R 7bbf6335d87c431b256bdcc0e37c4449
-U drh
-Z bcbd80bc941321d81490b0f3b639d622
+P 4d425e641d3c45692904018aa8fcff678836b45509e640e67fa2d1ade625a746 95cc7783457b39bbe0866295648a86e7ee5e1660048ab133f1ccf300498ef1bf
+R 066113fe997854e21efe7108e9d23406
+U dan
+Z 8826b40f6989cab227702a244668a78d
diff --git a/manifest.uuid b/manifest.uuid
index 4725df9725..6fb353864d 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-4d425e641d3c45692904018aa8fcff678836b45509e640e67fa2d1ade625a746
\ No newline at end of file
+4efefb5938c1ec83ee367ae5cc4bba906729b4e8699fa81adc6ca3618c73eb03
\ No newline at end of file
diff --git a/src/alter.c b/src/alter.c
index c0797db45e..047b407e5b 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -29,8 +29,9 @@
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
- if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
+ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || (pTab->tabFlags & TF_Eponymous)!=0
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlite3ReadOnlyShadowTables(pParse->db)
)
@@ -54,7 +55,7 @@ static void renameTestSchema(
const char *zDb, /* Name of db to verify schema of */
int bTemp, /* True if this is the temp db */
const char *zWhen, /* "when" part of error message */
- const char *zDropColumn /* Name of column being dropped */
+ int bNoDQS /* Do not allow DQS in the schema */
){
pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
@@ -62,9 +63,9 @@ static void renameTestSchema(
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %Q)=NULL ",
+ " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
zDb,
- zDb, bTemp, zWhen, zDropColumn
+ zDb, bTemp, zWhen, bNoDQS
);
if( bTemp==0 ){
@@ -73,8 +74,32 @@ static void renameTestSchema(
"FROM temp." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %Q)=NULL ",
- zDb, zWhen, zDropColumn
+ " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
+ zDb, zWhen, bNoDQS
+ );
+ }
+}
+
+/*
+** Generate VM code to replace any double-quoted strings (but not double-quoted
+** identifiers) within the "sql" column of the sqlite_schema table in
+** database zDb with their single-quoted equivalents. If argument bTemp is
+** not true, similarly update all SQL statements in the sqlite_schema table
+** of the temp db.
+*/
+static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." DFLT_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix(%Q, sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
+ );
+ if( bTemp==0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE temp." DFLT_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix('temp', sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'"
);
}
}
@@ -237,7 +262,7 @@ void sqlite3AlterRenameTable(
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
- " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename',0) "
+ " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
"THEN %Q ELSE tbl_name END "
"WHERE type IN ('view', 'trigger')"
, zDb, zTabName, zName, zTabName, zDb, zName);
@@ -596,6 +621,10 @@ void sqlite3AlterRenameColumn(
goto exit_rename_column;
}
+ /* Ensure the schema contains no double-quoted strings */
+ renameTestSchema(pParse, zDb, iSchema==1, "", 0);
+ renameFixQuotes(pParse, zDb, iSchema==1);
+
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_schema table.
@@ -625,7 +654,7 @@ void sqlite3AlterRenameColumn(
/* Drop and reload the database schema. */
renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
- renameTestSchema(pParse, zDb, iSchema==1, "after rename", 0);
+ renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);
exit_rename_column:
sqlite3SrcListDelete(db, pSrc);
@@ -806,7 +835,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
- if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
+ if( p->selFlags & SF_View ) return WRC_Prune;
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; inExpr; i++){
@@ -890,7 +919,9 @@ static RenameToken *renameTokenFind(
void *pPtr
){
RenameToken **pp;
- assert( pPtr!=0 );
+ if( NEVER(pPtr==0) ){
+ return 0;
+ }
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
if( (*pp)->p==pPtr ){
RenameToken *pToken = *pp;
@@ -1049,17 +1080,12 @@ static int renameParseSql(
const char *zDb, /* Name of schema SQL belongs to */
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL to parse */
- int bTemp, /* True if SQL is from temp schema */
- const char *zDropColumn /* Name of column being dropped */
+ int bTemp /* True if SQL is from temp schema */
){
int rc;
char *zErr = 0;
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
- if( zDropColumn ){
- db->init.bDropColumn = 1;
- db->init.azInit = (char**)&zDropColumn;
- }
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
@@ -1092,7 +1118,6 @@ static int renameParseSql(
#endif
db->init.iDb = 0;
- db->init.bDropColumn = 0;
return rc;
}
@@ -1116,47 +1141,72 @@ static int renameEditSql(
int nSql = sqlite3Strlen30(zSql);
sqlite3 *db = sqlite3_context_db_handle(pCtx);
int rc = SQLITE_OK;
- char *zQuot;
+ char *zQuot = 0;
char *zOut;
- int nQuot;
+ int nQuot = 0;
+ char *zBuf1 = 0;
+ char *zBuf2 = 0;
- /* Set zQuot to point to a buffer containing a quoted copy of the
- ** identifier zNew. If the corresponding identifier in the original
- ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
- ** point to zQuot so that all substitutions are made using the
- ** quoted version of the new column name. */
- zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
- if( zQuot==0 ){
- return SQLITE_NOMEM;
+ if( zNew ){
+ /* Set zQuot to point to a buffer containing a quoted copy of the
+ ** identifier zNew. If the corresponding identifier in the original
+ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
+ ** point to zQuot so that all substitutions are made using the
+ ** quoted version of the new column name. */
+ zQuot = sqlite3MPrintf(db, "\"%w\" ", zNew);
+ if( zQuot==0 ){
+ return SQLITE_NOMEM;
+ }else{
+ nQuot = sqlite3Strlen30(zQuot)-1;
+ }
+
+ assert( nQuot>=nNew );
+ zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
}else{
- nQuot = sqlite3Strlen30(zQuot);
- }
- if( bQuote ){
- zNew = zQuot;
- nNew = nQuot;
+ zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ if( zOut ){
+ zBuf1 = &zOut[nSql*2+1];
+ zBuf2 = &zOut[nSql*4+2];
+ }
}
/* At this point pRename->pList contains a list of RenameToken objects
** corresponding to all tokens in the input SQL that must be replaced
- ** with the new column name. All that remains is to construct and
- ** return the edited SQL string. */
- assert( nQuot>=nNew );
- zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ ** with the new column name, or with single-quoted versions of themselves.
+ ** All that remains is to construct and return the edited SQL string. */
if( zOut ){
int nOut = nSql;
memcpy(zOut, zSql, nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- RenameToken *pBest = renameColumnTokenNext(pRename);
-
u32 nReplace;
const char *zReplace;
- if( sqlite3IsIdChar(*pBest->t.z) ){
- nReplace = nNew;
- zReplace = zNew;
+ RenameToken *pBest = renameColumnTokenNext(pRename);
+
+ if( zNew ){
+ if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
+ nReplace = nNew;
+ zReplace = zNew;
+ }else{
+ nReplace = nQuot;
+ zReplace = zQuot;
+ if( pBest->t.z[pBest->t.n]=='"' ) nReplace++;
+ }
}else{
- nReplace = nQuot;
- zReplace = zQuot;
+ /* Dequote the double-quoted token. Then requote it again, this time
+ ** using single quotes. If the character immediately following the
+ ** original token within the input SQL was a single quote ('), then
+ ** add another space after the new, single-quoted version of the
+ ** token. This is so that (SELECT "string"'alias') maps to
+ ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
+ memcpy(zBuf1, pBest->t.z, pBest->t.n);
+ zBuf1[pBest->t.n] = 0;
+ sqlite3Dequote(zBuf1);
+ sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ pBest->t.z[pBest->t.n]=='\'' ? " " : ""
+ );
+ zReplace = zBuf2;
+ nReplace = sqlite3Strlen30(zReplace);
}
iOff = pBest->t.z - zSql;
@@ -1394,7 +1444,7 @@ static void renameColumnFunc(
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = 0;
#endif
- rc = renameParseSql(&sParse, zDb, db, zSql, bTemp, 0);
+ rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
/* Find tokens that need to be replaced. */
memset(&sWalker, 0, sizeof(Walker));
@@ -1528,7 +1578,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSelect->selFlags & SF_View ) return WRC_Prune;
- if( pSrc==0 ){
+ if( NEVER(pSrc==0) ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
@@ -1598,7 +1648,7 @@ static void renameTableFunc(
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
- rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, 0);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
@@ -1701,6 +1751,119 @@ static void renameTableFunc(
return;
}
+static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
+ renameTokenFind(pWalker->pParse, pWalker->u.pRename, (void*)pExpr);
+ }
+ return WRC_Continue;
+}
+
+/*
+** The implementation of an SQL scalar function that rewrites DDL statements
+** so that any string literals that use double-quotes are modified so that
+** they use single quotes.
+**
+** Two arguments must be passed:
+**
+** 0: Database name ("main", "temp" etc.).
+** 1: SQL statement to edit.
+**
+** The returned value is the modified SQL statement. For example, given
+** the database schema:
+**
+** CREATE TABLE t1(a, b, c);
+**
+** SELECT sqlite_rename_quotefix('main',
+** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
+** );
+**
+** returns the string:
+**
+** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
+*/
+static void renameQuotefixFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ char const *zDb = (const char*)sqlite3_value_text(argv[0]);
+ char const *zInput = (const char*)sqlite3_value_text(argv[1]);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ sqlite3BtreeEnterAll(db);
+
+ UNUSED_PARAMETER(NotUsed);
+ if( zDb && zInput ){
+ int rc;
+ Parse sParse;
+ rc = renameParseSql(&sParse, zDb, db, zInput, 0);
+
+ if( rc==SQLITE_OK ){
+ RenameCtx sCtx;
+ Walker sWalker;
+
+ /* Walker to find tokens that need to be replaced. */
+ memset(&sCtx, 0, sizeof(RenameCtx));
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = &sParse;
+ sWalker.xExprCallback = renameQuotefixExprCb;
+ sWalker.xSelectCallback = renameColumnSelectCb;
+ sWalker.u.pRename = &sCtx;
+
+ if( sParse.pNewTable ){
+ Select *pSelect = sParse.pNewTable->pSelect;
+ if( pSelect ){
+ pSelect->selFlags &= ~SF_View;
+ sParse.rc = SQLITE_OK;
+ sqlite3SelectPrep(&sParse, pSelect, 0);
+ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
+ if( rc==SQLITE_OK ){
+ sqlite3WalkSelect(&sWalker, pSelect);
+ }
+ }else{
+ int i;
+ sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ for(i=0; inCol; i++){
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
+ }
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+ }
+ }else if( sParse.pNewIndex ){
+ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
+ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
+ }else{
+#ifndef SQLITE_OMIT_TRIGGER
+ rc = renameResolveTrigger(&sParse);
+ if( rc==SQLITE_OK ){
+ renameWalkTrigger(&sWalker, sParse.pNewTrigger);
+ }
+#endif /* SQLITE_OMIT_TRIGGER */
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = renameEditSql(context, &sCtx, zInput, 0, 0);
+ }
+ renameTokenFree(db, sCtx.pList);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(context, rc);
+ }
+ renameParseCleanup(&sParse);
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+
+ sqlite3BtreeLeaveAll(db);
+}
+
/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
@@ -1714,7 +1877,7 @@ static void renameTableFunc(
** 3: Object name.
** 4: True if object is from temp schema.
** 5: "when" part of error message.
-** 6: Name of column being dropped, or NULL.
+** 6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
@@ -1733,7 +1896,7 @@ static void renameTableTest(
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
- char const *zDropColumn = (const char*)sqlite3_value_text(argv[6]);
+ int bNoDQS = sqlite3_value_int(argv[6]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
@@ -1741,10 +1904,14 @@ static void renameTableTest(
#endif
UNUSED_PARAMETER(NotUsed);
+
if( zDb && zInput ){
int rc;
Parse sParse;
- rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, zDropColumn);
+ int flags = db->flags;
+ if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
+ db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
@@ -1812,7 +1979,7 @@ static void dropColumnFunc(
#endif
UNUSED_PARAMETER(NotUsed);
- rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1, 0);
+ rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
if( rc!=SQLITE_OK ) goto drop_column_done;
pTab = sParse.pNewTable;
if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
@@ -1906,6 +2073,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
assert( iDb>=0 );
zDb = db->aDb[iDb].zDbSName;
renameTestSchema(pParse, zDb, iDb==1, "", 0);
+ renameFixQuotes(pParse, zDb, iDb==1);
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = sqlite_drop_column(%d, sql, %d) "
@@ -1915,7 +2083,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
/* Drop and reload the database schema. */
renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
- renameTestSchema(pParse, zDb, iDb==1, "after drop column", zCol);
+ renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);
/* Edit rows of table on disk */
if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
@@ -1931,33 +2099,44 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
reg = ++pParse->nMem;
- pParse->nMem += pTab->nCol;
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
+ pParse->nMem += pTab->nCol;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
+ pParse->nMem += pPk->nColumn;
+ for(i=0; inKeyCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
+ }
+ nField = pPk->nKeyCol;
}
+ regRec = ++pParse->nMem;
for(i=0; inCol; i++){
if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
int regOut;
if( pPk ){
int iPos = sqlite3TableColumnToIndex(pPk, i);
int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
+ if( iPosnKeyCol ) continue;
regOut = reg+1+iPos-(iPos>iColPos);
}else{
regOut = reg+1+nField;
}
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ if( i==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
+ }else{
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ }
nField++;
}
}
- regRec = reg + pTab->nCol;
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
}else{
sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
}
+ sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr);
@@ -1977,6 +2156,7 @@ void sqlite3AlterFunctions(void){
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
diff --git a/src/attach.c b/src/attach.c
index 8eb4486e58..2fc84e5b84 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -95,7 +95,7 @@ static void attachFunc(
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db) (0)
@@ -464,14 +464,17 @@ static int fixSelectCb(Walker *p, Select *pSelect){
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
if( pFix->bTemp==0 ){
- 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 WRC_Abort;
+ if( pItem->zDatabase ){
+ if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return WRC_Abort;
+ }
+ sqlite3DbFree(db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->fg.notCte = 1;
}
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
@@ -511,7 +514,7 @@ void sqlite3FixInit(
pFix->w.pParse = pParse;
pFix->w.xExprCallback = fixExprCb;
pFix->w.xSelectCallback = fixSelectCb;
- pFix->w.xSelectCallback2 = 0;
+ pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback;
pFix->w.walkerDepth = 0;
pFix->w.eCode = 0;
pFix->w.u.pFix = pFix;
@@ -573,14 +576,16 @@ int sqlite3FixTriggerStep(
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
- if( pStep->pUpsert ){
- Upsert *pUp = pStep->pUpsert;
- if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
- || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
- || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
- || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
- ){
- return 1;
+ {
+ Upsert *pUp;
+ for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
+ if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
+ || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
+ ){
+ return 1;
+ }
}
}
#endif
diff --git a/src/btree.c b/src/btree.c
index c6f205bba3..8c8268835a 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -780,7 +780,7 @@ static void invalidateIncrblobCursors(
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
+ assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
@@ -1688,6 +1688,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
unsigned char *src; /* Source of content */
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
+ int iCellStart; /* First cell offset in input */
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
@@ -1729,7 +1730,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
- }else if( NEVER(iFree+sz>usableSize) ){
+ }else if( iFree+sz>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -1748,6 +1749,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
cbrk = usableSize;
iCellLast = usableSize - 4;
+ iCellStart = get2byte(&data[hdr+5]);
for(i=0; iiCellLast ){
+ if( pciCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( pc>=iCellFirst && pc<=iCellLast );
+ assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
- if( cbrkusableSize ){
+ if( cbrkusableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+ assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
- int x;
if( cbrk==pc ) continue;
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
- x = get2byte(&data[hdr+5]);
- memcpy(&temp[x], &data[x], (cbrk+size) - x);
+ memcpy(&temp[iCellStart], &data[iCellStart], (cbrk+size) - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
@@ -5852,7 +5852,9 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; iiiPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
+ testcase( pCur->ix!=pCur->pPage->nCell-1 );
+ /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
*pRes = 0;
@@ -6629,7 +6631,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
- if( iPage>mxPage ){
+ if( iPage>mxPage || iPage<2 ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
@@ -6885,10 +6887,9 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
+** Free the overflow pages associated with the given Cell.
*/
-static int clearCell(
+static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
@@ -6900,10 +6901,7 @@ static int clearCell(
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
+ assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
@@ -6959,6 +6957,21 @@ static int clearCell(
return SQLITE_OK;
}
+/* Call xParseCell to compute the size of a cell. If the cell contains
+** overflow, then invoke cellClearOverflow to clear out that overflow.
+** STore the result code (SQLITE_OK or some error code) in rc.
+**
+** Implemented as macro to force inlining for performance.
+*/
+#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
+ pPage->xParseCell(pPage, pCell, &sInfo); \
+ if( sInfo.nLocal!=sInfo.nPayload ){ \
+ rc = clearCellOverflow(pPage, pCell, &sInfo); \
+ }else{ \
+ rc = SQLITE_OK; \
+ }
+
+
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
@@ -7479,7 +7492,7 @@ static int rebuildPage(
u8 *pCell = pCArray->apCell[i];
u16 sz = pCArray->szCell[i];
assert( sz>0 );
- if( SQLITE_WITHIN(pCell,aData,pEnd) ){
+ if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
}else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
@@ -7492,9 +7505,8 @@ static int rebuildPage(
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, sz);
+ memmove(pData, pCell, sz);
assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( sz!=pPg->xCellSize(pPg,pCell) )
i++;
if( i>=iEnd ) break;
if( pCArray->ixNx[k]<=i ){
@@ -7633,7 +7645,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( pFree+sz>pEnd ){
+ return 0;
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -8288,7 +8302,7 @@ static int balance_nonroot(
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
if( !pOld->leaf ){
assert( leafCorrection==0 );
- assert( pOld->hdrOffset==0 );
+ assert( pOld->hdrOffset==0 || CORRUPT_DB );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
@@ -8611,6 +8625,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -8654,6 +8669,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(kpgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -9196,13 +9217,23 @@ int sqlite3BtreeInsert(
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
+ if( loc && pCur->iPage<0 ){
+ /* This can only happen if the schema is corrupt such that there is more
+ ** than one table or index with the same root page as used by the cursor.
+ ** Which can only happen if the SQLITE_NoSchemaError flag was set when
+ ** the schema was loaded. This cannot be asserted though, as a user might
+ ** set the flag, load the schema, and then unset the flag. */
+ return SQLITE_CORRUPT_BKPT;
+ }
}
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ }
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
@@ -9283,7 +9314,6 @@ int sqlite3BtreeInsert(
return btreeOverwriteCell(pCur, &x2);
}
}
-
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc)
@@ -9293,7 +9323,7 @@ int sqlite3BtreeInsert(
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
- if( pCur->eState>CURSOR_INVALID ){
+ if( NEVER(pCur->eState>CURSOR_INVALID) ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
@@ -9337,7 +9367,7 @@ int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
@@ -9574,9 +9604,10 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
- if( rc ) return rc;
+ assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
+ if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}
- assert( pCur->eState==CURSOR_VALID );
+ assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
@@ -9629,7 +9660,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
+ if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
@@ -9638,7 +9669,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
@@ -9927,7 +9958,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange, pgnoRoot);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
@@ -9977,7 +10008,9 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ }
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange, (Pgno)iTable);
}
sqlite3BtreeLeave(p);
diff --git a/src/build.c b/src/build.c
index f201e00cdc..56ce41bc92 100644
--- a/src/build.c
+++ b/src/build.c
@@ -46,7 +46,7 @@ struct TableLock {
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
-void sqlite3TableLock(
+static SQLITE_NOINLINE void lockTable(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
@@ -59,10 +59,6 @@ void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
-#ifdef SQLITE_OMIT_CONCURRENT
- if( iDb==1 ) return;
- if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
-#endif
pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; inTableLock; i++){
p = &pToplevel->aTableLock[i];
@@ -86,6 +82,17 @@ void sqlite3TableLock(
sqlite3OomFault(pToplevel->db);
}
}
+void sqlite3TableLock(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database containing the table to lock */
+ Pgno iTab, /* Root page number of the table to be locked */
+ u8 isWriteLock, /* True for a write lock */
+ const char *zName /* Name of the table to be locked */
+){
+ if( iDb==1 ) return;
+ if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ lockTable(pParse, iDb, iTab, isWriteLock, zName);
+}
/*
** Code an OP_TableLock instruction for each table locked by the
@@ -440,7 +447,7 @@ Table *sqlite3LocateTable(
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
- if( pParse->disableVtab==0 ){
+ if( pParse->disableVtab==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
@@ -463,6 +470,8 @@ Table *sqlite3LocateTable(
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
+ }else{
+ assert( HasRowid(p) || p->iPKey<0 );
}
return p;
@@ -1048,6 +1057,23 @@ i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
}
#endif
+/*
+** Insert a single OP_JournalMode query opcode in order to force the
+** prepared statement to return false for sqlite3_stmt_readonly(). This
+** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
+** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
+** will return false for sqlite3_stmt_readonly() even if that statement
+** is a read-only no-op.
+*/
+static void sqlite3ForceNotReadOnly(Parse *pParse){
+ int iReg = ++pParse->nMem;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
+ sqlite3VdbeUsesBtree(v, 0);
+ }
+}
+
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -1147,6 +1173,7 @@ void sqlite3StartTable(
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
@@ -1175,17 +1202,6 @@ void sqlite3StartTable(
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
- /* If this is the magic sqlite_sequence table used by autoincrement,
- ** then record a pointer to this table in the main database structure
- ** so that INSERT can find the table easily.
- */
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pTable->pSchema->pSeqTab = pTable;
- }
-#endif
-
/* Begin generating the code that will insert the table record into
** the schema table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
@@ -1334,6 +1350,7 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pRet->retTrig.tr_tm = TRIGGER_AFTER;
pRet->retTrig.bReturning = 1;
pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.pTabSchema = db->aDb[1].pSchema;
pRet->retTrig.step_list = &pRet->retTStep;
pRet->retTStep.op = TK_RETURNING;
pRet->retTStep.pTrig = &pRet->retTrig;
@@ -2192,7 +2209,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
- if( pList==0 ) return;
+ if( pList==0 ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
@@ -2201,7 +2221,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
- if( db->mallocFailed || pParse->nErr ) return;
+ if( db->mallocFailed || pParse->nErr ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
@@ -2405,7 +2428,6 @@ void sqlite3EndTable(
if( pEnd==0 && pSelect==0 ){
return;
}
- assert( !db->mallocFailed );
p = pParse->pNewTable;
if( p==0 ) return;
@@ -2630,7 +2652,7 @@ void sqlite3EndTable(
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( (p->tabFlags & TF_Autoincrement)!=0 ){
+ if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){
Db *pDb = &db->aDb[iDb];
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->pSeqTab==0 ){
@@ -2653,6 +2675,7 @@ void sqlite3EndTable(
Table *pOld;
Schema *pSchema = p->pSchema;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ assert( HasRowid(p) || p->iPKey<0 );
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
@@ -2661,6 +2684,17 @@ void sqlite3EndTable(
}
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
+
+ /* If this is the magic sqlite_sequence table used by autoincrement,
+ ** then record a pointer to this table in the main database structure
+ ** so that INSERT can find the table easily. */
+ assert( !pParse->nested );
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( strcmp(p->zName, "sqlite_sequence")==0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ p->pSchema->pSeqTab = p;
+ }
+#endif
}
#ifndef SQLITE_OMIT_ALTERTABLE
@@ -2704,6 +2738,16 @@ void sqlite3CreateView(
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ) goto create_view_fail;
+
+ /* Legacy versions of SQLite allowed the use of the magic "rowid" column
+ ** on a view, even though views do not have rowids. The following flag
+ ** setting fixes this problem. But the fix can be disabled by compiling
+ ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
+ ** depend upon the old buggy behavior. */
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ p->tabFlags |= TF_NoVisibleRowid;
+#endif
+
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
@@ -3180,7 +3224,10 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
if( noErr ) db->suppressErr--;
if( pTab==0 ){
- if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ if( noErr ){
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
+ }
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -3750,6 +3797,7 @@ void sqlite3CreateIndex(
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
@@ -4230,7 +4278,7 @@ void sqlite3DefaultRowEst(Index *pIdx){
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
- if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
+ if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlite3LogEst(2) ); }
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
@@ -4265,9 +4313,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
if( !ifExists ){
- sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
+ sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
@@ -4579,8 +4628,8 @@ SrcList *sqlite3SrcListAppend(
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
SrcItem *pItem;
- assert(pList || pParse->db->mallocFailed );
- if( pList ){
+ assert( pList || pParse->db->mallocFailed );
+ if( ALWAYS(pList) ){
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
diff --git a/src/ctime.c b/src/ctime.c
index 7982f23aeb..fa69216c6d 100644
--- a/src/ctime.c
+++ b/src/ctime.c
@@ -58,8 +58,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_64BIT_STATS
"64BIT_STATS",
#endif
-#if SQLITE_ALLOW_COVERING_INDEX_SCAN
- "ALLOW_COVERING_INDEX_SCAN",
+#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
+ "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
+# endif
#endif
#if SQLITE_ALLOW_URI_AUTHORITY
"ALLOW_URI_AUTHORITY",
@@ -121,8 +123,10 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_DEFAULT_LOOKASIDE
"DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
-#if SQLITE_DEFAULT_MEMSTATUS
- "DEFAULT_MEMSTATUS",
+#ifdef SQLITE_DEFAULT_MEMSTATUS
+# if SQLITE_DEFAULT_MEMSTATUS != 1
+ "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
+# endif
#endif
#ifdef SQLITE_DEFAULT_MMAP_SIZE
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
@@ -196,7 +200,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_BYTECODE_VTAB
"ENABLE_BYTECODE_VTAB",
#endif
-#if SQLITE_ENABLE_CEROD
+#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
@@ -211,17 +215,17 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_CURSOR_HINTS
"ENABLE_CURSOR_HINTS",
#endif
+#if SQLITE_ENABLE_DBPAGE_VTAB
+ "ENABLE_DBPAGE_VTAB",
+#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
"ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
+#if SQLITE_ENABLE_EXPLAIN_COMMENTS
+ "ENABLE_EXPLAIN_COMMENTS",
#endif
#if SQLITE_ENABLE_FTS3
"ENABLE_FTS3",
@@ -280,6 +284,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_NULL_TRIM
"ENABLE_NULL_TRIM",
#endif
+#if SQLITE_ENABLE_OFFSET_SQL_FUNC
+ "ENABLE_OFFSET_SQL_FUNC",
+#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
@@ -310,7 +317,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_SQLLOG
"ENABLE_SQLLOG",
#endif
-#if defined(SQLITE_ENABLE_STAT4)
+#if SQLITE_ENABLE_STAT4
"ENABLE_STAT4",
#endif
#if SQLITE_ENABLE_STMTVTAB
@@ -364,8 +371,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
"HAVE_ISNAN",
#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
+ "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
+# endif
#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
"IGNORE_AFP_LOCK_ERRORS",
@@ -463,9 +472,6 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_MUTEX_NOOP
"MUTEX_NOOP",
#endif
-#if SQLITE_MUTEX_NREF
- "MUTEX_NREF",
-#endif
#if SQLITE_MUTEX_OMIT
"MUTEX_OMIT",
#endif
@@ -535,7 +541,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_CTE
"OMIT_CTE",
#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
"OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
@@ -544,6 +550,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_DEPRECATED
"OMIT_DEPRECATED",
#endif
+#if SQLITE_OMIT_DESERIALIZE
+ "OMIT_DESERIALIZE",
+#endif
#if SQLITE_OMIT_DISKIO
"OMIT_DISKIO",
#endif
@@ -571,6 +580,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_INTEGRITY_CHECK
"OMIT_INTEGRITY_CHECK",
#endif
+#if SQLITE_OMIT_INTROSPECTION_PRAGMAS
+ "OMIT_INTROSPECTION_PRAGMAS",
+#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
"OMIT_LIKE_OPTIMIZATION",
#endif
@@ -634,8 +646,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_TEST_CONTROL
"OMIT_TEST_CONTROL",
#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
+#ifdef SQLITE_OMIT_TRACE
+# if SQLITE_OMIT_TRACE != 1
+ "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
+# endif
#endif
#if SQLITE_OMIT_TRIGGER
"OMIT_TRIGGER",
@@ -670,8 +684,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_PERFORMANCE_TRACE
"PERFORMANCE_TRACE",
#endif
-#if SQLITE_POWERSAFE_OVERWRITE
- "POWERSAFE_OVERWRITE",
+#ifdef SQLITE_POWERSAFE_OVERWRITE
+# if SQLITE_POWERSAFE_OVERWRITE != 1
+ "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
+# endif
#endif
#if SQLITE_PREFER_PROXY_LOCKING
"PREFER_PROXY_LOCKING",
@@ -706,7 +722,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_SUBSTR_COMPATIBILITY
"SUBSTR_COMPATIBILITY",
#endif
-#if SQLITE_SYSTEM_MALLOC
+#if (!defined(SQLITE_WIN32_MALLOC) \
+ && !defined(SQLITE_ZERO_MALLOC) \
+ && !defined(SQLITE_MEMDEBUG) \
+ ) || defined(SQLITE_SYSTEM_MALLOC)
"SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
diff --git a/src/expr.c b/src/expr.c
index bd12ad9f0c..6af6493c70 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -52,6 +52,10 @@ char sqlite3ExprAffinity(const Expr *pExpr){
assert( pExpr!=0 );
}
op = pExpr->op;
+ if( op==TK_REGISTER ) op = pExpr->op2;
+ if( (op==TK_COLUMN || op==TK_AGG_COLUMN) && pExpr->y.pTab ){
+ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
+ }
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
assert( pExpr->x.pSelect!=0 );
@@ -59,16 +63,12 @@ char sqlite3ExprAffinity(const Expr *pExpr){
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
- if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
- return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
- }
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft->flags&EP_xIsSelect );
return sqlite3ExprAffinity(
@@ -95,18 +95,7 @@ Expr *sqlite3ExprAddCollateToken(
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
- assert( pExpr!=0 || pParse->db->mallocFailed );
- if( pExpr==0 ) return 0;
- if( pExpr->op==TK_VECTOR ){
- ExprList *pList = pExpr->x.pList;
- if( ALWAYS(pList!=0) ){
- int i;
- for(i=0; inExpr; i++){
- pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
- pCollName, dequote);
- }
- }
- }else if( pCollName->n>0 ){
+ if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
@@ -611,6 +600,7 @@ static void codeVectorCompare(
int regLeft = 0;
int regRight = 0;
u8 opx = op;
+ int addrCmp = 0;
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
@@ -630,21 +620,24 @@ static void codeVectorCompare(
assert( p5==0 || pExpr->op!=op );
assert( p5==SQLITE_NULLEQ || pExpr->op==op );
- p5 |= SQLITE_STOREP2;
- if( opx==TK_LE ) opx = TK_LT;
- if( opx==TK_GE ) opx = TK_GT;
+ if( op==TK_LE ) opx = TK_LT;
+ if( op==TK_GE ) opx = TK_GT;
+ if( op==TK_NE ) opx = TK_EQ;
regLeft = exprCodeSubselect(pParse, pLeft);
regRight = exprCodeSubselect(pParse, pRight);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, dest);
for(i=0; 1 /*Loop exits by "break"*/; i++){
int regFree1 = 0, regFree2 = 0;
Expr *pL, *pR;
int r1, r2;
assert( i>=0 && i0
@@ -958,8 +957,8 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
- sqlite3ExprDelete(db, pLeft);
- sqlite3ExprDelete(db, pRight);
+ sqlite3ExprDeferredDelete(pParse, pLeft);
+ sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
@@ -1156,6 +1155,22 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
+
+/*
+** Arrange to cause pExpr to be deleted when the pParse is deleted.
+** This is similar to sqlite3ExprDelete() except that the delete is
+** deferred untilthe pParse is deleted.
+**
+** The pExpr might be deleted immediately on an OOM error.
+**
+** The deferred delete is (currently) implemented by adding the
+** pExpr to the pParse->pConstExpr list with a register number of 0.
+*/
+void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ pParse->pConstExpr =
+ sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+}
+
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
@@ -1298,6 +1313,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
+ assert( zAlloc!=0 );
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
@@ -1376,7 +1392,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
- assert( p->pRight==0 || p->pRight==p->pLeft );
+ assert( p->pRight==0 || p->pRight==p->pLeft
+ || ExprHasProperty(p->pLeft, EP_Subquery) );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -1478,6 +1495,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
+ pNew->nAlloc = p->nAlloc;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; inExpr; i++, pItem++, pOldItem++){
@@ -1490,7 +1508,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
- assert( pOldExpr->pLeft==pOldExpr->pRight );
+ assert( pOldExpr->pLeft==pOldExpr->pRight
+ || ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
}else{
assert( i>0 );
@@ -1620,6 +1639,14 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
+ if( db->mallocFailed ){
+ /* Any prior OOM might have left the Select object incomplete.
+ ** Delete the whole thing rather than allow an incomplete Select
+ ** to be used by the code generator. */
+ pNew->pNext = 0;
+ sqlite3SelectDelete(db, pNew);
+ break;
+ }
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
@@ -1650,41 +1677,64 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
+static const struct ExprList_item zeroItem = {0};
+SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
+ sqlite3 *db, /* Database handle. Used for memory allocation */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pList;
+
+ pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ if( pList==0 ){
+ sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }
+ pList->nAlloc = 4;
+ pList->nExpr = 1;
+ pItem = &pList->a[0];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
+SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
+ sqlite3 *db, /* Database handle. Used for memory allocation */
+ ExprList *pList, /* List to which to append. Might be NULL */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pNew;
+ pList->nAlloc *= 2;
+ pNew = sqlite3DbRealloc(db, pList,
+ sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ if( pNew==0 ){
+ sqlite3ExprListDelete(db, pList);
+ sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }else{
+ pList = pNew;
+ }
+ pItem = &pList->a[pList->nExpr++];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
ExprList *sqlite3ExprListAppend(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
- sqlite3 *db = pParse->db;
- assert( db!=0 );
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
- if( pList==0 ){
- goto no_mem;
- }
- pList->nExpr = 0;
- }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- ExprList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0]));
- if( pNew==0 ){
- goto no_mem;
- }
- pList = pNew;
+ return sqlite3ExprListAppendNew(pParse->db,pExpr);
+ }
+ if( pList->nAllocnExpr+1 ){
+ return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr);
}
pItem = &pList->a[pList->nExpr++];
- assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
- assert( offsetof(struct ExprList_item,pExpr)==0 );
- memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
+ *pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
-
-no_mem:
- /* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(db, pExpr);
- sqlite3ExprListDelete(db, pList);
- return 0;
}
/*
@@ -2297,8 +2347,10 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
*/
int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
+ assert( p!=0 );
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
+ assert( p!=0 );
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
@@ -3148,7 +3200,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
*/
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
- if( (pIn->flags & EP_xIsSelect) ){
+ if( (pIn->flags & EP_xIsSelect)!=0 && !pParse->db->mallocFailed ){
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
return 1;
@@ -3339,6 +3391,7 @@ static void sqlite3ExprCodeIN(
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; ipLeft, i);
+ if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
@@ -3964,7 +4017,7 @@ expr_code_doover:
** Expr node to be passed into this function, it will be handled
** sanely and not crash. But keep the assert() to bring the problem
** to the attention of the developers. */
- assert( op==TK_NULL );
+ assert( op==TK_NULL || pParse->db->mallocFailed );
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
@@ -4030,8 +4083,9 @@ expr_code_doover:
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
- codeCompare(pParse, pLeft, pExpr->pRight, op,
- r1, r2, inReg, SQLITE_STOREP2 | p5,
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
+ codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
+ sqlite3VdbeCurrentAddr(v)+2, p5,
ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -4039,6 +4093,11 @@ expr_code_doover:
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
+ if( p5==SQLITE_NULLEQ ){
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
+ }
testcase( regFree1==0 );
testcase( regFree2==0 );
}
@@ -5781,8 +5840,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
@@ -5791,8 +5849,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
diff --git a/src/func.c b/src/func.c
index 5e7eae873c..83312c0cce 100644
--- a/src/func.c
+++ b/src/func.c
@@ -2073,9 +2073,7 @@ static void math2Func(
}
/*
-** Implementation of 2-argument SQL math functions:
-**
-** power(X,Y) - Compute X to the Y-th power
+** Implementation of 0-argument pi() function.
*/
static void piFunc(
sqlite3_context *context,
diff --git a/src/global.c b/src/global.c
index b5239ad81a..4648c26d95 100644
--- a/src/global.c
+++ b/src/global.c
@@ -37,7 +37,7 @@ const unsigned char sqlite3UpperToLower[] = {
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
+ 252,253,254,255,
#endif
#ifdef SQLITE_EBCDIC
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
@@ -57,7 +57,35 @@ const unsigned char sqlite3UpperToLower[] = {
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
+/* All of the upper-to-lower conversion data is above. The following
+** 18 integers are completely unrelated. They are appended to the
+** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
+** going on:
+**
+** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
+** by invoking sqlite3MemCompare(A,B) which compares values A and B and
+** returns negative, zero, or positive if A is less then, equal to, or
+** greater than B, respectively. Then the true false results is found by
+** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
+** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
+** is negative, zero, or positive, where opcode is the specific opcode.
+** The only works because the comparison opcodes are consecutive and in
+** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
+** ensure that is the case.
+**
+** These elements must be appended to another array. Otherwise the
+** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
+** be undefined behavior. That's goofy, but the C-standards people thought
+** it was a good idea, so here we are.
+*/
+/* NE EQ GT LE LT GE */
+ 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
+ 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
+ 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
};
+const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
+const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
+const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
/*
** The following 256 byte lookup table is used to support SQLites built-in
@@ -251,7 +279,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
diff --git a/src/insert.c b/src/insert.c
index 89b66baf07..1ed0b43156 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -358,7 +358,7 @@ static int autoIncBegin(
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
- || IsVirtual(pSeqTab)
+ || NEVER(IsVirtual(pSeqTab))
|| pSeqTab->nCol!=2
){
pParse->nErr++;
@@ -817,7 +817,7 @@ void sqlite3Insert(
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
- pTabList, 0, pColumn->a[i].zName);
+ pTabList->a, pColumn->a[i].zName);
pParse->checkSchema = 1;
goto insert_cleanup;
}
@@ -945,7 +945,7 @@ void sqlite3Insert(
if( nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol-nHidden, nColumn);
+ pTabList->a, pTab->nCol-nHidden, nColumn);
goto insert_cleanup;
}
}
@@ -1248,7 +1248,7 @@ void sqlite3Insert(
}else
#endif
{
- int isReplace; /* Set to true if constraints may cause a replace */
+ int isReplace = 0;/* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
@@ -1268,6 +1268,13 @@ void sqlite3Insert(
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ }else if( pParse->bReturning ){
+ /* If there is a RETURNING clause, populate the rowid register with
+ ** constant value -1, in case one or more of the returned expressions
+ ** refer to the "rowid" of the view. */
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
+#endif
}
/* Update the count of rows that are inserted
diff --git a/src/main.c b/src/main.c
index 02a61772ab..7ea1383d1c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -305,7 +305,7 @@ int sqlite3_initialize(void){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlite3MemdbInit();
}
@@ -720,12 +720,12 @@ int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
break;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
@@ -1274,7 +1274,7 @@ int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
-** leaves the connection option if there are unfinalized prepared
+** leaves the connection open if there are unfinalized prepared
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
** version forces the connection to become a zombie if there are
** unclosed resources, and arranges for deallocation when the last
@@ -1884,6 +1884,10 @@ int sqlite3CreateFunc(
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
+ }else if( xSFunc==0 && xFinal==0 ){
+ /* Trying to delete a function that does not exist. This is a no-op.
+ ** https://sqlite.org/forum/forumpost/726219164b */
+ return SQLITE_OK;
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
diff --git a/src/memdb.c b/src/memdb.c
index a48980aa34..965ec36d41 100644
--- a/src/memdb.c
+++ b/src/memdb.c
@@ -17,31 +17,88 @@
** sqlite3_deserialize().
*/
#include "sqliteInt.h"
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
+typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
+/* Storage for a memdb file.
+**
+** An memdb object can be shared or separate. Shared memdb objects can be
+** used by more than one database connection. Mutexes are used by shared
+** memdb objects to coordinate access. Separate memdb objects are only
+** connected to a single database connection and do not require additional
+** mutexes.
+**
+** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
+** using "file:/name?vfs=memdb". The first character of the name must be
+** "/" or else the object will be a separate memdb object. All shared
+** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
+**
+** Separate memdb objects are created using a name that does not begin
+** with "/" or using sqlite3_deserialize().
+**
+** Access rules for shared MemStore objects:
+**
+** * .zFName is initialized when the object is created and afterwards
+** is unchanged until the object is destroyed. So it can be accessed
+** at any time as long as we know the object is not being destroyed,
+** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
+** .pMutex is held or the object is not part of memdb_g.apMemStore[].
+**
+** * Can .pMutex can only be changed while holding the
+** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
+** of memdb_g.apMemStore[].
+**
+** * Other fields can only be changed while holding the .pMutex mutex
+** or when the .nRef is less than zero and the object is not part of
+** memdb_g.apMemStore[].
+**
+** * The .aData pointer has the added requirement that it can can only
+** be changed (for resizing) when nMmap is zero.
+**
+*/
+struct MemStore {
sqlite3_int64 sz; /* Size of the file */
sqlite3_int64 szAlloc; /* Space allocated to aData */
sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
+ sqlite3_mutex *pMutex; /* Used by shared stores only */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
+ int nRdLock; /* Number of readers */
+ int nWrLock; /* Number of writers. (Always 0 or 1) */
+ int nRef; /* Number of users of this MemStore */
+ char *zFName; /* The filename for shared stores */
+};
+
+/* An open file */
+struct MemFile {
+ sqlite3_file base; /* IO methods */
+ MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
+/*
+** File-scope variables for holding the memdb files that are accessible
+** to multiple database connections in separate threads.
+**
+** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
+*/
+static struct MemFS {
+ int nMemStore; /* Number of shared MemStore objects */
+ MemStore **apMemStore; /* Array of all shared MemStore objects */
+} memdb_g;
+
/*
** Methods for MemFile
*/
@@ -95,7 +152,10 @@ static sqlite3_vfs memdb_vfs = {
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+ memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 0, /* xSetSystemCall */
+ 0, /* xGetSystemCall */
+ 0, /* xNextSystemCall */
};
static const sqlite3_io_methods memdb_io_methods = {
@@ -120,19 +180,67 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbUnfetch /* xUnfetch */
};
+/*
+** Enter/leave the mutex on a MemStore
+*/
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+static void memdbEnter(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+static void memdbLeave(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+#else
+static void memdbEnter(MemStore *p){
+ sqlite3_mutex_enter(p->pMutex);
+}
+static void memdbLeave(MemStore *p){
+ sqlite3_mutex_leave(p->pMutex);
+}
+#endif
+
/*
** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
-** in which case we own the pData pointer and need to free it.
+** Free the underlying MemStore object when its refcount drops to zero
+** or less.
*/
static int memdbClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
- sqlite3_free(p->aData);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ if( p->zFName ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; ALWAYS(inRef==1 ){
+ memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
+ if( memdb_g.nMemStore==0 ){
+ sqlite3_free(memdb_g.apMemStore);
+ memdb_g.apMemStore = 0;
+ }
+ }
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ memdbEnter(p);
+ }
+ p->nRef--;
+ if( p->nRef<=0 ){
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
+ memdbLeave(p);
+ sqlite3_mutex_free(p->pMutex);
+ sqlite3_free(p);
+ }else{
+ memdbLeave(p);
}
return SQLITE_OK;
}
@@ -146,20 +254,23 @@ static int memdbRead(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
-static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
+static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
@@ -170,7 +281,7 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlite3Realloc(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
p->szAlloc = newSz;
return SQLITE_OK;
@@ -185,19 +296,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ /* Can't happen: memdbLock() will return SQLITE_READONLY before
+ ** reaching this point */
+ memdbLeave(p);
+ return SQLITE_IOERR_WRITE;
+ }
if( iOfst+iAmt>p->sz ){
int rc;
if( iOfst+iAmt>p->szAlloc
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
+ memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -209,16 +328,24 @@ static int memdbWrite(
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ int rc = SQLITE_OK;
+ memdbEnter(p);
+ if( NEVER(size>p->sz) ){
+ rc = SQLITE_FULL;
+ }else{
+ p->sz = size;
+ }
+ memdbLeave(p);
+ return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
+ UNUSED_PARAMETER(pFile);
+ UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
@@ -226,8 +353,10 @@ static int memdbSync(sqlite3_file *pFile, int flags){
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
*pSize = p->sz;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -235,19 +364,48 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- if( eLock>SQLITE_LOCK_SHARED
- && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
- ){
- return SQLITE_READONLY;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock==pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+ if( eLock>SQLITE_LOCK_SHARED ){
+ if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
+ rc = SQLITE_READONLY;
+ }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
+ if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ }else if( eLock==SQLITE_LOCK_SHARED ){
+ if( pThis->eLock > SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }else if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ }else{
+ assert( eLock==SQLITE_LOCK_NONE );
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }
+ assert( p->nRdLock>0 );
+ p->nRdLock--;
}
- p->eLock = eLock;
- return SQLITE_OK;
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
}
-#if 0 /* Never used because memdbAccess() always returns false */
+#if 0
/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
+** This interface is only used for crash recovery, which does not
+** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
@@ -255,12 +413,14 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
}
#endif
+
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
+ memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
@@ -278,6 +438,7 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
+ memdbLeave(p);
return rc;
}
@@ -294,6 +455,7 @@ static int memdbSectorSize(sqlite3_file *pFile){
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
+ UNUSED_PARAMETER(pFile);
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
@@ -307,20 +469,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
+ memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ UNUSED_PARAMETER(iOfst);
+ UNUSED_PARAMETER(pPage);
+ memdbEnter(p);
p->nMmap--;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -330,20 +498,79 @@ static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
static int memdbOpen(
sqlite3_vfs *pVfs,
const char *zName,
- sqlite3_file *pFile,
+ sqlite3_file *pFd,
int flags,
int *pOutFlags
){
- MemFile *p = (MemFile*)pFile;
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ memset(pFile, 0, sizeof(*p));
+ szName = sqlite3Strlen30(zName);
+ if( szName>1 && zName[0]=='/' ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; izFName,zName)==0 ){
+ p = memdb_g.apMemStore[i];
+ break;
+ }
+ }
+ if( p==0 ){
+ MemStore **apNew;
+ p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ if( p==0 ){
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ if( apNew==0 ){
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew[memdb_g.nMemStore++] = p;
+ memdb_g.apMemStore = apNew;
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ p->zFName = (char*)&p[1];
+ memcpy(p->zFName, zName, szName+1);
+ p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( p->pMutex==0 ){
+ memdb_g.nMemStore--;
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ p->nRef = 1;
+ memdbEnter(p);
+ }else{
+ memdbEnter(p);
+ p->nRef++;
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ p = sqlite3Malloc( sizeof(*p) );
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
+ pFile->pStore = p;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
- pFile->pMethods = &memdb_io_methods;
- p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ pFd->pMethods = &memdb_io_methods;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -371,6 +598,9 @@ static int memdbAccess(
int flags,
int *pResOut
){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(zPath);
+ UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
@@ -386,6 +616,7 @@ static int memdbFullPathname(
int nOut,
char *zOut
){
+ UNUSED_PARAMETER(pVfs);
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
@@ -458,9 +689,14 @@ static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
+ MemStore *pStore;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ pStore = p->pStore;
+ memdbEnter(pStore);
+ if( pStore->zFName!=0 ) p = 0;
+ memdbLeave(pStore);
return p;
}
@@ -496,12 +732,14 @@ unsigned char *sqlite3_serialize(
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
- if( piSize ) *piSize = p->sz;
+ MemStore *pStore = p->pStore;
+ assert( pStore->pMutex==0 );
+ if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
+ pOut = pStore->aData;
}else{
- pOut = sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
+ pOut = sqlite3_malloc64( pStore->sz );
+ if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
@@ -595,15 +833,16 @@ int sqlite3_deserialize(
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
+ MemStore *pStore = p->pStore;
+ pStore->aData = pData;
pData = 0;
- p->sz = szDb;
- p->szAlloc = szBuf;
- p->szMax = szBuf;
- if( p->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
+ pStore->sz = szDb;
+ pStore->szAlloc = szBuf;
+ pStore->szMax = szBuf;
+ if( pStore->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
}
- p->mFlags = mFlags;
+ pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
@@ -622,7 +861,7 @@ end_deserialize:
*/
int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
+ unsigned int sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
@@ -632,4 +871,4 @@ int sqlite3MemdbInit(void){
memdb_vfs.szOsFile = sz;
return sqlite3_vfs_register(&memdb_vfs, 0);
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
diff --git a/src/os.c b/src/os.c
index 693d78dc91..b11c49c1d5 100644
--- a/src/os.c
+++ b/src/os.c
@@ -229,7 +229,7 @@ int sqlite3OsOpen(
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
- return pVfs->xDelete(pVfs, zPath, dirSync);
+ return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
int sqlite3OsAccess(
sqlite3_vfs *pVfs,
diff --git a/src/os_unix.c b/src/os_unix.c
index c212aaf17a..2053fbac00 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -3980,6 +3980,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
+static int unixFcntlExternalReader(unixFile*, int*);
/*
** Information and control of an open file handle.
@@ -4099,6 +4100,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+
+ case SQLITE_FCNTL_EXTERNAL_READER: {
+ return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+ }
}
return SQLITE_NOTFOUND;
}
@@ -4380,6 +4385,40 @@ struct unixShm {
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+/*
+** Use F_GETLK to check whether or not there are any readers with open
+** wal-mode transactions in other processes on database file pFile. If
+** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
+** such transactions, or 0 otherwise. If an error occurs, return an
+** SQLite error code. The final value of *piOut is undefined in this
+** case.
+*/
+static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
+ int rc = SQLITE_OK;
+ *piOut = 0;
+ if( pFile->pShm){
+ unixShmNode *pShmNode = pFile->pShm->pShmNode;
+ struct flock f;
+
+ memset(&f, 0, sizeof(f));
+ f.l_type = F_WRLCK;
+ f.l_whence = SEEK_SET;
+ f.l_start = UNIX_SHM_BASE + 3;
+ f.l_len = SQLITE_SHM_NLOCK - 3;
+
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+ if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
+ rc = SQLITE_IOERR_LOCK;
+ }else{
+ *piOut = (f.l_type!=F_UNLCK);
+ }
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
+ }
+
+ return rc;
+}
+
+
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
@@ -8214,6 +8253,22 @@ int sqlite3_os_init(void){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+
+ /* Validate lock assumptions */
+ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
+ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
+ /* Locks:
+ ** WRITE UNIX_SHM_BASE 120
+ ** CKPT UNIX_SHM_BASE+1 121
+ ** RECOVER UNIX_SHM_BASE+2 122
+ ** READ-0 UNIX_SHM_BASE+3 123
+ ** READ-1 UNIX_SHM_BASE+4 124
+ ** READ-2 UNIX_SHM_BASE+5 125
+ ** READ-3 UNIX_SHM_BASE+6 126
+ ** READ-4 UNIX_SHM_BASE+7 127
+ ** DMS UNIX_SHM_BASE+8 128
+ */
+ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
return SQLITE_OK;
}
diff --git a/src/pager.c b/src/pager.c
index 698ff695f6..cd19eb5e1c 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -3998,7 +3998,8 @@ static void assertTruncateConstraint(Pager *pPager){
** then continue writing to the database.
*/
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
- assert( pPager->dbSize>=nPage );
+ assert( pPager->dbSize>=nPage || CORRUPT_DB );
+ testcase( pPager->dbSizeeState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
@@ -4732,7 +4733,7 @@ int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
@@ -4939,7 +4940,7 @@ int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
@@ -5922,7 +5923,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory;
- if( ALWAYS(pPager->eState==PAGER_READER) ){
+ if( pPager->eState==PAGER_READER ){
assert( pPager->pInJournal==0 );
if( pagerUseWal(pPager) ){
/* If the pager is configured to use locking_mode=exclusive, and an
diff --git a/src/parse.y b/src/parse.y
index bd3eb13ac2..0da6e47ff5 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -209,7 +209,7 @@ ifnotexists(A) ::= . {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
-temp(A) ::= TEMP. {A = 1;}
+temp(A) ::= TEMP. {A = pParse->db->init.busy==0;}
%endif SQLITE_OMIT_TEMPDB
temp(A) ::= . {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
@@ -1816,7 +1816,11 @@ frame_exclude(A) ::= GROUP|TIES(X). {A = @X; /*A-overwrites-X*/}
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
filter_over(A) ::= filter_clause(F) over_clause(O). {
- O->pFilter = F;
+ if( O ){
+ O->pFilter = F;
+ }else{
+ sqlite3ExprDelete(pParse->db, F);
+ }
A = O;
}
filter_over(A) ::= over_clause(O). {
diff --git a/src/prepare.c b/src/prepare.c
index eb4627f0d2..b18716c9e3 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -96,6 +96,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
db->mDbFlags |= DBFLAG_EncodingFixed;
+ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv, 0);
@@ -103,7 +104,6 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
}
assert( iDb>=0 && iDbnDb );
- if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[3]==0 ){
corruptSchema(pData, argv, 0);
}else if( argv[4]
@@ -380,15 +380,17 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
- }
+ }else
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
- /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
- ** current sqlite3_prepare() operation will fail, but the following one
- ** will attempt to compile the supplied statement against whatever subset
- ** of the schema was loaded before the error occurred. The primary
- ** purpose of this is to allow access to the sqlite_schema table
- ** even when its contents have been corrupted.
+ /* Hack: If the SQLITE_NoSchemaError flag is set, then consider
+ ** the schema loaded, even if errors (other than OOM) occurred. In
+ ** this situation the current sqlite3_prepare() operation will fail,
+ ** but the following one will attempt to compile the supplied statement
+ ** against whatever subset of the schema was loaded before the error
+ ** occurred.
+ **
+ ** The primary purpose of this is to allow access to the sqlite_schema
+ ** table even when its contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
@@ -498,6 +500,7 @@ static void schemaIsValid(Parse *pParse){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
+ pParse->rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
@@ -733,6 +736,7 @@ static int sqlite3Prepare(
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
+ sParse.checkSchema = 0;
}
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
if( sParse.checkSchema ){
diff --git a/src/printf.c b/src/printf.c
index 9aab863ed2..f663e1b1ed 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -29,7 +29,7 @@
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCLIST 12 /* a pointer to a SrcList */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
@@ -95,10 +95,16 @@ static const et_info fmtinfo[] = {
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'S', 0, 0, etSRCITEM, 0, 0 },
{ 'r', 10, 1, etORDINAL, 0, 0 },
};
+/* Notes:
+**
+** %S Takes a pointer to SrcItem. Shows name or database.name
+** %!S Like %S but prefer the zName over the zAlias
+*/
+
/* Floating point constants used for rounding */
static const double arRound[] = {
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
@@ -853,21 +859,24 @@ void sqlite3_str_vappendf(
length = width = 0;
break;
}
- case etSRCLIST: {
- SrcList *pSrc;
- int k;
+ case etSRCITEM: {
SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pSrc = va_arg(ap, SrcList*);
- k = va_arg(ap, int);
- pItem = &pSrc->a[k];
+ pItem = va_arg(ap, SrcItem*);
assert( bArgList==0 );
- assert( k>=0 && knSrc );
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
- sqlite3_str_append(pAccum, ".", 1);
+ if( pItem->zAlias && !flag_altform2 ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( pItem->zName ){
+ if( pItem->zDatabase ){
+ sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ sqlite3_str_append(pAccum, ".", 1);
+ }
+ sqlite3_str_appendall(pAccum, pItem->zName);
+ }else if( pItem->zAlias ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( ALWAYS(pItem->pSelect) ){
+ sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
}
- sqlite3_str_appendall(pAccum, pItem->zName);
length = width = 0;
break;
}
diff --git a/src/resolve.c b/src/resolve.c
index ee75d2acb8..d5cec3550a 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -81,7 +81,10 @@ static void resolveAlias(
assert( pOrig!=0 );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
- if( pDup!=0 ){
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ pDup = 0;
+ }else{
incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
@@ -103,10 +106,8 @@ static void resolveAlias(
pExpr->flags |= EP_MemToken;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( pExpr->y.pWin!=0 ){
+ if( ALWAYS(pExpr->y.pWin!=0) ){
pExpr->y.pWin->pOwner = pExpr;
- }else{
- assert( db->mallocFailed );
}
}
sqlite3DbFree(db, pDup);
@@ -376,15 +377,19 @@ static int lookupName(
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
- if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
+ if( pParse->bReturning ){
+ if( (pNC->ncFlags & NC_UBaseReg)!=0
+ && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
+ ){
+ pExpr->iTable = op!=TK_DELETE;
+ pTab = pParse->pTriggerTab;
+ }
+ }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
pTab = pParse->pTriggerTab;
}else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
- }else if( pParse->bReturning && (pNC->ncFlags & NC_UBaseReg)!=0 ){
- pExpr->iTable = op!=TK_DELETE;
- pTab = pParse->pTriggerTab;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
@@ -494,8 +499,8 @@ static int lookupName(
** is supported for backwards compatibility only. Hence, we issue a warning
** on sqlite3_log() whenever the capability is used.
*/
- if( (pNC->ncFlags & NC_UEList)!=0
- && cnt==0
+ if( cnt==0
+ && (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
@@ -559,7 +564,6 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted)
&& areDoubleQuotedStringsEnabled(db, pTopNC)
- && (db->init.bDropColumn==0 || sqlite3StrICmp(zCol, db->init.azInit[0])!=0)
){
/* If a double-quoted identifier does not match any known column name,
** then treat it as a string.
@@ -574,11 +578,6 @@ static int lookupName(
** Someday, I hope to get rid of this hack. Unfortunately there is
** a huge amount of legacy SQL that uses it. So for now, we just
** issue a warning.
- **
- ** 2021-03-15: ticket 1c24a659e6d7f3a1
- ** Do not do the ID-to-STRING conversion when doing the schema
- ** sanity check following a DROP COLUMN if the identifer name matches
- ** the name of the column being dropped.
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
@@ -609,7 +608,7 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
pParse->checkSchema = 1;
- pTopNC->nErr++;
+ pTopNC->nNcErr++;
}
/* If a column from a table in pSrcList is referenced, then record
@@ -916,7 +915,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3ErrorMsg(pParse,
"second argument to likelihood() must be a "
"constant between 0.0 and 1.0");
- pNC->nErr++;
+ pNC->nNcErr++;
}
}else{
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
@@ -938,7 +937,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( auth==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
pDef->zName);
- pNC->nErr++;
+ pNC->nNcErr++;
}
pExpr->op = TK_NULL;
return WRC_Prune;
@@ -994,7 +993,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
- pNC->nErr++;
+ pNC->nNcErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
@@ -1007,13 +1006,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zType = "aggregate";
}
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
- pNC->nErr++;
+ pNC->nNcErr++;
is_agg = 0;
}
#else
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
- pNC->nErr++;
+ pNC->nNcErr++;
is_agg = 0;
}
#endif
@@ -1023,11 +1022,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
+ pNC->nNcErr++;
}else if( wrong_num_args ){
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
nId, zId);
- pNC->nErr++;
+ pNC->nNcErr++;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
@@ -1035,7 +1034,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
"FILTER may not be used with non-aggregate %.*s()",
nId, zId
);
- pNC->nErr++;
+ pNC->nNcErr++;
}
#endif
if( is_agg ){
@@ -1259,8 +1258,8 @@ static int resolveOrderByTermToExprList(
nc.pParse = pParse;
nc.pSrcList = pSelect->pSrc;
nc.uNC.pEList = pEList;
- nc.ncFlags = NC_AllowAgg|NC_UEList;
- nc.nErr = 0;
+ nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect;
+ nc.nNcErr = 0;
db = pParse->db;
savedSuppErr = db->suppressErr;
if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
@@ -1519,7 +1518,7 @@ static int resolveOrderGroupBy(
Parse *pParse; /* Parsing context */
int nResult; /* Number of terms in the result set */
- if( pOrderBy==0 ) return 0;
+ assert( pOrderBy!=0 );
nResult = pSelect->pEList->nExpr;
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){
@@ -1609,8 +1608,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
while( p ){
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
+ assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */
p->selFlags |= SF_Resolved;
+
/* Resolve the expressions in the LIMIT and OFFSET clauses. These
** are not allowed to refer to any names, so pass an empty NameContext.
*/
@@ -1684,13 +1685,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sNC.ncFlags &= ~NC_AllowAgg;
}
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return WRC_Abort;
- }
-
/* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
@@ -1702,7 +1696,13 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
- if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ if( p->pHaving ){
+ if( !pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return WRC_Abort;
+ }
+ if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ }
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
/* Resolve names in table-valued-function arguments */
@@ -1715,6 +1715,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
*/
@@ -1742,7 +1755,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** is not detected until much later, and so we need to go ahead and
** resolve those symbols on the incorrect ORDER BY for consistency.
*/
- if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
+ if( p->pOrderBy!=0
+ && isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
){
return WRC_Abort;
@@ -1770,19 +1784,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( IN_RENAME_OBJECT ){
- Window *pWin;
- for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
- if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
- || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
- ){
- return WRC_Abort;
- }
- }
- }
-#endif
-
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
@@ -1866,7 +1867,7 @@ int sqlite3ResolveExprNames(
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
+ w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
@@ -1885,7 +1886,7 @@ int sqlite3ResolveExprNames(
testcase( pNC->ncFlags & NC_HasWin );
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
pNC->ncFlags |= savedHasAgg;
- return pNC->nErr>0 || w.pParse->nErr>0;
+ return pNC->nNcErr>0 || w.pParse->nErr>0;
}
/*
@@ -1930,7 +1931,7 @@ int sqlite3ResolveExprListNames(
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;
+ if( w.pParse->nErr>0 ) return WRC_Abort;
}
pNC->ncFlags |= savedHasAgg;
return WRC_Continue;
diff --git a/src/select.c b/src/select.c
index 1c001aa761..58f23caba9 100644
--- a/src/select.c
+++ b/src/select.c
@@ -741,31 +741,155 @@ static void codeOffset(
}
/*
-** Add code that will check to make sure the N registers starting at iMem
-** form a distinct entry. iTab is a sorting index that holds previously
-** seen combinations of the N values. A new entry is made in iTab
-** if the current N values are new.
+** Add code that will check to make sure the array of registers starting at
+** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
+** distinct aggregates ("SELECT count(DISTINCT ) ..."). Three strategies
+** are available. Which is used depends on the value of parameter eTnctType,
+** as follows:
**
-** A jump to addrRepeat is made and the N+1 values are popped from the
-** stack if the top N elements are not distinct.
+** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
+** Build an ephemeral table that contains all entries seen before and
+** skip entries which have been seen before.
+**
+** Parameter iTab is the cursor number of an ephemeral table that must
+** be opened before the VM code generated by this routine is executed.
+** The ephemeral cursor table is queried for a record identical to the
+** record formed by the current array of registers. If one is found,
+** jump to VM address addrRepeat. Otherwise, insert a new record into
+** the ephemeral cursor and proceed.
+**
+** The returned value in this case is a copy of parameter iTab.
+**
+** WHERE_DISTINCT_ORDERED:
+** In this case rows are being delivered sorted order. The ephermal
+** table is not required. Instead, the current set of values
+** is compared against previous row. If they match, the new row
+** is not distinct and control jumps to VM address addrRepeat. Otherwise,
+** the VM program proceeds with processing the new row.
+**
+** The returned value in this case is the register number of the first
+** in an array of registers used to store the previous result row so that
+** it can be compared to the next. The caller must ensure that this
+** register is initialized to NULL. (The fixDistinctOpenEph() routine
+** will take care of this initialization.)
+**
+** WHERE_DISTINCT_UNIQUE:
+** In this case it has already been determined that the rows are distinct.
+** No special action is required. The return value is zero.
+**
+** Parameter pEList is the list of expressions used to generated the
+** contents of each row. It is used by this routine to determine (a)
+** how many elements there are in the array of registers and (b) the
+** collation sequences that should be used for the comparisons if
+** eTnctType is WHERE_DISTINCT_ORDERED.
*/
-static void codeDistinct(
+static int codeDistinct(
Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
- int N, /* Number of elements */
- int iMem /* First element */
+ ExprList *pEList, /* Expression for each element */
+ int regElem /* First element */
){
- Vdbe *v;
- int r1;
+ int iRet = 0;
+ int nResultCol = pEList->nExpr;
+ Vdbe *v = pParse->pVdbe;
- v = pParse->pVdbe;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlite3ReleaseTempReg(pParse, r1);
+ switch( eTnctType ){
+ case WHERE_DISTINCT_ORDERED: {
+ int i;
+ int iJump; /* Jump destination */
+ int regPrev; /* Previous row content */
+
+ /* Allocate space for the previous row */
+ iRet = regPrev = pParse->nMem+1;
+ pParse->nMem += nResultCol;
+
+ iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
+ for(i=0; ia[i].pExpr);
+ if( idb->mallocFailed );
+ sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1);
+ break;
+ }
+
+ case WHERE_DISTINCT_UNIQUE: {
+ /* nothing to do */
+ break;
+ }
+
+ default: {
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlite3ReleaseTempReg(pParse, r1);
+ iRet = iTab;
+ break;
+ }
+ }
+
+ return iRet;
+}
+
+/*
+** This routine runs after codeDistinct(). It makes necessary
+** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
+** routine made use of. This processing must be done separately since
+** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
+** laid down.
+**
+** WHERE_DISTINCT_NOOP:
+** WHERE_DISTINCT_UNORDERED:
+**
+** No adjustments necessary. This function is a no-op.
+**
+** WHERE_DISTINCT_UNIQUE:
+**
+** The ephemeral table is not needed. So change the
+** OP_OpenEphemeral opcode into an OP_Noop.
+**
+** WHERE_DISTINCT_ORDERED:
+**
+** The ephemeral table is not needed. But we do need register
+** iVal to be initialized to NULL. So change the OP_OpenEphemeral
+** into an OP_Null on the iVal register.
+*/
+static void fixDistinctOpenEph(
+ Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
+ int iVal, /* Value returned by codeDistinct() */
+ int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
+){
+ if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
+ Vdbe *v = pParse->pVdbe;
+ sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
+ if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
+ sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
+ }
+ if( eTnctType==WHERE_DISTINCT_ORDERED ){
+ /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
+ ** bit on the first register of the previous value. This will cause the
+ ** OP_Ne added in codeDistinct() to always fail on the first iteration of
+ ** the loop even if the first row is all NULLs. */
+ VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
+ pOp->opcode = OP_Null;
+ pOp->p1 = 1;
+ pOp->p2 = iVal;
+ }
+ }
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -1013,59 +1137,11 @@ static void selectInnerLoop(
** part of the result.
*/
if( hasDistinct ){
- switch( pDistinct->eTnctType ){
- case WHERE_DISTINCT_ORDERED: {
- VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
- int iJump; /* Jump destination */
- int regPrev; /* Previous row content */
-
- /* Allocate space for the previous row */
- regPrev = pParse->nMem+1;
- pParse->nMem += nResultCol;
-
- /* Change the OP_OpenEphemeral coded earlier to an OP_Null
- ** sets the MEM_Cleared bit on the first register of the
- ** previous value. This will cause the OP_Ne below to always
- ** fail on the first iteration of the loop even if the first
- ** row is all NULLs.
- */
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
- pOp->opcode = OP_Null;
- pOp->p1 = 1;
- pOp->p2 = regPrev;
- pOp = 0; /* Ensure pOp is not used after sqlite3VdbeAddOp() */
-
- iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
- for(i=0; ipEList->a[i].pExpr);
- if( idb->mallocFailed );
- sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
- break;
- }
-
- case WHERE_DISTINCT_UNIQUE: {
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- break;
- }
-
- default: {
- assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
- codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
- regResult);
- break;
- }
- }
+ int eType = pDistinct->eTnctType;
+ int iTab = pDistinct->tabTnct;
+ assert( nResultCol==p->pEList->nExpr );
+ iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
+ fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
@@ -1731,7 +1807,13 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && iColpEList->nExpr ){
+ if( iColpEList->nExpr
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && iCol>=0
+#else
+ && ALWAYS(iCol>=0)
+#endif
+ ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
@@ -1873,7 +1955,7 @@ static void generateColumnTypes(
** then the result column name with the table name
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
-static void generateColumnNames(
+void sqlite3GenerateColumnNames(
Parse *pParse, /* Parser context */
Select *pSelect /* Generate column names for this SELECT statement */
){
@@ -1963,7 +2045,7 @@ static void generateColumnNames(
** and will break if those assumptions changes. Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
-** See Also: generateColumnNames()
+** See Also: sqlite3GenerateColumnNames()
*/
int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
@@ -2661,11 +2743,12 @@ static int multiSelect(
switch( p->op ){
case TK_ALL: {
int addr = 0;
- int nLimit;
+ int nLimit = 0; /* Initialize to suppress harmless compiler warning */
assert( !pPrior->pLimit );
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlite3Select(pParse, pPrior, &dest);
pPrior->pLimit = 0;
if( rc ){
@@ -2683,6 +2766,7 @@ static int multiSelect(
}
}
ExplainQueryPlan((pParse, 1, "UNION ALL"));
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
rc = sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -2735,6 +2819,7 @@ static int multiSelect(
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
@@ -2754,6 +2839,7 @@ static int multiSelect(
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
@@ -2814,6 +2900,7 @@ static int multiSelect(
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
@@ -2830,6 +2917,7 @@ static int multiSelect(
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -3463,6 +3551,9 @@ static int multiSelectOrderBy(
p->pPrior = pPrior;
pPrior->pNext = p;
+ sqlite3ExprListDelete(db, pPrior->pOrderBy);
+ pPrior->pOrderBy = 0;
+
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
ExplainQueryPlanPop(pParse);
@@ -3517,9 +3608,12 @@ static Expr *substExpr(
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
- }else{
+ }else
+#endif
+ {
Expr *pNew;
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
@@ -3539,10 +3633,14 @@ static Expr *substExpr(
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
- if( pNew && pSubst->isLeftJoin ){
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pNew);
+ return pExpr;
+ }
+ if( pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
+ if( ExprHasProperty(pExpr,EP_FromJoin) ){
sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
@@ -3550,15 +3648,13 @@ static Expr *substExpr(
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
- if( pExpr ){
- if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
- (pColl ? pColl->zName : "BINARY")
- );
- }
- ExprClearProperty(pExpr, EP_Collate);
+ if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ (pColl ? pColl->zName : "BINARY")
+ );
}
+ ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
@@ -3677,7 +3773,10 @@ static void srclistRenumberCursors(
for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){
if( i!=iExcept ){
Select *p;
- pItem->iCursor = aCsrMap[pItem->iCursor] = pParse->nTab++;
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
+ aCsrMap[pItem->iCursor] = pParse->nTab++;
+ }
+ pItem->iCursor = aCsrMap[pItem->iCursor];
for(p=pItem->pSelect; p; p=p->pPrior){
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
}
@@ -4117,7 +4216,7 @@ static int flattenSubquery(
p->pPrior = pPrior;
}else{
pNew->selId = ++pParse->nSelect;
- if( aCsrMap && db->mallocFailed==0 ){
+ if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
renumberCursors(pParse, pNew, iFrom, aCsrMap);
}
pNew->pPrior = pPrior;
@@ -4376,7 +4475,7 @@ static void constInsert(
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
- if( pExpr==0 ) return;
+ if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
@@ -4912,6 +5011,7 @@ static struct Cte *searchWith(
return &p->a[i];
}
}
+ if( p->bView ) break;
}
return 0;
}
@@ -4972,6 +5072,14 @@ static int resolveFromTermToCte(
** it cannot possibly be a CTE reference. */
return 0;
}
+ if( pFrom->fg.notCte ){
+ /* The FROM term is specifically excluded from matching a CTE.
+ ** (1) It is part of a trigger that used to have zDatabase but had
+ ** zDatabase removed by sqlite3FixTriggerStep().
+ ** (2) This is the first term in the FROM clause of an UPDATE.
+ */
+ return 0;
+ }
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
sqlite3 *db = pParse->db;
@@ -5120,7 +5228,7 @@ static int resolveFromTermToCte(
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements.
*/
-static void selectPopWith(Walker *pWalker, Select *p){
+void sqlite3SelectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
@@ -5130,8 +5238,6 @@ static void selectPopWith(Walker *pWalker, Select *p){
}
}
}
-#else
-#define selectPopWith 0
#endif
/*
@@ -5158,7 +5264,13 @@ int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral;
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ /* The usual case - do not allow ROWID on a subquery */
+ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
+#else
+ pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
+#endif
+
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
@@ -5212,6 +5324,15 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
+ if( pParse->pWith && (p->selFlags & SF_View) ){
+ if( p->pWith==0 ){
+ p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
+ if( p->pWith==0 ){
+ return WRC_Abort;
+ }
+ }
+ p->pWith->bView = 1;
+ }
sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
@@ -5512,7 +5633,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- w.xSelectCallback2 = selectPopWith;
+ w.xSelectCallback2 = sqlite3SelectPopWith;
w.eCode = 0;
sqlite3WalkSelect(&w, pSelect);
}
@@ -5645,8 +5766,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO);
+ pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
+ ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
+ pFunc->pFunc->zName));
}
}
}
@@ -5678,7 +5801,12 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
-static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
+static void updateAccumulator(
+ Parse *pParse,
+ int regAcc,
+ AggInfo *pAggInfo,
+ int eDistinctType
+){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
@@ -5724,13 +5852,12 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
nArg = 0;
regAgg = 0;
}
- if( pF->iDistinct>=0 ){
+ if( pF->iDistinct>=0 && pList ){
if( addrNext==0 ){
addrNext = sqlite3VdbeMakeLabel(pParse);
}
- testcase( nArg==0 ); /* Error condition */
- testcase( nArg>1 ); /* Also an error */
- codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
+ pF->iDistinct = codeDistinct(pParse, eDistinctType,
+ pF->iDistinct, addrNext, pList, regAgg);
}
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl = 0;
@@ -5782,7 +5909,7 @@ static void explainSimpleCount(
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
- sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
+ sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
@@ -6093,12 +6220,11 @@ int sqlite3Select(
}
if( pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, p);
+ sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- rc = sqlite3WindowRewrite(pParse, p);
- if( rc ){
+ if( sqlite3WindowRewrite(pParse, p) ){
assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
@@ -6224,7 +6350,8 @@ int sqlite3Select(
** as the equivalent optimization will be handled by query planner in
** sqlite3WhereBegin().
*/
- if( pTabList->nSrc>1
+ if( p->pWhere!=0
+ && p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
@@ -6355,10 +6482,10 @@ int sqlite3Select(
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->zName));
+ VdbeComment((v, "%!S", pItem));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
- ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
+ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
@@ -6402,17 +6529,17 @@ int sqlite3Select(
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
+ VdbeComment((v, "materialize %!S", pItem));
}else{
- VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
+ VdbeNoopComment((v, "materialize %!S", pItem));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->zName));
+ VdbeComment((v, "end %!S", pItem));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
@@ -6762,6 +6889,20 @@ int sqlite3Select(
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
int regReset; /* Return address register for reset subroutine */
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist = WHERE_DISTINCT_NOOP;
+
+ if( pAggInfo->nFunc==1
+ && pAggInfo->aFunc[0].iDistinct>=0
+ && pAggInfo->aFunc[0].pFExpr->x.pList
+ ){
+ Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
+ pExpr = sqlite3ExprDup(db, pExpr, 0);
+ pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
+ pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
+ }
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
@@ -6798,10 +6939,14 @@ int sqlite3Select(
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
- WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
+ WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
);
- if( pWInfo==0 ) goto select_end;
+ if( pWInfo==0 ){
+ sqlite3ExprListDelete(db, pDistinct);
+ goto select_end;
+ }
+ eDist = sqlite3WhereIsDistinct(pWInfo);
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
@@ -6919,7 +7064,7 @@ int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, iUseFlag, pAggInfo);
+ updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
@@ -6933,6 +7078,7 @@ int sqlite3Select(
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
+ sqlite3ExprListDelete(db, pDistinct);
/* Output the final row of result
*/
@@ -6975,7 +7121,11 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
+ if( eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = &pAggInfo->aFunc[0];
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
@@ -7039,6 +7189,9 @@ int sqlite3Select(
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -7062,6 +7215,9 @@ int sqlite3Select(
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
+ }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
+ pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
/* This case runs if the aggregate has no GROUP BY clause. The
@@ -7081,12 +7237,18 @@ int sqlite3Select(
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
- 0, minMaxFlag, 0);
+ pDistinct, minMaxFlag|distFlag, 0);
if( pWInfo==0 ){
goto select_end;
}
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
- updateAccumulator(pParse, regAcc, pAggInfo);
+ eDist = sqlite3WhereIsDistinct(pWInfo);
+ updateAccumulator(pParse, regAcc, pAggInfo, eDist);
+ if( eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = &pAggInfo->aFunc[0];
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
+
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( minMaxFlag ){
sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
@@ -7131,6 +7293,8 @@ int sqlite3Select(
** successful coding of the SELECT.
*/
select_end:
+ assert( db->mallocFailed==0 || db->mallocFailed==1 );
+ pParse->nErr += db->mallocFailed;
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
diff --git a/src/shell.c.in b/src/shell.c.in
index 2ec454ffbf..462cd717ba 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -2915,7 +2915,7 @@ static void bind_table_init(ShellState *p){
sqlite3_exec(p->db,
"CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
" key TEXT PRIMARY KEY,\n"
- " value ANY\n"
+ " value\n"
") WITHOUT ROWID;",
0, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
@@ -3978,8 +3978,8 @@ static const char *(azHelp[]) = {
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
" Options:",
" --append Use appendvfs to append database to the end of FILE",
-#ifdef SQLITE_ENABLE_DESERIALIZE
- " --deserialize Load into memory useing sqlite3_deserialize()",
+#ifndef SQLITE_OMIT_DESERIALIZE
+ " --deserialize Load into memory using sqlite3_deserialize()",
" --hexdb Load the output of \"dbtotxt\" as an in-memory db",
" --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
@@ -4300,7 +4300,7 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->zDbFilename. If p->zDbFilename
@@ -4389,7 +4389,7 @@ readHexDb_error:
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
/*
** Scalar function "shell_int32". The first argument to this function
@@ -4650,7 +4650,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
@@ -5779,7 +5779,7 @@ static int lintFkeyIndexes(
" || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
", "
- " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
+ " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
" || group_concat('*=?', ' AND ') || ')'"
", "
" s.name || '(' || group_concat(f.[from], ', ') || ')'"
@@ -5799,7 +5799,7 @@ static int lintFkeyIndexes(
"GROUP BY s.name, f.id "
"ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
;
- const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
+ const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
for(i=2; iout, "ANALYZE sqlite_schema;\n");
sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
- callback, &data, &zErrMsg);
+ callback, &data, 0);
data.cMode = data.mode = MODE_Insert;
data.zDestTable = "sqlite_stat1";
- shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
data.zDestTable = "sqlite_stat4";
- shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}
}else
@@ -8712,14 +8712,14 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1szMax = integerValue(azArg[++iName]);
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -10703,7 +10703,7 @@ static const char zOptions[] =
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -deserialize open the database using sqlite3_deserialize()\n"
#endif
" -echo print commands before execution\n"
@@ -10720,7 +10720,7 @@ static const char zOptions[] =
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
" -markdown set output mode to 'markdown'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -maxsize N maximum size for a --deserialize database\n"
#endif
" -memtrace trace all memory allocations and deallocations\n"
@@ -11050,7 +11050,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1
+**
+** [[SQLITE_FCNTL_EXTERNAL_READER]]
+** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
+** whether or not there is a database client in another process with a wal-mode
+** transaction open on the database or not. It is only available on unix.The
+** (void*) argument passed with this file-control should be a pointer to a
+** value of type (int). The integer value is set to 1 if the database is a wal
+** mode database and there exists at least one client in another process that
+** currently has an SQL transaction open on the database. It is set to 0 if
+** the database is not a wal-mode db, or if there is no such connection in any
+** other process. This opcode cannot be used to detect transactions opened
+** by clients within the current process, only within other processes.
+**
+**
+** [[SQLITE_FCNTL_CKSM_FILE]]
+** Used by the cksmvfs VFS module only.
+**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@@ -1167,6 +1184,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
+#define SQLITE_FCNTL_EXTERNAL_READER 40
+#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -4179,6 +4198,15 @@ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
+**
+** ^This routine returns false if there is any possibility that the
+** statement might change the database file. ^A false return does
+** not guarantee that the statement will change the database file.
+** ^For example, an UPDATE statement might have a WHERE clause that
+** makes it a no-op, but the sqlite3_stmt_readonly() result would still
+** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
+** read-only no-op if the table already exists, but
+** sqlite3_stmt_readonly() still returns false for such a statement.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -4348,18 +4376,22 @@ typedef struct sqlite3_context sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to the bind API fails,
-** except the destructor is not called if the third parameter is a NULL
-** pointer or the fourth parameter is negative.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlite3_bind_*() routine returns.
+** ^The fifth argument to the BLOB and string binding interfaces controls
+** or indicates the lifetime of the object referenced by the third parameter.
+** ^These three options exist:
+** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
+** with it may be passed. ^It is called to dispose of the BLOB or string even
+** if the call to the bind API fails, except the destructor is not called if
+** the third parameter is a NULL pointer or the fourth parameter is negative.
+** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
+** the application remains responsible for disposing of the object. ^In this
+** case, the object and the provided pointer to it must remain valid until
+** either the prepared statement is finalized or the same SQL parameter is
+** bound to something else, whichever occurs sooner.
+** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
+** object is to be copied prior to the return from sqlite3_bind_*(). ^The
+** object and pointer to it must remain valid until then. ^SQLite will then
+** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -9531,6 +9563,15 @@ int sqlite3_db_cacheflush(sqlite3*);
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
+** When the [sqlite3_blob_write()] API is used to update a blob column,
+** the pre-update hook is invoked with SQLITE_DELETE. This is because the
+** in this case the new values are not available. In this case, when a
+** callback made with op==SQLITE_DELETE is actuall a write using the
+** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
+** the index of the column being written. In other cases, where the
+** pre-update hook is being invoked for some other reason, including a
+** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
+**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@@ -9551,6 +9592,7 @@ int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
int sqlite3_preupdate_count(sqlite3 *);
int sqlite3_preupdate_depth(sqlite3 *);
int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif
/*
@@ -9814,8 +9856,8 @@ SQLITE_EXPERIMENTAL int sqlite3_wal_info(
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */
@@ -9866,8 +9908,8 @@ unsigned char *sqlite3_serialize(
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 3f662fe683..7bc9a7f6c3 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1544,10 +1544,7 @@ struct sqlite3 {
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
- unsigned bDropColumn : 1; /* Doing schema check after DROP COLUMN */
char **azInit; /* "type", "name", and "tbl_name" columns */
- /* or if bDropColumn, then azInit[0] is the */
- /* name of the column being dropped */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -1753,7 +1750,6 @@ struct sqlite3 {
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
-#define SQLITE_ExistsToIN 0x00020000 /* The EXISTS-to-IN optimization */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -2126,9 +2122,7 @@ struct CollSeq {
** operator is NULL. It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
-#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
-#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
@@ -2260,6 +2254,7 @@ struct Table {
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
#define TF_Ephemeral 0x4000 /* An ephemeral table */
+#define TF_Eponymous 0x8000 /* An eponymous virtual table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2625,6 +2620,7 @@ struct AggInfo {
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
+ int iDistAddr; /* Address of OP_OpenEphemeral */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
@@ -2897,6 +2893,7 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
+ int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
@@ -2970,6 +2967,7 @@ struct SrcItem {
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
+ unsigned notCte :1; /* This item may not match a CTE */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
@@ -3041,7 +3039,7 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
- /* 0x0400 not currently used */
+#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
/* 0x1000 not currently used */
/* 0x2000 not currently used */
@@ -3087,7 +3085,7 @@ struct NameContext {
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
- int nErr; /* Number of errors encountered while resolving names */
+ int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -3120,6 +3118,7 @@ struct NameContext {
#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -3814,7 +3813,7 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
@@ -3901,11 +3900,18 @@ int sqlite3SelectWalkNoop(Walker*, Select*);
int sqlite3SelectWalkFail(Walker*, Select*);
int sqlite3WalkerDepthIncrease(Walker*,Select*);
void sqlite3WalkerDepthDecrease(Walker*,Select*);
+void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
+#ifndef SQLITE_OMIT_CTE
+void sqlite3SelectPopWith(Walker*, Select*);
+#else
+# define sqlite3SelectPopWith 0
+#endif
+
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
@@ -3939,6 +3945,7 @@ struct Cte {
*/
struct With {
int nCte; /* Number of CTEs in the WITH clause */
+ int bView; /* Belongs to the outermost Select of a view */
With *pOuter; /* Containing WITH clause, or NULL */
Cte a[1]; /* For each CTE in the WITH clause.... */
};
@@ -4309,6 +4316,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
+void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
@@ -4330,6 +4338,7 @@ void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
+void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -4710,7 +4719,7 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrName(int);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int sqlite3MemdbInit(void);
#endif
@@ -4761,6 +4770,9 @@ void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];
+extern const unsigned char *sqlite3aLTb;
+extern const unsigned char *sqlite3aEQb;
+extern const unsigned char *sqlite3aGTb;
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index d80c25251c..2206bca321 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2600,7 +2600,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Reopen DATABASE (default "main") using the content in $VALUE
*/
case DB_DESERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
@@ -3167,7 +3167,7 @@ deserialize_error:
** Return a serialization of a database.
*/
case DB_SERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
diff --git a/src/test1.c b/src/test1.c
index 99bfecb0f8..22dfec9896 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -3825,9 +3825,11 @@ static int SQLITE_TCLAPI test_bind_text(
){
sqlite3_stmt *pStmt;
int idx;
+ int trueLength = 0;
int bytes;
char *value;
int rc;
+ char *toFree = 0;
if( objc!=5 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -3837,13 +3839,23 @@ static int SQLITE_TCLAPI test_bind_text(
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
+ value = (char*)Tcl_GetByteArrayFromObj(objv[3], &trueLength);
if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
-
+ if( bytes<0 ){
+ toFree = malloc( trueLength + 1 );
+ if( toFree==0 ){
+ Tcl_AppendResult(interp, "out of memory", (void*)0);
+ return TCL_ERROR;
+ }
+ memcpy(toFree, value, trueLength);
+ toFree[trueLength] = 0;
+ value = toFree;
+ }
rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
+ free(toFree);
if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+ Tcl_AppendResult(interp, sqlite3ErrName(rc), (void*)0);
return TCL_ERROR;
}
@@ -3869,7 +3881,9 @@ static int SQLITE_TCLAPI test_bind_text16(
int idx;
int bytes;
char *value;
+ char *toFree = 0;
int rc;
+ int trueLength = 0;
void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
Tcl_Obj *oStmt = objv[objc-4];
@@ -3885,10 +3899,20 @@ static int SQLITE_TCLAPI test_bind_text16(
if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
+ value = (char*)Tcl_GetByteArrayFromObj(oString, &trueLength);
if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
-
+ if( bytes<0 && xDel==SQLITE_TRANSIENT ){
+ toFree = malloc( trueLength + 3 );
+ if( toFree==0 ){
+ Tcl_AppendResult(interp, "out of memory", (void*)0);
+ return TCL_ERROR;
+ }
+ memcpy(toFree, value, trueLength);
+ memset(toFree+trueLength, 0, 3);
+ value = toFree;
+ }
rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
+ free(toFree);
if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
@@ -6490,6 +6514,42 @@ static int SQLITE_TCLAPI file_control_tempfilename(
return TCL_OK;
}
+/*
+** tclcmd: file_control_external_reader DB ?AUXDB?
+**
+** Return a string that is a temporary filename
+*/
+static int SQLITE_TCLAPI file_control_external_reader(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ const char *zName = "main";
+ int iRes = 0;
+ int rc = SQLITE_OK;
+
+ if( objc!=2 && objc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+ return TCL_ERROR;
+ }
+ if( objc==3 ){
+ zName = Tcl_GetString(objv[2]);
+ }
+ rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
+ if( rc!=SQLITE_OK ){
+ Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
+ return TCL_OK;
+}
+
/*
** tclcmd: sqlite3_vfs_list
@@ -8463,6 +8523,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_vfsname", file_control_vfsname, 0 },
{ "file_control_reservebytes", file_control_reservebytes, 0 },
{ "file_control_tempfilename", file_control_tempfilename, 0 },
+ { "file_control_external_reader", file_control_external_reader, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
diff --git a/src/test8.c b/src/test8.c
index f984c2e5f2..7a532346ed 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -389,6 +389,7 @@ static int echoDestructor(sqlite3_vtab *pVtab){
typedef struct EchoModule EchoModule;
struct EchoModule {
Tcl_Interp *interp;
+ sqlite3 *db;
};
/*
@@ -1352,6 +1353,9 @@ extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
extern const char *sqlite3ErrName(int);
static void moduleDestroy(void *p){
+ EchoModule *pMod = (EchoModule*)p;
+ sqlite3_create_function(pMod->db, "function_that_does_not_exist_0982ma98",
+ SQLITE_ANY, 1, 0, 0, 0, 0);
sqlite3_free(p);
}
@@ -1376,6 +1380,7 @@ static int SQLITE_TCLAPI register_echo_module(
/* Virtual table module "echo" */
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(
db, "echo", &echoModule, (void*)pMod, moduleDestroy
);
@@ -1384,6 +1389,7 @@ static int SQLITE_TCLAPI register_echo_module(
if( rc==SQLITE_OK ){
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(db, "echo_v2",
&echoModuleV2, (void*)pMod, moduleDestroy
);
diff --git a/src/test_config.c b/src/test_config.c
index de7ea9bb91..74484b6562 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -65,6 +65,13 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
#endif
+#ifdef CONFIG_SLOWDOWN_FACTOR
+ Tcl_SetVar2(interp, "sqlite_options","configslower",
+ STRINGVALUE(CONFIG_SLOWDOWN_FACTOR),TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options","configslower","1.0",TCL_GLOBAL_ONLY);
+#endif
+
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
#else
@@ -148,7 +155,7 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
@@ -226,6 +233,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_ENABLE_GEOPOLY
+ Tcl_SetVar2(interp, "sqlite_options", "geopoly", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "geopoly", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_ENABLE_JSON1
Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
diff --git a/src/tokenize.c b/src/tokenize.c
index 5e01de2b90..5d250e6f6a 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -56,6 +56,7 @@
#define CC_ID 27 /* unicode characters usable in IDs */
#define CC_ILLEGAL 28 /* Illegal character */
#define CC_NUL 29 /* 0x00 */
+#define CC_BOM 30 /* First byte of UTF8 BOM: 0xEF 0xBB 0xBF */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
@@ -68,14 +69,14 @@ static const unsigned char aiClass[] = {
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
-/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+/* 8x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 9x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ax */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Cx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Dx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ex */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
+/* Fx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
@@ -535,6 +536,14 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
i = 1;
break;
}
+ case CC_BOM: {
+ if( z[1]==0xbb && z[2]==0xbf ){
+ *tokenType = TK_SPACE;
+ return 3;
+ }
+ i = 1;
+ break;
+ }
case CC_NUL: {
*tokenType = TK_ILLEGAL;
return 0;
diff --git a/src/treeview.c b/src/treeview.c
index b696d764e0..12a6b21a87 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -134,19 +134,12 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d:*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
+ x.printfFlags |= SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
if( 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);
- }
if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
}
diff --git a/src/trigger.c b/src/trigger.c
index 689c7c741e..90e6ef4a72 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -57,29 +57,41 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
}
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
- if( p==0 ){
- return pTab->pTrigger;
- }
pList = pTab->pTrigger;
- if( pTmpSchema!=pTab->pSchema ){
- while( p ){
- Trigger *pTrig = (Trigger *)sqliteHashData(p);
- if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
- ){
- pTrig->pNext = pList;
- pList = pTrig;
- }else if( pTrig->op==TK_RETURNING ){
- assert( pParse->bReturning );
- assert( &(pParse->u1.pReturning->retTrig) == pTrig );
- pTrig->table = pTab->zName;
- pTrig->pTabSchema = pTab->pSchema;
- pTrig->pNext = pList;
- pList = pTrig;
- }
- p = sqliteHashNext(p);
- }
+ while( p ){
+ Trigger *pTrig = (Trigger *)sqliteHashData(p);
+ if( pTrig->pTabSchema==pTab->pSchema
+ && pTrig->table
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ && pTrig->pTabSchema!=pTmpSchema
+ ){
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }else if( pTrig->op==TK_RETURNING
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ && pParse->db->pVtabCtx==0
+#endif
+ ){
+ assert( pParse->bReturning );
+ assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ pTrig->table = pTab->zName;
+ pTrig->pTabSchema = pTab->pSchema;
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }
+ p = sqliteHashNext(p);
}
+#if 0
+ if( pList ){
+ Trigger *pX;
+ printf("Triggers for %s:", pTab->zName);
+ for(pX=pList; pX; pX=pX->pNext){
+ printf(" %s", pX->zName);
+ }
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
return pList;
}
@@ -209,12 +221,12 @@ void sqlite3BeginTrigger(
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
- (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
+ (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
- " trigger on table: %S", pTableName, 0);
+ " trigger on table: %S", pTableName->a);
goto trigger_orphan_error;
}
@@ -611,7 +623,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
}
if( !pTrigger ){
if( !noErr ){
- sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, zDb);
}
@@ -823,6 +835,25 @@ SrcList *sqlite3TriggerStepSrc(
return pSrc;
}
+/*
+** Return true if the pExpr term from the RETURNING clause argument
+** list is of the form "*". Raise an error if the terms if of the
+** form "table.*".
+*/
+static int isAsteriskTerm(
+ Parse *pParse, /* Parsing context */
+ Expr *pTerm /* A term in the RETURNING clause */
+){
+ assert( pTerm!=0 );
+ if( pTerm->op==TK_ASTERISK ) return 1;
+ if( pTerm->op!=TK_DOT ) return 0;
+ assert( pTerm->pRight!=0 );
+ assert( pTerm->pLeft!=0 );
+ if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
+ sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
+ return 1;
+}
+
/* The input list pList is the list of result set terms from a RETURNING
** clause. The table that we are returning from is pTab.
**
@@ -840,7 +871,8 @@ static ExprList *sqlite3ExpandReturning(
for(i=0; inExpr; i++){
Expr *pOldExpr = pList->a[i].pExpr;
- if( ALWAYS(pOldExpr!=0) && pOldExpr->op==TK_ASTERISK ){
+ if( NEVER(pOldExpr==0) ) continue;
+ if( isAsteriskTerm(pParse, pOldExpr) ){
int jj;
for(jj=0; jjnCol; jj++){
Expr *pNewExpr;
@@ -863,15 +895,6 @@ static ExprList *sqlite3ExpandReturning(
}
}
}
- if( !db->mallocFailed ){
- Vdbe *v = pParse->pVdbe;
- assert( v!=0 );
- sqlite3VdbeSetNumCols(v, pNew->nExpr);
- for(i=0; inExpr; i++){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, pNew->a[i].zEName,
- SQLITE_TRANSIENT);
- }
- }
return pNew;
}
@@ -887,13 +910,27 @@ static void codeReturningTrigger(
int regIn /* The first in an array of registers */
){
Vdbe *v = pParse->pVdbe;
+ sqlite3 *db = pParse->db;
ExprList *pNew;
Returning *pReturning;
+ Select sSelect;
+ SrcList sFrom;
assert( v!=0 );
assert( pParse->bReturning );
pReturning = pParse->u1.pReturning;
assert( pTrigger == &(pReturning->retTrig) );
+ memset(&sSelect, 0, sizeof(sSelect));
+ memset(&sFrom, 0, sizeof(sFrom));
+ sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
+ sSelect.pSrc = &sFrom;
+ sFrom.nSrc = 1;
+ sFrom.a[0].pTab = pTab;
+ sqlite3SelectPrep(pParse, &sSelect, 0);
+ if( db->mallocFailed==0 && pParse->nErr==0 ){
+ sqlite3GenerateColumnNames(pParse, &sSelect);
+ }
+ sqlite3ExprListDelete(db, sSelect.pEList);
pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
if( pNew ){
NameContext sNC;
@@ -914,13 +951,14 @@ static void codeReturningTrigger(
pParse->nMem += nCol+2;
pReturning->iRetReg = reg;
for(i=0; ia[i].pExpr, reg+i);
+ Expr *pCol = pNew->a[i].pExpr;
+ sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
}
- sqlite3ExprListDelete(pParse->db, pNew);
+ sqlite3ExprListDelete(db, pNew);
pParse->eTriggerOp = 0;
pParse->pTriggerTab = 0;
}
@@ -1123,8 +1161,8 @@ static TriggerPrg *codeRowTrigger(
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
+ if( db->mallocFailed==0
+ && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
){
iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
diff --git a/src/update.c b/src/update.c
index 8c37456948..15ebb77179 100644
--- a/src/update.c
+++ b/src/update.c
@@ -220,6 +220,7 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ pSrc->a[0].fg.notCte = 1;
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -249,7 +250,8 @@ static void updateFromSelect(
}
#endif
}
- if( ALWAYS(pChanges) ){
+ assert( pChanges!=0 || pParse->db->mallocFailed );
+ if( pChanges ){
for(i=0; inExpr; i++){
pList = sqlite3ExprListAppend(pParse, pList,
sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
@@ -810,7 +812,12 @@ void sqlite3Update(
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
+ if( aiCurOnePass[0]!=iDataCur
+ && aiCurOnePass[1]!=iDataCur
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && !isView
+#endif
+ ){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
VdbeCoverage(v);
diff --git a/src/vdbe.c b/src/vdbe.c
index 8a8d8854e0..a212734507 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -275,18 +275,36 @@ static VdbeCursor *allocateCursor(
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
- if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+ /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
+ ** the pMem used to hold space for the cursor has enough storage available
+ ** in pMem->zMalloc. But for the special case of the aMem[] entries used
+ ** to hold cursors, it is faster to in-line the logic. */
+ assert( pMem->flags==MEM_Undefined );
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+ if( pMem->szMallocszMalloc>0 ){
+ sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
}
+ pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
+ if( pMem->zMalloc==0 ){
+ pMem->szMalloc = 0;
+ return 0;
+ }
+ pMem->szMalloc = nByte;
+ }
+
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+ pCx->eCurType = eCurType;
+ pCx->iDb = iDb;
+ pCx->nField = nField;
+ pCx->aOffset = &pCx->aType[nField];
+ if( eCurType==CURTYPE_BTREE ){
+ pCx->uc.pCursor = (BtCursor*)
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
@@ -433,7 +451,10 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
- ExpandBlob(pMem);
+ if( ExpandBlob(pMem) ){
+ pMem->u.i = 0;
+ return MEM_Int;
+ }
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
if( rc<=0 ){
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
@@ -571,6 +592,11 @@ static void registerTrace(int iReg, Mem *p){
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
+/**/ void sqlite3PrintMem(Mem *pMem){
+ memTracePrint(pMem);
+ printf("\n");
+ fflush(stdout);
+}
#endif
#ifdef SQLITE_DEBUG
@@ -1473,7 +1499,7 @@ case OP_ResultRow: {
Mem *pMem;
int i;
assert( p->nResColumn==pOp->p2 );
- assert( pOp->p1>0 );
+ assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
/* Invalidate all ephemeral cursor row caches */
@@ -1915,8 +1941,7 @@ case OP_Cast: { /* in1 */
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then
-** store the result of comparison in register P2.
+** jump to address P2.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
@@ -1942,9 +1967,8 @@ case OP_Cast: { /* in1 */
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 0 (false).
-** In other words, a prior r[P2] value will not be overwritten by 1 (true).
+** This opcode saves the result of comparison for use by the new
+** OP_Jump opcode.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
@@ -1952,17 +1976,12 @@ case OP_Cast: { /* in1 */
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Eq opcode for
** additional information.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 1 (true).
-** In other words, a prior r[P2] value will not be overwritten by 0 (false).
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
+ if( (flags1 & flags3 & MEM_Int)!=0 ){
+ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
+ /* Common case of comparison of two integers */
+ if( pIn3->u.i > pIn1->u.i ){
+ iCompare = +1;
+ if( sqlite3aGTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else if( pIn3->u.i < pIn1->u.i ){
+ iCompare = -1;
+ if( sqlite3aLTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else{
+ iCompare = 0;
+ if( sqlite3aEQb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }
+ VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ break;
+ }
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -2044,22 +2091,16 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = 1; /* Operands are not equal */
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(2,3);
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- goto jump_to_p2;
- }
+ iCompare = 1; /* Operands are not equal */
+ VdbeBranchTaken(2,3);
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ goto jump_to_p2;
}
break;
}
}else{
- /* Neither operand is NULL. Do a comparison. */
+ /* Neither operand is NULL and we couldn't do the special high-speed
+ ** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
@@ -2072,14 +2113,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
applyNumericAffinity(pIn3,0);
}
}
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
@@ -2102,7 +2135,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-compare_op:
+
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
@@ -2111,16 +2144,14 @@ compare_op:
** order: NE, EQ, GT, LE, LT, GE */
assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
- if( res<0 ){ /* ne, eq, gt, le, lt, ge */
- static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
- res2 = aLTb[pOp->opcode - OP_Ne];
+ if( res<0 ){
+ res2 = sqlite3aLTb[pOp->opcode];
}else if( res==0 ){
- static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
- res2 = aEQb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aEQb[pOp->opcode];
}else{
- static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
- res2 = aGTb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aGTb[pOp->opcode];
}
+ iCompare = res;
/* Undo any changes made by applyAffinity() to the input registers. */
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
@@ -2128,67 +2159,39 @@ compare_op:
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = res;
- if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
- /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
- ** and prevents OP_Ne from overwriting NULL with 0. This flag
- ** is only used in contexts where either:
- ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
- ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
- ** Therefore it is not necessary to check the content of r[P2] for
- ** NULL. */
- assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
- assert( res2==0 || res2==1 );
- testcase( res2==0 && pOp->opcode==OP_Eq );
- testcase( res2==1 && pOp->opcode==OP_Eq );
- testcase( res2==0 && pOp->opcode==OP_Ne );
- testcase( res2==1 && pOp->opcode==OP_Ne );
- if( (pOp->opcode==OP_Eq)==res2 ) break;
- }
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = res2;
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
- if( res2 ){
- goto jump_to_p2;
- }
+ VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ if( res2 ){
+ goto jump_to_p2;
}
break;
}
-/* Opcode: ElseNotEq * P2 * * *
+/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
-** OP_Lt or OP_Gt. Furthermore, the prior OP_Lt or OP_Gt must have the
-** SQLITE_STOREP2 bit set in the P5 field.
+** OP_Lt or OP_Gt.
**
** If result of an OP_Eq comparison on the same two operands as the
-** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
-** jump to P2. If the result of an OP_Eq comparison on the two previous
-** operands would have been true (1), then fall through.
+** prior OP_Lt or OP_Gt would have been true, then jump to P2.
+** If the result of an OP_Eq comparison on the two previous
+** operands would have been false or NULL, then fall through.
*/
-case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
+case OP_ElseEq: { /* same as TK_ESCAPE, jump */
#ifdef SQLITE_DEBUG
/* Verify the preconditions of this opcode - that it follows an OP_Lt or
- ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
- ** OP_ReleaseReg opcodes */
+ ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
int iAddr;
for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
- assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
break;
}
#endif /* SQLITE_DEBUG */
- VdbeBranchTaken(iCompare!=0, 2);
- if( iCompare!=0 ) goto jump_to_p2;
+ VdbeBranchTaken(iCompare==0, 2);
+ if( iCompare==0 ) goto jump_to_p2;
break;
}
@@ -2499,6 +2502,24 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
break;
}
+/* Opcode: ZeroOrNull P1 P2 P3 * *
+** Synopsis: r[P2] = 0 OR NULL
+**
+** If all both registers P1 and P3 are NOT NULL, then store a zero in
+** register P2. If either registers P1 or P3 are NULL then put
+** a NULL in register P2.
+*/
+case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
+ if( (aMem[pOp->p1].flags & MEM_Null)!=0
+ || (aMem[pOp->p3].flags & MEM_Null)!=0
+ ){
+ sqlite3VdbeMemSetNull(aMem + pOp->p2);
+ }else{
+ sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
+ }
+ break;
+}
+
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
@@ -4591,8 +4612,18 @@ case OP_SeekHit: {
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHitp2 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
+ }
+#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
+ }
+#endif
pC->seekHit = pOp->p3;
}
break;
@@ -4707,6 +4738,11 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit is %d\n", pC->seekHit);
+ }
+#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
@@ -5136,7 +5172,7 @@ case OP_Insert: {
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
+ sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
}
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
/* Prevent post-update hook from running in cases when it should not */
@@ -5296,7 +5332,7 @@ case OP_Delete: {
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
- pOp->p3
+ pOp->p3, -1
);
}
if( opflags & OPFLAG_ISNOOP ) break;
@@ -6365,7 +6401,7 @@ case OP_ParseSchema: {
iDb = pOp->p1;
assert( iDb>=0 && iDbnDb );
- assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
+ assert( DbHasProperty(db, iDb, DB_SchemaLoaded) || db->mallocFailed );
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
@@ -7248,6 +7284,7 @@ case OP_JournalMode: { /* out2 */
pPager = sqlite3BtreePager(pBt);
eOld = sqlite3PagerGetJournalMode(pPager);
if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+ assert( sqlite3BtreeHoldsMutex(pBt) );
if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
#ifndef SQLITE_OMIT_WAL
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index cb423f20a1..5e3e523f92 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -472,6 +472,7 @@ struct PreUpdate {
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
+ int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
@@ -560,7 +561,8 @@ void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
+void sqlite3VdbePreUpdateHook(
+ Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
int sqlite3VdbeTransferError(Vdbe *p);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index ba3bdf6a5f..b21634dc80 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -1905,6 +1905,17 @@ int sqlite3_preupdate_depth(sqlite3 *db){
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+/*
+** This function is designed to be called from within a pre-update callback
+** only.
+*/
+int sqlite3_preupdate_blobwrite(sqlite3 *db){
+ PreUpdate *p = db->pPreUpdate;
+ return (p ? p->iBlobWrite : -1);
+}
+#endif
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index be0d3f9bb5..3ea07d3c07 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1487,11 +1487,7 @@ char *sqlite3VdbeDisplayComment(
char c;
zSynopsis = zOpName += nOpName + 1;
if( strncmp(zSynopsis,"IF ",3)==0 ){
- if( pOp->p5 & SQLITE_STOREP2 ){
- sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
- }else{
- sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
- }
+ sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
zSynopsis = zAlt;
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
@@ -5213,7 +5209,8 @@ void sqlite3VdbePreUpdateHook(
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
- int iReg /* Register for new.* record */
+ int iReg, /* Register for new.* record */
+ int iBlobWrite
){
sqlite3 *db = v->db;
i64 iKey2;
@@ -5249,6 +5246,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
+ preupdate.iBlobWrite = iBlobWrite;
db->pPreUpdate = &preupdate;
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index d34e3cf9f4..a4e79bf89b 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -420,7 +420,7 @@ static int blobReadWrite(
sqlite3_int64 iKey;
iKey = sqlite3BtreeIntegerKey(p->pCsr);
sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
+ v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
#endif
@@ -491,6 +491,7 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
rc = SQLITE_ABORT;
}else{
char *zErr;
+ ((Vdbe*)p->pStmt)->rc = SQLITE_OK;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 384eacc015..fd5212c8a9 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -75,7 +75,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
- || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
+ || (p->flags==MEM_Undefined
+ && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
+ || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@@ -239,7 +241,9 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
+ || (pMem->flags==MEM_Undefined
+ && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+ || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
diff --git a/src/vtab.c b/src/vtab.c
index ded12c13bb..c9dcadae4b 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -1221,6 +1221,7 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 );
pTab->iPKey = -1;
+ pTab->tabFlags |= TF_Eponymous;
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
diff --git a/src/wal.c b/src/wal.c
index ed7da63fd7..371312ffad 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -1315,7 +1315,6 @@ static void walCleanupHash(Wal *pWal){
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
- int rc; /* Return code form walHashGet() */
int iWal = walidxGetFile(&pWal->hdr);
u32 mxFrame = walidxGetMxFrame(&pWal->hdr, iWal);
@@ -1340,8 +1339,8 @@ static void walCleanupHash(Wal *pWal){
*/
assert( pWal->nWiData>walFramePage(iExternal) );
assert( pWal->apWiData[walFramePage(iExternal)] );
- rc = walHashGet(pWal, walFramePage(iExternal), &sLoc);
- if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */
+ i = walHashGet(pWal, walFramePage(iExternal), &sLoc);
+ if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
diff --git a/src/walker.c b/src/walker.c
index 927f7e52d7..8c0308473a 100644
--- a/src/walker.c
+++ b/src/walker.c
@@ -32,15 +32,10 @@ static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
-
- /* The next two are purely for calls to sqlite3RenameExprUnmap()
- ** within sqlite3WindowOffsetExpr(). Because of constraints imposed
- ** by sqlite3WindowOffsetExpr(), they can never fail. The results do
- ** not matter anyhow. */
rc = sqlite3WalkExpr(pWalker, pWin->pStart);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
if( bOneOnly ) break;
}
return WRC_Continue;
@@ -117,6 +112,16 @@ int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
return WRC_Continue;
}
+/*
+** This is a no-op callback for Walker->xSelectCallback2. If this
+** callback is set, then the Select->pWinDefn list is traversed.
+*/
+void sqlite3WalkWinDefnDummyCallback(Walker *pWalker, Select *p){
+ UNUSED_PARAMETER(pWalker);
+ UNUSED_PARAMETER(p);
+ /* No-op */
+}
+
/*
** Walk all expressions associated with SELECT statement p. Do
** not invoke the SELECT callback on p, but do (of course) invoke
@@ -130,10 +135,15 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
-#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
- {
- Parse *pParse = pWalker->pParse;
- if( pParse && IN_RENAME_OBJECT ){
+#if !defined(SQLITE_OMIT_WINDOWFUNC)
+ if( p->pWinDefn ){
+ Parse *pParse;
+ if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
+ || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
+#ifndef SQLITE_OMIT_CTE
+ || pWalker->xSelectCallback2==sqlite3SelectPopWith
+#endif
+ ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
int rc = walkWindowList(pWalker, p->pWinDefn, 0);
@@ -157,7 +167,7 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcItem *pItem;
pSrc = p->pSrc;
- if( pSrc ){
+ if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
@@ -170,7 +180,7 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
}
}
return WRC_Continue;
-}
+}
/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
diff --git a/src/where.c b/src/where.c
index 75b3ceff87..4062de7eab 100644
--- a/src/where.c
+++ b/src/where.c
@@ -261,7 +261,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlite3ExprSkipCollateAndLikely(p->pRight);
- if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
+ return p;
+ }
return 0;
}
@@ -336,6 +338,18 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
pScan->pWC = pWC;
pScan->k = k+1;
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ int ii;
+ sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
+ pTerm, pScan->nEquiv);
+ for(ii=0; iinEquiv; ii++){
+ sqlite3DebugPrintf(" {%d:%d}",
+ pScan->aiCur[ii], pScan->aiColumn[ii]);
+ }
+ sqlite3DebugPrintf("\n");
+ }
+#endif
return pTerm;
}
}
@@ -492,7 +506,7 @@ static int findIndexCol(
for(i=0; inExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( ALWAYS(p!=0)
- && p->op==TK_COLUMN
+ && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -557,7 +571,8 @@ static int isDistinctRedundant(
for(i=0; inExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
- if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+ if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
+ if( p->iTable==iBase && p->iColumn<0 ) return 1;
}
/* Loop through all indices on the table, checking each to see if it makes
@@ -575,6 +590,7 @@ static int isDistinctRedundant(
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !IsUniqueIndex(pIdx) ) continue;
+ if( pIdx->pPartIdxWhere ) continue;
for(i=0; inKeyCol; i++){
if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
@@ -629,14 +645,14 @@ static void translateColumnToCopy(
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
- if( iAutoidxCur ){
- pOp->opcode = OP_Sequence;
- pOp->p1 = iAutoidxCur;
- }else{
+ pOp->opcode = OP_Sequence;
+ pOp->p1 = iAutoidxCur;
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
- pOp->p1 = 0;
pOp->p3 = 0;
}
+#endif
}
}
}
@@ -801,7 +817,7 @@ static void constructAutomaticIndex(
}
}
}
- assert( nKeyCol>0 );
+ assert( nKeyCol>0 || pParse->db->mallocFailed );
pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
| WHERE_AUTO_INDEX;
@@ -1938,7 +1954,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
whereLoopClearUnion(db, pTo);
if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
- memset(&pTo->u, 0, sizeof(pTo->u));
+ memset(pTo, 0, WHERE_LOOP_XFER_SZ);
return SQLITE_NOMEM_BKPT;
}
memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
@@ -1981,6 +1997,17 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
sqlite3DbFreeNN(db, pWInfo);
}
+/* Undo all Expr node modifications
+*/
+static void whereUndoExprMods(WhereInfo *pWInfo){
+ while( pWInfo->pExprMods ){
+ WhereExprMod *p = pWInfo->pExprMods;
+ pWInfo->pExprMods = p->pNext;
+ memcpy(p->pExpr, &p->orig, sizeof(p->orig));
+ sqlite3DbFree(pWInfo->pParse->db, p);
+ }
+}
+
/*
** Return TRUE if all of the following are true:
**
@@ -2486,6 +2513,8 @@ static int whereLoopAddBtreeIndex(
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEqnColumn );
+ assert( pNew->u.btree.nEqnKeyCol
+ || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
@@ -2619,6 +2648,7 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
+ if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
}else if( eOp & WO_ISNULL ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
}else if( eOp & (WO_GT|WO_GE) ){
@@ -2762,6 +2792,8 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEqnColumn
+ && (pNew->u.btree.nEqnKeyCol ||
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
@@ -3593,7 +3625,9 @@ static int whereLoopAddOr(
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
- assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0
+ || rc==SQLITE_NOMEM );
+ testcase( rc==SQLITE_NOMEM && sCur.n>0 );
testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
@@ -3822,7 +3856,7 @@ static i8 wherePathSatisfiesOrderBy(
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( NEVER(pOBExpr==0) ) continue;
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, eqOpMask, 0);
@@ -3862,6 +3896,10 @@ static i8 wherePathSatisfiesOrderBy(
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
+ /* All relevant terms of the index must also be non-NULL in order
+ ** for isOrderDistinct to be true. So the isOrderDistint value
+ ** computed here might be a false positive. Corrections will be
+ ** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
@@ -3929,15 +3967,19 @@ static i8 wherePathSatisfiesOrderBy(
}
/* An unconstrained column that might be NULL means that this
- ** WhereLoop is not well-ordered
+ ** WhereLoop is not well-ordered. tag-20210426-1
*/
- if( isOrderDistinct
- && iColumn>=0
- && j>=pLoop->u.btree.nEq
- && pIndex->pTable->aCol[iColumn].notNull==0
- ){
- isOrderDistinct = 0;
- }
+ if( isOrderDistinct ){
+ if( iColumn>=0
+ && j>=pLoop->u.btree.nEq
+ && pIndex->pTable->aCol[iColumn].notNull==0
+ ){
+ isOrderDistinct = 0;
+ }
+ if( iColumn==XN_EXPR ){
+ isOrderDistinct = 0;
+ }
+ }
/* Find the ORDER BY term that corresponds to the j-th column
** of the index and mark that ORDER BY term off
@@ -3951,7 +3993,7 @@ static i8 wherePathSatisfiesOrderBy(
if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
@@ -4120,7 +4162,7 @@ static LogEst whereSortingCost(
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
- if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
+ if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -5052,7 +5094,8 @@ WhereInfo *sqlite3WhereBegin(
*/
notReady = ~(Bitmask)0;
if( pWInfo->nLevel>=2
- && pResultSet!=0 /* guarantees condition (1) above */
+ && pResultSet!=0 /* these two combine to guarantee */
+ && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
int i;
@@ -5311,6 +5354,8 @@ WhereInfo *sqlite3WhereBegin(
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
+ testcase( pWInfo->pExprMods!=0 );
+ whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
}
@@ -5407,6 +5452,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+ assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
+ || pParse->db->mallocFailed );
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
@@ -5431,6 +5478,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
+ /* Retarget the OP_IsNull against the left operand of IN so
+ ** it jumps past the OP_IfNoHope. This is because the
+ ** OP_IsNull also bypasses the OP_Affinity opcode that is
+ ** required by OP_IfNoHope. */
+ sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
@@ -5565,7 +5617,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
- assert( pOpnErr>0 && pOp==pLastOp) );
+ assert( pOp<=pLastOp );
do{
if( pOp->p1!=pLevel->iTabCur ){
/* no-op */
@@ -5610,16 +5662,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
- /* Undo all Expr node modifications */
- while( pWInfo->pExprMods ){
- WhereExprMod *p = pWInfo->pExprMods;
- pWInfo->pExprMods = p->pNext;
- memcpy(p->pExpr, &p->orig, sizeof(p->orig));
- sqlite3DbFree(db, p);
- }
-
/* Final cleanup
*/
+ if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
return;
diff --git a/src/whereInt.h b/src/whereInt.h
index 8896da0271..c5dd83cc8e 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -293,8 +293,8 @@ struct WhereScan {
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
- unsigned char nEquiv; /* Number of entries in aEquiv[] */
- unsigned char iEquiv; /* Next unused slot in aEquiv[] */
+ unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
+ unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */
int aiCur[11]; /* Cursors in the equivalence class */
@@ -603,5 +603,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
+#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
#endif /* !defined(SQLITE_WHEREINT_H) */
diff --git a/src/wherecode.c b/src/wherecode.c
index a7a76fb704..4d0ba880d1 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -148,16 +148,8 @@ int sqlite3WhereExplainOneScan(
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
- if( pItem->pSelect ){
- sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId);
- }else{
- sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
- }
-
- if( pItem->zAlias ){
- sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
- }
+ str.printfFlags = SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
@@ -305,6 +297,12 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
}else{
pTerm->wtFlags |= TERM_CODED;
}
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ sqlite3DebugPrintf("DISABLE-");
+ sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
+ }
+#endif
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
@@ -622,7 +620,22 @@ static int codeEqualityTerm(
sqlite3DbFree(pParse->db, aiMap);
#endif
}
- disableTerm(pLevel, pTerm);
+
+ /* As an optimization, try to disable the WHERE clause term that is
+ ** driving the index as it will always be true. The correct answer is
+ ** obtained regardless, but we might get the answer with fewer CPU cycles
+ ** by omitting the term.
+ **
+ ** But do not disable the term unless we are certain that the term is
+ ** not a transitive constraint. For an example of where that does not
+ ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
+ */
+ if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
+ || (pTerm->eOperator & WO_EQUIV)==0
+ ){
+ disableTerm(pLevel, pTerm);
+ }
+
return iReg;
}
@@ -708,6 +721,7 @@ static int codeAllEqualityTerms(
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1);
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
@@ -759,7 +773,7 @@ static int codeAllEqualityTerms(
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
- if( zAff ){
+ if( pParse->db->mallocFailed==0 ){
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
@@ -1735,9 +1749,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( (nEqnKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nKeyCol==nEq)
- ){
+ if( (nEqnColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
@@ -2158,7 +2170,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlite3PExpr() false, and this
- ** prevents sqlite3PExpr() from implementing AND short-circuit
+ ** prevents sqlite3PExpr() from applying the AND short-circuit
** optimization, which we do not want here. */
pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
}
@@ -2174,10 +2186,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
+ Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pOrExpr, EP_FromJoin)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
+ pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDelete);
+ continue;
+ }
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -2292,6 +2310,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
+ sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
@@ -2456,6 +2475,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
+ pAlt->wtFlags |= TERM_CODED;
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
diff --git a/src/whereexpr.c b/src/whereexpr.c
index 7b80c41393..31f2ea438e 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -511,6 +511,7 @@ static void whereCombineDisjuncts(
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
+ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
@@ -871,7 +872,7 @@ static void exprAnalyzeOrTerm(
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
- /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
+ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlite3ExprListDelete(db, pList);
@@ -995,6 +996,7 @@ static int exprMightBeIndexed(
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
pExpr = pExpr->x.pList->a[0].pExpr;
+
}
if( pExpr->op==TK_COLUMN ){
@@ -1007,275 +1009,6 @@ static int exprMightBeIndexed(
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
-/*
-** Expression callback for exprUsesSrclist().
-*/
-static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
- if( pExpr->op==TK_COLUMN ){
- SrcList *pSrc = p->u.pSrcList;
- int iCsr = pExpr->iTable;
- int ii;
- for(ii=0; iinSrc; ii++){
- if( pSrc->a[ii].iCursor==iCsr ){
- return p->eCode ? WRC_Abort : WRC_Continue;
- }
- }
- return p->eCode ? WRC_Continue : WRC_Abort;
- }
- return WRC_Continue;
-}
-
-/*
-** Select callback for exprUsesSrclist().
-*/
-static int exprUsesSrclistSelectCb(Walker *NotUsed1, Select *NotUsed2){
- UNUSED_PARAMETER(NotUsed1);
- UNUSED_PARAMETER(NotUsed2);
- return WRC_Abort;
-}
-
-/*
-** This function always returns true if expression pExpr contains
-** a sub-select.
-**
-** If there is no sub-select in pExpr, then return true if pExpr
-** contains a TK_COLUMN node for a table that is (bUses==1)
-** or is not (bUses==0) in pSrc.
-**
-** Said another way:
-**
-** bUses Return Meaning
-** -------- ------ ------------------------------------------------
-**
-** bUses==1 true pExpr contains either a sub-select or a
-** TK_COLUMN referencing pSrc.
-**
-** bUses==1 false pExpr contains no sub-selects and all TK_COLUMN
-** nodes reference tables not found in pSrc
-**
-** bUses==0 true pExpr contains either a sub-select or a TK_COLUMN
-** that references a table not in pSrc.
-**
-** bUses==0 false pExpr contains no sub-selects and all TK_COLUMN
-** nodes reference pSrc
-*/
-static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
- Walker sWalker;
- memset(&sWalker, 0, sizeof(Walker));
- sWalker.eCode = bUses;
- sWalker.u.pSrcList = pSrc;
- sWalker.xExprCallback = exprUsesSrclistCb;
- sWalker.xSelectCallback = exprUsesSrclistSelectCb;
- return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
-}
-
-/*
-** Context object used by exprExistsToInIter() as it iterates through an
-** expression tree.
-*/
-struct ExistsToInCtx {
- SrcList *pSrc; /* The tables in an EXISTS(SELECT ... FROM ...) */
- Expr *pInLhs; /* OUT: Use this as the LHS of the IN operator */
- Expr *pEq; /* OUT: The == term that include pInLhs */
- Expr **ppAnd; /* OUT: The AND operator that includes pEq as a child */
- Expr **ppParent; /* The AND operator currently being examined */
-};
-
-/*
-** Iterate through all AND connected nodes in the expression tree
-** headed by (*ppExpr), populating the structure passed as the first
-** argument with the values required by exprAnalyzeExistsFindEq().
-**
-** This function returns non-zero if the expression tree does not meet
-** the two conditions described by the header comment for
-** exprAnalyzeExistsFindEq(), or zero if it does.
-*/
-static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
- Expr *pExpr = *ppExpr;
- switch( pExpr->op ){
- case TK_AND:
- p->ppParent = ppExpr;
- if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
- p->ppParent = ppExpr;
- if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
- break;
- case TK_EQ: {
- int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
- int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
- if( bLeft || bRight ){
- if( (bLeft && bRight) || p->pInLhs ) return 1;
- p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
- if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
- p->pEq = pExpr;
- p->ppAnd = p->ppParent;
- }
- break;
- }
- default:
- if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-/*
-** This function is used by exprAnalyzeExists() when creating virtual IN(...)
-** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
-** clause of the Select object passed as the first argument into one or more
-** expressions joined by AND operators, and then tests if the following are
-** true:
-**
-** 1. Exactly one of the AND separated terms refers to the outer
-** query, and it is an == (TK_EQ) expression.
-**
-** 2. Only one side of the == expression refers to the outer query, and
-** it does not refer to any columns from the inner query.
-**
-** If both these conditions are true, then a pointer to the side of the ==
-** expression that refers to the outer query is returned. The caller will
-** use this expression as the LHS of the IN(...) virtual term. Or, if one
-** or both of the above conditions are not true, NULL is returned.
-**
-** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
-** to the == expression node before returning. If pppAnd is non-NULL and
-** the == node is not the root of the WHERE clause, then *pppAnd is set
-** to point to the pointer to the AND node that is the parent of the ==
-** node within the WHERE expression tree.
-*/
-static Expr *exprAnalyzeExistsFindEq(
- Select *pSel, /* The SELECT of the EXISTS */
- Expr **ppEq, /* OUT: == node from WHERE clause */
- Expr ***pppAnd /* OUT: Pointer to parent of ==, if any */
-){
- struct ExistsToInCtx ctx;
- memset(&ctx, 0, sizeof(ctx));
- ctx.pSrc = pSel->pSrc;
- if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
- return 0;
- }
- if( ppEq ) *ppEq = ctx.pEq;
- if( pppAnd ) *pppAnd = ctx.ppAnd;
- return ctx.pInLhs;
-}
-
-/*
-** Term idxTerm of the WHERE clause passed as the second argument is an
-** EXISTS expression with a correlated SELECT statement on the RHS.
-** This function analyzes the SELECT statement, and if possible adds an
-** equivalent "? IN(SELECT...)" virtual term to the WHERE clause.
-**
-** For an EXISTS term such as the following:
-**
-** EXISTS (SELECT ... FROM WHERE = AND )
-**
-** The virtual IN() term added is:
-**
-** IN (SELECT FROM WHERE )
-**
-** The virtual term is only added if the following conditions are met:
-**
-** 1. The sub-select must not be an aggregate or use window functions,
-**
-** 2. The sub-select must not be a compound SELECT,
-**
-** 3. Expression must refer to at least one column from the outer
-** query, and must not refer to any column from the inner query
-** (i.e. from ).
-**
-** 4. and must not refer to any values from the outer query.
-** In other words, once has been removed, the inner query
-** must not be correlated.
-**
-*/
-static void exprAnalyzeExists(
- SrcList *pSrc, /* the FROM clause */
- WhereClause *pWC, /* the WHERE clause */
- int idxTerm /* Index of the term to be analyzed */
-){
- Parse *pParse = pWC->pWInfo->pParse;
- WhereTerm *pTerm = &pWC->a[idxTerm];
- Expr *pExpr = pTerm->pExpr;
- Select *pSel = pExpr->x.pSelect;
- Expr *pDup = 0;
- Expr *pEq = 0;
- Expr *pRet = 0;
- Expr *pInLhs = 0;
- Expr **ppAnd = 0;
- int idxNew;
- sqlite3 *db = pParse->db;
-
- assert( pExpr->op==TK_EXISTS );
- assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );
-
- if( pSel->selFlags & SF_Aggregate ) return;
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pSel->pWin ) return;
-#endif
- if( pSel->pPrior ) return;
- if( pSel->pWhere==0 ) return;
- if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;
-
- pDup = sqlite3ExprDup(db, pExpr, 0);
- if( db->mallocFailed ){
- sqlite3ExprDelete(db, pDup);
- return;
- }
- pSel = pDup->x.pSelect;
- sqlite3ExprListDelete(db, pSel->pEList);
- pSel->pEList = 0;
-
- pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
- assert( pInLhs && pEq );
- assert( pEq==pSel->pWhere || ppAnd );
- if( pInLhs==pEq->pLeft ){
- pRet = pEq->pRight;
- }else{
- CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
- pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
- pRet = pEq->pLeft;
- }
-
- assert( pDup->pLeft==0 );
- pDup->op = TK_IN;
- pDup->pLeft = pInLhs;
- pDup->flags &= ~EP_VarSelect;
- if( pRet->op==TK_VECTOR ){
- pSel->pEList = pRet->x.pList;
- pRet->x.pList = 0;
- sqlite3ExprDelete(db, pRet);
- }else{
- pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
- }
- pEq->pLeft = 0;
- pEq->pRight = 0;
- if( ppAnd ){
- Expr *pAnd = *ppAnd;
- Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
- pAnd->pLeft = pAnd->pRight = 0;
- sqlite3ExprDelete(db, pAnd);
- *ppAnd = pOther;
- }else{
- assert( pSel->pWhere==pEq );
- pSel->pWhere = 0;
- }
- sqlite3ExprDelete(db, pEq);
-
-#ifdef WHERETRACE_ENABLED /* 0x20 */
- if( sqlite3WhereTrace & 0x20 ){
- sqlite3DebugPrintf("Convert EXISTS:\n");
- sqlite3TreeViewExpr(0, pExpr, 0);
- sqlite3DebugPrintf("into IN:\n");
- sqlite3TreeViewExpr(0, pDup, 0);
- }
-#endif
- idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pWC, idxNew);
- markTermAsChild(pWC, idxNew, idxTerm);
- pWC->a[idxTerm].wtFlags |= TERM_COPIED;
-}
/*
** The input to this routine is an WhereTerm structure with only the
@@ -1375,6 +1108,7 @@ static void exprAnalyze(
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
+ && !ExprHasProperty(pRight, EP_FixedCol)
){
WhereTerm *pNew;
Expr *pDup;
@@ -1467,16 +1201,6 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-
- else if( pExpr->op==TK_EXISTS ){
- /* Perhaps treat an EXISTS operator as an IN operator */
- if( (pExpr->flags & EP_VarSelect)!=0
- && OptimizationEnabled(db, SQLITE_ExistsToIN)
- ){
- exprAnalyzeExists(pSrc, pWC, idxTerm);
- }
- }
-
/* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
diff --git a/src/window.c b/src/window.c
index 26a82a9e33..a997b9c6c9 100644
--- a/src/window.c
+++ b/src/window.c
@@ -788,6 +788,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
case TK_AGG_FUNCTION:
case TK_COLUMN: {
int iCol = -1;
+ if( pParse->db->mallocFailed ) return WRC_Abort;
if( p->pSub ){
int i;
for(i=0; ipSub->nExpr; i++){
@@ -897,9 +898,14 @@ static ExprList *exprListAppendList(
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; inExpr; i++){
- Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
+ sqlite3 *db = pParse->db;
+ Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
- if( bIntToNull && pDup ){
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ break;
+ }
+ if( bIntToNull ){
int iDummy;
Expr *pSub;
for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
@@ -935,6 +941,14 @@ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
+static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
+ sqlite3ErrorMsg(pWalker->pParse,
+ "misuse of aggregate: %s()", pExpr->u.zToken);
+ }
+ return WRC_Continue;
+}
+
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
@@ -968,6 +982,11 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
+ if( (p->selFlags & SF_Aggregate)==0 ){
+ w.xExprCallback = disallowAggregatesInOrderByCb;
+ w.xSelectCallback = 0;
+ sqlite3WalkExprList(&w, p->pOrderBy);
+ }
p->pSrc = 0;
p->pWhere = 0;
@@ -1469,6 +1488,7 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
VdbeCoverageIf(v, eCond==2);
}
sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
@@ -1563,6 +1583,7 @@ struct WindowCodeArg {
int regGosub; /* Register used with OP_Gosub(addrGosub) */
int regArg; /* First in array of accumulator registers */
int eDelete; /* See above */
+ int regRowid;
WindowCsrAndReg start;
WindowCsrAndReg current;
@@ -1679,15 +1700,15 @@ static void windowAggStep(
}
if( pWin->bExprArgs ){
- int iStart = sqlite3VdbeCurrentAddr(v);
- VdbeOp *pOp, *pEnd;
+ int iOp = sqlite3VdbeCurrentAddr(v);
+ int iEnd;
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
- pEnd = sqlite3VdbeGetOp(v, -1);
- for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
+ for(iEnd=sqlite3VdbeCurrentAddr(v); iOpopcode==OP_Column && pOp->p1==pWin->iEphCsr ){
pOp->p1 = csr;
}
@@ -2046,7 +2067,7 @@ static void windowIfNewPeer(
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
-** a numeric type (real or integer), then the result of the addition addition
+** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
@@ -2065,8 +2086,13 @@ static void windowCodeRangeTest(
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
+ int addrDone = sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */
CollSeq *pColl;
+ /* Read the peer-value from each cursor into a register */
+ windowReadPeerValues(p, csr1, reg1);
+ windowReadPeerValues(p, csr2, reg2);
+
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
@@ -2078,34 +2104,11 @@ static void windowCodeRangeTest(
arith = OP_Subtract;
}
- /* Read the peer-value from each cursor into a register */
- windowReadPeerValues(p, csr1, reg1);
- windowReadPeerValues(p, csr2, reg2);
-
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
- /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
- ** This block adds (or subtracts for DESC) the numeric value in regVal
- ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
- ** then leave reg1 as it is. In pseudo-code, this is implemented as:
- **
- ** if( reg1>='' ) goto addrGe;
- ** reg1 = reg1 +/- regVal
- ** addrGe:
- **
- ** Since all strings and blobs are greater-than-or-equal-to an empty string,
- ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
- ** then the arithmetic is performed, but since adding or subtracting from
- ** NULL is always NULL anyway, this case is handled as required too. */
- sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
- addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
- sqlite3VdbeJumpHere(v, addrGe);
-
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
@@ -2142,16 +2145,38 @@ static void windowCodeRangeTest(
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
- sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
if( op==OP_Gt || op==OP_Ge ){
- sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
+ sqlite3VdbeChangeP2(v, -1, addrDone);
}
}
+ /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
+ ** This block adds (or subtracts for DESC) the numeric value in regVal
+ ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
+ ** then leave reg1 as it is. In pseudo-code, this is implemented as:
+ **
+ ** if( reg1>='' ) goto addrGe;
+ ** reg1 = reg1 +/- regVal
+ ** addrGe:
+ **
+ ** Since all strings and blobs are greater-than-or-equal-to an empty string,
+ ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
+ ** then the arithmetic is performed, but since adding or subtracting from
+ ** NULL is always NULL anyway, this case is handled as required too. */
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
+ addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
+ VdbeCoverage(v);
+ if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
+ sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ }
+ sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
+ sqlite3VdbeJumpHere(v, addrGe);
+
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
@@ -2159,6 +2184,7 @@ static void windowCodeRangeTest(
pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ sqlite3VdbeResolveLabel(v, addrDone);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
@@ -2234,16 +2260,24 @@ static int windowCodeOp(
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
- ** temporary table. It otherwise might, if (a>b). */
+ ** temporary table. It otherwise might, if (a>b). Also ensure that,
+ ** if the input cursor is still finding new rows, that the end
+ ** cursor does not go past it to EOF. */
if( pMWin->eStart==pMWin->eEnd && regCountdown
- && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
+ && pMWin->eFrmType==TK_RANGE
){
int regRowid1 = sqlite3GetTempReg(pParse);
int regRowid2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
- sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
- sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
- VdbeCoverage(v);
+ if( op==WINDOW_AGGINVERSE ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
+ sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
+ VdbeCoverage(v);
+ }else if( p->regRowid ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
+ sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
+ VdbeCoverageNeverNull(v);
+ }
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
@@ -2740,7 +2774,6 @@ void sqlite3WindowCodeStep(
int addrEmpty; /* Address of OP_Rewind in flush: */
int regNew; /* Array of registers holding new input row */
int regRecord; /* regNew array in record form */
- int regRowid; /* Rowid for regRecord in eph table */
int regNewPeer = 0; /* Peer values for new row (part of regNew) */
int regPeer = 0; /* Peer values for current row */
int regFlushPart = 0; /* Register for "Gosub flush_partition" */
@@ -2812,7 +2845,7 @@ void sqlite3WindowCodeStep(
regNew = pParse->nMem+1;
pParse->nMem += nInput;
regRecord = ++pParse->nMem;
- regRowid = ++pParse->nMem;
+ s.regRowid = ++pParse->nMem;
/* If the window frame contains an " PRECEDING" or " FOLLOWING"
** clause, allocate registers to store the results of evaluating each
@@ -2868,9 +2901,9 @@ void sqlite3WindowCodeStep(
}
/* Insert the new row into the ephemeral table */
- sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
- addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
+ addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
VdbeCoverageNeverNull(v);
/* This block is run for the first row of each partition */
@@ -2988,6 +3021,7 @@ void sqlite3WindowCodeStep(
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
+ s.regRowid = 0;
addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
VdbeCoverage(v);
if( pMWin->eEnd==TK_PRECEDING ){
diff --git a/test/alter4.test b/test/alter4.test
index 3aca7df338..c63ba6b072 100644
--- a/test/alter4.test
+++ b/test/alter4.test
@@ -318,16 +318,16 @@ ifcapable trigger&&tempdb {
END;
INSERT INTO t1 VALUES(1, 2);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2}
+ } {a 1 2 b 1 2}
do_test alter4-6.2 {
execsql {
ALTER TABLE t1 ADD COLUMN c DEFAULT 'c';
INSERT INTO t1(a, b) VALUES(3, 4);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2 b 3 4 a 3 4}
+ } {a 1 2 a 3 4 b 1 2 b 3 4}
}
# Ticket #1183 - Make sure adding columns to large tables does not cause
diff --git a/test/alterauth2.test b/test/alterauth2.test
index a411408b58..27ded1c3ea 100644
--- a/test/alterauth2.test
+++ b/test/alterauth2.test
@@ -82,6 +82,7 @@ do_auth_test 1.2 {
{SQLITE_ALTER_TABLE main t2 {} {}}
{SQLITE_FUNCTION {} like {} {}}
{SQLITE_FUNCTION {} sqlite_rename_column {} {}}
+ {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
{SQLITE_READ sqlite_master name main {}}
{SQLITE_READ sqlite_master sql main {}}
@@ -100,6 +101,7 @@ do_auth_test 1.3 {
} {
{SQLITE_FUNCTION {} like {} {}}
{SQLITE_FUNCTION {} sqlite_drop_column {} {}}
+ {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
{SQLITE_READ sqlite_master name main {}}
{SQLITE_READ sqlite_master sql main {}}
@@ -110,6 +112,7 @@ do_auth_test 1.3 {
{SQLITE_READ sqlite_temp_master type temp {}}
{SQLITE_SELECT {} {} {} {}}
{SQLITE_UPDATE sqlite_master sql main {}}
+ {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}
finish_test
diff --git a/test/altercol.test b/test/altercol.test
index 047917e5a1..d0c5c40ea6 100644
--- a/test/altercol.test
+++ b/test/altercol.test
@@ -567,7 +567,7 @@ do_execsql_test 13.1.6 {
do_catchsql_test 13.1.7 {
ALTER TABLE x1 RENAME COLUMN t TO ttt;
-} {1 {database disk image is malformed}}
+} {1 {error in index x1i: }}
do_execsql_test 13.1.8 {
DELETE FROM sqlite_master WHERE name = 'x1i';
@@ -835,5 +835,29 @@ do_execsql_test 22.0 {
{CREATE TABLE t2(c, othername, extra AS (c + 1))}
}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 22.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX x1 on t1("c"=b);
+ INSERT INTO t1 VALUES('a', 'a');
+ INSERT INTO t1 VALUES('b', 'b');
+ INSERT INTO t1 VALUES('c', 'c');
+ ALTER TABLE t1 RENAME COLUMN a TO "c";
+ PRAGMA integrity_check;
+} {ok}
+
+reset_db
+do_execsql_test 23.0 {
+ CREATE TABLE t1('a'"b",c);
+ CREATE INDEX i1 ON t1('a');
+ INSERT INTO t1 VALUES(1,2), (3,4);
+ ALTER TABLE t1 RENAME COLUMN a TO x;
+ PRAGMA integrity_check;
+ SELECT sql FROM sqlite_schema WHERE name='t1';
+
+} {ok {CREATE TABLE t1("x" "b",c)}}
+
finish_test
diff --git a/test/alterdropcol.test b/test/alterdropcol.test
index 3cca664151..8674e981a3 100644
--- a/test/alterdropcol.test
+++ b/test/alterdropcol.test
@@ -276,4 +276,64 @@ do_catchsql_test 6.1 {
ALTER TABLE t2 DROP COLUMN z;
} {1 {database disk image is malformed}}
+# 2021-04-06 dbsqlfuzz crash-331c5c29bb76257b198f1318eef3288f9624c8ce
+reset_db
+do_execsql_test 7.0 {
+ CREATE TABLE t1(a, b, c, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID;
+ INSERT INTO t1 VALUES(1, 2, 3);
+ INSERT INTO t1 VALUES(4, 5, 6);
+}
+do_execsql_test 7.1 {
+ ALTER TABLE t1 DROP COLUMN c;
+}
+do_execsql_test 7.2 {
+ SELECT sql FROM sqlite_schema;
+} {{CREATE TABLE t1(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID}}
+do_execsql_test 7.3 {
+ SELECT * FROM t1;
+} {1 2 4 5}
+
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = 'CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b)'
+}
+db close
+sqlite3 db test.db
+do_execsql_test 8.1 {
+ ALTER TABLE t1 DROP COLUMN b;
+}
+do_execsql_test 8.2 {
+ SELECT sql FROM sqlite_schema;
+} {{CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT)}}
+
+#-------------------------------------------------------------------------
+
+foreach {tn wo} {
+ 1 {}
+ 2 {WITHOUT ROWID}
+} {
+ reset_db
+ do_execsql_test 9.$tn.0 "
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) $wo;
+ "
+ do_execsql_test 9.$tn.1 {
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
+ )
+ INSERT INTO t1(a, b, c) SELECT i, 123, 456 FROM s;
+ }
+ do_execsql_test 9.$tn.2 {
+ ALTER TABLE t1 DROP COLUMN b;
+ }
+
+ do_execsql_test 9.$tn.3 {
+ SELECT count(*), c FROM t1 GROUP BY c;
+ } {50000 456}
+}
+
+
+
finish_test
diff --git a/test/altermalloc3.test b/test/altermalloc3.test
index d84f6bbc94..5e4e75149d 100644
--- a/test/altermalloc3.test
+++ b/test/altermalloc3.test
@@ -22,6 +22,14 @@ ifcapable !altertable {
}
do_execsql_test 1.0 {
+ CREATE TABLE x1(
+ one, two, three, PRIMARY KEY(one),
+ CHECK (three!="xyz"), CHECK (two!="one")
+ ) WITHOUT ROWID;
+ CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
+ CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
+ END;
CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 2, 3, 4);
}
@@ -37,4 +45,3 @@ do_faultsim_test 1 -prep {
finish_test
-
diff --git a/test/alterqf.test b/test/alterqf.test
new file mode 100644
index 0000000000..ce00f3b596
--- /dev/null
+++ b/test/alterqf.test
@@ -0,0 +1,111 @@
+# 2021 March 16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. This
+# script focuses on testing internal function sqlite_rename_quotefix().
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix alterqf
+
+sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a, b, c);
+}
+
+foreach {tn before after} {
+ 1 {CREATE VIEW v1 AS SELECT "a", "b", "notacolumn!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'notacolumn!', "c" FROM t1}
+
+ 2 {CREATE VIEW v1 AS SELECT "a", "b", "not'a'column!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'not''a''column!', "c" FROM t1}
+
+ 3 {CREATE VIEW v1 AS SELECT "a", "b", "not""a""column!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'not"a"column!', "c" FROM t1}
+
+ 4 {CREATE VIEW v1 AS SELECT "val", count("b") FROM t1 GROUP BY "abc"}
+ {CREATE VIEW v1 AS SELECT 'val', count("b") FROM t1 GROUP BY 'abc'}
+
+ 5 {CREATE TABLE xyz(a CHECK (a!="str"), b AS (a||"str"))}
+ {CREATE TABLE xyz(a CHECK (a!='str'), b AS (a||'str'))}
+
+ 6 {CREATE INDEX i1 ON t1(a || "str", "b", "val")}
+ {CREATE INDEX i1 ON t1(a || 'str', "b", 'val')}
+
+ 7 {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT "abcd"; END}
+ {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 'abcd'; END}
+
+ 8 {CREATE VIEW v1 AS SELECT "string"'alias' FROM t1}
+ {CREATE VIEW v1 AS SELECT 'string' 'alias' FROM t1}
+
+ 9 {CREATE INDEX i1 ON t1(a) WHERE "b"="bb"}
+ {CREATE INDEX i1 ON t1(a) WHERE "b"='bb'}
+
+ 10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))}
+ {CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))}
+
+ 11 {
+ CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
+ SELECT max("str", new."a") FROM t1
+ WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
+ UPDATE t1 SET c= b + "str";
+ DELETE FROM t1 WHERE EXISTS (
+ SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
+ );
+ END;
+ } {
+ CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
+ SELECT max('str', new."a") FROM t1
+ WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
+ UPDATE t1 SET c= b + 'str';
+ DELETE FROM t1 WHERE EXISTS (
+ SELECT 1 FROM t1 AS o WHERE o."a" = 'o.a' AND t1.b IN('t1.b')
+ );
+ END;
+ }
+
+} {
+ do_execsql_test 1.$tn {
+ SELECT sqlite_rename_quotefix('main', $before)
+ } [list $after]
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.0 {
+ CREATE TABLE x1(
+ one, two, three, PRIMARY KEY(one),
+ CHECK (three!="xyz"), CHECK (two!="one")
+ ) WITHOUT ROWID;
+ CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
+ CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
+ END;
+}
+
+do_execsql_test 2.1 {
+ ALTER TABLE x1 RENAME two TO 'four';
+ SELECT sql FROM sqlite_schema;
+ SELECT sql FROM sqlite_temp_schema;
+} {{CREATE TABLE x1(
+ one, "four", three, PRIMARY KEY(one),
+ CHECK (three!='xyz'), CHECK ("four"!="one")
+ ) WITHOUT ROWID}
+ {CREATE INDEX x1i ON x1(one+"four"+'four') WHERE 'five'}
+ {CREATE TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET "four"=new.three || 'new' WHERE one=new.one||'';
+ END}
+}
+
+
+finish_test
diff --git a/test/altertab.test b/test/altertab.test
index 0ed8fe5962..576d391ced 100644
--- a/test/altertab.test
+++ b/test/altertab.test
@@ -736,6 +736,67 @@ do_catchsql_test 24.2.1 {
ALTER TABLE t1 RENAME TO t2;
} {1 {error in trigger AFTER: no such table: main.nosuchtable}}
+#--------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 25.1 {
+ CREATE TABLE xx(x);
+ CREATE VIEW v3(b) AS WITH b AS (SELECT b FROM (SELECT * FROM t2)) VALUES(1);
+}
+
+ifcapable json1&&vtab {
+ do_catchsql_test 25.2 {
+ ALTER TABLE json_each RENAME TO t4;
+ } {1 {table json_each may not be altered}}
+}
+
+# 2021-05-01 dbsqlfuzz bc17a306a09329bba0ecc61547077f6178bcf321
+# Remove a NEVER() inserted on 2019-12-09 that is reachable after all.
+#
+reset_db
+do_execsql_test 26.1 {
+ CREATE TABLE t1(k,v);
+ CREATE TABLE t2_a(k,v);
+ CREATE VIEW t2 AS SELECT * FROM t2_a;
+ CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
+ UPDATE t1
+ SET (k,v)=((WITH cte1(a) AS (SELECT 1 FROM t2) SELECT t2.k FROM t2, cte1),1);
+ END;
+ ALTER TABLE t1 RENAME TO t1x;
+ INSERT INTO t2_a VALUES(2,3);
+ INSERT INTO t1x VALUES(98,99);
+ SELECT * FROM t1x;
+} {2 1}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 27.1 {
+
+ create table t_sa (
+ c_muyat INTEGER NOT NULL,
+ c_d4u TEXT
+ );
+
+ create table t2 ( abc );
+
+ CREATE TRIGGER trig AFTER DELETE ON t_sa
+ BEGIN
+ DELETE FROM t_sa WHERE (
+ SELECT 123 FROM t2
+ WINDOW oamat7fzf AS ( PARTITION BY t_sa.c_d4u )
+ );
+ END;
+}
+
+
+breakpoint
+do_execsql_test 27.2 {
+ alter table t_sa rename column c_muyat to c_dg;
+}
+
+
+
+
finish_test
-
diff --git a/test/analyze3.test b/test/analyze3.test
index 1f4a2722b0..7469c537c0 100644
--- a/test/analyze3.test
+++ b/test/analyze3.test
@@ -124,10 +124,10 @@ do_execsql_test analyze3-1.1.x {
#
do_eqp_test analyze3-1.1.2 {
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
-} {SCAN TABLE t1}
+} {SCAN t1}
# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
# the use of bound parameters by STAT4
@@ -137,27 +137,27 @@ unset -nocomplain l
unset -nocomplain u
do_eqp_test analyze3-1.1.3.100 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
set l 200
set u 300
do_eqp_test analyze3-1.1.3.101 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
set l 0
set u 1100
do_eqp_test analyze3-1.1.3.102 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SCAN TABLE t1}
+} {SCAN t1}
db cache flush
sqlite3_db_config db ENABLE_QPSG 1
do_eqp_test analyze3-1.1.3.103 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
db cache flush
sqlite3_db_config db ENABLE_QPSG 0
do_eqp_test analyze3-1.1.3.104 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SCAN TABLE t1}
+} {SCAN t1}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -207,10 +207,10 @@ do_execsql_test analyze3-2.1.x {
} {200 990}
do_eqp_test analyze3-1.2.2 {
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
-} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x)}
+} {SEARCH t2 USING INDEX i2 (x>? AND x)}
do_eqp_test analyze3-1.2.3 {
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
-} {SCAN TABLE t2}
+} {SCAN t2}
do_test analyze3-1.2.4 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
@@ -259,10 +259,10 @@ do_execsql_test analyze3-1.3.x {
} {99 1000}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
-} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x)}
+} {SEARCH t3 USING INDEX i3 (x>? AND x)}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
-} {SCAN TABLE t3}
+} {SCAN t3}
do_test analyze3-1.3.4 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
@@ -314,10 +314,10 @@ do_test analyze3-2.1 {
} {}
do_eqp_test analyze3-2.2 {
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
-} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b)}
+} {SEARCH t1 USING INDEX i1 (b>? AND b)}
do_eqp_test analyze3-2.3 {
SELECT count(a) FROM t1 WHERE b LIKE '%a'
-} {SCAN TABLE t1}
+} {SCAN t1}
# Return the first argument if like_match_blobs is true (the default)
# or the second argument if not
@@ -704,11 +704,11 @@ do_test analyze3-6.1 {
do_eqp_test analyze3-6-3 {
SELECT * FROM t1 WHERE a = 5 AND c = 13;
-} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
+} {SEARCH t1 USING INDEX i2 (c=?)}
do_eqp_test analyze3-6-2 {
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
-} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
+} {SEARCH t1 USING INDEX i2 (c=?)}
#-----------------------------------------------------------------------------
# 2015-04-20.
diff --git a/test/analyze4.test b/test/analyze4.test
index 9fc98aa8f2..e3b0d23f6f 100644
--- a/test/analyze4.test
+++ b/test/analyze4.test
@@ -38,7 +38,7 @@ do_test analyze4-1.0 {
# Should choose the t1a index since it is more specific than t1b.
db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
# Verify that the t1b index shows that it does not narrow down the
# search any at all.
diff --git a/test/analyze6.test b/test/analyze6.test
index b6353f2668..807fec132a 100644
--- a/test/analyze6.test
+++ b/test/analyze6.test
@@ -61,7 +61,7 @@ do_test analyze6-1.0 {
#
do_test analyze6-1.1 {
eqp {SELECT count(*) FROM ev, cat WHERE x=y}
-} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
+} {/*SCAN cat USING COVERING INDEX catx*SEARCH ev USING COVERING INDEX evy (y=?)*/}
# The same plan is chosen regardless of the order of the tables in the
# FROM clause.
@@ -70,8 +70,8 @@ do_eqp_test analyze6-1.2 {
SELECT count(*) FROM cat, ev WHERE x=y
} {
QUERY PLAN
- |--SCAN TABLE cat USING COVERING INDEX catx
- `--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
+ |--SCAN cat USING COVERING INDEX catx
+ `--SEARCH ev USING COVERING INDEX evy (y=?)
}
@@ -86,26 +86,26 @@ do_test analyze6-2.1 {
ANALYZE;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.2 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.3 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.4 {
execsql {
INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
ANALYZE t201;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.5 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.6 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.7 {
execsql {
INSERT INTO t201 VALUES(4,5,7);
@@ -115,12 +115,12 @@ do_test analyze6-2.7 {
ANALYZE t201;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.8 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.9 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
finish_test
diff --git a/test/analyze7.test b/test/analyze7.test
index b3dba02563..53a80f6419 100644
--- a/test/analyze7.test
+++ b/test/analyze7.test
@@ -37,13 +37,13 @@ do_test analyze7-1.0 {
WHERE value BETWEEN 1 AND 256;
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-1.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-1.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
# Run an analyze on one of the three indices. Verify that this
# effects the row-count estimate on the one query that uses that
@@ -53,20 +53,20 @@ do_test analyze7-2.0 {
execsql {ANALYZE t1a;}
db cache flush
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
# Verify that since the query planner now things that t1a is more
# selective than t1b, it prefers to use t1a.
#
do_test analyze7-2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
# Run an analysis on another of the three indices. Verify that this
# new analysis works and does not disrupt the previous analysis.
@@ -75,40 +75,40 @@ do_test analyze7-3.0 {
execsql {ANALYZE t1cd;}
db cache flush;
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-3.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
ifcapable stat4 {
# If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
# row count for (c=2) than it does for (c=?).
do_test analyze7-3.2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+ } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
} else {
# If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
# same as that for (c=?).
do_test analyze7-3.2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+ } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
}
do_test analyze7-3.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
ifcapable {!stat4} {
do_test analyze7-3.4 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
- } {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+ } {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.5 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
- } {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+ } {/*SEARCH t1 USING INDEX t1a (a=?)*/}
}
do_test analyze7-3.6 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=? AND d=?)*/}
finish_test
diff --git a/test/analyze8.test b/test/analyze8.test
index 7c61652e51..69605fd6f7 100644
--- a/test/analyze8.test
+++ b/test/analyze8.test
@@ -61,25 +61,25 @@ do_test 1.0 {
#
do_test 1.1 {
eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.2 {
eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.3 {
eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.4 {
eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.5 {
eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.6 {
eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 2.1 {
eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b)*/}
+} {/*SEARCH t1 USING INDEX t1b (b>? AND b)*/}
# There are many more values of c between 0 and 100000 than there are
# between 800000 and 900000. So t1c is more selective for the latter
@@ -99,17 +99,17 @@ do_execsql_test 3.0 {
} {50 376 32}
do_test 3.1 {
eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b)*/}
+} {/*SEARCH t1 USING INDEX t1b (b>? AND b)*/}
do_test 3.2 {
eqp {SELECT * FROM t1
WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
-} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c)*/}
+} {/*SEARCH t1 USING INDEX t1c (c>? AND c)*/}
do_test 3.3 {
eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 3.4 {
eqp {SELECT * FROM t1
WHERE a=100 AND c BETWEEN 800000 AND 900000}
-} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c)*/}
+} {/*SEARCH t1 USING INDEX t1c (c>? AND c)*/}
finish_test
diff --git a/test/analyze9.test b/test/analyze9.test
index 75a02653d1..a7f9b5deae 100644
--- a/test/analyze9.test
+++ b/test/analyze9.test
@@ -578,16 +578,16 @@ do_test 13.1 {
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<12
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
-} {/SEARCH TABLE t1 USING INDEX i2/}
+} {/SEARCH t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
-} {/SEARCH TABLE t1 USING INDEX i2/}
+} {/SEARCH t1 USING INDEX i2/}
#-------------------------------------------------------------------------
# Check also that affinities are taken into account when using stat4 data
@@ -609,10 +609,10 @@ do_test 14.1 {
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='ott' AND b<10 AND c=1
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
#-------------------------------------------------------------------------
# By default, 16 non-periodic samples are collected for the stat4 table.
@@ -1056,11 +1056,11 @@ do_eqp_test 23.1 {
-- Formerly used index i41. But i41 is not a covering index whereas
-- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
-- PRIMARY KEY is preferred.
-} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a)}
+} {SEARCH t4 USING PRIMARY KEY (c=? AND b=? AND a)}
do_eqp_test 23.2 {
SELECT * FROM t4 WHERE
(e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
-} {SEARCH TABLE t4 USING INDEX i42 (f)}
+} {SEARCH t4 USING INDEX i42 (f)}
do_execsql_test 24.0 {
CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
@@ -1106,25 +1106,25 @@ ifcapable stat4&&cte {
# Term (b) is estimated at 25%. Better than (a<30) but not as
# good as (a<20).
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b } \
- {SEARCH TABLE t6 USING INDEX bb (b)}
+ {SEARCH t6 USING INDEX bb (b)}
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b } \
- {SEARCH TABLE t6 USING INDEX aa (a)}
+ {SEARCH t6 USING INDEX aa (a)}
# Term (b BETWEEN ? AND ?) is estimated at 1/64.
do_eqp_test 25.3.1 {
SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ?
- } {SEARCH TABLE t6 USING INDEX bb (b>? AND b)}
+ } {SEARCH t6 USING INDEX bb (b>? AND b)}
# Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
# 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
# (a<20) but not as good as (a<10).
do_eqp_test 25.4.1 {
SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
- } {SEARCH TABLE t6 USING INDEX aa (a)}
+ } {SEARCH t6 USING INDEX aa (a)}
do_eqp_test 25.4.2 {
SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
- } {SEARCH TABLE t6 USING INDEX bb (b>? AND b)}
+ } {SEARCH t6 USING INDEX bb (b>? AND b)}
}
#-------------------------------------------------------------------------
@@ -1180,7 +1180,7 @@ do_execsql_test 26.1.3 {
#
do_eqp_test 26.1.4 {
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
-} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
+} {SEARCH t1 USING INDEX t1z (z=?)}
# This test - 26.2.* - tests that another manifestation of the same problem
@@ -1229,7 +1229,7 @@ do_execsql_test 26.2.1 {
do_eqp_test 26.2.2 {
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
-} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
+} {SEARCH t1 USING INDEX i1 (x=? AND y>?)}
finish_test
diff --git a/test/analyzeC.test b/test/analyzeC.test
index 2a0a897810..2f43d57a1e 100644
--- a/test/analyzeC.test
+++ b/test/analyzeC.test
@@ -50,7 +50,7 @@ do_execsql_test 1.2 {
do_execsql_test 1.3 {
EXPLAIN QUERY PLAN
SELECT c FROM t1 ORDER BY a;
-} {/.*SCAN TABLE t1 USING INDEX t1a.*/}
+} {/.*SCAN t1 USING INDEX t1a.*/}
do_execsql_test 1.3x {
EXPLAIN QUERY PLAN
SELECT c FROM t1 ORDER BY a;
diff --git a/test/analyzeD.test b/test/analyzeD.test
index 9c7ed7586d..7a51785a1c 100644
--- a/test/analyzeD.test
+++ b/test/analyzeD.test
@@ -63,7 +63,7 @@ do_test 1.1 {
#
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
do_test 1.3 {
execsql { DELETE FROM sqlite_stat1 }
@@ -78,7 +78,7 @@ do_test 1.3 {
#
do_eqp_test 1.4 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
+} {SEARCH t1 USING INDEX t1_ab (a=?)}
do_test 1.5 {
execsql {
@@ -89,7 +89,7 @@ do_test 1.5 {
do_eqp_test 1.6 {
SELECT * FROM t1 WHERE a=13 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
do_test 1.7 {
execsql { DELETE FROM sqlite_stat1 }
@@ -102,6 +102,6 @@ do_test 1.7 {
# gets this right, even without stat1 data.
do_eqp_test 1.8 {
SELECT * FROM t1 WHERE a=13 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
finish_test
diff --git a/test/analyzeE.test b/test/analyzeE.test
index 66db1e122c..733b79367f 100644
--- a/test/analyzeE.test
+++ b/test/analyzeE.test
@@ -36,47 +36,47 @@ do_execsql_test analyzeE-1.0 {
do_execsql_test analyzeE-1.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-1.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-1.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Verify that everything works the same on a DESCENDING index.
#
@@ -88,47 +88,47 @@ do_execsql_test analyzeE-2.0 {
do_execsql_test analyzeE-2.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-2.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Now do a range query on the second term of an ASCENDING index
# where the first term is constrained by equality.
@@ -145,47 +145,47 @@ do_execsql_test analyzeE-3.0 {
do_execsql_test analyzeE-3.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-3.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-3.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Repeat the 3.x tests using a DESCENDING index
#
@@ -197,46 +197,46 @@ do_execsql_test analyzeE-4.0 {
do_execsql_test analyzeE-4.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-4.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-4.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
finish_test
diff --git a/test/analyzeF.test b/test/analyzeF.test
index 143cecdf57..00107993eb 100644
--- a/test/analyzeF.test
+++ b/test/analyzeF.test
@@ -62,7 +62,7 @@ foreach {tn where idx} {
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
} {
- set res "SEARCH TABLE t1 USING INDEX $idx"
+ set res "SEARCH t1 USING INDEX $idx"
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
}
@@ -92,7 +92,7 @@ foreach {tn where idx} {
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
} {
- set res "SEARCH TABLE t1 USING INDEX $idx"
+ set res "SEARCH t1 USING INDEX $idx"
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
}
diff --git a/test/analyzeG.test b/test/analyzeG.test
index eb1853b1dc..ca65bc3b96 100644
--- a/test/analyzeG.test
+++ b/test/analyzeG.test
@@ -20,16 +20,6 @@ ifcapable !stat4 {
}
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
@@ -54,15 +44,17 @@ do_execsql_test 1.0 {
# 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 {
+do_eqp_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 {
+do_eqp_test 1.1.2 {
SELECT * FROM t2, t1 WHERE a=44 AND b=44
} {
- {SCAN TABLE t2} {SCAN TABLE t1}
+ QUERY PLAN
+ |--SCAN t2
+ `--SCAN t1
}
do_execsql_test 1.2 {
@@ -73,15 +65,19 @@ do_execsql_test 1.2 {
# 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 {
+do_eqp_test 1.3.1 {
SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
- {SCAN TABLE t1} {SCAN TABLE t2}
+ QUERY PLAN
+ |--SCAN t1
+ `--SCAN t2
}
-do_scan_order_test 1.3.2 {
+do_eqp_test 1.3.2 {
SELECT * FROM t2, t1 WHERE a=44 AND b=44
} {
- {SCAN TABLE t1} {SCAN TABLE t2}
+ QUERY PLAN
+ |--SCAN t1
+ `--SCAN t2
}
diff --git a/test/attach4.test b/test/attach4.test
index 87911814a0..9d54e7df57 100644
--- a/test/attach4.test
+++ b/test/attach4.test
@@ -135,4 +135,3 @@ do_execsql_test 2.2 {
}
finish_test
-
diff --git a/test/autoindex1.test b/test/autoindex1.test
index b08f8cfeb6..6b437f1867 100644
--- a/test/autoindex1.test
+++ b/test/autoindex1.test
@@ -183,18 +183,18 @@ do_eqp_test autoindex1-500.1 {
WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
} {
QUERY PLAN
- |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
`--LIST SUBQUERY xxxxxx
- `--SCAN TABLE t502
+ `--SCAN t502
}
do_eqp_test autoindex1-501 {
SELECT b FROM t501
WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
QUERY PLAN
- |--SCAN TABLE t501
+ |--SCAN t501
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
+ `--SEARCH t502 USING AUTOMATIC COVERING INDEX (y=?)
}
do_eqp_test autoindex1-502 {
SELECT b FROM t501
@@ -202,9 +202,9 @@ do_eqp_test autoindex1-502 {
AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
QUERY PLAN
- |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SCAN TABLE t502
+ `--SCAN t502
}
# The following code checks a performance regression reported on the
@@ -277,13 +277,13 @@ do_eqp_test autoindex1-600a {
ORDER BY x.registering_flock;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE sheep AS s
- | |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date)
+ |--MATERIALIZE y
+ | |--SCAN s
+ | |--SEARCH prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date)
| `--CORRELATED SCALAR SUBQUERY xxxxxx
- | `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date)
- |--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
- `--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
+ | `--SEARCH later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date)
+ |--SCAN x USING INDEX sheep_reg_flock_index
+ `--SEARCH y USING AUTOMATIC COVERING INDEX (sheep_no=?)
}
@@ -294,7 +294,7 @@ do_eqp_test autoindex1-700a {
SELECT a FROM t5 WHERE b=10 ORDER BY c;
} {
QUERY PLAN
- |--SCAN TABLE t5
+ |--SCAN t5
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -413,7 +413,7 @@ do_execsql_test autoindex1-800 {
JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id)
JOIN accounts ON (raw_contacts.account_id=accounts._id)
WHERE mimetype_id=10 AND data14 IS NOT NULL;
-} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
+} {/SEARCH data .*SEARCH raw_contacts/}
do_execsql_test autoindex1-801 {
EXPLAIN QUERY PLAN
SELECT * FROM
@@ -421,7 +421,7 @@ do_execsql_test autoindex1-801 {
JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id)
JOIN accounts ON (raw_contacts.account_id=accounts._id)
WHERE mimetypes._id=10 AND data14 IS NOT NULL;
-} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
+} {/SEARCH data .*SEARCH raw_contacts/}
# Another test case from an important user of SQLite. The key feature of
# this test is that the "aggindex" subquery should make use of an
diff --git a/test/autoindex3.test b/test/autoindex3.test
index 9dcf2491ff..824a82973b 100644
--- a/test/autoindex3.test
+++ b/test/autoindex3.test
@@ -74,8 +74,8 @@ do_execsql_test 210 {
# At one point, SQLite was using the inferior plan:
#
-# 0|0|1|SEARCH TABLE v USING INDEX ve (e>?)
-# 0|1|0|SEARCH TABLE u USING COVERING INDEX uab (ANY(a) AND b=?)
+# 0|0|1|SEARCH v USING INDEX ve (e>?)
+# 0|1|0|SEARCH u USING COVERING INDEX uab (ANY(a) AND b=?)
#
# on the basis that the real index "uab" must be better than the automatic
# index. This is not right - a skip-scan is not necessarily better than an
@@ -85,8 +85,8 @@ do_eqp_test 220 {
select count(*) from u, v where u.b = v.b and v.e > 34;
} {
QUERY PLAN
- |--SEARCH TABLE v USING INDEX ve (e>?)
- `--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
+ |--SEARCH v USING INDEX ve (e>?)
+ `--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
}
diff --git a/test/autoindex5.test b/test/autoindex5.test
index 94e220328c..36695d7f74 100644
--- a/test/autoindex5.test
+++ b/test/autoindex5.test
@@ -102,7 +102,7 @@ do_eqp_test autoindex5-1.1 {
AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
-} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
+} {SEARCH debian_cve USING AUTOMATIC COVERING INDEX (bug_name=?)}
#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
@@ -123,7 +123,7 @@ do_execsql_test 2.1 {
SELECT sum(z) FROM vvv WHERE x='aaa'
) FROM one;
} {8.0}
-do_execsql_test 2.2 {
+do_catchsql_test 2.2 {
DROP TABLE t1;
CREATE TABLE t1(aaa);
INSERT INTO t1(aaa) VALUES(9);
@@ -136,7 +136,7 @@ do_execsql_test 2.2 {
) WHERE bbb = 1
)
);
-} {9}
+} {1 {no such column: rowid}}
# Ticket https://www.sqlite.org/src/info/787fa716be3a7f65
# Segfault due to multiple uses of the same subquery where the
diff --git a/test/bestindex1.test b/test/bestindex1.test
index b97af11140..0d69469943 100644
--- a/test/bestindex1.test
+++ b/test/bestindex1.test
@@ -51,11 +51,11 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM x1 WHERE a = 'abc'
-} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
+} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}
do_eqp_test 1.2 {
SELECT * FROM x1 WHERE a IN ('abc', 'def');
-} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
+} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}
#-------------------------------------------------------------------------
#
@@ -141,17 +141,17 @@ foreach {tn mode} {
set plan(use) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
`--USE TEMP B-TREE FOR ORDER BY
}
set plan(omit) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
`--USE TEMP B-TREE FOR ORDER BY
}
set plan(use2) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/bestindex2.test b/test/bestindex2.test
index c17665f6f5..81ed9ebf61 100644
--- a/test/bestindex2.test
+++ b/test/bestindex2.test
@@ -89,40 +89,40 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a='abc'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a='abc' AND b='def'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a='abc' AND a='def'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
do_eqp_test 1.4 {
SELECT * FROM t1,t2 WHERE c=a
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- `--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ `--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
}
do_eqp_test 1.5 {
SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
do_eqp_test 1.6 {
SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
do_execsql_test 1.7.1 {
@@ -133,10 +133,10 @@ do_eqp_test 1.7.2 {
WHERE t1.a = t2.c AND t1.b = t3.e
} {
QUERY PLAN
- |--SCAN TABLE x1
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN x1
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
finish_test
diff --git a/test/bestindex3.test b/test/bestindex3.test
index 80038e2855..1ee3975f8b 100644
--- a/test/bestindex3.test
+++ b/test/bestindex3.test
@@ -79,11 +79,11 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a LIKE 'abc';
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a = 'abc';
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
@@ -91,9 +91,9 @@ do_eqp_test 1.3 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
+ | `--SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?
`--INDEX 2
- `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
+ `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}
do_eqp_test 1.4 {
@@ -102,9 +102,9 @@ do_eqp_test 1.4 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
+ | `--SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?
`--INDEX 2
- `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
+ `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}
do_execsql_test 1.5 {
@@ -155,9 +155,9 @@ ifcapable !icu {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX t2x (x>? AND x)
+ | `--SEARCH t2 USING INDEX t2x (x>? AND x)
`--INDEX 2
- `--SEARCH TABLE t2 USING INDEX t2y (y=?)
+ `--SEARCH t2 USING INDEX t2y (y=?)
}]
}
diff --git a/test/bestindex4.test b/test/bestindex4.test
index e395012c4f..f90bf41e94 100644
--- a/test/bestindex4.test
+++ b/test/bestindex4.test
@@ -159,16 +159,16 @@ do_eqp_test 2.1 {
SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
QUERY PLAN
- |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
+ |--SCAN x1 VIRTUAL TABLE INDEX 0:
+ `--SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
}
do_eqp_test 2.2 {
SELECT * FROM t1, x1(t1.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555:
+ |--SCAN t1
+ `--SCAN x1 VIRTUAL TABLE INDEX 555:
}
diff --git a/test/bestindex7.test b/test/bestindex7.test
index aa1d70b86c..f8d42b2b00 100644
--- a/test/bestindex7.test
+++ b/test/bestindex7.test
@@ -76,4 +76,3 @@ 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
-
diff --git a/test/between.test b/test/between.test
index e2b25ca3ce..16c3913d12 100644
--- a/test/between.test
+++ b/test/between.test
@@ -58,10 +58,10 @@ proc queryplan {sql} {
set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
# puts eqp=$eqp
foreach {a b c x} $eqp {
- if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
- $x all as tab idx]} {
+ if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data $tab $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
lappend data $tab *
}
}
diff --git a/test/bigmmap.test b/test/bigmmap.test
index 62e035b05f..7802fd58ec 100644
--- a/test/bigmmap.test
+++ b/test/bigmmap.test
@@ -94,9 +94,9 @@ for {set i 0} {$i < 9} {incr i} {
ORDER BY b, c;
" [string map {"\n " "\n"} "
QUERY PLAN
- |--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
+ |--SCAN o USING COVERING INDEX sqlite_autoindex_t${t}_1
`--CORRELATED SCALAR SUBQUERY xxxxxx
- `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH i USING INTEGER PRIMARY KEY (rowid=?)
"]
}
}
diff --git a/test/busy2.test b/test/busy2.test
index db8ca0e389..61fb8496a8 100644
--- a/test/busy2.test
+++ b/test/busy2.test
@@ -168,4 +168,3 @@ do_multiclient_test tn {
}
finish_test
-
diff --git a/test/columncount.test b/test/columncount.test
index 3ecc1f8d8a..669a35a72f 100644
--- a/test/columncount.test
+++ b/test/columncount.test
@@ -54,4 +54,3 @@ do_ccsql_test 1.6 { DROP TABLE t3 } {0}
finish_test
-
diff --git a/test/corrupt4.test b/test/corrupt4.test
index 55969c6a8c..5b0965a836 100644
--- a/test/corrupt4.test
+++ b/test/corrupt4.test
@@ -13,10 +13,10 @@
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
-# $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix corrupt4
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
@@ -79,4 +79,71 @@ do_test corrupt4-1.4 {
}
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+
+reset_db
+do_execsql_test 2.0 {
+ PRAGMA page_size = 512;
+ CREATE TABLE t1(a, b, c);
+}
+
+# Create a database with a schema so large that the root of the
+# sqlite_schema table is the grandparent of its leaves.
+#
+set nView 1000
+do_test 2.1 {
+ execsql BEGIN
+ for {set ii 0} {$ii<$nView} {incr ii} {
+ execsql " CREATE VIEW v$ii AS SELECT a, b, c FROM t1 "
+ }
+ execsql COMMIT
+} {}
+db close
+
+proc get2byte {fd offset} {
+ seek $fd $offset
+ set bin [read $fd 2]
+ binary scan $bin S val
+ set val
+}
+proc get4byte {fd offset} {
+ seek $fd $offset
+ set bin [read $fd 4]
+ binary scan $bin I val
+ set val
+}
+proc put4byte {fd offset val} {
+ seek $fd $offset
+ set bin [binary format I $val]
+ puts -nonewline $fd $bin
+}
+
+# Page 1 is now the grandparent of its leaves. Corrupt the database by setting
+# the second rightmost child page number of page 1 to 1.
+#
+set fd [open test.db r+]
+fconfigure $fd -encoding binary -translation binary
+set nChild [get2byte $fd 103]
+set offChild [get2byte $fd [expr 100+12+($nChild-2)*2]]
+set pgnoChild [get4byte $fd $offChild]
+put4byte $fd $offChild 1
+close $fd
+
+if {![info exists ::G(perm:presql)]} {
+ sqlite3 db test.db
+
+ do_catchsql_test 2.2 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM sqlite_schema;
+ } {1 {database disk image is malformed}}
+
+ do_test 2.3 {
+ list [catch {
+ for {set ii $nView} {$ii<$nView*2} {incr ii} {
+ execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
+ }
+ } msg] $msg
+ } {1 {database disk image is malformed}}
+}
+
finish_test
diff --git a/test/corruptL.test b/test/corruptL.test
index 9af9fd2cfd..5ade7010d7 100644
--- a/test/corruptL.test
+++ b/test/corruptL.test
@@ -1337,5 +1337,93 @@ if {[wal_is_capable]} {
} {}
}
+#-------------------------------------------------------------------------
+reset_db
+do_test 18.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 12288 pagesize 4096 filename crash-40d5739835cbdb.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
+| 96: 00 00 00 00 0d 00 00 00 02 0f 4e 00 0f a2 0f 4e ..........N....N
+| 3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 52 02 ..............R.
+| 3920: 07 17 11 11 01 81 0f 74 61 62 6c 65 74 32 74 32 .......tablet2t2
+| 3936: 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 .CREATE TABLE t2
+| 3952: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 45 47 45 (a INT, b INTEGE
+| 3968: 52 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 61 R, PRIMARY KEY(a
+| 3984: 2c 62 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 ,b)) WITHOUT ROW
+| 4000: 49 44 5c 01 07 16 11 11 01 81 23 74 61 62 6c 65 ID........#table
+| 4016: 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c t1t1.CREATE TABL
+| 4032: 45 20 74 31 28 61 20 49 4e 54 20 50 52 49 4d 41 E t1(a INT PRIMA
+| 4048: 52 59 20 4b 45 59 2c 20 62 20 54 45 58 54 2c 20 RY KEY, b TEXT,
+| 4064: 63 20 54 45 58 54 2c 20 64 20 49 4e 54 45 47 45 c TEXT, d INTEGE
+| 4080: 52 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 R) WITHOUT ROWID
+| page 2 offset 4096
+| 0: 0a 00 00 00 06 0f a7 00 0f f4 0f e5 0f d5 0f c5 ................
+| 16: 0f b6 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4000: 00 00 00 00 00 00 00 0f 05 01 15 13 01 06 65 7f ..............e.
+| 4016: 25 6e 73 69 78 06 0e 05 01 13 15 03 b5 6f 64 64 %nsix........odd
+| 4032: 66 69 76 65 05 0f 05 01 15 15 01 04 65 76 65 61 five........evea
+| 4048: e6 6f 75 82 04 0f 05 01 13 17 01 03 6f 64 64 74 .ou.........oddt
+| 4064: 68 72 61 15 03 0e 05 01 15 12 01 02 64 76 64 6e hra.........dvdn
+| 4080: 74 77 6f 02 00 00 00 00 00 00 00 00 00 00 00 00 two.............
+| page 3 offset 8192
+| 2816: 00 00 00 00 00 00 00 00 00 00 00 06 03 02 01 00 ................
+| 2832: c8 07 06 03 02 01 00 c7 11 06 03 02 01 02 a6 52 ...............R
+| 2848: 06 d5 02 01 10 c5 1b 06 03 02 00 ef c4 53 06 03 .............S..
+| 2864: 02 01 00 c3 22 06 04 02 01 00 c2 26 06 03 02 01 ...........&....
+| 2880: 00 c2 1e 02 b3 02 01 00 c0 3a 06 03 3c 01 00 bf .........:..<...
+| 2896: 2c 06 03 02 01 00 be 27 00 83 02 01 01 bd 15 06 ,......'........
+| 2912: 03 02 01 00 bc 21 06 03 02 01 00 bb 54 16 13 02 .....!......T...
+| 2928: 01 09 9a 0a 06 03 02 01 00 b9 53 06 03 02 01 00 ..........S.....
+| 2944: b8 52 06 13 02 01 00 b7 1e 06 03 02 01 00 b6 34 .R.............4
+| 2960: 06 13 02 01 00 b5 3a 05 f3 12 01 00 b4 45 05 03 ......:......E..
+| 2976: 02 00 00 b4 6f 06 03 02 01 00 b2 03 06 03 02 01 ....o...........
+| 2992: 00 b1 63 06 03 02 01 00 b0 24 06 03 02 01 00 9f ..c......$......
+| 3008: ac 06 03 02 01 00 a2 2f 07 03 02 01 01 ad 21 06 ......./......!.
+| 3024: 03 02 01 fb cd 5b 06 c0 01 f1 00 ab 23 06 03 02 .....[......#...
+| 3040: 01 00 aa 5b 06 03 02 01 00 a3 ce 06 02 03 01 00 ...[............
+| 3056: a8 0e 06 03 02 01 00 a7 0c 06 02 f1 01 00 a6 0d ................
+| 3072: 06 03 02 01 00 95 25 06 03 02 01 00 a4 17 06 03 ......%.........
+| 3088: 02 01 00 a3 09 06 03 02 01 00 a2 51 06 03 02 02 ...........Q....
+| 3104: 00 a1 40 06 01 e2 00 00 a0 4b 06 13 02 00 00 9e ..@......K......
+| 3120: 5d 06 03 02 01 10 9e 81 06 03 02 01 00 9d 42 06 ].............B.
+| 3136: 03 69 01 00 9c 48 06 03 02 01 00 9b 48 06 03 01 .i...H......H...
+| 3152: 01 00 9a 09 06 03 02 01 00 99 2f 06 03 02 01 00 ........../.....
+| 3168: 98 3a 06 03 02 01 00 97 24 06 03 02 01 00 96 4a .:......$......J
+| 3184: 06 03 02 11 00 f9 50 02 93 02 01 00 94 2f 06 03 ......P....../..
+| 3200: 02 11 04 93 1a 06 03 01 04 e0 92 1a 06 03 02 01 ................
+| 3216: 00 91 27 06 03 02 01 00 90 23 06 03 02 01 00 8f ..'......#......
+| 3232: 3b 06 03 02 01 00 8e 46 06 16 02 01 00 8d 1d 07 ;......F........
+| 3248: 23 12 01 00 8c 5a 06 03 02 01 00 8a 39 06 03 02 #....Z......9...
+| 3264: 00 ff 84 b5 06 03 02 01 00 89 07 06 03 02 11 00 ................
+| 3280: 88 02 06 03 02 01 00 87 19 06 03 02 01 00 86 4d ...............M
+| 3296: 06 13 12 00 00 85 4b 06 03 02 01 00 84 37 06 13 ......K......7..
+| 3312: 02 01 00 83 2c 06 03 02 01 00 81 60 06 13 02 11 ....,......`....
+| 3328: 00 81 3b 06 03 02 01 0a b0 5a 06 03 01 01 7f 22 ..;......Z......
+| 3344: 05 03 01 01 7e 21 05 03 01 01 7d 0b 15 03 01 02 ....~!..........
+| 3360: 7b 08 05 03 06 91 7b 22 05 03 01 01 7a 58 05 03 ............zX..
+| 3376: 01 01 7a 4f 05 03 01 01 78 49 05 03 01 01 77 16 ..zO....xI....w.
+| 3392: 05 03 01 01 76 5f 05 03 01 01 75 0f 05 03 01 01 ....v_....u.....
+| 3408: 74 2f 05 03 01 01 3f 1f 05 03 01 02 72 14 05 03 t/....?.....r...
+| 3424: 00 f1 71 08 05 03 01 01 70 0c 05 03 01 47 7f 29 ..q.....p....G.)
+| 3440: 05 03 01 01 6e 57 05 03 01 01 6d 33 05 13 00 f1 ....nW....m3....
+| 3456: 6c 0b 05 03 01 01 6b 49 05 03 01 01 69 05 05 03 l.....kI....i...
+| 3472: 01 02 ed 23 00 00 01 00 00 00 00 00 00 00 00 00 ...#............
+| end crash-40d5739835cbdb.db
+}]} {}
+
+ifcapable json1 {
+do_catchsql_test 18.1 {
+ SELECT
+ json_group_array(c) OVER win4
+ FROM t1
+ WINDOW win4 AS (
+ ORDER BY a COLLATE nocase RANGE BETWEEN 1.0 PRECEDING AND CURRENT ROW
+ )
+} {1 {JSON cannot hold BLOB values}}
+} ;# ifcapable json1
finish_test
diff --git a/test/corruptN.test b/test/corruptN.test
index 4f7667ce1e..e6997b24f7 100644
--- a/test/corruptN.test
+++ b/test/corruptN.test
@@ -102,5 +102,121 @@ do_catchsql_test 1.1 {
VACUUM;
} {1 {database disk image is malformed}}
+# 2021-04-05 dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618
+do_test 2.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 16384 pagesize 4096 filename c-b92b.txt.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 96: 00 00 00 00 0d 0f f8 00 04 0f 12 00 0f 91 0f d3 ................
+| 112: 0f 67 0f 12 00 00 00 00 00 00 00 00 00 00 00 00 .g..............
+| 3856: 00 00 53 04 07 1b 13 11 08 81 0d 74 72 69 67 67 ..S........trigg
+| 3872: 65 72 74 72 30 74 31 43 52 45 41 54 45 20 54 52 ertr0t1CREATE TR
+| 3888: 49 47 47 45 52 20 74 72 30 20 44 45 4c 45 54 45 IGGER tr0 DELETE
+| 3904: 20 4f 4e 20 74 31 20 42 45 47 49 4e 0a 20 20 55 ON t1 BEGIN. U
+| 3920: 50 44 41 54 45 20 74 31 20 53 45 54 20 62 20 3d PDATE t1 SET b =
+| 3936: 20 61 3b 0a 45 4e 44 28 03 06 17 11 11 01 3d 69 a;.END(......=i
+| 3952: 6e 64 65 78 69 30 74 31 04 43 52 45 41 54 45 20 ndexi0t1.CREATE
+| 3968: 49 4e 44 45 58 20 69 30 20 4f 4e 20 74 31 28 62 INDEX i0 ON t1(b
+| 3984: 29 40 01 06 17 11 11 01 6d 74 61 62 6c 65 74 31 )@......mtablet1
+| 4000: 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 t1.CREATE TABLE
+| 4016: 74 31 28 61 20 55 4e 49 51 55 45 20 4f 4e 20 43 t1(a UNIQUE ON C
+| 4032: 4f 4e 46 4c 49 43 54 20 52 45 50 4c 41 43 45 2c ONFLICT REPLACE,
+| 4048: 20 62 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b)#...7...index
+| 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex
+| 4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00 _t1_1t1.........
+| page 2 offset 4096
+| 0: 0d 00 00 00 02 0f 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 05 02 03 01 01 09 0d 05 01 03 01 01 04 0c ................
+| page 3 offset 8192
+| 0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00 ................
+| 4080: 00 00 00 00 00 05 03 01 01 09 02 04 03 01 09 04 ................
+| page 4 offset 12288
+| 0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00 ................
+| 4080: 00 00 00 00 00 05 03 01 01 0d 02 04 03 00 00 00 ................
+| end c-b92b.txt.db
+}]} {}
+
+prng_seed 0 db
+do_catchsql_test 2.1 {
+SELECT count(*) FROM sqlite_schema;
+WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
+INSERT INTO t1(a) SELECT randomblob(null) FROM c;
+} {0 4}
+
+reset_db
+if {![info exists ::G(perm:presql)]} {
+ do_execsql_test 3.0 {
+ CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = 'CREATE TABLE sqlite_sequence(name-seq)'
+ WHERE name = 'sqlite_sequence';
+ }
+ db close
+ sqlite3 db test.db
+ do_catchsql_test 3.1 {
+ PRAGMA writable_schema = 1;
+ INSERT INTO t1(y) VALUES('abc');
+ } {1 {database disk image is malformed}}
+ reset_db
+
+ do_execsql_test 4.1 {
+ CREATE TABLE x1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE);
+ INSERT INTO x1 VALUES(1, 1, 2);
+ INSERT INTO x1 VALUES(2, 2, 3);
+ INSERT INTO x1 VALUES(3, 3, 4);
+ INSERT INTO x1 VALUES(4, 5, 6);
+ PRAGMA writable_schema = 1;
+
+ UPDATE sqlite_schema SET rootpage = (
+ SELECT rootpage FROM sqlite_schema WHERE name = 'sqlite_autoindex_x1_2'
+ ) WHERE name = 'sqlite_autoindex_x1_1';
+ }
+
+ db close
+ sqlite3 db test.db
+ breakpoint
+ do_catchsql_test 4.2 {
+ PRAGMA writable_schema = 1;
+ REPLACE INTO x1 VALUES(5, 2, 3);
+ } {1 {database disk image is malformed}}
+
+}
+
+#-------------------------------------------------------------------------
+
+reset_db
+
+ifcapable json1&&vtab {
+ db func strreplace strreplace
+ proc strreplace {orig a b} {
+ string map [list $a $b] $orig
+ }
+
+ do_execsql_test 5.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = strreplace(sql, 't1', 'json_each')
+ WHERE type='index';
+ }
+
+ db close
+ sqlite3 db test.db
+
+ do_execsql_test 5.1 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM t1
+ }
+}; # ifcapable json1&&vtab
+
finish_test
diff --git a/test/cost.test b/test/cost.test
index 592973ab56..5684177a13 100644
--- a/test/cost.test
+++ b/test/cost.test
@@ -25,8 +25,8 @@ do_eqp_test 1.2 {
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
} {
QUERY PLAN
- |--SCAN TABLE t3 USING COVERING INDEX i3
- `--SEARCH TABLE t4 USING INDEX i4 (c=?)
+ |--SCAN t3 USING COVERING INDEX i3
+ `--SEARCH t4 USING INDEX i4 (c=?)
}
@@ -39,7 +39,7 @@ do_execsql_test 2.1 {
# if the index is a non-covering index.
do_eqp_test 2.2 {
SELECT * FROM t1 ORDER BY a;
-} {SCAN TABLE t1 USING INDEX i1}
+} {SCAN t1 USING INDEX i1}
do_execsql_test 3.1 {
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
@@ -59,11 +59,11 @@ do_eqp_test 3.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t5 USING INDEX t5b (b=?)
+ | | `--SEARCH t5 USING INDEX t5b (b=?)
| |--INDEX 2
- | | `--SEARCH TABLE t5 USING INDEX t5c (c=?)
+ | | `--SEARCH t5 USING INDEX t5c (c=?)
| `--INDEX 3
- | `--SEARCH TABLE t5 USING INDEX t5d (d=?)
+ | `--SEARCH t5 USING INDEX t5d (d=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -83,11 +83,11 @@ do_execsql_test 4.1 {
}
do_eqp_test 4.2 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test 4.3 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
-} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b)}
+} {SEARCH t1 USING INDEX i2 (b>? AND b)}
#-------------------------------------------------------------------------
@@ -102,7 +102,7 @@ do_eqp_test 5.2 {
SELECT * FROM t2 ORDER BY x, y;
} {
QUERY PLAN
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
@@ -110,7 +110,7 @@ do_eqp_test 5.3 {
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
} {
QUERY PLAN
- |--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x)
+ |--SEARCH t2 USING INDEX t2i1 (x>? AND x)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -128,9 +128,9 @@ do_eqp_test 6.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b)
+ | | `--SEARCH t3 USING INDEX t3i1 (b>? AND b)
| `--INDEX 2
- | `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
+ | `--SEARCH t3 USING INDEX t3i2 (c=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -155,9 +155,9 @@ do_eqp_test 7.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t1 USING INDEX t1b (b>? AND b)
+ | | `--SEARCH t1 USING INDEX t1b (b>? AND b)
| `--INDEX 2
- | `--SEARCH TABLE t1 USING INDEX t1b (b=?)
+ | `--SEARCH t1 USING INDEX t1b (b=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -166,11 +166,11 @@ do_eqp_test 7.3 {
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test 7.4 {
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
-} {SCAN TABLE t1}
+} {SCAN t1}
#-------------------------------------------------------------------------
#
@@ -202,9 +202,9 @@ do_eqp_test 8.2 {
AND unlikely(album.aid=track.aid);
} {
QUERY PLAN
- |--SCAN TABLE track
- |--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
- |--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN track
+ |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR DISTINCT
}
@@ -271,19 +271,19 @@ ifcapable stat4 {
do_eqp_test 10.3 {
SELECT rowid FROM t6 WHERE a=0 AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
+ } {SEARCH t6 USING INDEX t6i2 (c=?)}
do_eqp_test 10.4 {
SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
+ } {SEARCH t6 USING INDEX t6i2 (c=?)}
do_eqp_test 10.5 {
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
+ } {SEARCH t6 USING INDEX t6i1 (a=?)}
do_eqp_test 10.6 {
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
+ } {SEARCH t6 USING INDEX t6i1 (a=? AND b=?)}
}
finish_test
diff --git a/test/count.test b/test/count.test
index 250eb669b0..9769b765f4 100644
--- a/test/count.test
+++ b/test/count.test
@@ -212,25 +212,25 @@ do_eqp_test count-7.2 {
SELECT count(1) FROM t1;
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX t1b
+ `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.3 {
SELECT count(1) FROM t1 NOT INDEXED
} {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
do_eqp_test count-7.3 {
SELECT count(*) FROM t1;
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX t1b
+ `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.4 {
SELECT count(*) FROM t1 NOT INDEXED
} {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
diff --git a/test/coveridxscan.test b/test/coveridxscan.test
index cc98644390..c87227cabc 100644
--- a/test/coveridxscan.test
+++ b/test/coveridxscan.test
@@ -109,11 +109,11 @@ do_execsql_test 5.1.0 "
do_eqp_test 5.1.1 {
SELECT * FROM t1 ORDER BY c1, c2;
-} {SCAN TABLE t1 USING COVERING INDEX i1}
+} {SCAN t1 USING COVERING INDEX i1}
do_eqp_test 5.1.2 {
SELECT * FROM t2 ORDER BY c1, c2;
-} {SCAN TABLE t2 USING COVERING INDEX i2}
+} {SCAN t2 USING COVERING INDEX i2}
finish_test
diff --git a/test/dbfuzz2.c b/test/dbfuzz2.c
index 6b30490dde..f0062915df 100644
--- a/test/dbfuzz2.c
+++ b/test/dbfuzz2.c
@@ -31,8 +31,7 @@
**
** mkdir dir
** cp dbfuzz2-seed*.db dir
-** clang-6.0 -I. -g -O1 -fsanitize=fuzzer \
-** -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \
+** clang-6.0 -I. -g -O1 -fsanitize=fuzzer -DTHREADSAFE=0 \
** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
** ./a.out dir
*/
diff --git a/test/distinct.test b/test/distinct.test
index f6f3c6cdce..a3cb1afc8a 100644
--- a/test/distinct.test
+++ b/test/distinct.test
@@ -30,12 +30,11 @@ proc is_distinct_noop {sql} {
set program1 [list]
set program2 [list]
db eval "EXPLAIN $sql1" {
- if {$opcode != "Noop"} { lappend program1 $opcode }
+ if {$opcode != "Noop" && $opcode != "Explain"} { lappend program1 $opcode }
}
db eval "EXPLAIN $sql2" {
- if {$opcode != "Noop"} { lappend program2 $opcode }
+ if {$opcode != "Noop" && $opcode != "Explain"} { lappend program2 $opcode }
}
-
return [expr {$program1==$program2}]
}
@@ -128,7 +127,6 @@ foreach {tn noop sql} {
21 0 "SELECT DISTINCT c2 FROM t3"
22 0 "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
- 23 1 "SELECT DISTINCT rowid FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
24 0 "SELECT DISTINCT rowid/2 FROM t1"
25 1 "SELECT DISTINCT rowid/2, rowid FROM t1"
@@ -294,4 +292,13 @@ do_execsql_test 7.1 {
WHERE (t1.a=t3.a) AND (SELECT count(*) FROM t2 AS y WHERE t4.x!='abc')=t1.a
} {2 2 2}
+# 2021-04-06 forum post https://sqlite.org/forum/forumpost/66954e9ece
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE person ( pid INT) ;
+ CREATE UNIQUE INDEX idx ON person ( pid ) WHERE pid == 1;
+ INSERT INTO person VALUES (1), (10), (10);
+ SELECT DISTINCT pid FROM person where pid = 10;
+} {10}
+
finish_test
diff --git a/test/distinctagg.test b/test/distinctagg.test
index 9b5dc21678..a34312ef98 100644
--- a/test/distinctagg.test
+++ b/test/distinctagg.test
@@ -16,6 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix distinctagg
do_test distinctagg-1.1 {
execsql {
@@ -31,7 +32,7 @@ do_test distinctagg-1.1 {
} {1 2 3 3}
do_test distinctagg-1.2 {
execsql {
- SELECT b, count(distinct c) FROM t1 GROUP BY b ORDER BY b
+ SELECT b, count(distinct c) FROM t1 GROUP BY b
}
} {2 1 3 2}
do_test distinctagg-1.3 {
@@ -59,4 +60,158 @@ do_test distinctagg-2.2 {
}
} {1 {DISTINCT aggregates must have exactly one argument}}
+#--------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a, b, c);
+ CREATE TABLE t2(d, e, f);
+
+ INSERT INTO t1 VALUES (1, 1, 1);
+ INSERT INTO t1 VALUES (2, 2, 2);
+ INSERT INTO t1 VALUES (3, 3, 3);
+ INSERT INTO t1 VALUES (4, 1, 4);
+ INSERT INTO t1 VALUES (5, 2, 1);
+ INSERT INTO t1 VALUES (5, 3, 2);
+ INSERT INTO t1 VALUES (4, 1, 3);
+ INSERT INTO t1 VALUES (3, 2, 4);
+ INSERT INTO t1 VALUES (2, 3, 1);
+ INSERT INTO t1 VALUES (1, 1, 2);
+
+ INSERT INTO t2 VALUES('a', 'a', 'a');
+ INSERT INTO t2 VALUES('b', 'b', 'b');
+ INSERT INTO t2 VALUES('c', 'c', 'c');
+
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1bc ON t1(b, c);
+}
+
+foreach {tn use_eph sql res} {
+ 1 0 "SELECT count(DISTINCT a) FROM t1" 5
+ 2 0 "SELECT count(DISTINCT b) FROM t1" 3
+ 3 1 "SELECT count(DISTINCT c) FROM t1" 4
+ 4 0 "SELECT count(DISTINCT c) FROM t1 WHERE b=3" 3
+ 5 0 "SELECT count(DISTINCT rowid) FROM t1" 10
+ 6 0 "SELECT count(DISTINCT a) FROM t1, t2" 5
+ 7 0 "SELECT count(DISTINCT a) FROM t2, t1" 5
+ 8 1 "SELECT count(DISTINCT a+b) FROM t1, t2, t2, t2" 6
+ 9 0 "SELECT count(DISTINCT c) FROM t1 WHERE c=2" 1
+ 10 1 "SELECT count(DISTINCT t1.rowid) FROM t1, t2" 10
+} {
+ do_test 3.$tn.1 {
+ set prg [db eval "EXPLAIN $sql"]
+ set idx [lsearch $prg OpenEphemeral]
+ expr {$idx>=0}
+ } $use_eph
+
+ do_execsql_test 3.$tn.2 $sql $res
+}
+
+do_execsql_test 3.10 {
+ SELECT a, count(DISTINCT b) FROM t1 GROUP BY a;
+} {
+ 1 1 2 2 3 2 4 1 5 2
+}
+
+#--------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a, b, c);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1bc ON t1(b, c);
+
+ INSERT INTO t1 VALUES(1, 'A', 1);
+ INSERT INTO t1 VALUES(1, 'A', 1);
+ INSERT INTO t1 VALUES(2, 'A', 2);
+ INSERT INTO t1 VALUES(2, 'A', 2);
+ INSERT INTO t1 VALUES(1, 'B', 1);
+ INSERT INTO t1 VALUES(2, 'B', 2);
+ INSERT INTO t1 VALUES(3, 'B', 3);
+ INSERT INTO t1 VALUES(NULL, 'B', NULL);
+ INSERT INTO t1 VALUES(NULL, 'C', NULL);
+ INSERT INTO t1 VALUES('d', 'D', 'd');
+
+ CREATE TABLE t2(d, e, f);
+ CREATE INDEX t2def ON t2(d, e, f);
+
+ INSERT INTO t2 VALUES(1, 1, 'a');
+ INSERT INTO t2 VALUES(1, 1, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'b');
+ INSERT INTO t2 VALUES(1, 3, 'b');
+ INSERT INTO t2 VALUES(1, 3, 'a');
+ INSERT INTO t2 VALUES(1, 3, 'b');
+ INSERT INTO t2 VALUES(2, 3, 'x');
+ INSERT INTO t2 VALUES(2, 3, 'y');
+ INSERT INTO t2 VALUES(2, 3, 'z');
+
+ CREATE TABLE t3(x, y, z);
+ INSERT INTO t3 VALUES(1,1,1);
+ INSERT INTO t3 VALUES(2,2,2);
+}
+
+foreach {tn use_eph sql res} {
+ 1 0 "SELECT count(DISTINCT c) FROM t1 GROUP BY b" {2 3 0 1}
+ 2 1 "SELECT count(DISTINCT a) FROM t1 GROUP BY b" {2 3 0 1}
+ 3 1 "SELECT count(DISTINCT a) FROM t1 GROUP BY b+c" {0 1 1 1 1}
+
+ 4 0 "SELECT count(DISTINCT f) FROM t2 GROUP BY d, e" {1 2 2 3}
+ 5 1 "SELECT count(DISTINCT f) FROM t2 GROUP BY d" {2 3}
+ 6 0 "SELECT count(DISTINCT f) FROM t2 WHERE d IS 1 GROUP BY e" {1 2 2}
+} {
+ do_test 4.$tn.1 {
+ set prg [db eval "EXPLAIN $sql"]
+ set idx [lsearch $prg OpenEphemeral]
+ expr {$idx>=0}
+ } $use_eph
+
+ do_execsql_test 4.$tn.2 $sql $res
+}
+
+
+set t3root [db one {SELECT rootpage FROM sqlite_schema WHERE name='t3'}]
+foreach {tn use_t3 sql res} {
+ 1 1 "SELECT count(*) FROM t3" 2
+ 2 0 "SELECT count(*) FROM t1" 10
+ 2 1 "SELECT count(DISTINCT a) FROM t1, t3" 4
+ 3 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3" 4
+ 4 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 4
+ 5 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
+ 6 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 ON (t3.x=0)" 4
+ 7 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3" 2
+ 8 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 1
+ 9 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
+ 10 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 ON (t3.x=0)" 0
+
+} {
+ do_test 5.$tn.1 {
+ set bUse 0
+ db eval "EXPLAIN $sql" a {
+ if {$a(opcode)=="OpenRead" && $a(p2)==$t3root} {set bUse 1}
+ }
+ set bUse
+ } $use_t3
+
+ do_execsql_test 5.$tn.2 $sql $res
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 6.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(c, d);
+ INSERT INTO t1 VALUES(123,456);
+ INSERT INTO t2 VALUES(123,456);
+}
+do_execsql_test 6.1 {
+ SELECT count(DISTINCT c) FROM t1 LEFT JOIN t2;
+} {1}
+
+do_execsql_test 7.0 {
+ CREATE TABLE v1 ( v2 UNIQUE, v3 AS( TYPEOF ( NULL ) ) UNIQUE );
+ SELECT COUNT ( DISTINCT TRUE ) FROM v1 GROUP BY likelihood ( v3 , 0.100000 );
+}
+
+
finish_test
+
diff --git a/test/e_createtable.test b/test/e_createtable.test
index e83e5cca1c..c2cd1bc2c1 100644
--- a/test/e_createtable.test
+++ b/test/e_createtable.test
@@ -1393,13 +1393,13 @@ do_execsql_test 4.10.0 {
}
do_createtable_tests 4.10 {
1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5"
- {/*SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
+ {/*SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
2 "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
- {/*SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1*/}
+ {/*SCAN t2 USING INDEX sqlite_autoindex_t2_1*/}
3 "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
- {/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
+ {/*SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
}
# EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
diff --git a/test/e_fkey.test b/test/e_fkey.test
index 40fa075df3..e5eb0d49c1 100644
--- a/test/e_fkey.test
+++ b/test/e_fkey.test
@@ -992,15 +992,15 @@ do_detail_test e_fkey-25.2 {
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
} {
- {SCAN TABLE artist}
- {SCAN TABLE track}
+ {SCAN artist}
+ {SCAN track}
}
do_detail_test e_fkey-25.3 {
PRAGMA foreign_keys = ON;
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
} {
- {SCAN TABLE artist}
- {SCAN TABLE track}
+ {SCAN artist}
+ {SCAN track}
}
do_test e_fkey-25.4 {
execsql {
@@ -1117,15 +1117,15 @@ do_test e_fkey-27.2 {
do_detail_test e_fkey-27.3 {
EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
} {
- {SCAN TABLE artist}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
+ {SCAN artist}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}
do_detail_test e_fkey-27.4 {
EXPLAIN QUERY PLAN DELETE FROM artist
} {
- {SCAN TABLE artist}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
+ {SCAN artist}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}
###########################################################################
diff --git a/test/eqp.test b/test/eqp.test
index f931f8f340..19d6ea91ae 100644
--- a/test/eqp.test
+++ b/test/eqp.test
@@ -46,111 +46,131 @@ do_eqp_test 1.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t1 USING INDEX i1 (a=?)
+ | | `--SEARCH t1 USING INDEX i1 (a=?)
| `--INDEX 2
- | `--SEARCH TABLE t1 USING INDEX i2 (b=?)
- `--SCAN TABLE t2
+ | `--SEARCH t1 USING INDEX i2 (b=?)
+ `--SCAN t2
}
do_eqp_test 1.3 {
SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
} {
QUERY PLAN
- |--SCAN TABLE t2
+ |--SCAN t2
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t1 USING INDEX i1 (a=?)
+ | `--SEARCH t1 USING INDEX i1 (a=?)
`--INDEX 2
- `--SEARCH TABLE t1 USING INDEX i2 (b=?)
+ `--SEARCH t1 USING INDEX i2 (b=?)
}
do_eqp_test 1.3 {
SELECT a FROM t1 ORDER BY a
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX i1
+ `--SCAN t1 USING COVERING INDEX i1
}
do_eqp_test 1.4 {
SELECT a FROM t1 ORDER BY +a
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
+ |--SCAN t1 USING COVERING INDEX i1
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 1.5 {
SELECT a FROM t1 WHERE a=4
} {
QUERY PLAN
- `--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)
+ `--SEARCH t1 USING COVERING INDEX i1 (a=?)
}
do_eqp_test 1.6 {
SELECT DISTINCT count(*) FROM t3 GROUP BY a;
} {
QUERY PLAN
- |--SCAN TABLE t3
+ |--SCAN t3
|--USE TEMP B-TREE FOR GROUP BY
`--USE TEMP B-TREE FOR DISTINCT
}
-do_eqp_test 1.7 {
+do_eqp_test 1.7.1 {
SELECT * FROM t3 JOIN (SELECT 1)
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE SUBQUERY xxxxxx
| `--SCAN CONSTANT ROW
|--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ `--SCAN t3
}
+do_eqp_test 1.7.2 {
+ SELECT * FROM t3 JOIN (SELECT 1) AS v1
+} {
+ QUERY PLAN
+ |--MATERIALIZE v1
+ | `--SCAN CONSTANT ROW
+ |--SCAN v1
+ `--SCAN t3
+}
+do_eqp_test 1.7.3 {
+ SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy
+} {
+ QUERY PLAN
+ |--MATERIALIZE yy
+ | `--SCAN CONSTANT ROW
+ |--SCAN yy
+ `--SCAN xx
+}
+
+
do_eqp_test 1.8 {
SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE SUBQUERY xxxxxx
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--UNION USING TEMP B-TREE
| `--SCAN CONSTANT ROW
|--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ `--SCAN t3
}
do_eqp_test 1.9 {
- SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--EXCEPT USING TEMP B-TREE
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
do_eqp_test 1.10 {
- SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--INTERSECT USING TEMP B-TREE
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
do_eqp_test 1.11 {
- SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--UNION ALL
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
#-------------------------------------------------------------------------
@@ -166,57 +186,57 @@ do_execsql_test 2.1 {
det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
|--USE TEMP B-TREE FOR GROUP BY
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
QUERY PLAN
- |--SCAN TABLE t2 USING COVERING INDEX t2i1
+ |--SCAN t2 USING COVERING INDEX t2i1
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.3 "SELECT DISTINCT * FROM t1" {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
QUERY PLAN
- |--SCAN TABLE t1
- |--SCAN TABLE t2
+ |--SCAN t1
+ |--SCAN t2
`--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
QUERY PLAN
- |--SCAN TABLE t1
- |--SCAN TABLE t2
+ |--SCAN t1
+ |--SCAN t2
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
QUERY PLAN
- |--SCAN TABLE t2 USING COVERING INDEX t2i1
- `--SCAN TABLE t1
+ |--SCAN t2 USING COVERING INDEX t2i1
+ `--SCAN t1
}
det 2.3.1 "SELECT max(x) FROM t2" {
QUERY PLAN
- `--SEARCH TABLE t2 USING COVERING INDEX t2i1
+ `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.2 "SELECT min(x) FROM t2" {
QUERY PLAN
- `--SEARCH TABLE t2 USING COVERING INDEX t2i1
+ `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.3 "SELECT min(x), max(x) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}
@@ -228,42 +248,42 @@ do_eqp_test 3.1.1 {
SELECT (SELECT x FROM t1 AS sub) FROM t1;
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t1 AS sub
+ `--SCAN sub
}
do_eqp_test 3.1.2 {
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t1 AS sub
+ `--SCAN sub
}
do_eqp_test 3.1.3 {
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- |--SCAN TABLE t1 AS sub
+ |--SCAN sub
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 3.1.4 {
SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
det 3.2.1 {
SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
} {
QUERY PLAN
- |--CO-ROUTINE xxxxxx
- | |--SCAN TABLE t1
+ |--CO-ROUTINE SUBQUERY xxxxxx
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
|--SCAN SUBQUERY xxxxxx
`--USE TEMP B-TREE FOR ORDER BY
@@ -275,13 +295,13 @@ det 3.2.2 {
ORDER BY x2.y LIMIT 5
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE t1
+ |--MATERIALIZE x1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
- |--MATERIALIZE xxxxxx
- | `--SCAN TABLE t2 USING INDEX t2i1
- |--SCAN SUBQUERY xxxxxx AS x1
- |--SCAN SUBQUERY xxxxxx AS x2
+ |--MATERIALIZE x2
+ | `--SCAN t2 USING INDEX t2i1
+ |--SCAN x1
+ |--SCAN x2
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -289,25 +309,25 @@ det 3.3.1 {
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--LIST SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 3.3.2 {
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 3.3.3 {
SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--CORRELATED SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
#-------------------------------------------------------------------------
@@ -319,9 +339,9 @@ do_eqp_test 4.1.1 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
`--UNION ALL
- `--SCAN TABLE t2
+ `--SCAN t2
}
do_eqp_test 4.1.2 {
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
@@ -329,10 +349,10 @@ do_eqp_test 4.1.2 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.3 {
@@ -341,10 +361,10 @@ do_eqp_test 4.1.3 {
QUERY PLAN
`--MERGE (UNION)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.4 {
@@ -353,10 +373,10 @@ do_eqp_test 4.1.4 {
QUERY PLAN
`--MERGE (INTERSECT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.5 {
@@ -365,10 +385,10 @@ do_eqp_test 4.1.5 {
QUERY PLAN
`--MERGE (EXCEPT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -378,10 +398,10 @@ do_eqp_test 4.2.2 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- `--SCAN TABLE t2 USING INDEX t2i1
+ `--SCAN t2 USING INDEX t2i1
}
do_eqp_test 4.2.3 {
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
@@ -389,10 +409,10 @@ do_eqp_test 4.2.3 {
QUERY PLAN
`--MERGE (UNION)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.4 {
@@ -401,10 +421,10 @@ do_eqp_test 4.2.4 {
QUERY PLAN
`--MERGE (INTERSECT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.5 {
@@ -413,10 +433,10 @@ do_eqp_test 4.2.5 {
QUERY PLAN
`--MERGE (EXCEPT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
@@ -426,9 +446,9 @@ do_eqp_test 4.3.1 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
`--UNION USING TEMP B-TREE
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
do_eqp_test 4.3.2 {
@@ -437,11 +457,11 @@ do_eqp_test 4.3.2 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
|--UNION USING TEMP B-TREE
- | `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ | `--SCAN t2 USING COVERING INDEX t2i1
`--UNION USING TEMP B-TREE
- `--SCAN TABLE t1
+ `--SCAN t1
}
do_eqp_test 4.3.3 {
SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
@@ -451,12 +471,12 @@ do_eqp_test 4.3.3 {
|--LEFT
| `--MERGE (UNION)
| |--LEFT
- | | |--SCAN TABLE t1
+ | | |--SCAN t1
| | `--USE TEMP B-TREE FOR ORDER BY
| `--RIGHT
- | `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ | `--SCAN t2 USING COVERING INDEX t2i1
`--RIGHT
- |--SCAN TABLE t1
+ |--SCAN t1
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -469,145 +489,145 @@ drop_all_tables
# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
# FROM t1 WHERE a=1;
-# 0|0|0|SCAN TABLE t1
+# 0|0|0|SCAN t1
#
do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SCAN TABLE t1}
+ 0 0 0 {SCAN t1}
}
# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
-# 0|0|0|SEARCH TABLE t1 USING INDEX i1
+# 0|0|0|SEARCH t1 USING INDEX i1
#
do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+ 0 0 0 {SEARCH t1 USING INDEX i1 (a=?)}
}
# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
#
do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
}
# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
-# 0|1|1|SCAN TABLE t2
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
+# 0|1|1|SCAN t2
#
do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
- 0 1 1 {SCAN TABLE t2}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
+ 0 1 1 {SCAN t2}
}
# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
-# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
-# 0|1|0|SCAN TABLE t2
+# 0|0|1|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
+# 0|1|0|SCAN t2
#
det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
- 0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
- 0 1 0 {SCAN TABLE t2}
+ 0 0 1 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
+ 0 1 0 {SCAN t2}
}
# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
-# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
+# 0|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
- 0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
+ 0 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}
# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
# SELECT c, d FROM t2 ORDER BY c;
-# 0|0|0|SCAN TABLE t2
+# 0|0|0|SCAN t2
# 0|0|0|USE TEMP B-TREE FOR ORDER BY
#
det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
- 0 0 0 {SCAN TABLE t2}
+ 0 0 0 {SCAN t2}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
-# 0|0|0|SCAN TABLE t2 USING INDEX i4
+# 0|0|0|SCAN t2 USING INDEX i4
#
do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
- 0 0 0 {SCAN TABLE t2 USING INDEX i4}
+ 0 0 0 {SCAN t2 USING INDEX i4}
}
# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
-# 0|0|0|SCAN TABLE t2
+# 0|0|0|SCAN t2
# 0|0|0|EXECUTE SCALAR SUBQUERY 1
-# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
+# 1|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
-# 2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
+# 2|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
det 5.9 {
SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
} {
- 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
+ 0 0 0 {SCAN t2 USING COVERING INDEX i4}
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
- 1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
+ 1 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
- 2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
+ 2 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}
# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
-# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
+# 1|0|0|SCAN t1 USING COVERING INDEX i2
# 0|0|0|SCAN SUBQUERY 1
# 0|0|0|USE TEMP B-TREE FOR GROUP BY
#
det 5.10 {
SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
} {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i2}
0 0 0 {SCAN SUBQUERY 1}
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
}
# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
-# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
-# 0|1|1|SCAN TABLE t1
+# 0|0|0|SEARCH t2 USING INDEX i4 (c=?)
+# 0|1|1|SCAN t1
#
det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
- 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
- 0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
+ 0 0 0 {SEARCH t2 USING INDEX i4 (c=?)}
+ 0 1 1 {SCAN t1 USING COVERING INDEX i2}
}
# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 UNION SELECT c FROM t2;
-# 1|0|0|SCAN TABLE t1
-# 2|0|0|SCAN TABLE t2
+# 1|0|0|SCAN t1
+# 2|0|0|SCAN t2
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
#
det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
- 2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i2}
+ 2 0 0 {SCAN t2 USING COVERING INDEX i4}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
}
# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
-# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
-# 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
+# 1|0|0|SCAN t1 USING COVERING INDEX i2
+# 2|0|0|SCAN t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
#
det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
- 2 0 0 {SCAN TABLE t2}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i1}
+ 2 0 0 {SCAN t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}
@@ -647,8 +667,8 @@ if {![nonzero_reserved_bytes]} {
do_peqp_test 6.1 {
SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
} [string trimleft {
-1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
-2 0 0 SCAN TABLE t2
+1 0 0 SCAN t1 USING COVERING INDEX i2
+2 0 0 SCAN t2
2 0 0 USE TEMP B-TREE FOR ORDER BY
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
}]
@@ -669,12 +689,12 @@ do_execsql_test 7.0 {
det 7.1 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 7.2 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX i1
+ `--SCAN t2 USING COVERING INDEX i1
}
do_execsql_test 7.3 {
@@ -693,12 +713,12 @@ sqlite3 db test.db
det 7.4 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 7.5 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX i1
+ `--SCAN t2 USING COVERING INDEX i1
}
#-------------------------------------------------------------------------
@@ -714,37 +734,37 @@ do_execsql_test 8.0 {
det 8.1.1 "SELECT * FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
QUERY PLAN
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
det 8.1.3 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 8.2.1 "SELECT * FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (b=?)
+ `--SEARCH t1 USING PRIMARY KEY (b=?)
}
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)
+ `--SEARCH t1 USING PRIMARY KEY (b=? AND c=?)
}
det 8.2.4 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
# 2018-08-16: While working on Fossil I discovered that EXPLAIN QUERY PLAN
@@ -814,16 +834,16 @@ do_eqp_test 9.1 {
ORDER BY 1;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE forumpost AS x USING INDEX forumthread
+ |--MATERIALIZE thread
+ | |--SCAN x USING INDEX forumthread
| |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
| |--CORRELATED SCALAR SUBQUERY xxxxxx
- | | |--SEARCH TABLE forumpost USING COVERING INDEX forumthread (froot=?)
+ | | |--SEARCH forumpost USING COVERING INDEX forumthread (froot=?)
| | `--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
| `--USE TEMP B-TREE FOR ORDER BY
- |--SCAN SUBQUERY xxxxxx
- |--SEARCH TABLE blob USING INTEGER PRIMARY KEY (rowid=?)
- |--SEARCH TABLE event USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN thread
+ |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/exists2.test b/test/exists2.test
deleted file mode 100644
index c4fc9dc373..0000000000
--- a/test/exists2.test
+++ /dev/null
@@ -1,188 +0,0 @@
-# 2021 January 15
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this file is testing cases where EXISTS expressions are
-# transformed to IN() expressions by where.c
-#
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-set testprefix exists2
-
-do_execsql_test 1.0 {
- CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t1 VALUES(4, 'four');
- INSERT INTO t1 VALUES(5, 'five');
- INSERT INTO t1 VALUES(6, 'six');
- INSERT INTO t1 VALUES(7, 'seven');
-
- CREATE TABLE t2(c INTEGER, d INTEGER);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(3, 2);
- INSERT INTO t2 VALUES(5, 3);
- INSERT INTO t2 VALUES(7, 4);
-}
-
-proc do_execsql_eqp_test {tn sql eqp res} {
- uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]]
- uplevel [list do_execsql_test $tn.2 $sql $res]
-}
-
-do_execsql_eqp_test 1.1 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c);
-} {
- USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.2 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a);
-} {
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.3 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a);
-} {
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY
-} {
- 2 two 4 four 6 six
-}
-
-do_execsql_eqp_test 1.4 {
- SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1);
-} {
- SCAN TABLE t1
-} {
- 1 one 3 three 5 five 7 seven
-}
-
-do_execsql_eqp_test 1.5 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3)
- );
-} {
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-do_execsql_eqp_test 1.6 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
- );
-} {
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-do_execsql_eqp_test 1.7 {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c
- );
-} {
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY
-} {
- 1 one 3 three 5 five
-}
-
-#-------------------------------------------------------------------------
-#
-reset_db
-do_execsql_test 2.0 {
- CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID;
- CREATE TABLE t4(c TEXT COLLATE nocase, y INT);
-
- INSERT INTO t3 VALUES('one', 'i', 1);
- INSERT INTO t3 VALUES('two', 'ii', 2);
- INSERT INTO t3 VALUES('three', 'iii', 3);
- INSERT INTO t3 VALUES('four', 'iv', 4);
- INSERT INTO t3 VALUES('five', 'v', 5);
-
- INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1);
-}
-
-do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one}
-do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two}
-
-do_execsql_eqp_test 2.3 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
-} {
- SEARCH TABLE t3 USING PRIMARY KEY
-} {
- four one
-}
-
-do_execsql_eqp_test 2.4 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
-} {
- SCAN TABLE t3
-} {
- five four one two
-}
-
-do_execsql_test 2.5 {
- CREATE INDEX t3anc ON t3(a COLLATE nocase, x);
-}
-
-do_execsql_eqp_test 2.6 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
-} {
- SEARCH TABLE t3 USING COVERING INDEX t3anc
-} {
- five four one two
-}
-do_execsql_test 2.6a {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x))
-} {five four one two}
-
-do_execsql_eqp_test 2.7 {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
-} {
- SEARCH TABLE t3 USING PRIMARY KEY
-} {
- four one
-}
-do_execsql_test 2.7a {
- SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y))
-} {
- four one
-}
-
-# EXISTS clauses using vector expressions in the WHERE clause.
-#
-reset_db
-do_execsql_test 3.0 {
- CREATE TABLE t1(a,b);
- INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888);
- CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
- INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333);
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b));
-} {222}
-do_execsql_test 3.1 {
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y));
-} {222}
-do_execsql_test 3.2 {
- SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y));
-} {222}
-
-
-
-
-
-finish_test
diff --git a/test/existsfault.test b/test/existsfault.test
deleted file mode 100644
index 24e44a7b58..0000000000
--- a/test/existsfault.test
+++ /dev/null
@@ -1,52 +0,0 @@
-# 2021 January 15
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this file is testing cases where EXISTS expressions are
-# transformed to IN() expressions by where.c
-#
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-set testprefix existsfault
-
-do_execsql_test 1 {
- CREATE TABLE t1(a PRIMARY KEY, b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
- INSERT INTO t1 VALUES(3, 'three');
- INSERT INTO t1 VALUES(4, 'four');
- INSERT INTO t1 VALUES(5, 'five');
- INSERT INTO t1 VALUES(6, 'six');
- INSERT INTO t1 VALUES(7, 'seven');
-
- CREATE TABLE t2(c INTEGER, d INTEGER);
- INSERT INTO t2 VALUES(1, 1);
- INSERT INTO t2 VALUES(3, 2);
- INSERT INTO t2 VALUES(5, 3);
- INSERT INTO t2 VALUES(7, 4);
-}
-faultsim_save_and_close
-
-do_faultsim_test 1 -prep {
- faultsim_restore_and_reopen
-} -body {
- execsql {
- SELECT t1.* FROM t1 WHERE EXISTS(
- SELECT * FROM t2 WHERE t2.c=t1.a AND d IN (1, 2, 3)
- )
- }
-} -test {
- faultsim_test_result {0 {1 one 3 three 5 five}}
-}
-
-
-finish_test
-
diff --git a/test/exprfault.test b/test/exprfault.test
new file mode 100644
index 0000000000..9e5977e1d2
--- /dev/null
+++ b/test/exprfault.test
@@ -0,0 +1,35 @@
+# 2021 April 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix exprfault
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a);
+ CREATE TABLE t2(d);
+}
+faultsim_save_and_close
+
+do_faultsim_test 1.1 -faults oom* -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql {
+ SELECT a = ( SELECT d FROM (SELECT d FROM t2) ) FROM t1
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+
+finish_test
diff --git a/test/external_reader.test b/test/external_reader.test
new file mode 100644
index 0000000000..5d293981c5
--- /dev/null
+++ b/test/external_reader.test
@@ -0,0 +1,74 @@
+# 2021 April 2
+#
+# 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
+source $testdir/lock_common.tcl
+set testprefix external_reader
+
+ifcapable !wal {
+ finish_test
+ return
+}
+if {$::tcl_platform(platform)!="unix"} {
+ finish_test
+ return
+}
+
+do_multiclient_test tn {
+
+ set bExternal 1
+ if {[info commands db3]!=""} { set bExternal 0 }
+
+ do_test 1.$tn.0 {
+ sql1 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES(1, 2);
+ }
+ } {wal}
+
+ do_test 1.$tn.1 {
+ sql2 { SELECT * FROM t1 }
+ } {1 2}
+
+ do_test 1.$tn.2 {
+ code1 {
+ file_control_external_reader db
+ }
+ } {0}
+
+ do_test 1.$tn.3 {
+ sql2 {
+ BEGIN;
+ SELECT * FROM t1;
+ }
+ } {1 2}
+
+ do_test 1.$tn.4 {
+ code1 {
+ file_control_external_reader db
+ }
+ } $bExternal
+
+ do_test 1.$tn.5 {
+ sql2 { COMMIT }
+ } {}
+
+ do_test 1.$tn.6 {
+ code1 { file_control_external_reader db }
+ } 0
+
+}
+
+
+finish_test
diff --git a/test/fts3aux1.test b/test/fts3aux1.test
index c7e1ac1a5c..1524d6d30f 100644
--- a/test/fts3aux1.test
+++ b/test/fts3aux1.test
@@ -105,10 +105,10 @@ db func rec rec
#
do_execsql_test 2.1.1.1 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 1:*/}
do_execsql_test 2.1.1.2 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
# Now show that using "term='braid'" means the virtual table returns
# only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
@@ -154,24 +154,24 @@ do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}
do_execsql_test 2.2.1.1 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 2:*/}
do_execsql_test 2.2.1.2 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_execsql_test 2.2.1.3 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 4:*/}
do_execsql_test 2.2.1.4 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_execsql_test 2.2.1.5 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 6:*/}
do_execsql_test 2.2.1.6 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_test 2.2.2.1 {
set cnt 0
@@ -335,7 +335,7 @@ foreach {tn sort orderby} {
9 1 "ORDER BY occurrences DESC"
} {
- set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
+ set res {SCAN terms VIRTUAL TABLE INDEX 0:}
if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} }
set res "/*$res*/"
@@ -413,8 +413,8 @@ do_plansql_test 4.2 {
SELECT y FROM x2, terms WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE x2
- `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
+ |--SCAN x2
+ `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
a b c d e f g h i j k l
}
@@ -423,8 +423,8 @@ do_plansql_test 4.3 {
SELECT y FROM terms, x2 WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE x2
- `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
+ |--SCAN x2
+ `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
a b c d e f g h i j k l
}
@@ -433,8 +433,8 @@ do_plansql_test 4.4 {
SELECT y FROM x3, terms WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
+ |--SCAN terms VIRTUAL TABLE INDEX 0:
+ `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
a b c d e f g h i j k l
}
@@ -443,8 +443,8 @@ do_plansql_test 4.5 {
SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
+ |--SCAN terms VIRTUAL TABLE INDEX 0:
+ `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
a k l
}
diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test
index 851119a2fe..51016ab19c 100644
--- a/test/fts3corrupt4.test
+++ b/test/fts3corrupt4.test
@@ -6385,5 +6385,208 @@ do_catchsql_test 48.1 {
INSERT INTO x1(x1) VALUES( 'merge=3,4' ),('merge=3,4');
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_test 49.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 28672 pagesize 4096 filename crash-58821b8eae6883.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 0e ef 00 07 0d 4d 00 0f bd 0f 5f ..........M...._
+| 112: 0e f7 0e 06 0e bc 0d a4 0d 4d 00 00 00 00 00 00 .........M......
+| 3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 55 07 07 .............U..
+| 3408: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 73 74 ......tablet1_st
+| 3424: 61 74 74 31 5f 73 74 61 74 07 43 52 45 41 54 45 att1_stat.CREATE
+| 3440: 20 54 41 42 4c 45 20 27 74 31 5f 73 74 61 74 27 TABLE 't1_stat'
+| 3456: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
+| 3472: 41 52 59 20 4b 45 59 2c 20 76 61 6c 75 65 20 42 ARY KEY, value B
+| 3488: 4c 4f 42 29 60 06 07 17 21 21 01 81 0b 74 61 62 LOB)`...!!...tab
+| 3504: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
+| 3520: 6f 63 73 69 7a 65 06 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
+| 3536: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
+| 3552: 28 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50 (docid INTEGER P
+| 3568: 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 69 7a 65 RIMARY KEY, size
+| 3584: 20 42 4c 4f 42 29 81 33 04 07 17 1f 1f 01 82 35 BLOB).3.......5
+| 3600: 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72 74 31 tablet1_segdirt1
+| 3616: 5f 73 65 67 64 69 72 04 43 52 45 41 54 45 20 54 _segdir.CREATE T
+| 3632: 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69 72 27 ABLE 't1_segdir'
+| 3648: 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52 2c 69 (level INTEGER,i
+| 3664: 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61 72 74 dx INTEGER,start
+| 3680: 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c _block INTEGER,l
+| 3696: 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20 eaves_end_block
+| 3712: 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63 INTEGER,end_bloc
+| 3728: 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42 k INTEGER,root B
+| 3744: 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45 59 28 LOB,PRIMARY KEY(
+| 3760: 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 05 06 17 level, idx))1...
+| 3776: 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74 65 5f E...indexsqlite_
+| 3792: 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73 65 67 autoindex_t1_seg
+| 3808: 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72 05 00 dir_1t1_segdir..
+| 3824: 00 00 08 00 00 00 00 66 03 07 17 23 23 01 81 13 .......f...##...
+| 3840: 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e 74 73 tablet1_segments
+| 3856: 74 31 5f 73 65 67 6d 65 6e 74 73 03 43 52 45 41 t1_segments.CREA
+| 3872: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 TE TABLE 't1_seg
+| 3888: 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64 20 49 ments'(blockid I
+| 3904: 4e 54 45 47 45 52 20 f9 52 49 4d 41 52 59 20 4b NTEGER .RIMARY K
+| 3920: 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c EY, block BLOB).
+| 3936: 02 07 17 21 21 01 81 03 74 61 62 6c 65 74 31 5f ...!!...tablet1_
+| 3952: 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 65 6e contentt1_conten
+| 3968: 74 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
+| 3984: 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69 t1_content'(doci
+| 4000: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
+| 4016: 59 20 4b 45 59 2c 20 27 63 30 61 27 29 41 01 06 Y KEY, 'c0a')A..
+| 4032: 17 11 11 08 71 74 61 62 6c 65 74 31 74 31 43 52 ....qtablet1t1CR
+| 4048: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
+| 4064: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 34 LE t1 USING fts4
+| 4080: 28 61 2c 70 72 65 66 69 78 3d 27 32 2c 32 27 29 (a,prefix='2,2')
+| page 2 offset 4096
+| 0: 0d 00 00 00 08 0e 1f 00 0f c4 0f 7c 0f 34 0f 07 ...........|.4..
+| 16: 0e c3 0e 97 0e 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 ...............B
+| 3616: 08 04 00 81 09 73 75 6e 74 20 69 6e 20 63 75 6c .....sunt in cul
+| 3632: 70 61 20 71 75 69 20 6f 66 66 69 63 69 61 20 64 pa qui officia d
+| 3648: 65 73 65 72 75 6e 74 20 6d 6f 6c 6c 69 74 20 61 eserunt mollit a
+| 3664: 6e 69 6d 20 69 64 20 65 73 74 20 6c 61 62 6f 72 nim id est labor
+| 3680: 75 6d 2e 32 07 03 00 6b 45 78 63 65 70 74 65 75 um.2...kExcepteu
+| 3696: 72 20 73 69 6e 74 20 6f 63 63 61 65 63 61 74 20 r sint occaecat
+| 3712: 63 75 70 69 64 61 74 61 74 20 6e 6f 6e 20 70 72 cupidatat non pr
+| 3728: 6f 69 64 65 6e 74 2c 2a 06 03 00 5b 63 69 6c 6c oident,*...[cill
+| 3744: 75 6d 20 64 6f 6c 6f 72 65 20 65 75 20 66 75 67 um dolore eu fug
+| 3760: 69 61 74 20 6e 75 6c 6c 61 20 70 61 72 69 61 74 iat nulla pariat
+| 3776: 75 72 2e 42 05 04 00 81 09 44 75 69 73 20 61 75 ur.B.....Duis au
+| 3792: 74 65 20 69 72 75 72 65 20 64 6f 6c 6f 72 20 69 te irure dolor i
+| 3808: 6e 20 72 65 70 72 65 68 65 6e 64 65 72 69 74 20 n reprehenderit
+| 3824: 69 6e 20 76 6f 6c 75 70 74 61 74 65 20 76 65 6c in voluptate vel
+| 3840: 69 74 20 65 73 73 65 2b 04 03 00 5d 6e 69 73 69 it esse+...]nisi
+| 3856: 20 75 74 20 61 6c 69 71 75 69 70 20 65 78 20 65 ut aliquip ex e
+| 3872: 61 20 63 6f 6d 6d 6f 64 6f 20 63 6f 6e 73 65 71 a commodo conseq
+| 3888: 75 61 74 2e 46 03 04 00 81 11 55 74 20 65 6e 69 uat.F.....Ut eni
+| 3904: 6d 20 61 64 20 6d 69 6e 69 6d 20 76 65 6e 69 61 m ad minim venia
+| 3920: 6d 2c 20 71 75 69 73 20 6e 6f 73 74 72 75 64 20 m, quis nostrud
+| 3936: 65 78 65 72 63 69 74 61 74 69 6f 6e 20 75 6c 6c exercitation ull
+| 3952: 61 6d 63 6f 20 6c 61 62 6f 72 69 73 46 02 04 00 amco laborisF...
+| 3968: 81 11 73 65 64 20 64 6f 20 65 69 75 73 6d 6f 64 ..sed do eiusmod
+| 3984: 20 74 65 6d 70 6f 72 20 69 6e 63 69 64 69 64 75 tempor incididu
+| 4000: 6e 74 20 75 74 20 6c 61 62 6f 72 65 20 65 74 20 nt ut labore et
+| 4016: 64 6f 6c 6f 72 65 20 6d 61 67 6e 61 20 61 6c 69 dolore magna ali
+| 4032: 71 75 61 2e 3a 01 03 00 7b 4c 6f 72 65 6d 20 69 qua.:....Lorem i
+| 4048: 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61 psum dolor sit a
+| 4064: 6d 65 74 2c 20 63 6f 6e 73 65 63 74 65 74 75 72 met, consectetur
+| 4080: 20 61 64 69 70 69 73 63 69 6e 67 20 65 00 01 00 adipiscing e...
+| page 4 offset 12288
+| 0: 0d 00 00 00 03 0a a6 00 0d 57 0c 4a 0a a6 00 00 .........W.J....
+| 2720: 00 00 00 00 00 00 83 21 03 08 02 08 08 08 17 86 .......!........
+| 2736: 30 08 00 30 20 34 30 32 00 02 61 64 06 01 08 00 0..0 402..ad....
+| 2752: 02 04 00 01 01 6c 06 02 0c 00 02 04 00 01 01 6d .....l.........m
+| 2768: 03 01 06 00 01 01 6e 03 08 09 00 01 01 75 03 05 ......n......u..
+| 2784: 03 00 00 02 63 69 03 06 02 00 01 01 6f 07 01 07 ....ci......o...
+| 2800: 00 03 07 03 00 01 01 75 06 07 05 00 01 04 00 00 .......u........
+| 2816: 02 64 65 03 08 07 00 01 01 6f 0d 01 04 00 01 03 .de......o......
+| 2832: 09 00 03 05 00 01 03 00 01 01 75 03 05 02 00 00 ..........u.....
+| 2848: 02 65 61 03 04 06 00 01 01 69 03 02 04 00 01 01 .ea......i......
+| 2864: 6c 03 01 09 00 01 01 6e 03 03 03 00 01 01 73 06 l......n......s.
+| 2880: 05 0b 00 03 0b 00 01 01 74 03 02 09 00 01 01 75 ........t......u
+| 2896: 03 06 04 00 01 01 78 09 03 09 00 01 05 00 03 02 ......x.........
+| 2912: 00 00 02 66 75 03 06 05 00 00 02 69 64 03 08 0a ...fu......id...
+| 2928: 00 01 01 6e 0a 02 06 00 03 06 04 00 03 03 00 01 ...n............
+| 2944: 01 70 03 01 03 00 01 01 72 03 05 04 00 00 02 6c .p......r......l
+| 2960: 61 09 02 08 00 01 0b 00 05 0c 00 01 01 6f 03 01 a............o..
+| 2976: 02 00 00 02 6d 61 03 02 0b 00 01 01 69 03 03 05 ....ma......i...
+| 2992: 00 01 01 6f 03 08 08 00 00 02 6e 69 03 04 02 00 ...o......ni....
+| 3008: 01 01 6f 06 03 08 00 04 06 00 01 01 75 03 06 06 ..o.........u...
+| 3024: 00 00 02 6f 63 03 07 04 00 01 01 66 03 08 06 00 ...oc......f....
+| 3040: 00 02 70 61 03 06 07 00 01 01 72 03 07 07 00 00 ..pa......r.....
+| 3056: 02 71 75 06 03 07 00 05 05 00 00 02 72 65 03 05 .qu.........re..
+| 3072: 07 00 00 02 73 65 03 02 02 00 01 01 69 06 01 05 ....se......i...
+| 3088: 00 06 03 00 01 01 75 03 08 02 00 00 02 74 65 03 ......u......te.
+| 3104: 02 05 00 00 02 75 6c 03 03 0a 00 01 01 74 09 02 .....ul......t..
+| 3120: 07 00 01 02 00 01 03 00 00 02 76 65 06 03 06 00 ..........ve....
+| 3136: 02 0a 00 01 01 6f 03 05 09 00 82 0a 02 08 02 08 .....o..........
+| 3152: 08 08 17 84 02 04 00 30 20 32 35 31 00 01 61 13 .......0 251..a.
+| 3168: 01 06 04 00 01 0c 00 01 04 00 01 04 00 01 03 00 ................
+| 3184: 03 09 00 00 01 63 10 01 07 00 03 07 03 00 02 02 .....c..........
+| 3200: 00 01 05 00 01 04 00 00 01 64 11 01 04 00 01 03 .........d......
+| 3216: 09 00 03 02 05 00 01 03 00 02 07 00 00 01 65 1b ..............e.
+| 3232: 01 09 00 01 04 07 00 01 03 08 00 01 05 03 00 01 ................
+| 3248: 0b 00 01 04 00 01 02 00 01 0b 00 00 01 66 03 06 .............f..
+| 3264: 05 00 00 01 69 0f 01 03 00 01 06 00 03 04 04 04 ....i...........
+| 3280: 00 03 03 09 00 00 01 6c 0c 01 02 00 01 08 00 01 .......l........
+| 3296: 0b 00 05 0c 00 00 01 6d 09 02 0b 00 01 05 00 05 .......m........
+| 3312: 08 00 00 01 6e 0c 03 08 00 01 02 00 02 06 00 01 ....n...........
+| 3328: 06 00 00 01 6f 06 07 04 00 01 06 00 00 01 70 06 ....o.........p.
+| 3344: 06 07 00 01 07 00 00 01 71 06 03 07 00 05 05 00 ........q.......
+| 3360: 00 01 72 03 05 07 00 00 01 73 0c 01 05 00 01 02 ..r......s......
+| 3376: 00 05 03 00 01 02 00 00 01 74 03 02 05 00 00 01 .........t......
+| 3392: 75 0a 02 07 00 01 02 0a 00 01 03 00 00 01 76 07 u.............v.
+| 3408: 03 06 00 02 09 03 00 85 26 01 08 08 08 08 08 17 ........&.......
+| 3424: 8a 3e 30 20 36 36 35 00 02 61 65 03 03 04 00 02 .>0 665..ae.....
+| 3440: 08 69 70 69 73 63 69 6e 67 03 01 08 00 01 05 6c .ipiscing......l
+| 3456: 69 71 75 61 03 02 0c 00 05 02 69 70 03 04 04 00 iqua......ip....
+| 3472: 01 03 6d 65 74 03 01 06 00 01 03 6e 69 6d 03 08 ..met......nim..
+| 3488: 09 00 01 03 75 74 65 03 05 03 00 00 06 63 69 6c ....ute......cil
+| 3504: 6c 75 6d 03 06 02 00 01 06 6f 6d 6d 6f 64 6f 03 lum......ommodo.
+| 3520: 04 07 00 02 09 6e 73 65 63 74 65 74 b5 72 03 01 .....nsectet.r..
+| 3536: 07 00 05 04 71 75 61 74 03 04 08 00 01 04 75 6c ....quat......ul
+| 3552: 70 61 03 08 04 00 02 07 70 69 64 61 74 61 74 03 pa......pidatat.
+| 3568: 07 05 00 00 08 64 65 73 65 72 75 6e 74 03 08 07 .....deserunt...
+| 3584: 00 01 01 6f 03 02 03 00 02 03 6c 6f 72 06 01 04 ...o......lor...
+| 3600: 00 04 05 00 05 01 65 06 02 0a 00 04 03 00 01 03 ......e.........
+| 3616: 75 69 73 03 05 02 00 00 02 65 61 03 04 06 00 01 uis......ea.....
+| 3632: 06 69 75 73 6d 6f 64 03 02 04 00 01 03 6c 69 74 .iusmod......lit
+| 3648: 03 01 09 00 01 03 6e 69 6d 03 03 03 00 01 03 73 ......nim......s
+| 3664: 73 65 03 05 0b 00 02 01 74 03 08 0b 00 01 01 74 se......t......t
+| 3680: 03 02 09 00 01 01 75 03 06 04 00 01 01 78 03 04 ......u......x..
+| 3696: 05 00 02 07 63 65 70 74 65 75 72 03 07 02 00 02 ....cepteur.....
+| 3712: 0a 65 72 63 69 74 61 74 69 6f 6e 03 03 09 00 00 .ercitation.....
+| 3728: 06 66 75 67 69 61 74 03 06 05 00 00 02 69 64 03 .fugiat......id.
+| 3744: 08 0a 00 01 01 6e 07 05 06 04 00 03 03 00 02 08 .....n..........
+| 3760: 63 69 64 69 64 75 6e 74 03 02 06 00 01 04 70 73 cididunt......ps
+| 3776: 75 6d 03 01 03 00 01 04 72 75 72 65 03 05 04 00 um......rure....
+| 3792: 00 06 6c 61 62 6f 72 65 03 02 08 00 05 02 69 73 ..labore......is
+| 3808: 03 03 0b 00 05 02 75 6d 03 08 0c 00 01 04 6f 72 ......um......or
+| 3824: 65 6d 03 01 02 00 00 05 6d 61 67 6e 61 03 02 0b em......magna...
+| 3840: 00 01 04 69 6e 69 6d 03 03 05 00 01 05 6f 6c 6c ...inim......oll
+| 3856: 69 74 03 08 08 00 00 04 6e 69 73 69 03 04 02 00 it......nisi....
+| 3872: 01 02 6f 6e 03 07 06 00 02 05 73 74 72 75 64 03 ..on......strud.
+| 3888: 03 08 00 01 04 75 6c 6c 61 03 06 06 00 00 08 6f .....ulla......o
+| 3904: 63 63 61 65 63 61 74 03 07 04 00 01 06 66 66 69 ccaecat......ffi
+| 3920: 63 69 61 03 08 06 00 00 08 70 61 72 69 61 74 75 cia......pariatu
+| 3936: 72 03 06 07 00 01 07 72 6f 69 64 65 6e 74 03 07 r......roident..
+| 3952: 07 00 00 03 71 75 69 03 08 05 00 03 01 73 03 03 ....qui......s..
+| 3968: 07 00 00 0d 72 65 70 72 65 68 65 6e 64 65 72 69 ....reprehenderi
+| 3984: 74 03 05 07 00 00 03 73 65 64 03 02 02 00 01 03 t......sed......
+| 4000: 69 6e 74 03 07 03 00 02 01 74 03 01 05 00 01 03 int......t......
+| 4016: 75 6e 74 03 08 02 00 00 06 74 65 6d 70 6f 72 03 unt......tempor.
+| 4032: 02 05 00 00 07 75 6c 6c 61 6d 63 6f 03 03 0a 00 .....ullamco....
+| 4048: 01 01 74 09 02 07 00 01 02 00 01 03 00 00 05 76 ..t............v
+| 4064: 65 6c 69 74 03 05 0a 00 02 04 6e 69 61 6d 03 03 elit......niam..
+| 4080: 06 00 01 08 6f 6c 75 70 74 61 74 65 03 05 09 00 ....oluptate....
+| page 5 offset 16384
+| 0: 0a 00 00 00 03 0f eb 00 0f fb 0f f3 0f eb 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 07 04 02 08 01 ................
+| 4080: 08 00 03 07 04 02 08 01 04 00 02 04 04 08 08 09 ................
+| page 6 offset 20480
+| 0: 0d 00 00 00 08 0f d0 00 0f fa 0f f4 0f ee 0f e8 ................
+| 16: 0f e2 0f dc 0f d6 0f d0 00 00 00 00 00 00 00 00 ................
+| 4048: 04 08 03 00 0e 0b 04 07 03 00 0e 06 04 06 03 00 ................
+| 4064: 0e 06 04 05 03 00 0e 0a 04 04 03 00 0e 07 04 03 ................
+| 4080: 03 00 0e 0a 04 02 03 00 0e 0b 04 01 03 00 0e 08 ................
+| page 7 offset 24576
+| 0: 0d 00 00 00 01 0f f7 00 0f f7 00 00 00 00 01 00 ................
+| 4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03 .............E..
+| end crash-58821b8eae6883.db
+}]} {}
+
+do_catchsql_test 49.1 {
+ SAVEPOINT one;
+ DELETE FROM t1 WHERE t1 MATCH 'c*';
+ SELECT matchinfo(t1,'pcx') IS NULL FROM t1 WHERE t1 MATCH 'f*e*';
+} {0 0}
+
+
finish_test
diff --git a/test/fts3corrupt6.test b/test/fts3corrupt6.test
index 5cb0a18691..8788a61d67 100644
--- a/test/fts3corrupt6.test
+++ b/test/fts3corrupt6.test
@@ -64,5 +64,3 @@ do_execsql_test 2.1 {
set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test
-
-
diff --git a/test/fts3join.test b/test/fts3join.test
index f3b9b3639a..9a7994193f 100644
--- a/test/fts3join.test
+++ b/test/fts3join.test
@@ -97,10 +97,10 @@ do_eqp_test 4.2 {
WHERE t4.y = ?;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | `--SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:
- |--SCAN TABLE t4
- `--SEARCH SUBQUERY xxxxxx AS rr USING AUTOMATIC COVERING INDEX (docid=?)
+ |--MATERIALIZE rr
+ | `--SCAN ft4 VIRTUAL TABLE INDEX 3:
+ |--SCAN t4
+ `--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?)
}
finish_test
diff --git a/test/fts3query.test b/test/fts3query.test
index ca3ee6695a..70ee005291 100644
--- a/test/fts3query.test
+++ b/test/fts3query.test
@@ -119,29 +119,29 @@ do_eqp_test fts3query-4.2 {
SELECT t1.number FROM t1, ft WHERE t1.number=ft.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.3 {
SELECT t1.number FROM ft, t1 WHERE t1.number=ft.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.4 {
SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test fts3query-4.5 {
SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}
diff --git a/test/fts3snippet2.test b/test/fts3snippet2.test
index fc39941890..607b01e0f8 100644
--- a/test/fts3snippet2.test
+++ b/test/fts3snippet2.test
@@ -57,4 +57,3 @@ do_execsql_test 2.2 {
set sqlite_fts3_enable_parentheses 0
finish_test
-
diff --git a/test/fts4upfrom.test b/test/fts4upfrom.test
index b1b43a0374..889b64ad68 100644
--- a/test/fts4upfrom.test
+++ b/test/fts4upfrom.test
@@ -137,4 +137,3 @@ foreach {tn create_table} {
}
finish_test
-
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index cb8509e23a..6ec2f8460c 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -936,7 +936,12 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0);
/* Consistent PRNG seed */
+#ifdef SQLITE_TESTCTRL_PRNG_SEED
+ sqlite3_table_column_metadata(cx.db, 0, "x", 0, 0, 0, 0, 0, 0);
+ sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, cx.db);
+#else
sqlite3_randomness(0,0);
+#endif
zSql = sqlite3_malloc( nSql + 1 );
if( zSql==0 ){
@@ -980,6 +985,8 @@ testrun_finished:
sqlite3_memory_used(), nAlloc);
exit(1);
}
+ sqlite3_hard_heap_limit64(0);
+ sqlite3_soft_heap_limit64(0);
return 0;
}
@@ -1428,9 +1435,10 @@ static void showHelp(void){
" --limit-heap N Limit heap memory to N. Default: 100M\n"
" --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
" --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
-" --load-sql ARGS... Load SQL scripts fron files into SOURCE-DB\n"
-" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
-" --load-dbsql ARGS.. Load dbsqlfuzz outputs into the xsql table\n"
+" --load-sql FILE.. Load SQL scripts fron files into SOURCE-DB\n"
+" --load-db FILE.. Load template databases from files into SOURCE_DB\n"
+" --load-dbsql FILE.. Load dbsqlfuzz outputs into the xsql table\n"
+" ^^^^------ Use \"-\" for FILE to read filenames from stdin\n"
" -m TEXT Add a description to the database\n"
" --native-vfs Use the native VFS for initially empty database files\n"
" --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
@@ -1771,10 +1779,25 @@ int main(int argc, char **argv){
rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
if( rc ) fatalError("cannot start a transaction");
for(i=iFirstInsArg; i0 && zLine[kk-1]<=' ' ) kk--;
+ sqlite3_bind_text(pStmt, 1, zLine, kk, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ if( rc ) fatalError("insert failed for %s", zLine);
+ }
+ }else{
+ sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %s\n", argv[i]);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ if( rc ) fatalError("insert failed for %s", argv[i]);
+ }
}
sqlite3_finalize(pStmt);
rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
@@ -2043,7 +2066,8 @@ int main(int argc, char **argv){
}
}
if( bSpinner ){
- printf("\n");
+ int nTotal = g.nDb*g.nSql;
+ printf("\r%s: %d/%d \n", zDbName, nTotal, nTotal);
}else if( !quietFlag && !verboseFlag ){
printf(" 100%% - %d tests\n", g.nDb*g.nSql);
}
diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db
index a5e9084192..a552177591 100644
Binary files a/test/fuzzdata8.db and b/test/fuzzdata8.db differ
diff --git a/test/hook.test b/test/hook.test
index 0b72b2dcff..1dba87f272 100644
--- a/test/hook.test
+++ b/test/hook.test
@@ -1015,4 +1015,3 @@ do_catchsql_test 12.6 {
} {1 {UNIQUE constraint failed: t4.a}}
finish_test
-
diff --git a/test/in4.test b/test/in4.test
index bbb32d8a7a..de8c2d6dbc 100644
--- a/test/in4.test
+++ b/test/in4.test
@@ -330,7 +330,7 @@ do_execsql_test in4-6.1 {
do_execsql_test in4-6.1-eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
-} {~/SCAN TABLE t6a/}
+} {~/SCAN t6a/}
do_execsql_test in4-6.2 {
SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {3 4 4 44}
diff --git a/test/in6.test b/test/in6.test
index 3719a6cbf3..f477f60ef2 100644
--- a/test/in6.test
+++ b/test/in6.test
@@ -97,4 +97,23 @@ do_execsql_test in6-3.110 {
SELECT quote(v5) FROM v0 LEFT JOIN v3 ON v4 = NULL AND v5 IN(0);
} {NULL}
+# 2021-04-29 forum https://sqlite.org/forum/forumpost/6a3ec138e9
+# An early OP_IsNull bypass might skip over the OP_Affinity and
+# cause the OP_IfNoHope to jump on a false-positive, resulting in
+# incomplete output.
+#
+reset_db
+do_execsql_test in6-3.120 {
+ CREATE TABLE t1(a TEXT, b TEXT);
+ INSERT INTO t1 VALUES(null,10),(0,10),(10,10);
+ CREATE INDEX t1ab ON t1(a,b);
+ SELECT quote(a), quote(b), '|' FROM t1 WHERE b in (SELECT a FROM t1) AND a=0;
+} {'0' '10' |}
+do_execsql_test in6-3.130 {
+ CREATE TABLE t2(x TEXT);
+ INSERT INTO t2(x) VALUES(NULL),(0),(10);
+ SELECT quote(x), quote(a), quote(b), 'x'
+ FROM t2 LEFT JOIN t1 ON a=x AND b in (null,0,10);
+} {NULL NULL NULL x '0' '0' '10' x '10' '10' '10' x}
+
finish_test
diff --git a/test/incrvacuum.test b/test/incrvacuum.test
index d2b505efe1..d06005c1f6 100644
--- a/test/incrvacuum.test
+++ b/test/incrvacuum.test
@@ -832,5 +832,61 @@ ifcapable mmap {
set res
} {1 2 3 4}
}
-
+
+# 2021-04-05 dbsqlfuzz cced0668cfd4da4eb2382cb9dd26c17c64aaff76
+#
+# This is an incremental vacuum database that has one free page that
+# needs to be filled. After removing the last page from the end of
+# the database file to fill the free page slot, the last page that
+# is left is the tail of an overflow chain.
+#
+# But the size of the database file is shorter than the actual data
+# so that after incremental vacuum runs, the file is actually too
+# small to hold the last page of the overflow chain.
+#
+# At one point this caused an assertion fault in
+# sqlite3PagerTruncateImage().
+#
+do_test incrvacuum-17.0 {
+ sqlite3 db {}
+ database_may_be_corrupt
+ db deserialize [decode_hexdb {
+| size 20480 pagesize 4096 filename x2.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 05 00 00 00 07 .....@ ........
+| 32: 00 00 00 04 00 00 00 01 00 00 00 03 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 03 00 00 00 01 00 00 00 00 ................
+| 64: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 ................
+| 96: 00 2e 53 60 0d 0f dc 00 01 0f b8 00 0f b8 0f b8 ..S`............
+| 4016: 00 00 00 00 00 00 00 00 22 02 06 17 11 11 01 31 ...............1
+| 4032: 74 61 62 6c 65 74 32 74 32 03 43 52 45 41 54 45 tablet2t2.CREATE
+| 4048: 20 54 41 42 4c 45 20 74 32 28 79 29 00 00 00 24 TABLE t2(y)...$
+| 4064: 11 11 01 31 74 61 62 6c 65 74 31 74 31 03 43 52 ...1tablet1t1.CR
+| 4080: 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 78 29 EATE TABLE t1(x)
+| page 2 offset 4096
+| 0: 01 00 00 00 00 02 00 00 00 00 03 00 00 00 03 04 ................
+| 16: 00 00 00 05 03 00 00 00 03 00 00 00 00 00 00 00 ................
+| page 3 offset 8192
+| 0: 0d 00 00 00 02 05 47 00 08 dd 05 47 00 00 00 00 ......G....G....
+| 1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00 ................
+| 2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01 ................
+| 2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00 ...,............
+| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 ................
+| page 4 offset 12288
+| 0: 00 00 00 00 00 00 00 00 08 dd 05 47 00 00 00 00 ...........G....
+| 1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00 ................
+| 2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01 ................
+| 2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00 ...,............
+| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 ................
+| page 5 offset 16384
+| 0: 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| end x2.db
+}]} {}
+do_catchsql_test incrvacuum-17.1 {
+ PRAGMA writable_schema=ON;
+ PRAGMA incremental_vacuum(10);
+} {0 {}}
+
finish_test
diff --git a/test/index6.test b/test/index6.test
index d385692584..d22c4d47df 100644
--- a/test/index6.test
+++ b/test/index6.test
@@ -158,7 +158,7 @@ do_test index6-2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a=5;
}
-} {/.* TABLE t2 USING INDEX t2a1 .*/}
+} {/(SEARCH|SCAN) t2 USING INDEX t2a1 /}
ifcapable stat4 {
execsql ANALYZE
do_test index6-2.3stat4 {
@@ -166,21 +166,21 @@ ifcapable stat4 {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NOT NULL;
}
- } {/.* TABLE t2 USING INDEX t2a1 .*/}
+ } {/(SEARCH|SCAN) t2 USING INDEX t2a1 /}
} else {
do_test index6-2.3stat4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NOT NULL AND a>0;
}
- } {/.* TABLE t2 USING INDEX t2a1 .*/}
+ } {/(SEARCH|SCANE) t2 USING INDEX t2a1 /}
}
do_test index6-2.4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NULL;
}
-} {~/.*INDEX t2a1.*/}
+} {~/INDEX t2a1/}
do_execsql_test index6-2.101 {
DROP INDEX t2a1;
@@ -319,8 +319,8 @@ do_eqp_test index6-8.1 {
SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
QUERY PLAN
- |--SCAN TABLE t8a
- `--SEARCH TABLE t8b USING INDEX i8c (y=?)
+ |--SCAN t8a
+ `--SEARCH t8b USING INDEX i8c (y=?)
}
do_execsql_test index6-8.2 {
diff --git a/test/index7.test b/test/index7.test
index 084e8c3c7d..eeb36bab5c 100644
--- a/test/index7.test
+++ b/test/index7.test
@@ -113,7 +113,7 @@ do_execsql_test index7-1.7 {
do_execsql_test index7-1.7eqp {
EXPLAIN QUERY PLAN
SELECT b FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
-} {/SEARCH TABLE t1 USING COVERING INDEX bad1 /}
+} {/SEARCH t1 USING COVERING INDEX bad1 /}
do_execsql_test index7-1.8 {
DELETE FROM t1 WHERE c>=101;
DROP INDEX IF EXISTS bad1;
@@ -202,28 +202,28 @@ do_test index7-2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a=5;
}
-} {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
+} {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
ifcapable stat4 {
do_test index7-2.3stat4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NOT NULL;
}
- } {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
+ } {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
} else {
do_test index7-2.3stat4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NOT NULL AND a>0;
}
- } {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
+ } {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
}
do_test index7-2.4 {
execsql {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a IS NULL;
}
-} {~/.*INDEX t2a1.*/}
+} {~/INDEX t2a1/}
do_execsql_test index7-2.101 {
DROP INDEX t2a1;
@@ -321,7 +321,7 @@ do_execsql_test index7-6.3 {
}
do_eqp_test index7-6.4 {
SELECT * FROM v4 WHERE d='xyz' AND c='def'
-} {SEARCH TABLE t4 USING INDEX i4 (c=?)}
+} {SEARCH t4 USING INDEX i4 (c=?)}
do_catchsql_test index7-6.5 {
CREATE INDEX t5a ON t5(a) WHERE a=#1;
@@ -349,7 +349,7 @@ do_execsql_test index7-8.1 {
INSERT INTO t1(x) VALUES(1),(2);
ANALYZE;
EXPLAIN QUERY PLAN SELECT 1 FROM t1 WHERE y=5;
-} {/SEARCH TABLE t1 USING COVERING INDEX t1y/}
+} {/SEARCH t1 USING COVERING INDEX t1y/}
finish_test
diff --git a/test/index8.test b/test/index8.test
index bb58228527..41ccf4bbcf 100644
--- a/test/index8.test
+++ b/test/index8.test
@@ -41,7 +41,7 @@ do_execsql_test 1.0 {
do_execsql_test 1.0eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
-} {/SCAN TABLE t1 USING INDEX t1abc/}
+} {/SCAN t1 USING INDEX t1abc/}
# If we change the index so that it no longer covers the WHERE clause,
# then we should (correctly) revert to using a table scan.
diff --git a/test/indexedby.test b/test/indexedby.test
index 41a52d8224..6a371112b3 100644
--- a/test/indexedby.test
+++ b/test/indexedby.test
@@ -42,16 +42,16 @@ proc EQP {sql} {
#
do_eqp_test indexedby-1.2 {
select * from t1 WHERE a = 10;
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-1.3 {
select * from t1 ;
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test indexedby-1.4 {
select * from t1, t2 WHERE c = 10;
} {
QUERY PLAN
- |--SEARCH TABLE t2 USING INDEX i3 (c=?)
- `--SCAN TABLE t1
+ |--SEARCH t2 USING INDEX i3 (c=?)
+ `--SCAN t1
}
# Parser tests. Test that an INDEXED BY or NOT INDEX clause can be
@@ -118,21 +118,21 @@ do_test indexedby-2.7 {
#
do_eqp_test indexedby-3.1 {
SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
-} {/SEARCH TABLE t1 USING INDEX/}
+} {/SEARCH t1 USING INDEX/}
do_eqp_test indexedby-3.1.1 {
SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test indexedby-3.1.2 {
SELECT * FROM t1 NOT INDEXED WHERE rowid=1
-} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
+} {/SEARCH t1 USING INTEGER PRIMARY KEY .rowid=/}
do_eqp_test indexedby-3.2 {
SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-3.3 {
SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
-} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
+} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-3.4 {
catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
} {0 {}}
@@ -148,10 +148,10 @@ do_test indexedby-3.7 {
do_eqp_test indexedby-3.8 {
SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e
-} {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}
+} {SCAN t3 USING INDEX sqlite_autoindex_t3_1}
do_eqp_test indexedby-3.9 {
SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10
-} {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
+} {SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
do_test indexedby-3.10 {
catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
} {0 {}}
@@ -165,15 +165,15 @@ do_eqp_test indexedby-4.1 {
SELECT * FROM t1, t2 WHERE a = c
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SEARCH TABLE t2 USING INDEX i3 (c=?)
+ |--SCAN t1
+ `--SEARCH t2 USING INDEX i3 (c=?)
}
do_eqp_test indexedby-4.2 {
SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c
} {
QUERY PLAN
- |--SCAN TABLE t1 USING INDEX i1
- `--SEARCH TABLE t2 USING INDEX i3 (c=?)
+ |--SCAN t1 USING INDEX i1
+ `--SEARCH t2 USING INDEX i3 (c=?)
}
do_test indexedby-4.3 {
catchsql {
@@ -193,10 +193,10 @@ do_test indexedby-4.4 {
do_execsql_test indexedby-5.1 {
CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
EXPLAIN QUERY PLAN SELECT * FROM v2
-} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
+} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_execsql_test indexedby-5.2 {
EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10
-} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
+} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_test indexedby-5.3 {
execsql { DROP INDEX i1 }
catchsql { SELECT * FROM v2 }
@@ -217,10 +217,10 @@ do_test indexedby-5.5 {
#
do_eqp_test indexedby-6.1 {
SELECT * FROM t1 WHERE b = 10 ORDER BY rowid
-} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
+} {SEARCH t1 USING INDEX i2 (b=?)}
do_eqp_test indexedby-6.2 {
SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid
-} {SCAN TABLE t1}
+} {SCAN t1}
# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
# query planner to use a particular named index on a DELETE, SELECT, or
@@ -230,19 +230,19 @@ do_eqp_test indexedby-6.2 {
#
do_eqp_test indexedby-7.1 {
DELETE FROM t1 WHERE a = 5
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.2 {
DELETE FROM t1 NOT INDEXED WHERE a = 5
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test indexedby-7.3 {
DELETE FROM t1 INDEXED BY i1 WHERE a = 5
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.4 {
DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.5 {
DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
-} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
+} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-7.6 {
catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
} {0 {}}
@@ -251,19 +251,19 @@ do_test indexedby-7.6 {
#
do_eqp_test indexedby-8.1 {
UPDATE t1 SET rowid=rowid+1 WHERE a = 5
-} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
+} {SEARCH t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.2 {
UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test indexedby-8.3 {
UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5
-} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
+} {SEARCH t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.4 {
UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-8.5 {
UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10
-} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
+} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-8.6 {
catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
} {0 {}}
@@ -338,7 +338,7 @@ do_execsql_test 11.4 {
} {1 1 3}
do_eqp_test 11.5 {
SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
-} {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}
+} {SEARCH x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}
do_execsql_test 11.6 {
CREATE TABLE x2(c INTEGER PRIMARY KEY, a, b TEXT);
@@ -359,7 +359,7 @@ do_execsql_test 11.9 {
} {1 1 3}
do_eqp_test 11.10 {
SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
-} {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}
+} {SEARCH x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}
#-------------------------------------------------------------------------
# Check INDEXED BY works (throws an exception) with partial indexes that
diff --git a/test/indexexpr1.test b/test/indexexpr1.test
index 19c2573509..a31b876955 100644
--- a/test/indexexpr1.test
+++ b/test/indexexpr1.test
@@ -97,14 +97,14 @@ do_execsql_test indexexpr1-170 {
do_execsql_test indexexpr1-170eqp {
EXPLAIN QUERY PLAN
SELECT length(a) FROM t1 ORDER BY length(a);
-} {/SCAN TABLE t1 USING INDEX t1alen/}
+} {/SCAN t1 USING INDEX t1alen/}
do_execsql_test indexexpr1-171 {
SELECT length(a) FROM t1 ORDER BY length(a) DESC;
} {52 38 29 27 25 20}
do_execsql_test indexexpr1-171eqp {
EXPLAIN QUERY PLAN
SELECT length(a) FROM t1 ORDER BY length(a) DESC;
-} {/SCAN TABLE t1 USING INDEX t1alen/}
+} {/SCAN t1 USING INDEX t1alen/}
do_execsql_test indexexpr1-200 {
DROP TABLE t1;
diff --git a/test/indexexpr2.test b/test/indexexpr2.test
index 35caef3c24..8c1171e038 100644
--- a/test/indexexpr2.test
+++ b/test/indexexpr2.test
@@ -93,7 +93,7 @@ ifcapable json1 {
ORDER BY json_extract(x, '$.b') COLLATE nocase;
} [string map {"\n " \n} {
QUERY PLAN
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR GROUP BY
}]
@@ -108,7 +108,7 @@ ifcapable json1 {
ORDER BY json_extract(x, '$.b') COLLATE nocase;
} [string map {"\n " \n} {
QUERY PLAN
- |--SEARCH TABLE t3 USING INDEX i3 (=?)
+ |--SEARCH t3 USING INDEX i3 (=?)
`--USE TEMP B-TREE FOR GROUP BY
}]
}
@@ -154,7 +154,7 @@ do_execsql_test 3.4.5 {
do_execsql_test 3.4.5eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE nocase;
-} {/SCAN TABLE t4 USING INDEX i4/}
+} {/SCAN t4 USING INDEX i4/}
do_execsql_test 3.4.6 {
SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary;
} {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4}
@@ -265,7 +265,7 @@ do_execsql_test 6.1.2 {
} {1 123 2 123 3 123abc 4 123.0}
do_eqp_test 6.1.3 {
SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
-} {SEARCH TABLE x1 USING INDEX x1i (=?)}
+} {SEARCH x1 USING INDEX x1i (=?)}
do_execsql_test 6.2.1 {
SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
@@ -276,7 +276,7 @@ do_execsql_test 6.2.2 {
} {1 123 2 123}
do_eqp_test 6.2.3 {
SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
-} {SEARCH TABLE x1 USING INDEX x1i2 (=?)}
+} {SEARCH x1 USING INDEX x1i2 (=?)}
do_execsql_test 7.0 {
CREATE TABLE IF NOT EXISTS t0(c0);
diff --git a/test/intpkey.test b/test/intpkey.test
index a56cab4c69..d6b8833a27 100644
--- a/test/intpkey.test
+++ b/test/intpkey.test
@@ -129,7 +129,7 @@ do_test intpkey-1.12.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a==4;
}
-} {/SEARCH TABLE t1 /}
+} {/SEARCH t1 /}
# Try to insert a non-integer value into the primary key field. This
# should result in a data type mismatch.
diff --git a/test/join2.test b/test/join2.test
index f004fda071..170000ca27 100644
--- a/test/join2.test
+++ b/test/join2.test
@@ -113,16 +113,16 @@ do_eqp_test 3.1 {
SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3);
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test 3.2 {
SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3);
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
#-------------------------------------------------------------------------
@@ -161,16 +161,16 @@ do_eqp_test 4.1.5 {
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
QUERY PLAN
- |--SCAN TABLE c1
- |--SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)
- `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN c1
+ |--SEARCH c2 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test 4.1.6 {
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
QUERY PLAN
- |--SCAN TABLE c1
- `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN c1
+ `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}
do_execsql_test 4.2.0 {
@@ -208,16 +208,16 @@ do_eqp_test 4.2.5 {
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
QUERY PLAN
- |--SCAN TABLE c1
- |--SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
- `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
+ |--SCAN c1
+ |--SEARCH c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
+ `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}
do_eqp_test 4.2.6 {
SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
QUERY PLAN
- |--SCAN TABLE c1
- `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
+ |--SCAN c1
+ `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}
# 2017-11-23 (Thanksgiving day)
@@ -251,11 +251,11 @@ do_execsql_test 5.0 {
}
do_eqp_test 5.1 {
SELECT s1.a FROM s1 left join s2 using (a);
-} {SCAN TABLE s1}
+} {SCAN s1}
do_eqp_test 5.2 {
SELECT s1.a FROM s1 left join s3 using (a);
-} {SCAN TABLE s1}
+} {SCAN s1}
do_execsql_test 6.0 {
CREATE TABLE u1(a INTEGER PRIMARY KEY, b, c);
@@ -264,7 +264,7 @@ do_execsql_test 6.0 {
}
do_eqp_test 6.1 {
SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c );
-} {SCAN TABLE u2}
+} {SCAN u2}
db close
sqlite3 db :memory:
diff --git a/test/join5.test b/test/join5.test
index 6724419e6d..e2ff2f6c27 100644
--- a/test/join5.test
+++ b/test/join5.test
@@ -277,12 +277,12 @@ do_eqp_test 7.2 {
);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
+ | `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
`--INDEX 2
- `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
+ `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
}
do_execsql_test 7.3 {
@@ -302,8 +302,8 @@ do_eqp_test 7.4 {
SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
} {
QUERY PLAN
- |--SCAN TABLE t3
- `--SEARCH TABLE t4 USING INDEX t4xz (x=?)
+ |--SCAN t3
+ `--SEARCH t4 USING INDEX t4xz (x=?)
}
reset_db
diff --git a/test/like.test b/test/like.test
index 8ea7cff782..e8662dc6c3 100644
--- a/test/like.test
+++ b/test/like.test
@@ -168,13 +168,13 @@ proc queryplan {sql} {
set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
# puts eqp=$eqp
foreach {a b c x} $eqp {
- if {[regexp { TABLE (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
- $x all as tab idx]} {
+ if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data {} $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
- $x all as tab idx]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data $tab $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
lappend data $tab *
}
}
@@ -726,7 +726,7 @@ ifcapable like_opt&&!icu {
set res [sqlite3_exec_hex db {
EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
}]
- regexp {SCAN TABLE t2} $res
+ regexp {SCAN t2} $res
} {1}
}
do_test like-9.5.1 {
@@ -1036,16 +1036,18 @@ do_test like-14.1 {
set x [lindex [time {
db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'GLOB'*a*a*a*a*a*a*a*a*y'}
}] 0]
- puts -nonewline " ($x ms - want less than 1000) "
- expr {$x<1000}
+ set tlimit [expr {1000 * $::sqlite_options(configslower)}]
+ puts -nonewline " ($x ms - want less than $tlimit) "
+ expr {$x<$tlimit}
} {1}
ifcapable !icu {
do_test like-14.2 {
set x [lindex [time {
db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'LIKE'%a%a%a%a%a%a%a%a%y'}
}] 0]
- puts -nonewline " ($x ms - want less than 1000) "
- expr {$x<1000}
+ set tlimit [expr {1000 * $::sqlite_options(configslower)}]
+ puts -nonewline " ($x ms - want less than $tlimit) "
+ expr {$x<$tlimit}
} {1}
}
diff --git a/test/like3.test b/test/like3.test
index 3bfe30c318..a93e113d62 100644
--- a/test/like3.test
+++ b/test/like3.test
@@ -125,7 +125,7 @@ do_eqp_test like3-5.101 {
SELECT x FROM t5a WHERE x LIKE '/%';
} {
QUERY PLAN
- `--SCAN TABLE t5a
+ `--SCAN t5a
}
do_execsql_test like3-5.110 {
SELECT x FROM t5a WHERE x LIKE '/a%';
@@ -135,7 +135,7 @@ do_eqp_test like3-5.111 {
SELECT x FROM t5a WHERE x LIKE '/a%';
} {
QUERY PLAN
- `--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x)
+ `--SEARCH t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x)
}
}
do_execsql_test like3-5.120 {
@@ -145,7 +145,7 @@ do_eqp_test like3-5.121 {
SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {
QUERY PLAN
- `--SCAN TABLE t5a
+ `--SCAN t5a
}
do_execsql_test like3-5.122 {
SELECT x FROM t5a WHERE x LIKE '^-2%' ESCAPE '^';
@@ -154,7 +154,7 @@ do_eqp_test like3-5.123 {
SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {
QUERY PLAN
- `--SCAN TABLE t5a
+ `--SCAN t5a
}
do_execsql_test like3-5.200 {
@@ -166,7 +166,7 @@ do_eqp_test like3-5.201 {
SELECT x FROM t5b WHERE x GLOB '/*';
} {
QUERY PLAN
- `--SCAN TABLE t5b
+ `--SCAN t5b
}
do_execsql_test like3-5.210 {
SELECT x FROM t5b WHERE x GLOB '/a*';
@@ -175,7 +175,7 @@ do_eqp_test like3-5.211 {
SELECT x FROM t5b WHERE x GLOB '/a*';
} {
QUERY PLAN
- `--SEARCH TABLE t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x)
+ `--SEARCH t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x)
}
# 2019-05-01
@@ -234,13 +234,13 @@ do_eqp_test like3-6.110 {
SELECT * FROM t1 WHERE path LIKE 'a%';
} {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path)
+ `--SEARCH t1 USING PRIMARY KEY (path>? AND path)
}
do_eqp_test like3-6.120 {
SELECT * FROM t1 WHERE path LIKE 'a%' ESCAPE 'x';
} {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path)
+ `--SEARCH t1 USING PRIMARY KEY (path>? AND path)
}
do_execsql_test like3-6.200 {
DROP TABLE IF EXISTS t2;
@@ -252,26 +252,26 @@ do_eqp_test like3-6.210 {
SELECT * FROM t2 WHERE path LIKE 'a%';
} {
QUERY PLAN
- `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path)
+ `--SEARCH t2 USING INDEX t2path (path>? AND path)
}
do_eqp_test like3-6.220 {
SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
QUERY PLAN
- `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path)
+ `--SEARCH t2 USING INDEX t2path (path>? AND path)
}
db eval {PRAGMA case_sensitive_like=ON}
do_eqp_test like3-6.230 {
SELECT * FROM t2 WHERE path LIKE 'a%';
} {
QUERY PLAN
- `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path)
+ `--SEARCH t2 USING INDEX t2path2 (path>? AND path)
}
do_eqp_test like3-6.240 {
SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
QUERY PLAN
- `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path)
+ `--SEARCH t2 USING INDEX t2path2 (path>? AND path)
}
}
diff --git a/test/mallocK.test b/test/mallocK.test
index 139644d834..567a4c1f9d 100644
--- a/test/mallocK.test
+++ b/test/mallocK.test
@@ -123,7 +123,7 @@ ifcapable stat4 {
SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx';
} [string map {"\n " \n} {
QUERY PLAN
- |--SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b)
+ |--SEARCH t3 USING INDEX i3 (ANY(a) AND b>? AND b)
`--USE TEMP B-TREE FOR DISTINCT
}]
}
diff --git a/test/memdb1.test b/test/memdb1.test
index 81e9359211..ae2f5d50d1 100644
--- a/test/memdb1.test
+++ b/test/memdb1.test
@@ -157,6 +157,16 @@ do_execsql_test 410 {
PRAGMA integrity_check;
SELECT * FROM t4;
} {ok hello world!}
+do_execsql_test 420 {
+ PRAGMA journal_mode=TRUNCATE;
+ PRAGMA journal_mode=OFF;
+ PRAGMA journal_mode=DELETE;
+ PRAGMA journal_mode=WAL;
+ PRAGMA journal_mode=PERSIST;
+ PRAGMA journal_mode=MEMORY;
+ PRAGMA journal_mode=OFF;
+ PRAGMA journal_mode=DELETE;
+} {truncate off delete delete persist memory off delete}
# Deserialize something that is not a database.
#
diff --git a/test/minmax.test b/test/minmax.test
index 04a3f06dff..295fac4e93 100644
--- a/test/minmax.test
+++ b/test/minmax.test
@@ -294,17 +294,22 @@ do_test minmax-8.2 {
# is a subquery.
#
ifcapable {compound && subquery} {
+ do_test minmax-9.0 {
+ execsql {
+ SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
+ }
+ } {3}
do_test minmax-9.1 {
execsql {
- SELECT max(rowid) FROM (
- SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
+ SELECT max(yy) FROM (
+ SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
)
}
- } {{}}
+ } {3}
do_test minmax-9.2 {
execsql {
- SELECT max(rowid) FROM (
- SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
+ SELECT max(yy) FROM (
+ SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
)
}
} {{}}
diff --git a/test/minmax2.test b/test/minmax2.test
index 5129146259..9ea6b679c6 100644
--- a/test/minmax2.test
+++ b/test/minmax2.test
@@ -283,17 +283,22 @@ do_test minmax2-8.2 {
# is a subquery.
#
ifcapable {compound && subquery} {
+ do_test minmax2-9.0 {
+ execsql {
+ SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
+ }
+ } {3}
do_test minmax2-9.1 {
execsql {
- SELECT max(rowid) FROM (
- SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
+ SELECT max(yy) FROM (
+ SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
)
}
- } {{}}
+ } {3}
do_test minmax2-9.2 {
execsql {
- SELECT max(rowid) FROM (
- SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
+ SELECT max(yy) FROM (
+ SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
)
}
} {{}}
diff --git a/test/misc2.test b/test/misc2.test
index bb544c5fbb..4796d5d374 100644
--- a/test/misc2.test
+++ b/test/misc2.test
@@ -54,19 +54,22 @@ do_test misc2-2.1 {
}
} {}
ifcapable subquery {
- do_test misc2-2.2 {
- execsql {
- SELECT rowid, * FROM (SELECT * FROM t1, t2);
- }
- } {{} 1 2 3 7 8 9}
+ do_catchsql_test misc2-2.2 {
+ SELECT rowid, * FROM (SELECT * FROM t1, t2);
+ } {1 {no such column: rowid}}
+ do_catchsql_test misc2-2.2b {
+ SELECT 'rowid', * FROM (SELECT * FROM t1, t2);
+ } {0 {rowid 1 2 3 7 8 9}}
}
+
ifcapable view {
- do_test misc2-2.3 {
- execsql {
- CREATE VIEW v1 AS SELECT * FROM t1, t2;
- SELECT rowid, * FROM v1;
- }
- } {{} 1 2 3 7 8 9}
+ do_catchsql_test misc2-2.3 {
+ CREATE VIEW v1 AS SELECT * FROM t1, t2;
+ SELECT rowid, * FROM v1;
+ } {1 {no such column: rowid}}
+ do_catchsql_test misc2-2.3b {
+ SELECT 'rowid', * FROM v1;
+ } {0 {rowid 1 2 3 7 8 9}}
} ;# ifcapable view
# Ticket #2002 and #1952.
diff --git a/test/misc7.test b/test/misc7.test
index 25f96af34c..add9014b08 100644
--- a/test/misc7.test
+++ b/test/misc7.test
@@ -280,19 +280,19 @@ ifcapable explain {
SELECT * FROM abc AS t2 WHERE rowid = 1;
} {
QUERY PLAN
- `--SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test misc7-14.2 {
SELECT * FROM abc AS t2 WHERE a = 1;
} {
QUERY PLAN
- `--SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
+ `--SEARCH t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
}
do_eqp_test misc7-14.3 {
SELECT * FROM abc AS t2 ORDER BY a;
} {
QUERY PLAN
- `--SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1
+ `--SCAN t2 USING INDEX sqlite_autoindex_abc_1
}
}
diff --git a/test/misc8.test b/test/misc8.test
index b0308adab3..32b3a597dc 100644
--- a/test/misc8.test
+++ b/test/misc8.test
@@ -100,7 +100,7 @@ do_execsql_test misc8-2.1 {
# 2016-02-26: An assertion fault found by the libFuzzer project
#
-do_execsql_test misc8-3.0 {
+do_catchsql_test misc8-3.0 {
SELECT *
FROM
(
@@ -110,7 +110,7 @@ do_execsql_test misc8-3.0 {
(SELECT 6 AS j UNION ALL SELECT 7) AS x4
WHERE i'xray' RETURNING a, b, '@';
+} {1 9 @ happy glad @}
+do_execsql_test 11.4 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {I1 1 2 I1 happy glad U1 1 9 D1 1 9 D1 happy glad}
+do_execsql_test 11.5 {
+ INSERT INTO t2 VALUES('bravo','charlie') RETURNING d, c, 'z';
+} {charlie bravo z}
+do_execsql_test 11.6 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {I2 bravo charlie}
+do_execsql_test 11.7 {
+ INSERT INTO t3(e) VALUES(1),(2),(3) RETURNING 'I', e;
+ UPDATE t3 SET f=e+100 RETURNING 'U', e, f;
+ DELETE FROM t3 WHERE f>100 RETURNING 'D', e, f;
+} {I 1 I 2 I 3 U 1 101 U 2 102 U 3 103 D 1 101 D 2 102 D 3 103}
+do_execsql_test 11.6 {
+ SELECT * FROM log;
+ DELETE FROM log;
+} {U3 1 101 U3 2 102 U3 3 103 D3 1 101 D3 2 102 D3 3 103}
+
+reset_db
+do_execsql_test 11.11 {
+ CREATE TEMP TABLE t1(a,b);
+ CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN SELECT 1; END;
+ DELETE FROM t1 RETURNING *;
+ DROP TRIGGER r1;
+ INSERT INTO t1 VALUES(5,30);
+} {}
+do_execsql_test 11.12 {
+ SELECT * FROM t1;
+} {5 30}
+
+# RETURNING column names are dequoted.
+# https://sqlite.org/forum/forumpost/033daf0b32
+#
+reset_db
+do_test 12.1 {
+ db eval {CREATE TABLE t1(x INT, y INT)}
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(1) RETURNING "x";} cname {}
+ lsort [array names cname]
+} {* x}
+do_test 12.2 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(2) RETURNING [x];} cname {}
+ lsort [array names cname]
+} {* x}
+do_test 12.3 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x) VALUES(3) RETURNING x AS [xyz];} cname {}
+ lsort [array names cname]
+} {* xyz}
+do_test 12.4 {
+ unset -nocomplain cname
+ db eval {INSERT INTO t1(x,y) VALUES(4,5) RETURNING "x"+"y";} cname {}
+ lsort [array names cname]
+} {{"x"+"y"} *}
+
+finish_test
diff --git a/test/rollback2.test b/test/rollback2.test
index 70aecc3377..21ebdeaca0 100644
--- a/test/rollback2.test
+++ b/test/rollback2.test
@@ -101,7 +101,7 @@ do_rollback_test 2.2 -setup {
#
do_eqp_test 3.1 {
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
-} {SCAN TABLE t1 USING INDEX i1}
+} {SCAN t1 USING INDEX i1}
do_rollback_test 3.2 -setup {
BEGIN;
DELETE FROM t1 WHERE (i%2)==1;
@@ -131,7 +131,7 @@ do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; }
do_eqp_test 4.2 {
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
-} {SCAN TABLE t1 USING INDEX i1}
+} {SCAN t1 USING INDEX i1}
do_rollback_test 4.3 -setup {
BEGIN;
DELETE FROM t1 WHERE (i%2)==1;
diff --git a/test/rowvalue.test b/test/rowvalue.test
index b9967a865a..79cde62762 100644
--- a/test/rowvalue.test
+++ b/test/rowvalue.test
@@ -175,19 +175,19 @@ do_execsql_test 7.0 {
foreach {tn sql res eqp} {
1 "SELECT * FROM xy WHERE (i, j) IS (2, 2)" {2 2 2}
- "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)"
+ "SEARCH xy USING INTEGER PRIMARY KEY (rowid=?)"
2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
- "SCAN TABLE xy"
+ "SCAN xy"
3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
- "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid)"
+ "SEARCH xy USING INTEGER PRIMARY KEY (rowid)"
4 "SELECT * FROM xy WHERE (i, j) > (2, 1)" {2 2 2 3 3 3 4 4 4}
- "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
+ "SEARCH xy USING INTEGER PRIMARY KEY (rowid>?)"
5 "SELECT * FROM xy WHERE (i, j) > ('2', 1)" {2 2 2 3 3 3 4 4 4}
- "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
+ "SEARCH xy USING INTEGER PRIMARY KEY (rowid>?)"
} {
do_eqp_test 7.$tn.1 $sql $eqp
diff --git a/test/rowvalue4.test b/test/rowvalue4.test
index 2929a97d10..784859cb19 100644
--- a/test/rowvalue4.test
+++ b/test/rowvalue4.test
@@ -185,31 +185,31 @@ ifcapable stat4 {
}
do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } \
- {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
+ {SEARCH c1 USING INDEX c1cd (c=?)}
do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \
- {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
+ {SEARCH c1 USING INDEX c1cd (c=?)}
do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } \
- {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
+ {SEARCH c1 USING INDEX c1ab (a=? AND b>?)}
do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
- {SEARCH TABLE c1 USING INDEX c1cd (c>?)}
+ {SEARCH c1 USING INDEX c1cd (c>?)}
do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \
- {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
+ {SEARCH c1 USING INDEX c1ab (a=?)}
do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
- {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
+ {SEARCH c1 USING INDEX c1ab (a=?)}
do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \
- {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
+ {SEARCH c1 USING INDEX c1ab (a=?)}
do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \
- {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
+ {SEARCH c1 USING INDEX c1cd ((c,d)>(?,?))}
do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \
- {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
+ {SEARCH c1 USING INDEX c1ab (a=?)}
}
@@ -234,11 +234,11 @@ do_eqp_test 5.1 {
(c) IN (SELECT y FROM d1)
} {
QUERY PLAN
- |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)
+ |--SEARCH d2 USING INDEX d2ab (a=? AND b=?)
|--LIST SUBQUERY xxxxxx
- | `--SCAN TABLE d1
+ | `--SCAN d1
`--LIST SUBQUERY xxxxxx
- `--SCAN TABLE d1
+ `--SCAN d1
}
do_execsql_test 6.0 {
@@ -249,23 +249,23 @@ do_execsql_test 6.0 {
do_eqp_test 6.1 {
SELECT * FROM e1 WHERE (a, b) > (?, ?)
-} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
+} {SEARCH e1 USING INDEX e1ab ((a,b)>(?,?))}
do_eqp_test 6.2 {
SELECT * FROM e1 WHERE (a, b) < (?, ?)
-} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
+} {SEARCH e1 USING INDEX e1ab ((a,b)<(?,?))}
do_eqp_test 6.3 {
SELECT * FROM e1 WHERE c = ? AND (d, e) > (?, ?)
-} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
+} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
do_eqp_test 6.4 {
SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?)
-} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
+} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
do_eqp_test 6.5 {
SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ?
-} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
+} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
#-------------------------------------------------------------------------
diff --git a/test/scanstatus.test b/test/scanstatus.test
index 1b92ef3fe1..46249f665d 100644
--- a/test/scanstatus.test
+++ b/test/scanstatus.test
@@ -45,8 +45,8 @@ proc do_scanstatus_test {tn res} {
do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
do_scanstatus_test 1.2 {
- nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN TABLE t1}
- nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN TABLE t2}
+ nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN t1}
+ nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN t2}
}
do_execsql_test 1.3 {
@@ -54,8 +54,8 @@ do_execsql_test 1.3 {
SELECT count(*) FROM t1, t2;
} 6
do_scanstatus_test 1.4 {
- nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
- nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN TABLE t2}
+ nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN t1}
+ nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN t2}
}
do_execsql_test 1.5 { ANALYZE }
@@ -64,8 +64,8 @@ do_execsql_test 1.6 {
} 4
do_scanstatus_test 1.7 {
nLoop 1 nVisit 2 nEst 2.0 zName t2 zExplain
- {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
+ {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
+ nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN t1}
}
do_execsql_test 1.8 {
@@ -74,8 +74,8 @@ do_execsql_test 1.8 {
do_scanstatus_test 1.9 {
nLoop 2 nVisit 4 nEst 2.0 zName t2 zExplain
- {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
+ {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
+ nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN t1}
}
do_test 1.9 {
@@ -84,8 +84,8 @@ do_test 1.9 {
do_scanstatus_test 1.10 {
nLoop 0 nVisit 0 nEst 2.0 zName t2 zExplain
- {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
+ {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
+ nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN t1}
}
#-------------------------------------------------------------------------
@@ -105,7 +105,7 @@ do_execsql_test 2.1 {
do_scanstatus_test 2.2 {
nLoop 1 nVisit 1 nEst 1.0 zName x1
- zExplain {SEARCH TABLE x1 USING INTEGER PRIMARY KEY (rowid=?)}
+ zExplain {SEARCH x1 USING INTEGER PRIMARY KEY (rowid=?)}
}
do_execsql_test 2.3.1 {
@@ -113,7 +113,7 @@ do_execsql_test 2.3.1 {
} {2 two}
do_scanstatus_test 2.3.2 {
nLoop 1 nVisit 1 nEst 10.0 zName x1j
- zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j=?)}
+ zExplain {SEARCH x1 USING COVERING INDEX x1j (j=?)}
}
do_execsql_test 2.4.1 {
@@ -121,7 +121,7 @@ do_execsql_test 2.4.1 {
} {4 four 1 one 3 three}
do_scanstatus_test 2.4.2 {
nLoop 1 nVisit 3 nEst 262144.0 zName x1j
- zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j)}
+ zExplain {SEARCH x1 USING COVERING INDEX x1j (j)}
}
do_execsql_test 2.5.1 {
@@ -129,7 +129,7 @@ do_execsql_test 2.5.1 {
} {2 two}
do_scanstatus_test 2.5.2 {
nLoop 1 nVisit 1 nEst 262144.0 zName x1j
- zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>?)}
+ zExplain {SEARCH x1 USING COVERING INDEX x1j (j>?)}
}
do_execsql_test 2.6.1 {
@@ -137,7 +137,7 @@ do_execsql_test 2.6.1 {
} {3 three 2 two}
do_scanstatus_test 2.6.2 {
nLoop 1 nVisit 2 nEst 16384.0 zName x1j
- zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j)}
+ zExplain {SEARCH x1 USING COVERING INDEX x1j (j>? AND j)}
}
do_execsql_test 2.7.1 {
@@ -150,7 +150,7 @@ do_execsql_test 2.7.1 {
do_scanstatus_test 2.7.2 {
nLoop 1 nVisit 2 nEst 16384.0 zName x2j
- zExplain {SEARCH TABLE x2 USING INDEX x2j (j>? AND j)}
+ zExplain {SEARCH x2 USING INDEX x2j (j>? AND j)}
}
do_execsql_test 2.8.1 {
@@ -158,7 +158,7 @@ do_execsql_test 2.8.1 {
}
do_scanstatus_test 2.8.2 {
nLoop 1 nVisit 0 nEst 8.0 zName x2ij
- zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
+ zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}
do_execsql_test 2.9.1 {
@@ -166,7 +166,7 @@ do_execsql_test 2.9.1 {
}
do_scanstatus_test 2.9.2 {
nLoop 1 nVisit 0 nEst 8.0 zName x2ij
- zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
+ zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}
do_execsql_test 2.10.1 {
@@ -174,7 +174,7 @@ do_execsql_test 2.10.1 {
} {3 three {3 three}}
do_scanstatus_test 2.10.2 {
nLoop 1 nVisit 1 nEst 8.0 zName x2ij
- zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
+ zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}
#-------------------------------------------------------------------------
@@ -194,9 +194,9 @@ do_execsql_test 3.2.1 {
} {4 13}
do_scanstatus_test 3.2.2 {
nLoop 1 nVisit 1 nEst 10.0 zName a1a
- zExplain {SEARCH TABLE a1 USING INDEX a1a (a=?)}
+ zExplain {SEARCH a1 USING INDEX a1a (a=?)}
nLoop 1 nVisit 1 nEst 10.0 zName a1bc
- zExplain {SEARCH TABLE a1 USING INDEX a1bc (b=?)}
+ zExplain {SEARCH a1 USING INDEX a1bc (b=?)}
}
do_execsql_test 3.2.1 {
@@ -204,9 +204,9 @@ do_execsql_test 3.2.1 {
} {30}
do_scanstatus_test 3.2.2 {
nLoop 1 nVisit 9 nEst 16384.0 zName a1a
- zExplain {SEARCH TABLE a1 USING INDEX a1a (a>? AND a)}
+ zExplain {SEARCH a1 USING INDEX a1a (a>? AND a)}
nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
- zExplain {SEARCH TABLE a1 USING INDEX a1bc (b>? AND b)}
+ zExplain {SEARCH a1 USING INDEX a1bc (b>? AND b)}
}
do_execsql_test 3.3.1 {
@@ -215,9 +215,9 @@ do_execsql_test 3.3.1 {
} {90}
do_scanstatus_test 3.2.2 {
nLoop 1 nVisit 10 nEst 16384.0 zName a1bc
- zExplain {SEARCH TABLE a1 AS y USING COVERING INDEX a1bc (b>? AND b)}
+ zExplain {SEARCH y USING COVERING INDEX a1bc (b>? AND b)}
nLoop 10 nVisit 90 nEst 16384.0 zName a1a
- zExplain {SEARCH TABLE a1 AS x USING COVERING INDEX a1a (a>? AND a)}
+ zExplain {SEARCH x USING COVERING INDEX a1a (a>? AND a)}
}
do_execsql_test 3.4.1 {
@@ -225,7 +225,7 @@ do_execsql_test 3.4.1 {
} {4}
do_scanstatus_test 3.4.2 {
nLoop 1 nVisit 4 nEst 40.0 zName a1a
- zExplain {SEARCH TABLE a1 USING COVERING INDEX a1a (a=?)}
+ zExplain {SEARCH a1 USING COVERING INDEX a1a (a=?)}
}
do_execsql_test 3.4.1 {
@@ -233,7 +233,7 @@ do_execsql_test 3.4.1 {
} {4}
do_scanstatus_test 3.4.2 {
nLoop 1 nVisit 4 nEst 4.0 zName a1
- zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)}
+ zExplain {SEARCH a1 USING INTEGER PRIMARY KEY (rowid=?)}
}
#-------------------------------------------------------------------------
@@ -266,9 +266,9 @@ do_execsql_test 4.2 {
do_execsql_test 4.2.1 { DELETE FROM p1 WHERE x=4 }
do_scanstatus_test 4.2.2 {
nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1
- zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}
+ zExplain {SEARCH p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}
- nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN TABLE c1}
+ nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN c1}
}
#-------------------------------------------------------------------------
@@ -313,9 +313,9 @@ do_execsql_test 5.1.1 {
} {2}
do_scanstatus_test 5.1.2 {
nLoop 1 nVisit 10 nEst 10.0 zName t1bc
- zExplain {SCAN TABLE t1 AS ii USING COVERING INDEX t1bc}
+ zExplain {SCAN ii USING COVERING INDEX t1bc}
nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
- zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
+ zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}
do_execsql_test 5.2.1 {
@@ -323,51 +323,51 @@ do_execsql_test 5.2.1 {
} {2}
do_scanstatus_test 5.2.2 {
nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1
- zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
+ zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}
do_eqp_test 5.3.1 {
SELECT count(*) FROM t2 WHERE y = 'j';
-} {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
+} {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
do_execsql_test 5.3.2 {
SELECT count(*) FROM t2 WHERE y = 'j';
} {19}
do_scanstatus_test 5.3.3 {
nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
- {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
+ {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
do_eqp_test 5.4.1 {
SELECT count(*) FROM t1, t2 WHERE y = c;
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX t1bc
- `--SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
+ |--SCAN t1 USING COVERING INDEX t1bc
+ `--SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
}
do_execsql_test 5.4.2 {
SELECT count(*) FROM t1, t2 WHERE y = c;
} {200}
do_scanstatus_test 5.4.3 {
nLoop 1 nVisit 10 nEst 10.0 zName t1bc
- zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
+ zExplain {SCAN t1 USING COVERING INDEX t1bc}
nLoop 10 nVisit 200 nEst 56.0 zName t2xy
- zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
+ zExplain {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
do_eqp_test 5.5.1 {
SELECT count(*) FROM t1, t3 WHERE y = c;
} {
QUERY PLAN
- |--SCAN TABLE t3
- `--SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)
+ |--SCAN t3
+ `--SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?)
}
do_execsql_test 5.5.2 {
SELECT count(*) FROM t1, t3 WHERE y = c;
} {200}
do_scanstatus_test 5.5.3 {
- nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3}
+ nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN t3}
nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain
- {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
+ {SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?)}
}
#-------------------------------------------------------------------------
@@ -392,7 +392,7 @@ ifcapable fts3 {
} {6}
do_scanstatus_test 6.1.2 {
nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain
- {SCAN TABLE ft1 VIRTUAL TABLE INDEX 3:}
+ {SCAN ft1 VIRTUAL TABLE INDEX 3:}
}
}
diff --git a/test/select4.test b/test/select4.test
index 6dbfd4d0a1..d49708ece8 100644
--- a/test/select4.test
+++ b/test/select4.test
@@ -1025,5 +1025,19 @@ do_execsql_test select4-18.3 {
WHERE abs(z1.aa)=z2.aa AND z1.aa=123;
} {123}
+# 2021-03-31 Fix an assert() problem in the logic at the end of sqlite3Select()
+# that validates AggInfo. The checks to ensure that AggInfo.aCol[].pCExpr
+# references a valid expression was looking at an expression that had been
+# deleted by the truth optimization in sqlite3ExprAnd() which was invoked by
+# the push-down optimization. This is harmless in delivery builds, as that code
+# only runs with SQLITE_DEBUG. But it should still be fixed. The problem
+# was discovered by dbsqlfuzz (crash-dece7b67a3552ed7e571a7bda903afd1f7bd9b21)
+#
+reset_db
+do_execsql_test select4-19.1 {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES(99);
+ SELECT sum((SELECT 1 FROM (SELECT 2 WHERE x IS NULL) WHERE 0)) FROM t1;
+} {{}}
finish_test
diff --git a/test/select5.test b/test/select5.test
index 8f451eacbb..8de306cf40 100644
--- a/test/select5.test
+++ b/test/select5.test
@@ -12,7 +12,6 @@
# focus of this file is testing aggregate functions and the
# GROUP BY and HAVING clauses of SELECT statements.
#
-# $Id: select5.test,v 1.20 2008/08/21 14:15:59 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -251,7 +250,13 @@ do_test select5-8.8 {
}
} {two 3 one 9}
+# 2021-04-26 forum https://sqlite.org/forum/forumpost/74330094d8
+reset_db
+do_execsql_test select5-9.1 {
+ CREATE TABLE t1(a INT, b INT);
+ INSERT INTO t1(a,b) VALUES(1,null),(null,null),(1,null);
+ CREATE UNIQUE INDEX t1b ON t1(abs(b));
+ SELECT quote(a), quote(b), '|' FROM t1 GROUP BY a, abs(b);
+} {NULL NULL | 1 NULL |}
-
-
finish_test
diff --git a/test/select9.test b/test/select9.test
index 4c42236dc8..bbed8e18fe 100644
--- a/test/select9.test
+++ b/test/select9.test
@@ -436,19 +436,19 @@ do_test select9-5.1 {
EXPLAIN QUERY PLAN
SELECT * FROM v5 WHERE x='12345' ORDER BY y;
}
-} {~/SCAN TABLE/} ;# Uses indices with "*"
+} {~/SCAN/} ;# Uses indices with "*"
do_test select9-5.2 {
db eval {
EXPLAIN QUERY PLAN
SELECT x, y FROM v5 WHERE x='12345' ORDER BY y;
}
-} {~/SCAN TABLE/} ;# Uses indices with "x, y"
+} {~/SCAN/} ;# Uses indices with "x, y"
do_test select9-5.3 {
db eval {
EXPLAIN QUERY PLAN
SELECT x, y FROM v5 WHERE +x='12345' ORDER BY y;
}
-} {/SCAN TABLE/} ;# Full table scan if the "+x" prevents index usage.
+} {/SCAN/} ;# Full table scan if the "+x" prevents index usage.
# 2013-07-09: Ticket [490a4b7235624298]:
# "WHERE 0" on the first element of a UNION causes an assertion fault
diff --git a/test/selectA.test b/test/selectA.test
index 7ca0096b1d..ce7f8eba9c 100644
--- a/test/selectA.test
+++ b/test/selectA.test
@@ -1339,10 +1339,10 @@ do_eqp_test 4.1.2 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
- | |--SCAN TABLE t5 USING INDEX i2
+ | |--SCAN t5 USING INDEX i2
| `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
`--RIGHT
- |--SCAN TABLE t4 USING INDEX i1
+ |--SCAN t4 USING INDEX i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
@@ -1468,4 +1468,19 @@ do_execsql_test 7.4 {
SELECT sum(d) OVER( PARTITION BY(SELECT 0 FROM c JOIN a WHERE b =(SELECT b INTERSECT SELECT d FROM c) AND b = 123)) FROM c;
} {}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE x1(x);
+ CREATE TABLE t1(a, b, c, d);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+}
+
+do_execsql_test 8.1 {
+ SELECT 'ABCD' FROM t1
+ WHERE (a=? OR b=?)
+ AND (0 OR (SELECT 'xyz' INTERSECT SELECT a ORDER BY 1))
+} {}
+
finish_test
diff --git a/test/selectD.test b/test/selectD.test
index 9c09b2cca6..818d8ccc0b 100644
--- a/test/selectD.test
+++ b/test/selectD.test
@@ -169,6 +169,6 @@ do_execsql_test selectD-4.1 {
WHERE x1.d>5
GROUP BY x1.d) AS x2
ON t41.b=x2.d;
-} {/*SEARCH SUBQUERY * AS x2 USING AUTOMATIC*/}
+} {/SEARCH x2 USING AUTOMATIC/}
finish_test
diff --git a/test/skipscan1.test b/test/skipscan1.test
index 367cd2a108..94062fb17e 100644
--- a/test/skipscan1.test
+++ b/test/skipscan1.test
@@ -341,7 +341,7 @@ optimization_control db skip-scan 0
do_execsql_test skipscan1-9.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t9a WHERE b IN (SELECT x FROM t9b WHERE y!=5);
-} {/{SCAN TABLE t9a}/}
+} {/{SCAN t9a}/}
optimization_control db skip-scan 1
do_execsql_test skipscan1-2.1 {
@@ -394,7 +394,7 @@ do_eqp_test skipscan1-3.2 {
FROM t1 WHERE t1.c3 = 1;
} {
QUERY PLAN
- |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
+ |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
`--USE TEMP B-TREE FOR DISTINCT
}
diff --git a/test/skipscan2.test b/test/skipscan2.test
index 6fa04d54c6..47b2b3fffa 100644
--- a/test/skipscan2.test
+++ b/test/skipscan2.test
@@ -199,7 +199,7 @@ do_test skipscan2-3.2 {
} {}
do_eqp_test skipscan2-3.3eqp {
SELECT * FROM t3 WHERE b=42;
-} {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}
+} {SEARCH t3 USING PRIMARY KEY (ANY(a) AND b=?)}
diff --git a/test/skipscan5.test b/test/skipscan5.test
index c128e614c1..026356e6c0 100644
--- a/test/skipscan5.test
+++ b/test/skipscan5.test
@@ -41,20 +41,20 @@ do_test 1.2 {
foreach {tn q res} {
1 "b = 5" {/*ANY(a) AND b=?*/}
2 "b > 12 AND b < 16" {/*ANY(a) AND b>? AND b*/}
- 3 "b > 2 AND b < 16" {/*SCAN TABLE t1*/}
+ 3 "b > 2 AND b < 16" {/*SCAN t1*/}
4 "b > 18 AND b < 25" {/*ANY(a) AND b>? AND b*/}
5 "b > 16" {/*ANY(a) AND b>?*/}
- 6 "b > 5" {/*SCAN TABLE t1*/}
- 7 "b < 15" {/*SCAN TABLE t1*/}
+ 6 "b > 5" {/*SCAN t1*/}
+ 7 "b < 15" {/*SCAN t1*/}
8 "b < 5" {/*ANY(a) AND b*/}
9 "5 > b" {/*ANY(a) AND b*/}
10 "b = '5'" {/*ANY(a) AND b=?*/}
11 "b > '12' AND b < '16'" {/*ANY(a) AND b>? AND b*/}
- 12 "b > '2' AND b < '16'" {/*SCAN TABLE t1*/}
+ 12 "b > '2' AND b < '16'" {/*SCAN t1*/}
13 "b > '18' AND b < '25'" {/*ANY(a) AND b>? AND b*/}
14 "b > '16'" {/*ANY(a) AND b>?*/}
- 15 "b > '5'" {/*SCAN TABLE t1*/}
- 16 "b < '15'" {/*SCAN TABLE t1*/}
+ 15 "b > '5'" {/*SCAN t1*/}
+ 16 "b < '15'" {/*SCAN t1*/}
17 "b < '5'" {/*ANY(a) AND b*/}
18 "'5' > b" {/*ANY(a) AND b*/}
} {
@@ -104,10 +104,10 @@ foreach {tn dbenc coll} {
foreach {tn2 q res} {
1 { c BETWEEN 'd' AND 'e' } {/*ANY(a) AND ANY(b) AND c>? AND c*/}
- 2 { c BETWEEN 'b' AND 'r' } {/*SCAN TABLE t2*/}
+ 2 { c BETWEEN 'b' AND 'r' } {/*SCAN t2*/}
3 { c > 'q' } {/*ANY(a) AND ANY(b) AND c>?*/}
- 4 { c > 'e' } {/*SCAN TABLE t2*/}
- 5 { c < 'q' } {/*SCAN TABLE t2*/}
+ 4 { c > 'e' } {/*SCAN t2*/}
+ 5 { c < 'q' } {/*SCAN t2*/}
6 { c < 'b' } {/*ANY(a) AND ANY(b) AND c*/}
} {
set sql "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE $q"
@@ -169,11 +169,11 @@ do_test 3.2 {
foreach {tn q res} {
1 "b BETWEEN -10000 AND -8000" {/*ANY(a) AND b>? AND b*/}
- 2 "b BETWEEN -10000 AND 'qqq'" {/*SCAN TABLE t3*/}
- 3 "b < X'5555'" {/*SCAN TABLE t3*/}
+ 2 "b BETWEEN -10000 AND 'qqq'" {/*SCAN t3*/}
+ 3 "b < X'5555'" {/*SCAN t3*/}
4 "b > X'5555'" {/*ANY(a) AND b>?*/}
5 "b > 'zzz'" {/*ANY(a) AND b>?*/}
- 6 "b < 'zzz'" {/*SCAN TABLE t3*/}
+ 6 "b < 'zzz'" {/*SCAN t3*/}
} {
set sql "EXPLAIN QUERY PLAN SELECT * FROM t3 WHERE $q"
do_execsql_test 3.3.$tn $sql $res
diff --git a/test/skipscan6.test b/test/skipscan6.test
index a53be1d952..4f592bc0e0 100644
--- a/test/skipscan6.test
+++ b/test/skipscan6.test
@@ -179,13 +179,13 @@ do_execsql_test 3.0 {
#
do_eqp_test 3.1 {
SELECT * FROM t3 WHERE a = ? AND c = ?
-} {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
+} {SEARCH t3 USING INDEX t3_a (a=?)}
# The same query on table t2. This should use index "t2_a", for the
# same reason. At one point though, it was mistakenly using a skip-scan.
#
do_eqp_test 3.2 {
SELECT * FROM t2 WHERE a = ? AND c = ?
-} {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
+} {SEARCH t2 USING INDEX t2_a (a=?)}
finish_test
diff --git a/test/tabfunc01.test b/test/tabfunc01.test
index 04bc6f42ad..797267b338 100644
--- a/test/tabfunc01.test
+++ b/test/tabfunc01.test
@@ -227,6 +227,50 @@ do_test tabfunc01-751 {
}
} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}
+ifcapable altertable {
+ do_test tabfunc01-800 {
+ catchsql {
+ ALTER TABLE generate_series ADD COLUMN col2;
+ }
+ } {1 {virtual tables may not be altered}}
+ do_test tabfunc01-810 {
+ catchsql {
+ ALTER TABLE generate_series RENAME TO flubber;
+ }
+ } {1 {table generate_series may not be altered}}
+ do_test tabfunc01-820 {
+ catchsql {
+ ALTER TABLE generate_series RENAME start TO flubber;
+ }
+ } {1 {table generate_series may not be altered}}
+ do_test tabfunc01-830 {
+ catchsql {
+ ALTER TABLE generate_series DROP COLUMN start;
+ }
+ } {1 {table generate_series may not be altered}}
+ do_test tabfunc01-900 {
+ catchsql {
+ ALTER TABLE pragma_compile_options ADD COLUMN col2;
+ }
+ } {1 {virtual tables may not be altered}}
+ do_test tabfunc01-910 {
+ catchsql {
+ ALTER TABLE pragma_compile_options RENAME TO flubber;
+ }
+ } {1 {table pragma_compile_options may not be altered}}
+ do_test tabfunc01-920 {
+ catchsql {
+ ALTER TABLE pragma_compile_options RENAME start TO flubber;
+ }
+ } {1 {table pragma_compile_options may not be altered}}
+ do_test tabfunc01-930 {
+ catchsql {
+ ALTER TABLE pragma_compile_options DROP COLUMN start;
+ }
+ } {1 {table pragma_compile_options may not be altered}}
+}
+
+
# Free up memory allocations
intarray_addr
int64array_addr
diff --git a/test/threadtest5.c b/test/threadtest5.c
new file mode 100644
index 0000000000..6e6610ff66
--- /dev/null
+++ b/test/threadtest5.c
@@ -0,0 +1,339 @@
+/*
+** 2021-05-12
+**
+** 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.
+**
+*************************************************************************
+**
+** Testing threading behavior when multiple database connections in separate
+** threads of the same process are all talking to the same database file.
+**
+** For best results, ensure that SQLite is compiled with HAVE_USLEEP=1
+**
+** Only works on unix platforms.
+**
+** Usage:
+**
+** ./threadtest5 ?DATABASE?
+**
+** If DATABASE is omitted, it defaults to using file:/mem?vfs=memdb.
+*/
+#include "sqlite3.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Name of the in-memory database */
+static char *zDbName = 0;
+
+/* True for debugging */
+static int eVerbose = 0;
+
+/* If rc is not SQLITE_OK, then print an error message and stop
+** the test.
+*/
+static void error_out(int rc, const char *zCtx, int lineno){
+ if( rc!=SQLITE_OK ){
+ fprintf(stderr, "error %d at %d in \"%s\"\n", rc, lineno, zCtx);
+ exit(-1);
+ }
+}
+
+#if 0
+/* Return the number of milliseconds since the Julian epoch (-4714-11-24).
+*/
+static sqlite3_int64 gettime(void){
+ sqlite3_int64 tm;
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
+ pVfs->xCurrentTimeInt64(pVfs, &tm);
+ return tm;
+}
+#endif
+
+/* Run the SQL in the second argument.
+*/
+static int exec(
+ sqlite3 *db,
+ const char *zId,
+ int lineno,
+ const char *zFormat,
+ ...
+){
+ int rc;
+ va_list ap;
+ char *zSql;
+ va_start(ap, zFormat);
+ zSql = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( eVerbose){
+ printf("%s:%d: [%s]\n", zId, lineno, zSql);
+ fflush(stdout);
+ }
+ rc = sqlite3_exec(db, zSql, 0, 0, 0);
+ if( rc && eVerbose ){
+ printf("%s:%d: return-code %d\n", zId, lineno, rc);
+ fflush(stdout);
+ }
+ sqlite3_free(zSql);
+ return rc;
+}
+
+/* Generate a perpared statement from the input SQL
+*/
+static sqlite3_stmt *prepare(
+ sqlite3 *db,
+ const char *zId,
+ int lineno,
+ const char *zFormat,
+ ...
+){
+ int rc;
+ va_list ap;
+ char *zSql;
+ sqlite3_stmt *pStmt = 0;
+ va_start(ap, zFormat);
+ zSql = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( eVerbose){
+ printf("%s:%d: [%s]\n", zId, lineno, zSql);
+ fflush(stdout);
+ }
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc ){
+ printf("%s:%d: ERROR - %s\n", zId, lineno, sqlite3_errmsg(db));
+ exit(-1);
+ }
+ sqlite3_free(zSql);
+ return pStmt;
+}
+
+/*
+** Wait for table zTable to exist in the schema.
+*/
+static void waitOnTable(sqlite3 *db, const char *zWorker, const char *zTable){
+ while(1){
+ int eFound = 0;
+ sqlite3_stmt *q = prepare(db, zWorker, __LINE__,
+ "SELECT 1 FROM sqlite_schema WHERE name=%Q", zTable);
+ if( sqlite3_step(q)==SQLITE_ROW && sqlite3_column_int(q,0)!=0 ){
+ eFound = 1;
+ }
+ sqlite3_finalize(q);
+ if( eFound ) return;
+ sqlite3_sleep(1);
+ }
+}
+
+/*
+** Return true if x is a prime number
+*/
+static int isPrime(int x){
+ int i;
+ if( x<2 ) return 1;
+ for(i=2; i*i<=x; i++){
+ if( (x%i)==0 ) return 0;
+ }
+ return 1;
+}
+
+/* Each worker thread runs an instance of the following */
+static void *worker(void *pArg){
+ int rc;
+ const char *zName = (const char*)pArg;
+ sqlite3 *db = 0;
+
+ if( eVerbose ){
+ printf("%s: startup\n", zName);
+ fflush(stdout);
+ }
+
+ rc = sqlite3_open(zDbName, &db);
+ error_out(rc, "sqlite3_open", __LINE__);
+ sqlite3_busy_timeout(db, 2000);
+
+ while( 1 ){
+ sqlite3_stmt *q1;
+ int tid = -1;
+ q1 = prepare(db, zName, __LINE__,
+ "UPDATE task SET doneby=%Q"
+ " WHERE tid=(SELECT tid FROM task WHERE doneby IS NULL LIMIT 1)"
+ "RETURNING tid", zName
+ );
+ if( sqlite3_step(q1)==SQLITE_ROW ){
+ tid = sqlite3_column_int(q1,0);
+ }
+ sqlite3_finalize(q1);
+ if( tid<0 ) break;
+ if( eVerbose ){
+ printf("%s: starting task %d\n", zName, tid);
+ fflush(stdout);
+ }
+ if( tid==1 ){
+ exec(db, zName, __LINE__,
+ "CREATE TABLE IF NOT EXISTS p1(x INTEGER PRIMARY KEY);"
+ );
+ }else if( tid>=2 && tid<=51 ){
+ int a, b, i;
+ waitOnTable(db, zName, "p1");
+ a = (tid-2)*200 + 1;
+ b = a+200;
+ for(i=a; i=53 && tid<=62 ){
+ int a, b, i;
+ waitOnTable(db, zName, "p2");
+ a = (tid-53)*10 + 2;
+ b = a+9;
+ for(i=a; i<=b; i++){
+ exec(db, zName, __LINE__,
+ "DELETE FROM p2 WHERE x>%d AND (x %% %d)==0", i, i);
+ }
+ }
+ if( eVerbose ){
+ printf("%s: completed task %d\n", zName, tid);
+ fflush(stdout);
+ }
+ sqlite3_sleep(1);
+ }
+
+ sqlite3_close(db);
+
+ if( eVerbose ){
+ printf("%s: exit\n", zName);
+ fflush(stdout);
+ }
+ return 0;
+}
+
+/* Print a usage comment and die */
+static void usage(const char *argv0){
+ printf("Usage: %s [options]\n", argv0);
+ printf(
+ " -num-workers N Run N worker threads\n"
+ " -v Debugging output\n"
+ );
+ exit(1);
+}
+
+/* Maximum number of threads */
+#define MX_WORKER 100
+
+/*
+** Main routine
+*/
+int main(int argc, char **argv){
+ int i;
+ int nWorker = 4;
+ int rc;
+ sqlite3 *db = 0;
+ sqlite3_stmt *q;
+ pthread_t aWorker[MX_WORKER];
+ char aWorkerName[MX_WORKER][8];
+
+ for(i=1; iMX_WORKER ){
+ printf("number of threads must be between 1 and %d\n", MX_WORKER);
+ exit(1);
+ }
+ continue;
+ }
+ printf("unknown option: %s\n", argv[i]);
+ usage(argv[0]);
+ }
+ if( zDbName==0 ) zDbName = "file:/mem?vfs=memdb";
+
+ sqlite3_config(SQLITE_CONFIG_URI, (int)1);
+ rc = sqlite3_open(zDbName, &db);
+ error_out(rc, "sqlite3_open", __LINE__);
+
+ rc = exec(db, "SETUP", __LINE__,
+ "DROP TABLE IF EXISTS task;\n"
+ "DROP TABLE IF EXISTS p1;\n"
+ "DROP TABLE IF EXISTS p2;\n"
+ "DROP TABLE IF EXISTS verify;\n"
+ "CREATE TABLE IF NOT EXISTS task(\n"
+ " tid INTEGER PRIMARY KEY,\n"
+ " doneby TEXT\n"
+ ");\n"
+ "WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)"
+ "INSERT INTO task(tid) SELECT x FROM c;\n"
+ );
+ error_out(rc, "sqlite3_exec", __LINE__);
+
+ for(i=0; i? AND O_ORDERDATE)
- |--SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)
- |--SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)
- |--SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)
+ |--SEARCH orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE)
+ |--SEARCH customer USING INDEX cpki (C_CUSTKEY=?)
+ |--SEARCH nation USING INDEX npki (N_NATIONKEY=?)
+ |--SEARCH lineitem USING INDEX lpki (L_ORDERKEY=?)
|--USE TEMP B-TREE FOR GROUP BY
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/transitive1.test b/test/transitive1.test
index 97dc5a71a9..8755338492 100644
--- a/test/transitive1.test
+++ b/test/transitive1.test
@@ -344,13 +344,40 @@ do_execsql_test transitive1-560 {
do_execsql_test transitive1-560eqp {
EXPLAIN QUERY PLAN
SELECT * FROM c1 WHERE x=y AND y=z AND z='abc';
-} {/SCAN TABLE c1/}
+} {/SCAN c1/}
do_execsql_test transitive1-570 {
SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
} {}
do_execsql_test transitive1-570eqp {
EXPLAIN QUERY PLAN
SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
-} {/SEARCH TABLE c1 USING INDEX c1x/}
+} {/SEARCH c1 USING INDEX c1x/}
+
+# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
+reset_db
+do_execsql_test transitive1-600 {
+ CREATE TABLE t0(a0 INT, b1 INT);
+ CREATE INDEX t0b1 ON t0(b1);
+ CREATE TABLE t1(w,x,y,z3 INT);
+ INSERT INTO t0(a0, b1) VALUES (0,1);
+ INSERT INTO t1(w,x,y,z3) VALUES (7,8,9,1);
+} {}
+do_execsql_test transitive1-610 {
+ SELECT ALL * FROM t0,t1 WHERE b1=z3 AND a0=z3;
+} {}
+do_execsql_test transitive1-620 {
+ SELECT ALL * FROM t0,t1 WHERE likely(b1=z3) AND a0=z3;
+} {}
+do_execsql_test transitive1-630 {
+ DROP TABLE t0;
+ DROP TABLE t1;
+ CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
+ CREATE TABLE t1(c0 INT);
+ INSERT INTO t0(c0, c1) VALUES (0, 1);
+ INSERT INTO t1(c0) VALUES (1);
+ SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (t1.c0=t0.c1);
+ SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (likely(t1.c0=t0.c1));
+ SELECT ALL * FROM t1,t0 WHERE (likely(t1.c0=t0.c1) AND t1.c0=t0.c0);
+} {}
finish_test
diff --git a/test/trigger2.test b/test/trigger2.test
index 1be72131f7..6e007e969a 100644
--- a/test/trigger2.test
+++ b/test/trigger2.test
@@ -49,6 +49,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix trigger2
ifcapable {!trigger} {
finish_test
return
@@ -769,6 +770,24 @@ do_execsql_test trigger2-10.1 {
} ;# ifcapable view
-integrity_check trigger2-999
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 11.1 {
+ CREATE TABLE t1(a INT PRIMARY KEY, b, c REAL, d, e);
+ CREATE TABLE t2(a INT, b, c REAL, d, e, PRIMARY KEY(a,b)) WITHOUT ROWID;
+ CREATE UNIQUE INDEX t2c ON t2(c);
+ CREATE UNIQUE INDEX t2d ON t2(d);
+ CREATE UNIQUE INDEX t2e ON t2(e);
+}
+
+do_catchsql_test 11.2 {
+ CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN
+ INSERT INTO t2(a,b,c,d,e) VALUES(91,NULL,93,94,?1)
+ ON CONFLICT(b,a) DO NOTHING
+ ON CONFLICT DO UPDATE SET b=?1;
+ END;
+} {1 {trigger cannot use variables}}
+
finish_test
+
diff --git a/test/trigger9.test b/test/trigger9.test
index 326fa63d4c..6e31d1af97 100644
--- a/test/trigger9.test
+++ b/test/trigger9.test
@@ -242,15 +242,12 @@ do_execsql_test 4.1 {
END;
}
-do_execsql_test 4.2 {
+do_catchsql_test 4.2 {
DELETE FROM v1 WHERE rowid=1;
-} {}
+} {1 {no such column: rowid}}
-do_execsql_test 4.3 {
+do_catchsql_test 4.3 {
UPDATE v1 SET a=b WHERE rowid=2;
-} {}
-
-
-
+} {1 {no such column: rowid}}
finish_test
diff --git a/test/triggerupfrom.test b/test/triggerupfrom.test
index 9bfacb8430..a731045c4e 100644
--- a/test/triggerupfrom.test
+++ b/test/triggerupfrom.test
@@ -171,4 +171,3 @@ do_execsql_test 4.3 {
finish_test
-
diff --git a/test/unionall.test b/test/unionall.test
index 2f8027ccb7..7554a3b308 100644
--- a/test/unionall.test
+++ b/test/unionall.test
@@ -355,4 +355,13 @@ do_execsql_test 6.1 {
9 10 800 100 9 10 800 400
}
+# 2021-04-26 dbsqlfuzz 88ed5c66789fced139d148aed823cba7c0926dd7
+reset_db
+do_execsql_test 7.1 {
+ WITH c1(x) AS (VALUES(0) UNION ALL SELECT 100+x FROM c1 WHERE x<100 UNION ALL SELECT 1+x FROM c1 WHERE x<1)
+ SELECT x, y, '|'
+ FROM c1 AS x1, (SELECT x+1 AS y FROM c1 WHERE x<1 UNION ALL SELECT 1+x FROM c1 WHERE 1 100"
- {SEARCH TABLE t1 USING INDEX i1 (a>?)}
- {SCAN TABLE t1}
+ {SEARCH t1 USING INDEX i1 (a>?)}
+ {SCAN t1}
3 "SELECT * FROM t1 WHERE a = ? ORDER BY rowid"
- {SEARCH TABLE t1 USING INDEX i1 (a=?)}
- {SEARCH TABLE t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
+ {SEARCH t1 USING INDEX i1 (a=?)}
+ {SEARCH t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
4 "SELECT max(a) FROM t1"
- {SEARCH TABLE t1 USING COVERING INDEX i1}
- {SEARCH TABLE t1}
+ {SEARCH t1 USING COVERING INDEX i1}
+ {SEARCH t1}
5 "SELECT group_concat(b) FROM t1 GROUP BY a"
- {SCAN TABLE t1 USING INDEX i1}
- {SCAN TABLE t1*USE TEMP B-TREE FOR GROUP BY}
+ {SCAN t1 USING INDEX i1}
+ {SCAN t1*USE TEMP B-TREE FOR GROUP BY}
6 "SELECT * FROM t1 WHERE a = ?"
- {SEARCH TABLE t1 USING INDEX i1 (a=?)}
- {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+ {SEARCH t1 USING INDEX i1 (a=?)}
+ {SEARCH t1 USING INDEX i1 (a=?)}
7 "SELECT count(*) FROM t1"
- {SCAN TABLE t1 USING COVERING INDEX i1}
- {SCAN TABLE t1}
+ {SCAN t1 USING COVERING INDEX i1}
+ {SCAN t1}
} {
do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
}
diff --git a/test/upfrom1.test b/test/upfrom1.test
index 7996f97702..204f3512e5 100644
--- a/test/upfrom1.test
+++ b/test/upfrom1.test
@@ -175,4 +175,36 @@ do_execsql_test 3.1 {
SELECT * FROM t0, t1;
} {}
+# Problem described by forum post https://sqlite.org/forum/forumpost/a274248080
+#
+reset_db
+do_execsql_test 4.1 {
+ CREATE TABLE t1(x INT); INSERT INTO t1 VALUES(1);
+ CREATE TABLE t2(y INT); INSERT INTO t2 VALUES(2);
+ WITH t1 AS (SELECT y+100 AS x FROM t2)
+ UPDATE t1 SET x=(SELECT x FROM t1);
+ SELECT x, y FROM t1, t2;
+} {102 2}
+do_execsql_test 4.2 {
+ WITH t1 AS (SELECT y+100 AS x FROM t2)
+ UPDATE t1 SET x=x+y FROM t2;
+ SELECT x, y FROM t1, t2;
+} {104 2}
+
+# 2021-05-20
+# Forum https://sqlite.org/forum/forumpost/339f487de5 by Yu Liang
+# A bad assert()
+#
+reset_db
+do_execsql_test 5.1 {
+ CREATE TABLE t1(a);
+ INSERT INTO t1(a) VALUES(5);
+ CREATE VIEW t2 AS SELECT a FROM t1 UNION ALL SELECT a FROM t1;
+ CREATE TABLE t3(b,c);
+ INSERT INTO t3(b,c) VALUES(1,2);
+ UPDATE t3 SET (c,b) = (SELECT 3,4) FROM t1, t2;
+ SELECT * FROM t3;
+} {4 3}
+
+
finish_test
diff --git a/test/upfrom2.test b/test/upfrom2.test
index f903c1f4f7..81c847a604 100644
--- a/test/upfrom2.test
+++ b/test/upfrom2.test
@@ -367,5 +367,3 @@ foreach {tn update nm} {
finish_test
-
-
diff --git a/test/upfrom3.test b/test/upfrom3.test
index d30b3fa28c..9936716b51 100644
--- a/test/upfrom3.test
+++ b/test/upfrom3.test
@@ -259,4 +259,3 @@ foreach {tn wo} {
}
finish_test
-
diff --git a/test/upfromfault.test b/test/upfromfault.test
index fcb5956089..e876c071cb 100644
--- a/test/upfromfault.test
+++ b/test/upfromfault.test
@@ -137,4 +137,3 @@ do_faultsim_test 2.3 -prep {
finish_test
-
diff --git a/test/view2.test b/test/view2.test
new file mode 100644
index 0000000000..e5df1437fe
--- /dev/null
+++ b/test/view2.test
@@ -0,0 +1,49 @@
+# 2021 May 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 regression tests for SQLite library. The
+# focus of this file is testing VIEW statements.
+#
+# $Id: view.test,v 1.39 2008/12/14 14:45:21 danielk1977 Exp $
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Omit this entire file if the library is not configured with views enabled.
+ifcapable !view {
+ finish_test
+ return
+}
+set testprefix view2
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1, 2);
+ CREATE VIEW v1 AS SELECT * FROM (
+ WITH x1 AS (SELECT y, x FROM t1)
+ SELECT * FROM x1
+ );
+}
+
+do_execsql_test 1.1 {
+ SELECT * FROM v1
+} {2 1}
+
+do_execsql_test 1.2 {
+ CREATE VIEW v3 AS SELECT * FROM main.t1;
+ WITH t1(a, b) AS ( SELECT 3, 4 ) SELECT * FROM v3;
+} {1 2}
+
+breakpoint
+do_execsql_test 1.3 {
+ CREATE VIEW v2 AS SELECT * FROM t1;
+ WITH t1(a, b) AS ( SELECT 3, 4 ) SELECT * FROM v2;
+} {1 2}
+
+finish_test
diff --git a/test/vtab1.test b/test/vtab1.test
index e8891a632c..3d2e233366 100644
--- a/test/vtab1.test
+++ b/test/vtab1.test
@@ -983,6 +983,7 @@ do_test vtab1.10-5 {
proc match_func {args} {return ""}
do_test vtab1.10-6 {
set echo_module ""
+ sqlite_delete_function db match
db function match match_func
execsql {
SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
diff --git a/test/walsetlk.test b/test/walsetlk.test
index 66513ad2dc..8c0a9659f7 100644
--- a/test/walsetlk.test
+++ b/test/walsetlk.test
@@ -195,4 +195,3 @@ do_test 3.1 {
} {1 {database is locked}}
finish_test
-
diff --git a/test/where.test b/test/where.test
index fa3bcd836c..298248a6ea 100644
--- a/test/where.test
+++ b/test/where.test
@@ -70,10 +70,10 @@ do_test where-1.1.1b {
} {3 121 10 3}
do_eqp_test where-1.1.2 {
SELECT x, y, w FROM t1 WHERE w=10
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.1.2b {
SELECT x, y, w FROM t1 WHERE w IS 10
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.1.3 {
db status step
} {0}
@@ -85,13 +85,13 @@ do_test where-1.1.5 {
} {99}
do_eqp_test where-1.1.6 {
SELECT x, y, w FROM t1 WHERE +w=10
-} {*SCAN TABLE t1*}
+} {*SCAN t1*}
do_test where-1.1.7 {
count {SELECT x, y, w AS abc FROM t1 WHERE abc=10}
} {3 121 10 3}
do_eqp_test where-1.1.8 {
SELECT x, y, w AS abc FROM t1 WHERE abc=10
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.1.9 {
db status step
} {0}
@@ -118,22 +118,22 @@ do_test where-1.4.1b {
} {11 3 144 3}
do_eqp_test where-1.4.2 {
SELECT w, x, y FROM t1 WHERE 11=w AND x>2
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.4.2b {
SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.4.3 {
count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3}
do_eqp_test where-1.4.4 {
SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.5 {
count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_eqp_test where-1.5.2 {
SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2
-} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
+} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.6 {
count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
@@ -145,10 +145,10 @@ do_test where-1.8 {
} {3 144 3}
do_eqp_test where-1.8.2 {
SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3
-} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*}
+} {*SEARCH t1 USING INDEX i1xy (x=? AND y=?)*}
do_eqp_test where-1.8.3 {
SELECT x, y FROM t1 WHERE y=144 AND x=3
-} {*SEARCH TABLE t1 USING COVERING INDEX i1xy (x=? AND y=?)*}
+} {*SEARCH t1 USING COVERING INDEX i1xy (x=? AND y=?)*}
do_test where-1.9 {
count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
diff --git a/test/where2.test b/test/where2.test
index 0a0533506a..7a7e9b92ed 100644
--- a/test/where2.test
+++ b/test/where2.test
@@ -76,10 +76,12 @@ proc queryplan {sql} {
set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
# puts eqp=$eqp
foreach {a b c x} $eqp {
- if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
- $x all as tab idx]} {
+ if {[regexp {SCAN CONSTANT} $x]} {
+ # noop
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data $tab $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
lappend data $tab *
}
}
@@ -753,7 +755,7 @@ do_execsql_test where2-12.1 {
SELECT a.x, b.x
FROM t12 AS a JOIN t12 AS b ON a.y=b.x
WHERE (b.x=$abc OR b.y=$abc);
-} {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/}
+} {/SEARCH b .*SEARCH b /}
}
# Verify that all necessary OP_OpenRead opcodes occur in the OR optimization.
diff --git a/test/where3.test b/test/where3.test
index 4d4ea3ee68..20af995cfe 100644
--- a/test/where3.test
+++ b/test/where3.test
@@ -111,10 +111,12 @@ proc queryplan {sql} {
set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
# puts eqp=$eqp
foreach {a b c x} $eqp {
- if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
- $x all as tab idx]} {
+ if {[regexp {SCAN CONSTANT} $x]} {
+ # noop
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data $tab $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
lappend data $tab *
}
}
@@ -240,15 +242,15 @@ do_eqp_test where3-3.0a {
SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
} {
QUERY PLAN
- |--SCAN TABLE t302
- `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t302
+ `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test where3-3.1 {
SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y;
} {
QUERY PLAN
- |--SCAN TABLE t302
- `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t302
+ `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
}
do_execsql_test where3-3.2 {
SELECT * FROM t301 WHERE c=3 AND a IS NULL;
@@ -269,25 +271,25 @@ do_execsql_test where3-4.0 {
EXPLAIN QUERY PLAN
SELECT * FROM t400, t401, t402 WHERE t402.z GLOB 'abc*';
} {
- 0 0 2 {SCAN TABLE t402}
- 0 1 0 {SCAN TABLE t400}
- 0 2 1 {SCAN TABLE t401}
+ 0 0 2 {SCAN t402}
+ 0 1 0 {SCAN t400}
+ 0 2 1 {SCAN t401}
}
do_execsql_test where3-4.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t400, t401, t402 WHERE t401.r GLOB 'abc*';
} {
- 0 0 1 {SCAN TABLE t401}
- 0 1 0 {SCAN TABLE t400}
- 0 2 2 {SCAN TABLE t402}
+ 0 0 1 {SCAN t401}
+ 0 1 0 {SCAN t400}
+ 0 2 2 {SCAN t402}
}
do_execsql_test where3-4.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t400, t401, t402 WHERE t400.c GLOB 'abc*';
} {
- 0 0 0 {SCAN TABLE t400}
- 0 1 1 {SCAN TABLE t401}
- 0 2 2 {SCAN TABLE t402}
+ 0 0 0 {SCAN t400}
+ 0 1 1 {SCAN t401}
+ 0 2 2 {SCAN t402}
}
} ;# endif
@@ -321,8 +323,8 @@ do_eqp_test where3-5.0a {
ORDER BY bbb.title COLLATE NOCASE ASC;
} {
QUERY PLAN
- |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
- |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH aaa USING INDEX aaa_333 (fk=?)
+ |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.1 {
@@ -334,8 +336,8 @@ do_eqp_test where3-5.1 {
ORDER BY bbb.title COLLATE NOCASE ASC;
} {
QUERY PLAN
- |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
- |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH aaa USING INDEX aaa_333 (fk=?)
+ |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.2 {
@@ -347,8 +349,8 @@ do_eqp_test where3-5.2 {
ORDER BY bbb.title COLLATE NOCASE ASC;
} {
QUERY PLAN
- |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
- |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH aaa USING INDEX aaa_333 (fk=?)
+ |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.3 {
@@ -360,8 +362,8 @@ do_eqp_test where3-5.3 {
ORDER BY bbb.title COLLATE NOCASE ASC;
} {
QUERY PLAN
- |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
- |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH aaa USING INDEX aaa_333 (fk=?)
+ |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/where7.test b/test/where7.test
index 81111a9de4..830530634f 100644
--- a/test/where7.test
+++ b/test/where7.test
@@ -23354,10 +23354,10 @@ do_eqp_test where7-3.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)
+ | | `--SEARCH t301 USING COVERING INDEX t301_c4 (c4=?)
| `--INDEX 2
- | `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
- |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
+ | `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/where9.test b/test/where9.test
index 0f770dfee8..429708f1fe 100644
--- a/test/where9.test
+++ b/test/where9.test
@@ -362,12 +362,12 @@ ifcapable explain {
WHERE t1.a=80 AND ((t1.c=t2.c AND t1.d=t2.d) OR t1.f=t2.f)
} [string map {"\n " \n} {
QUERY PLAN
- |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX t2d (d=?)
+ | `--SEARCH t2 USING INDEX t2d (d=?)
`--INDEX 3
- `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
+ `--SEARCH t2 USING COVERING INDEX t2f (f=?)
}]
do_eqp_test where9-3.2 {
SELECT coalesce(t2.a,9999)
@@ -375,12 +375,12 @@ ifcapable explain {
WHERE t1.a=80
} [string map {"\n " \n} {
QUERY PLAN
- |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX t2d (d=?)
+ | `--SEARCH t2 USING INDEX t2d (d=?)
`--INDEX 2
- `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
+ `--SEARCH t2 USING COVERING INDEX t2f (f=?)
}]
}
@@ -461,23 +461,23 @@ do_eqp_test where9-5.1 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t1 USING INDEX t1c (c=?)
+ | `--SEARCH t1 USING INDEX t1c (c=?)
`--INDEX 2
- `--SEARCH TABLE t1 USING INDEX t1d (d=?)
+ `--SEARCH t1 USING INDEX t1d (d=?)
}
# In contrast, b=1000 is preferred over any OR-clause.
#
do_eqp_test where9-5.2 {
SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
-} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
+} {SEARCH t1 USING INDEX t1b (b=?)}
# Likewise, inequalities in an AND are preferred over inequalities in
# an OR.
#
do_eqp_test where9-5.3 {
SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
-} {SEARCH TABLE t1 USING INDEX t1b (b>?)}
+} {SEARCH t1 USING INDEX t1b (b>?)}
############################################################################
# Make sure OR-clauses work correctly on UPDATE and DELETE statements.
@@ -982,6 +982,23 @@ do_test where9-10.2 {
}
} {1 {} 1}
-
+# dbsqlfuzz 9df1d53c24c4c96af0dae15ee764897af415ac76
+# The MULTI-INDEX OR processing evaluates the same WHERE-clause sub-expression
+# twice. But if that sub-expression contains a UNION ALL SELECT statement
+# subject to query flattening, the sub-expression might be transformed in a
+# way that it can only be code-generated once. An assert() will fail on
+# the second attempt to generate code from the same sub-expression.
+# The solution is to make a copy of sub-expressions used by MULTI-INDEX OR
+#
+reset_db
+do_execsql_test where9-11.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
+ CREATE TABLE t2_a(k INTEGER PRIMARY KEY, v TEXT);
+ CREATE TABLE t2_b(k INTEGER PRIMARY KEY, v TEXT);
+ CREATE VIEW t2 AS SELECT * FROM t2_a UNION ALL SELECT * FROM t2_b;
+ SELECT 1 FROM t1 JOIN t1 USING(a)
+ WHERE (a=1)
+ OR (a=2 AND (SELECT 4 FROM t2,(SELECT 5 FROM t1 ORDER BY a) WHERE a));
+} {}
finish_test
diff --git a/test/whereE.test b/test/whereE.test
index a6b8f481b2..31086b2492 100644
--- a/test/whereE.test
+++ b/test/whereE.test
@@ -47,16 +47,16 @@ do_execsql_test 1.1 {
CREATE UNIQUE INDEX t2zx ON t2(z,x);
EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
-} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
+} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.2 {
EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
-} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
+} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.3 {
ANALYZE;
EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
-} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
+} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.4 {
EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
-} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
+} {/.*SCAN t1.*SEARCH t2.*/}
finish_test
diff --git a/test/whereF.test b/test/whereF.test
index 121cc3cf22..ac7fd807b8 100644
--- a/test/whereF.test
+++ b/test/whereF.test
@@ -63,7 +63,7 @@ foreach {tn sql} {
} {
do_test 1.$tn {
db eval "EXPLAIN QUERY PLAN $sql"
- } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
+ } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}
do_execsql_test 2.0 {
@@ -84,7 +84,7 @@ foreach {tn sql} {
} {
do_test 2.$tn {
db eval "EXPLAIN QUERY PLAN $sql"
- } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
+ } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}
do_execsql_test 3.0 {
@@ -109,7 +109,7 @@ foreach {tn sql} {
} {
do_test 3.$tn {
db eval "EXPLAIN QUERY PLAN $sql"
- } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
+ } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}
do_execsql_test 4.0 {
diff --git a/test/whereG.test b/test/whereG.test
index abff2270b7..f39f3e8fce 100644
--- a/test/whereG.test
+++ b/test/whereG.test
@@ -156,16 +156,16 @@ do_execsql_test whereG-3.0 {
} {}
do_eqp_test whereG-3.1 {
SELECT * FROM a, b WHERE b1=a1 AND a2=5;
-} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
+} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.2 {
SELECT * FROM a, b WHERE a1=b1 AND a2=5;
-} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
+} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.3 {
SELECT * FROM a, b WHERE a2=5 AND b1=a1;
-} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
+} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.4 {
SELECT * FROM a, b WHERE a2=5 AND a1=b1;
-} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
+} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
# Ticket [1e64dd782a126f48d78c43a664844a41d0e6334e]:
# Incorrect result in a nested GROUP BY/DISTINCT due to the use of an OP_SCopy
@@ -195,13 +195,13 @@ do_execsql_test 5.1 {
}
do_eqp_test 5.1.2 {
SELECT * FROM t1 WHERE a>?
-} {SEARCH TABLE t1 USING INDEX i1 (a>?)}
+} {SEARCH t1 USING INDEX i1 (a>?)}
do_eqp_test 5.1.3 {
SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test 5.1.4 {
SELECT * FROM t1 WHERE likely(a>?)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_test 5.2 {
for {set i 0} {$i < 100} {incr i} {
@@ -212,29 +212,29 @@ do_test 5.2 {
} {}
do_eqp_test 5.2.2 {
SELECT * FROM t1 WHERE likelihood(b>?, 0.01)
-} {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}
+} {SEARCH t1 USING INDEX i1 (ANY(a) AND b>?)}
do_eqp_test 5.2.3 {
SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test 5.2.4 {
SELECT * FROM t1 WHERE likely(b>?)
-} {SCAN TABLE t1}
+} {SCAN t1}
ifcapable stat4 {
do_eqp_test 5.3.1.stat4 {
SELECT * FROM t1 WHERE a=?
- } {SCAN TABLE t1}
+ } {SCAN t1}
} else {
do_eqp_test 5.3.1 {
SELECT * FROM t1 WHERE a=?
- } {SEARCH TABLE t1 USING INDEX i1}
+ } {SEARCH t1 USING INDEX i1}
}
do_eqp_test 5.3.2 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test 5.3.3 {
SELECT * FROM t1 WHERE likely(a=?)
-} {SCAN TABLE t1}
+} {SCAN t1}
# 2015-06-18
# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
@@ -334,4 +334,37 @@ do_execsql_test 10.1 {
SELECT g = g FROM f GROUP BY h;
} {1}
+reset_db
+do_execsql_test 11.0 {
+ CREATE TABLE t1(x PRIMARY KEY, y);
+ INSERT INTO t1 VALUES('AAA', 'BBB');
+
+ CREATE TABLE t2(z);
+ INSERT INTO t2 VALUES('t2');
+
+ CREATE TABLE t3(x PRIMARY KEY, y);
+ INSERT INTO t3 VALUES('AAA', 'AAA');
+}
+
+do_execsql_test 11.1.1 {
+ SELECT * FROM t1 JOIN t2 ON unlikely(x=y) AND y='AAA'
+}
+do_execsql_test 11.1.2 {
+ SELECT * FROM t1 JOIN t2 ON likely(x=y) AND y='AAA'
+}
+do_execsql_test 11.1.3 {
+ SELECT * FROM t1 JOIN t2 ON x=y AND y='AAA'
+}
+
+do_execsql_test 11.2.1 {
+ SELECT * FROM t3 JOIN t2 ON unlikely(x=y) AND y='AAA'
+} {AAA AAA t2}
+do_execsql_test 11.2.2 {
+ SELECT * FROM t3 JOIN t2 ON likely(x=y) AND y='AAA'
+} {AAA AAA t2}
+do_execsql_test 11.2.3 {
+ SELECT * FROM t3 JOIN t2 ON x=y AND y='AAA'
+} {AAA AAA t2}
+
+
finish_test
diff --git a/test/whereI.test b/test/whereI.test
index 7bb4ba39de..38e0148844 100644
--- a/test/whereI.test
+++ b/test/whereI.test
@@ -32,9 +32,9 @@ do_eqp_test 1.1 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t1 USING INDEX i1 (b=?)
+ | `--SEARCH t1 USING INDEX i1 (b=?)
`--INDEX 2
- `--SEARCH TABLE t1 USING INDEX i2 (c=?)
+ `--SEARCH t1 USING INDEX i2 (c=?)
}
do_execsql_test 1.2 {
@@ -64,9 +64,9 @@ do_eqp_test 2.1 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX i3 (b=?)
+ | `--SEARCH t2 USING INDEX i3 (b=?)
`--INDEX 2
- `--SEARCH TABLE t2 USING INDEX i4 (c=?)
+ `--SEARCH t2 USING INDEX i4 (c=?)
}
do_execsql_test 2.2 {
diff --git a/test/whereJ.test b/test/whereJ.test
index af6ffafb3f..c31ab8c370 100644
--- a/test/whereJ.test
+++ b/test/whereJ.test
@@ -402,7 +402,7 @@ do_eqp_test 3.4 {
a = 4 AND b BETWEEN 20 AND 80 -- Matches 80 rows
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
-} {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c)}
+} {SEARCH t1 USING INDEX idx_c (c>? AND c)}
# This one should use index "idx_ab".
do_eqp_test 3.5 {
@@ -410,7 +410,7 @@ do_eqp_test 3.5 {
a = 5 AND b BETWEEN 20 AND 80 -- Matches 1 row
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
-} {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b)}
+} {SEARCH t1 USING INDEX idx_ab (a=? AND b>? AND b)}
###########################################################################################
@@ -633,7 +633,7 @@ do_execsql_test 4.2 {
AND px.cx_id = cx.cx_id
AND px.px_tid = 0
AND px.le_id = le.le_id;
-} {/.*SCAN TABLE cx.*SEARCH TABLE px.*SEARCH TABLE le.*/}
+} {/.*SCAN cx.*SEARCH px.*SEARCH le.*/}
# The following test is derived from a performance problem reported from
diff --git a/test/whereK.test b/test/whereK.test
index 13c86508f9..060d470ff9 100644
--- a/test/whereK.test
+++ b/test/whereK.test
@@ -33,7 +33,7 @@ do_execsql_test 1.1 {
do_execsql_test 1.1eqp {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
-} {/SEARCH TABLE t1 USING INDEX t1bc/}
+} {/SEARCH t1 USING INDEX t1bc/}
do_execsql_test 1.2 {
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
@@ -41,7 +41,7 @@ do_execsql_test 1.2 {
do_execsql_test 1.2eqp {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
-} {/SEARCH TABLE t1 USING INDEX t1bc/}
+} {/SEARCH t1 USING INDEX t1bc/}
do_execsql_test 1.3 {
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
@@ -49,7 +49,7 @@ do_execsql_test 1.3 {
do_execsql_test 1.3eqp {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
-} {/SEARCH TABLE t1 USING INDEX t1bc/}
+} {/SEARCH t1 USING INDEX t1bc/}
do_execsql_test 1.4 {
SELECT a FROM t1 WHERE (b=8 AND c>7) OR 87) OR 87) OR (b>8 AND c NOT IN (4,5,6))
@@ -67,6 +67,6 @@ do_execsql_test 1.5eqp {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
ORDER BY +a;
-} {/SEARCH TABLE t1 USING INDEX t1bc/}
+} {/SEARCH t1 USING INDEX t1bc/}
finish_test
diff --git a/test/whereL.test b/test/whereL.test
index c78ae160b3..b6f86fc2d2 100644
--- a/test/whereL.test
+++ b/test/whereL.test
@@ -28,11 +28,11 @@ do_eqp_test 110 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
- | `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ | |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ | `--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
`--UNION ALL
- |--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
- `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ `--SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
}
# The scan of the t1 table goes first since that enables the ORDER BY
@@ -45,9 +45,9 @@ do_eqp_test 120 {
ORDER BY t1.a;
} {
QUERY PLAN
- |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
- |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
- `--SCAN TABLE t3
+ |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
+ |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
+ `--SCAN t3
}
# Constant propagation in the face of collating sequences:
diff --git a/test/wherefault.test b/test/wherefault.test
index 60330a92dd..7f07ad5f53 100644
--- a/test/wherefault.test
+++ b/test/wherefault.test
@@ -56,4 +56,28 @@ do_malloc_test 2 -tclprep {
SELECT count(*) FROM t1 WHERE a BETWEEN 5 AND 995 OR b BETWEEN 5 AND 900000;
}
+reset_db
+do_execsql_test 3.0 {
+ PRAGMA writable_schema = 1;
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(
+ a INT AS (c*11),
+ b TEXT AS (substr(d,1,3)) STORED,
+ c INTEGEB PRIMARI KEY, d TEXT
+ );
+ CREATE INDEX t1a ON t1(a);
+ COMMIT;
+}
+faultsim_save_and_close
+
+do_faultsim_test 3.1 -faults oom* -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql {
+ SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT b FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT CASE b WHEN 82 THEN 207 WHEN 869 THEN 406 WHEN 85 THEN 83 WHEN 705 THEN 698 ELSE 1992229051 END%5 FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT b FROM t1 ORDER BY b) WHERE a IN (SELECT b FROM t1 ORDER BY b))) WHERE a );
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
finish_test
diff --git a/test/wherelimit.test b/test/wherelimit.test
index aeadc6f39b..f6efab6682 100644
--- a/test/wherelimit.test
+++ b/test/wherelimit.test
@@ -237,8 +237,8 @@ ifcapable {update_delete_limit} {
} {11}
create_test_data 6
do_test wherelimit-3.2 {
- execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, old.y, '|' LIMIT 5}
- } {1 1 | 1 2 | 1 3 | 1 4 | 1 5 |}
+ execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, y, '|' LIMIT 5}
+ } {1 1 | 1 1 | 1 1 | 1 1 | 1 1 |}
do_test wherelimit-3.2cnt {
execsql {SELECT count(*) FROM t1 WHERE y=1}
} {10}
diff --git a/test/window1.test b/test/window1.test
index dbaf4388fb..f4b573d298 100644
--- a/test/window1.test
+++ b/test/window1.test
@@ -374,6 +374,38 @@ do_execsql_test 9.3 {
SELECT *, min(z) OVER (ORDER BY x) FROM aaa ORDER BY 1;
} {1 g g g 2 i i g 3 l l g 4 g l g 5 a l g 6 m m g}
+do_catchsql_test 9.4 {
+ -- 2021-04-17 dbsqlfuzz d9cf66100064952b66951845dfab41de1c124611
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a,b,c,d);
+ DROP TABLE IF EXISTS t2;
+ CREATE TABLE t2(x,y);
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t2(x,y)
+ SELECT a, max(d) OVER w1 FROM t1
+ WINDOW w1 AS (PARTITION BY EXISTS(SELECT 1 FROM t1 WHERE c=?1) );
+ END;
+} {1 {trigger cannot use variables}}
+
+do_catchsql_test 9.4.2 {
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t1(a,b)
+ SELECT a, max(d) OVER w1 FROM t1
+ WINDOW w1 AS (
+ ORDER BY a ROWS BETWEEN ? PRECEDING AND UNBOUNDED FOLLOWING
+ );
+ END;
+} {1 {trigger cannot use variables}}
+do_catchsql_test 9.4.3 {
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO t1(a,b)
+ SELECT a, max(d) OVER w1 FROM t1
+ WINDOW w1 AS (
+ ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND ? FOLLOWING
+ );
+ END;
+} {1 {trigger cannot use variables}}
+
#-------------------------------------------------------------------------
#
do_execsql_test 10.0 {
@@ -1883,11 +1915,59 @@ do_execsql_test 60.1 {
# the Parse object is destroyed.
#
reset_db
-do_execsql_test 61.1 {
+do_catchsql_test 61.1 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(5),(NULL),('seventeen');
SELECT (SELECT max(x)OVER(ORDER BY x) % min(x)OVER(ORDER BY CASE x WHEN 889 THEN x WHEN x THEN x END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST((SELECT (SELECT max(x)OVER(ORDER BY x) / min(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN -true THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x) & sum ( a )OVER(ORDER BY CASE x WHEN -8 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a AS )) FROM t1) AS x FROM t1)) AS t1 )) FROM t1) AS x FROM t1)) AS x )) FROM t1) AS x FROM t1)) AS real)) FROM t1) AS x FROM t1);
-} {{} {} {}}
+} {0 {{} {} {}}}
+
+foreach tn {1 2} {
+ if {$tn==2} { optimization_control db query-flattener 0 }
+ do_catchsql_test 61.2.$tn {
+ SELECT
+ (SELECT max(x)OVER(ORDER BY x) / min(x) OVER() )
+ FROM (
+ SELECT (SELECT sum(a) FROM t1 ) AS x FROM t1
+ )
+
+ } {0 {1.0 1.0 1.0}}
+}
+
+reset_db
+optimization_control db all 0
+do_execsql_test 61.3.0 {
+ CREATE TABLE t1(a);
+ CREATE TABLE t2(y);
+}
+
+do_execsql_test 61.3.1 {
+ SELECT (
+ SELECT count(a) OVER ( ORDER BY (SELECT sum(y) FROM t2) )
+ + total(a) OVER()
+ )
+ FROM t1
+} {}
+do_execsql_test 61.4.2 {
+ SELECT (
+ SELECT count(a) OVER ( ORDER BY sum(a) )
+ + total(a) OVER()
+ )
+ FROM t1
+} {0.0}
+
+do_catchsql_test 61.4.3 {
+ SELECT
+ sum(a) OVER ( ORDER BY a )
+ FROM t1
+ ORDER BY (SELECT sum(a) FROM t2)
+} {1 {misuse of aggregate: sum()}}
+do_execsql_test 61.4.4 {
+ SELECT
+ sum(a) OVER ( ORDER BY a )
+ FROM t1
+ ORDER BY (SELECT sum(y) FROM t2)
+}
+
#-------------------------------------------------------------------------
reset_db
@@ -2001,4 +2081,82 @@ do_execsql_test 65.4 {
FROM t1;
} {{}}
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 66.1 {
+ CREATE TABLE t1(a INTEGER);
+ INSERT INTO t1 VALUES(3578824042033200656);
+ INSERT INTO t1 VALUES(3029012920382354029);
+}
+
+foreach {tn spec} {
+ 1 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
+ 2 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 0.1 PRECEDING"
+ 3 "ORDER BY a RANGE BETWEEN 0.3 FOLLOWING AND 10 FOLLOWING"
+ 4 "ORDER BY a DESC RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
+ 5 "ORDER BY a NULLS LAST RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
+ 6 "ORDER BY a RANGE BETWEEN 1.0 PRECEDING AND 2.0 PRECEDING"
+} {
+ do_execsql_test 66.2.$tn "
+ SELECT total(a) OVER ( $spec ) FROM t1 ORDER BY a
+ " {
+ 3.02901292038235e+18 3.5788240420332e+18
+ }
+}
+
+
+do_execsql_test 66.3 {
+ CREATE TABLE t2(a INTEGER);
+ INSERT INTO t2 VALUES(45);
+ INSERT INTO t2 VALUES(30);
+}
+
+foreach {tn spec res} {
+ 1 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING" {30.0 45.0}
+ 2 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 0.1 PRECEDING" {0.0 0.0}
+ 3 "ORDER BY a RANGE BETWEEN 0.3 FOLLOWING AND 10 FOLLOWING" {0.0 0.0}
+ 4 "ORDER BY a DESC RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING" {30.0 45.0}
+ 5 "ORDER BY a NULLS LAST RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING" {30.0 45.0}
+ 6 "ORDER BY a RANGE BETWEEN 1.0 PRECEDING AND 2.0 PRECEDING" {0.0 0.0}
+} {
+ do_execsql_test 66.2.$tn "
+ SELECT total(a) OVER ( $spec ) FROM t2 ORDER BY a
+ " $res
+}
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 67.0 {
+ CREATE TABLE t1(a, b, c);
+ CREATE TABLE t2(a, b, c);
+}
+
+do_catchsql_test 67.1 {
+ SELECT a,c,b FROM t1 INTERSECT SELECT a,b,c FROM t1 ORDER BY (
+ SELECT nth_value(a,2) OVER w1
+ WINDOW w1 AS ( ORDER BY ((SELECT 1 FROM v1)) )
+ )
+} {1 {no such table: v1}}
+
+do_catchsql_test 67.2 {
+ SELECT a,c,b FROM t1 INTERSECT SELECT a,b,c FROM t1 ORDER BY (
+ SELECT nth_value(a,2) OVER w1
+ WINDOW w1 AS ( ORDER BY ((SELECT 1 FROM t2)) )
+ )
+} {1 {1st ORDER BY term does not match any column in the result set}}
+
+# 2021-05-07
+# Do not allow aggregate functions in the ORDER BY clause even if
+# there are window functions in the result set.
+# Forum: /forumpost/540fdfef77
+#
+reset_db
+do_catchsql_test 68.0 {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1(a,b) VALUES(0,0),(1,1),(2,4),(3,9),(4,99);
+ SELECT rowid, a, b, sum(a)OVER() FROM t1 ORDER BY count(b);
+} {1 {misuse of aggregate: count()}}
+
finish_test
diff --git a/test/window8.tcl b/test/window8.tcl
index a8333f1907..69ad0ad263 100644
--- a/test/window8.tcl
+++ b/test/window8.tcl
@@ -418,6 +418,76 @@ execsql_test 7.$tn.9 "
"
}
+==========
+
+execsql_test 8.0 {
+ DROP TABLE IF EXISTS tx;
+ CREATE TABLE tx(a INTEGER PRIMARY KEY);
+ INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);
+
+ DROP TABLE IF EXISTS map;
+ CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
+ INSERT INTO map VALUES
+ (1, 'odd'), (2, 'even'), (3, 'odd'),
+ (4, 'even'), (5, 'odd'), (6, 'even');
+}
+
+execsql_test 8.1 {
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+}
+
+execsql_test 8.2 {
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ );
+}
+
+execsql_test 8.3 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+}
+
+execsql_test 8.4 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ );
+}
+
+==========
+
+execsql_test 9.1 {
+ DROP TABLE IF EXISTS t1;
+ DROP TABLE IF EXISTS t2;
+ CREATE TABLE t1(a INTEGER);
+ CREATE TABLE t2(y INTEGER);
+}
+
+execsql_test 9.2 {
+ SELECT (
+ SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
+ + min(a) OVER()
+ )
+ FROM t1
+}
finish_test
diff --git a/test/window8.test b/test/window8.test
index ed720ebd41..0c5d39badb 100644
--- a/test/window8.test
+++ b/test/window8.test
@@ -6469,4 +6469,75 @@ do_execsql_test 7.4.9 {
);
} {4 4 4 {} {} {}}
+#==========================================================================
+
+do_execsql_test 8.0 {
+ DROP TABLE IF EXISTS tx;
+ CREATE TABLE tx(a INTEGER PRIMARY KEY);
+ INSERT INTO tx VALUES(1), (2), (3), (4), (5), (6);
+
+ DROP TABLE IF EXISTS map;
+ CREATE TABLE map(v INTEGER PRIMARY KEY, t TEXT);
+ INSERT INTO map VALUES
+ (1, 'odd'), (2, 'even'), (3, 'odd'),
+ (4, 'even'), (5, 'odd'), (6, 'even');
+} {}
+
+do_execsql_test 8.1 {
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.2 {
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map WHERE v=a
+ ) ORDER BY a
+ );
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.3 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ ) FROM tx;
+} {2 6 12 1 4 9}
+
+do_execsql_test 8.4 {
+ WITH map2 AS (
+ SELECT * FROM map
+ )
+ SELECT sum(a) OVER win FROM tx
+ WINDOW win AS (
+ PARTITION BY (
+ SELECT t FROM map2 WHERE v=a
+ ) ORDER BY a
+ );
+} {2 6 12 1 4 9}
+
+#==========================================================================
+
+do_execsql_test 9.1 {
+ DROP TABLE IF EXISTS t1;
+ DROP TABLE IF EXISTS t2;
+ CREATE TABLE t1(a INTEGER);
+ CREATE TABLE t2(y INTEGER);
+} {}
+
+do_execsql_test 9.2 {
+ SELECT (
+ SELECT max(a) OVER ( ORDER BY (SELECT sum(a) FROM t1) )
+ + min(a) OVER()
+ )
+ FROM t1
+} {}
+
finish_test
diff --git a/test/window9.test b/test/window9.test
index c342a4d790..4b8e4fa58f 100644
--- a/test/window9.test
+++ b/test/window9.test
@@ -265,4 +265,21 @@ do_execsql_test 8.4 {
FROM v1;
} {0.0 0.0}
+#--------------------------------------------------------------------------
+reset_db
+do_execsql_test 9.0 {
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(NULL,'bb',356);
+ INSERT INTO t1 VALUES('CB','aa',158);
+ INSERT INTO t1 VALUES('BB','aa',399);
+ INSERT INTO t1 VALUES('FF','bb',938);
+}
+
+do_catchsql_test 9.1 {
+ SELECT sum(c) OVER (
+ ORDER BY c RANGE BETWEEN 0 PRECEDING AND '-700' PRECEDING
+ )
+ FROM t1
+} {1 {frame ending offset must be a non-negative number}}
+
finish_test
diff --git a/test/windowfault.test b/test/windowfault.test
index 27c7742b30..b5d7433112 100644
--- a/test/windowfault.test
+++ b/test/windowfault.test
@@ -284,7 +284,7 @@ do_faultsim_test 12 -faults oom* -prep {
} -body {
execsql {
WITH v(a, b, row_number) AS (
- SELECT a, b, row_number() OVER (PARTITION BY a ORDER BY b) FROM t1
+ SELECT a, b, row_number() OVER (PARTITION BY a COLLATE nocase ORDER BY b) FROM t1
)
SELECT * FROM v WHERE a=2
}
diff --git a/test/windowpushd.test b/test/windowpushd.test
index 4462a0b4b4..f2e04d72fb 100644
--- a/test/windowpushd.test
+++ b/test/windowpushd.test
@@ -51,7 +51,7 @@ do_execsql_test 1.3 {
do_eqp_test 1.4 {
SELECT * FROM lll WHERE grp_id=2
-} {SEARCH TABLE t1 USING COVERING INDEX i1 (grp_id=?)}
+} {SEARCH t1 USING COVERING INDEX i1 (grp_id=?)}
#-------------------------------------------------------------------------
reset_db
@@ -158,10 +158,10 @@ foreach tn {0 1} {
if {$tn==1} {
do_eqp_test 2.$tn.3.3 {
SELECT * FROM v3 WHERE b='E'
- } {SEARCH TABLE t1 USING INDEX i2 (b=?)}
+ } {SEARCH t1 USING INDEX i2 (b=?)}
do_eqp_test 2.$tn.3.4 {
SELECT * FROM v3 WHERE b>'C'
- } {SEARCH TABLE t1 USING INDEX i2 (b>?)}
+ } {SEARCH t1 USING INDEX i2 (b>?)}
}
do_execsql_test 2.$tn.3.5 { SELECT * FROM v3 WHERE d<0.55; } {
@@ -172,7 +172,7 @@ foreach tn {0 1} {
if {$tn==1} {
do_eqp_test 2.$tn.3.6 {
SELECT * FROM v3 WHERE d<0.55
- } {SCAN TABLE t1 USING INDEX i2}
+ } {SCAN t1 USING INDEX i2}
}
do_execsql_test 2.$tn.4.1 {
@@ -234,4 +234,3 @@ foreach tn {0 1} {
finish_test
-
diff --git a/test/with1.test b/test/with1.test
index 74997c1db0..5765399d10 100644
--- a/test/with1.test
+++ b/test/with1.test
@@ -1025,10 +1025,10 @@ do_eqp_test 19.1b {
SELECT * FROM t1;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE x1
| `--SCAN CONSTANT ROW
- |--SCAN SUBQUERY xxxxxx
- `--SCAN SUBQUERY xxxxxx
+ |--SCAN x1
+ `--SCAN x1
}
# 2017-10-28.
@@ -1149,20 +1149,26 @@ do_execsql_test 24.2 {
# had to continue to recognize "true" and "false" as identifiers for
# backwards compatibility.
#
-reset_db
-do_execsql_test 25.1 {
- CREATE TABLE dual(dummy);
- INSERT INTO dual(dummy) VALUES('X');
- WITH cte1 AS (
- SELECT TRUE, (
- WITH cte2 AS (SELECT avg(DISTINCT TRUE) FROM dual)
- SELECT 2571 FROM cte2
- ) AS subquery1
- FROM dual
- GROUP BY 1
- )
- SELECT (SELECT 1324 FROM cte1) FROM cte1;
-} {1324}
+foreach {id dual} {
+ 1 {CREATE TABLE dual AS SELECT 'X' AS dummy}
+ 2 {CREATE TEMP TABLE dual AS SELECT 'X' AS dummy}
+ 3 {CREATE VIEW dual(dummy) AS VALUES('X')}
+ 4 {CREATE TEMP VIEW dual(dummy) AS VALUES('X')}
+} {
+ reset_db
+ db eval $dual
+ do_execsql_test 25.$id {
+ WITH cte1 AS (
+ SELECT TRUE, (
+ WITH cte2 AS (SELECT avg(DISTINCT TRUE) FROM dual)
+ SELECT 2571 FROM cte2
+ ) AS subquery1
+ FROM dual
+ GROUP BY 1
+ )
+ SELECT (SELECT 1324 FROM cte1) FROM cte1;
+ } {1324}
+}
do_catchsql_test 26.0 {
WITH i(x) AS (
@@ -1207,4 +1213,28 @@ do_execsql_test 26.3 {
SELECT * FROM cte ORDER BY +label, +step;
} {a 1 a 2 a 3 b 1 b 2 b 3}
+# 2021-05-20
+# forum post https://sqlite.org/forum/forumpost/8590e3f6dc
+#
+reset_db
+do_execsql_test 27.1 {
+ CREATE TABLE t1(k);
+ CREATE TABLE log(k, cte_map, main_map);
+ CREATE TABLE map(k, v);
+ INSERT INTO map VALUES(1, 'main1'), (2, 'main2');
+
+ CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO log
+ WITH map(k,v) AS (VALUES(1,'cte1'),(2,'cte2'))
+ SELECT
+ new.k,
+ (SELECT v FROM map WHERE k=new.k),
+ (SELECT v FROM main.map WHERE k=new.k);
+ END;
+
+ INSERT INTO t1 VALUES(1);
+ INSERT INTO t1 VALUES(2);
+ SELECT k, cte_map, main_map, '|' FROM log ORDER BY k;
+} {1 cte1 main1 | 2 cte2 main2 |}
+
finish_test
diff --git a/test/with3.test b/test/with3.test
index 6dffb84077..8e8eba89f6 100644
--- a/test/with3.test
+++ b/test/with3.test
@@ -89,13 +89,13 @@ ifcapable analyze {
SELECT * FROM cnt, y1 WHERE i=a
} [string map {"\n " \n} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE cnt
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
- | `--SCAN TABLE cnt
- |--SCAN SUBQUERY xxxxxx
- `--SEARCH TABLE y1 USING INDEX y1a (a=?)
+ | `--SCAN cnt
+ |--SCAN cnt
+ `--SEARCH y1 USING INDEX y1a (a=?)
}]
do_eqp_test 3.1.3 {
@@ -103,13 +103,13 @@ ifcapable analyze {
SELECT * FROM cnt, y1 WHERE i=a
} [string map {"\n " \n} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE cnt
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
- | `--SCAN TABLE cnt
- |--SCAN TABLE y1
- `--SEARCH SUBQUERY xxxxxx USING AUTOMATIC COVERING INDEX (i=?)
+ | `--SCAN cnt
+ |--SCAN y1
+ `--SEARCH cnt USING AUTOMATIC COVERING INDEX (i=?)
}]
}
@@ -125,17 +125,17 @@ do_eqp_test 3.2.2 {
WHERE c.id=w2.pk AND c.id=w1.pk;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| |--SETUP
| | |--SCAN CONSTANT ROW
| | `--SCALAR SUBQUERY xxxxxx
- | | `--SCAN TABLE w2
+ | | `--SCAN w2
| `--RECURSIVE STEP
- | |--SCAN TABLE w1
- | `--SCAN TABLE c
- |--SCAN SUBQUERY xxxxxx
- |--SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)
- `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)
+ | |--SCAN w1
+ | `--SCAN c
+ |--SCAN c
+ |--SEARCH w2 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH w1 USING INTEGER PRIMARY KEY (rowid=?)
}
do_execsql_test 4.0 {
@@ -207,15 +207,15 @@ do_eqp_test 5.1 {
ORDER BY 1;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
- | `--SCAN TABLE c
- |--SCAN SUBQUERY xxxxxx AS x1
- |--SCAN SUBQUERY xxxxxx AS x2
- |--SCAN SUBQUERY xxxxxx AS x3
- |--SCAN SUBQUERY xxxxxx AS x4
+ | `--SCAN c
+ |--SCAN x1
+ |--SCAN x2
+ |--SCAN x3
+ |--SCAN x4
`--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 5.2 {
diff --git a/test/with6.test b/test/with6.test
index ef63ec8bee..333147d8be 100644
--- a/test/with6.test
+++ b/test/with6.test
@@ -30,11 +30,11 @@ do_eqp_test 101 {
SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| `--SCAN 2 CONSTANT ROWS
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
do_execsql_test 110 {
@@ -46,11 +46,11 @@ do_eqp_test 111 {
SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| `--SCAN 2 CONSTANT ROWS
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
# Even though the CTE is not materialized, the self-join optimization
@@ -65,11 +65,11 @@ do_eqp_test 121 {
SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| `--SCAN 2 CONSTANT ROWS
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
do_execsql_test 130 {
@@ -87,21 +87,21 @@ do_eqp_test 131 {
(SELECT x FROM c LIMIT 5) AS c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--CO-ROUTINE xxxxxx
+ |--MATERIALIZE c1
+ | |--CO-ROUTINE c
| | `--SCAN 2 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | |--CO-ROUTINE xxxxxx
+ | `--SCAN c
+ |--MATERIALIZE c2
+ | |--CO-ROUTINE c
| | `--SCAN 2 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | |--CO-ROUTINE xxxxxx
+ | `--SCAN c
+ |--MATERIALIZE c3
+ | |--CO-ROUTINE c
| | `--SCAN 2 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ | `--SCAN c
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
# The (SELECT x FROM c LIMIT N) subqueries get materialized once each.
@@ -123,17 +123,17 @@ do_eqp_test 141 {
(SELECT x FROM c LIMIT 7) AS c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c1
+ | |--MATERIALIZE c
| | `--SCAN 2 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | `--SCAN SUBQUERY xxxxxx
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ | `--SCAN c
+ |--MATERIALIZE c2
+ | `--SCAN c
+ |--MATERIALIZE c3
+ | `--SCAN c
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
do_execsql_test 150 {
@@ -151,17 +151,17 @@ do_eqp_test 151 {
(SELECT x FROM c LIMIT 7) AS c3;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c1
+ | |--MATERIALIZE c
| | `--SCAN 2 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | `--SCAN SUBQUERY xxxxxx
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- `--SCAN SUBQUERY xxxxxx AS c3
+ | `--SCAN c
+ |--MATERIALIZE c2
+ | `--SCAN c
+ |--MATERIALIZE c3
+ | `--SCAN c
+ |--SCAN c1
+ |--SCAN c2
+ `--SCAN c3
}
do_execsql_test 160 {
@@ -175,11 +175,11 @@ do_eqp_test 161 {
FROM c AS c2 WHERE c2.x<10;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c
| `--SCAN 2 CONSTANT ROWS
- |--SCAN SUBQUERY xxxxxx AS c2
+ |--SCAN c2
`--CORRELATED SCALAR SUBQUERY xxxxxx
- `--SCAN SUBQUERY xxxxxx
+ `--SCAN c
}
do_execsql_test 170 {
@@ -193,13 +193,13 @@ do_eqp_test 171 {
FROM c AS c2 WHERE c2.x<10;
} {
QUERY PLAN
- |--CO-ROUTINE xxxxxx
+ |--CO-ROUTINE c
| `--SCAN 2 CONSTANT ROWS
- |--SCAN SUBQUERY xxxxxx AS c2
+ |--SCAN c2
`--CORRELATED SCALAR SUBQUERY xxxxxx
- |--CO-ROUTINE xxxxxx
+ |--CO-ROUTINE c
| `--SCAN 2 CONSTANT ROWS
- `--SCAN SUBQUERY xxxxxx
+ `--SCAN c
}
@@ -228,15 +228,15 @@ do_eqp_test 211 {
SELECT y FROM t2 ORDER BY y;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--MATERIALIZE xxxxxx
+ |--MATERIALIZE c1
+ | |--MATERIALIZE c
| | `--SCAN 3 CONSTANT ROWS
- | `--SCAN SUBQUERY xxxxxx
- |--MATERIALIZE xxxxxx
- | `--SCAN SUBQUERY xxxxxx
- |--SCAN SUBQUERY xxxxxx AS c1
- |--SCAN SUBQUERY xxxxxx AS c2
- |--SCAN TABLE t1
+ | `--SCAN c
+ |--MATERIALIZE c2
+ | `--SCAN c
+ |--SCAN c1
+ |--SCAN c2
+ |--SCAN t1
`--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 220 {
diff --git a/test/without_rowid1.test b/test/without_rowid1.test
index 02a089610d..e4e69eb727 100644
--- a/test/without_rowid1.test
+++ b/test/without_rowid1.test
@@ -452,5 +452,18 @@ do_execsql_test 13.10 {
PRAGMA integrity_check;
SELECT * FROM t0, t1;
} {ok abc xyz abc xyz}
+
+# 2021-05-13 https://sqlite.org/forum/forumpost/6c8960f545
+reset_db
+do_execsql_test 14.1 {
+ CREATE TABLE t1(a INT PRIMARY KEY) WITHOUT ROWID;
+ INSERT INTO t1(a) VALUES(10);
+ ALTER TABLE t1 ADD COLUMN b INT;
+ SELECT * FROM t1 WHERE a=20 OR (a=10 AND b=10);
+} {}
+do_execsql_test 14.2 {
+ CREATE TABLE dual AS SELECT 'X' AS dummy;
+ EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10;
+} {~/b=/}
finish_test
diff --git a/test/without_rowid6.test b/test/without_rowid6.test
index 567acfaed6..06fc7435b0 100644
--- a/test/without_rowid6.test
+++ b/test/without_rowid6.test
@@ -64,7 +64,7 @@ do_execsql_test_if_vtab without_rowid6-201 {
do_execsql_test without_rowid6-210 {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>3 ORDER BY b;
-} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-220 {
PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}
@@ -83,7 +83,7 @@ do_execsql_test without_rowid6-300 {
do_execsql_test without_rowid6-310 {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>3 ORDER BY b;
-} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-320 {
PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}
@@ -101,7 +101,7 @@ do_execsql_test without_rowid6-400 {
do_execsql_test without_rowid6-410 {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>3 ORDER BY b;
-} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-420 {
PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}
@@ -121,7 +121,7 @@ do_execsql_test_if_vtab without_rowid6-501 {
do_execsql_test without_rowid6-510 {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b>3 ORDER BY b;
-} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
+} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-520 {
PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_1 1 pk/}
diff --git a/test/zipfile.test b/test/zipfile.test
index 79298a0506..8749f17c38 100644
--- a/test/zipfile.test
+++ b/test/zipfile.test
@@ -843,4 +843,16 @@ do_catchsql_test 16.20 {
REPLACE INTO zipfile VALUES(null,null,null,null,null,123,null);
} {1 {zipfile: missing filename}}
+# 2021-04-22 forum https://sqlite.org/forum/forumpost/d82289d69f
+do_execsql_test 17.1 {
+ WITH vlist(x) AS (
+ VALUES(9223372036854775807),
+ (-9223372036854775808),
+ (9223372036854775806),
+ (-9223372036854775807)
+ )
+ SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist;
+} {blob}
+
+
finish_test
diff --git a/tool/lemon.c b/tool/lemon.c
index 06ba1be2bd..75fc7aa2fb 100644
--- a/tool/lemon.c
+++ b/tool/lemon.c
@@ -2708,7 +2708,7 @@ static void parseonetoken(struct pstate *psp)
** in order to control their assigned integer number. The number for
** each token is assigned when it is first seen. So by including
**
- ** %token ONE TWO THREE
+ ** %token ONE TWO THREE.
**
** early in the grammar file, that assigns small consecutive values
** to each of the tokens ONE TWO and THREE.
diff --git a/tool/mkctimec.tcl b/tool/mkctimec.tcl
index 499d5a5639..2f15ac9fb7 100644
--- a/tool/mkctimec.tcl
+++ b/tool/mkctimec.tcl
@@ -4,16 +4,28 @@
#
# const char **azCompileOpt[]
#
-# declaration used in src/ctime.c, run this script.
+# definition used in src/ctime.c, run this script from
+# the checkout root. It alters src/ctime.c in-place.
#
-# All Boolean compile time options.
+# All Boolean compile time options which default to something
+# other than 0 or empty. The default is paired with the PP
+# symbol so that a differing define can be detected.
#
-set boolean_options {
+set boolean_defnnz_options {
+ {SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1}
+ {SQLITE_POWERSAFE_OVERWRITE 1}
+ {SQLITE_DEFAULT_MEMSTATUS 1}
+ {SQLITE_OMIT_TRACE 1}
+ {SQLITE_ALLOW_COVERING_INDEX_SCAN 1}
+}
+
+# All Boolean compile time options which default to 0 or empty.
+#
+set boolean_defnil_options {
SQLITE_32BIT_ROWID
SQLITE_4_BYTE_ALIGNED_MALLOC
SQLITE_64BIT_STATS
- SQLITE_ALLOW_COVERING_INDEX_SCAN
SQLITE_ALLOW_URI_AUTHORITY
SQLITE_BUG_COMPATIBLE_20160819
SQLITE_CASE_SENSITIVE_LIKE
@@ -25,7 +37,6 @@ set boolean_options {
SQLITE_DEFAULT_CKPTFULLFSYNC
SQLITE_DEFAULT_FOREIGN_KEYS
SQLITE_DEFAULT_LOCKING_MODE
- SQLITE_DEFAULT_MEMSTATUS
SQLITE_DEFAULT_RECURSIVE_TRIGGERS
SQLITE_DEFAULT_SYNCHRONOUS
SQLITE_DEFAULT_WAL_SYNCHRONOUS
@@ -40,40 +51,49 @@ set boolean_options {
SQLITE_ENABLE_8_3_NAMES
SQLITE_ENABLE_API_ARMOR
SQLITE_ENABLE_ATOMIC_WRITE
- SQLITE_ENABLE_CEROD
+ SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ SQLITE_ENABLE_BYTECODE_VTAB
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_COLUMN_USED_MASK
SQLITE_ENABLE_COSTMULT
SQLITE_ENABLE_CURSOR_HINTS
+ SQLITE_ENABLE_DBPAGE_VTAB
SQLITE_ENABLE_DBSTAT_VTAB
SQLITE_ENABLE_EXPENSIVE_ASSERT
- SQLITE_ENABLE_FTS1
- SQLITE_ENABLE_FTS2
+ SQLITE_ENABLE_EXPLAIN_COMMENTS
SQLITE_ENABLE_FTS3
SQLITE_ENABLE_FTS3_PARENTHESIS
SQLITE_ENABLE_FTS3_TOKENIZER
SQLITE_ENABLE_FTS4
SQLITE_ENABLE_FTS5
+ SQLITE_ENABLE_GEOPOLY
SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_ENABLE_ICU
SQLITE_ENABLE_IOTRACE
SQLITE_ENABLE_JSON1
SQLITE_ENABLE_LOAD_EXTENSION
SQLITE_ENABLE_LOCKING_STYLE
+ SQLITE_ENABLE_MATH_FUNCTIONS
SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_ENABLE_MEMSYS3
SQLITE_ENABLE_MEMSYS5
SQLITE_ENABLE_MULTIPLEX
+ SQLITE_ENABLE_NORMALIZE
SQLITE_ENABLE_NULL_TRIM
+ SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
SQLITE_ENABLE_PREUPDATE_HOOK
+ SQLITE_ENABLE_QPSG
SQLITE_ENABLE_RBU
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_SELECTTRACE
SQLITE_ENABLE_SESSION
SQLITE_ENABLE_SNAPSHOT
+ SQLITE_ENABLE_SORTER_REFERENCES
SQLITE_ENABLE_SQLLOG
+ SQLITE_ENABLE_STAT4
SQLITE_ENABLE_STMT_SCANSTATUS
+ SQLITE_ENABLE_STMTVTAB
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SQLITE_ENABLE_UNLOCK_NOTIFY
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
@@ -85,8 +105,6 @@ set boolean_options {
SQLITE_EXTRA_IFNULLROW
SQLITE_FTS5_ENABLE_TEST_MI
SQLITE_FTS5_NO_WITHOUT_ROWID
- SQLITE_HAS_CODEC
- SQLITE_HOMEGROWN_RECURSIVE_MUTEX
SQLITE_IGNORE_AFP_LOCK_ERRORS
SQLITE_IGNORE_FLOCK_LOCK_ERRORS
SQLITE_INLINE_MEMCPY
@@ -98,7 +116,6 @@ set boolean_options {
SQLITE_MIXED_ENDIAN_64BIT_FLOAT
SQLITE_MMAP_READWRITE
SQLITE_MUTEX_NOOP
- SQLITE_MUTEX_NREF
SQLITE_MUTEX_OMIT
SQLITE_MUTEX_PTHREADS
SQLITE_MUTEX_W32
@@ -116,16 +133,15 @@ set boolean_options {
SQLITE_OMIT_AUTOVACUUM
SQLITE_OMIT_BETWEEN_OPTIMIZATION
SQLITE_OMIT_BLOB_LITERAL
- SQLITE_OMIT_BTREECOUNT
SQLITE_OMIT_CAST
SQLITE_OMIT_CHECK
SQLITE_OMIT_COMPLETE
SQLITE_OMIT_COMPOUND_SELECT
SQLITE_OMIT_CONFLICT_CLAUSE
SQLITE_OMIT_CTE
- SQLITE_OMIT_DATETIME_FUNCS
SQLITE_OMIT_DECLTYPE
SQLITE_OMIT_DEPRECATED
+ SQLITE_OMIT_DESERIALIZE
SQLITE_OMIT_DISKIO
SQLITE_OMIT_EXPLAIN
SQLITE_OMIT_FLAG_PRAGMAS
@@ -135,6 +151,7 @@ set boolean_options {
SQLITE_OMIT_HEX_INTEGER
SQLITE_OMIT_INCRBLOB
SQLITE_OMIT_INTEGRITY_CHECK
+ SQLITE_OMIT_INTROSPECTION_PRAGMAS
SQLITE_OMIT_LIKE_OPTIMIZATION
SQLITE_OMIT_LOAD_EXTENSION
SQLITE_OMIT_LOCALTIME
@@ -156,7 +173,6 @@ set boolean_options {
SQLITE_OMIT_TCL_VARIABLE
SQLITE_OMIT_TEMPDB
SQLITE_OMIT_TEST_CONTROL
- SQLITE_OMIT_TRACE
SQLITE_OMIT_TRIGGER
SQLITE_OMIT_TRUNCATE_OPTIMIZATION
SQLITE_OMIT_UTF16
@@ -168,7 +184,6 @@ set boolean_options {
SQLITE_OMIT_XFER_OPT
SQLITE_PCACHE_SEPARATE_HEADER
SQLITE_PERFORMANCE_TRACE
- SQLITE_POWERSAFE_OVERWRITE
SQLITE_PREFER_PROXY_LOCKING
SQLITE_PROXY_DEBUG
SQLITE_REVERSE_UNORDERED_SELECTS
@@ -177,7 +192,6 @@ set boolean_options {
SQLITE_SMALL_STACK
SQLITE_SOUNDEX
SQLITE_SUBSTR_COMPATIBILITY
- SQLITE_SYSTEM_MALLOC
SQLITE_TCL
SQLITE_TEST
SQLITE_UNLINK_AFTER_CLOSE
@@ -191,7 +205,15 @@ set boolean_options {
SQLITE_ZERO_MALLOC
}
-# All compile time options for which the assigned value is other than boolean.
+# All compile time options for which the assigned value is other than boolean
+# and is a comma-separated scalar pair.
+#
+set value2_options {
+ SQLITE_DEFAULT_LOOKASIDE
+}
+
+# All compile time options for which the assigned value is other than boolean
+# and is a single scalar.
#
set value_options {
SQLITE_BITMASK_TYPE
@@ -200,7 +222,6 @@ set value_options {
SQLITE_DEFAULT_FILE_PERMISSIONS
SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
SQLITE_DEFAULT_LOCKING_MODE
- SQLITE_DEFAULT_LOOKASIDE
SQLITE_DEFAULT_MMAP_SIZE
SQLITE_DEFAULT_PAGE_SIZE
SQLITE_DEFAULT_PCACHE_INITSZ
@@ -212,6 +233,7 @@ set value_options {
SQLITE_DEFAULT_WAL_SYNCHRONOUS
SQLITE_DEFAULT_WORKER_THREADS
SQLITE_ENABLE_8_3_NAMES
+ SQLITE_ENABLE_CEROD
SQLITE_ENABLE_LOCKING_STYLE
SQLITE_EXTRA_INIT
SQLITE_EXTRA_SHUTDOWN
@@ -245,13 +267,6 @@ set value_options {
# Options that require custom code.
#
-set options(ENABLE_STAT3) {
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#elif defined(SQLITE_ENABLE_STAT3)
- "ENABLE_STAT3",
-#endif
-}
set options(COMPILER) {
#if defined(__clang__) && defined(__clang_major__)
"COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
@@ -268,13 +283,26 @@ set options(HAVE_ISNAN) {
"HAVE_ISNAN",
#endif
}
+set options(OMIT_DATETIME_FUNCS) {
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
+ "OMIT_DATETIME_FUNCS",
+#endif
+}
+set options(SYSTEM_MALLOC) "\
+#if (!defined(SQLITE_WIN32_MALLOC) \\
+ && !defined(SQLITE_ZERO_MALLOC) \\
+ && !defined(SQLITE_MEMDEBUG) \\
+ ) || defined(SQLITE_SYSTEM_MALLOC)
+ \"SYSTEM_MALLOC\",
+#endif
+"
set options(THREADSAFE) {
#if defined(SQLITE_THREADSAFE)
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#elif defined(THREADSAFE)
"THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
#else
- "THREADSAFE=1"
+ "THREADSAFE=1",
#endif
}
@@ -286,7 +314,20 @@ proc trim_name {in} {
return $ret
}
-foreach b $boolean_options {
+foreach name_defval $boolean_defnnz_options {
+ set b [lindex $name_defval 0]
+ set defval [lindex $name_defval 1]
+ set name [trim_name $b]
+ set options($name) [subst {
+#ifdef $b
+# if $b != $defval
+ "$name=" CTIMEOPT_VAL($b),
+# endif
+#endif
+}]
+}
+
+foreach b $boolean_defnil_options {
set name [trim_name $b]
set options($name) [subst {
#if $b
@@ -303,9 +344,70 @@ foreach v $value_options {
#endif
}]
}
+
+foreach v $value2_options {
+ set name [trim_name $v]
+ set options($name) [subst {
+#ifdef $v
+ "$name=" CTIMEOPT_VAL2($v),
+#endif
+}]
+}
-foreach o [lsort [array names options]] {
- puts [string trim $options($o)]
+# Split a string on a regex, return all parts in order.
+# Any elements with an even index may be empty.
+# Elements with odd indices will match the regex.
+proc split_on_re {re str {nrepps 1}} {
+ set chunks {}
+ set cix 0
+ set resm [regexp -all -inline -indices $re $str]
+ if {[llength $resm]==0} {
+ return $str
+ }
+ set rix 0
+ while {$rix < [llength $resm]} {
+ set mre [lindex $resm $rix]
+ incr rix $nrepps
+ set mbx [lindex $mre 0]
+ set mex [lindex $mre 1]
+ lappend chunks [string range $str $cix [expr $mbx - 1]]
+ lappend chunks [string range $str $mbx $mex]
+ set cix [expr $mex + 1]
+ }
+ lappend chunks [string range $str $cix end]
+ return $chunks
}
+set ctime_c "src/ctime.c"
+if {[catch {set cfd [open $ctime_c r]}]!=0} {
+ puts stderr "File '$ctime_c' unreadable. Run this script from checkout root."
+ exit 1;
+}
+
+set ctfc [read $cfd]
+close $cfd
+
+set re {/\*\s+\*+\s*((BEGIN)|(END)) CODE GENERATED BY (\S+)\s+\*/\s+}
+set renpp 5
+
+set ctfcChunks [split_on_re $re $ctfc $renpp]
+if {[llength $ctfcChunks] != 5} {
+ puts stderr "File '$ctime_c' has too few generated code markers."
+ exit 1;
+}
+
+if {[catch {set cfd [open $ctime_c w]}]!=0} {
+ puts stderr "File '$ctime_c' unwritable."
+ exit 1;
+}
+
+puts -nonewline $cfd [lindex $ctfcChunks 0]
+puts -nonewline $cfd [lindex $ctfcChunks 1]
+foreach o [lsort [array names options]] {
+ puts $cfd [string trim $options($o)]
+}
+puts -nonewline $cfd [lindex $ctfcChunks 3]
+puts -nonewline $cfd [lindex $ctfcChunks 4]
+
+close $cfd
diff --git a/tool/mkopcodeh.tcl b/tool/mkopcodeh.tcl
index 57017364a0..cc372e404a 100644
--- a/tool/mkopcodeh.tcl
+++ b/tool/mkopcodeh.tcl
@@ -145,7 +145,9 @@ foreach name {OP_Noop OP_Explain OP_Abortable} {
incr nOp
}
-# The following are the opcodes that are processed by resolveP2Values()
+# The following are the opcodes that receive special processing in the
+# resolveP2Values() routine. Update this list whenever new cases are
+# added to the pOp->opcode switch within resolveP2Values().
#
set rp2v_ops {
OP_Transaction
@@ -157,13 +159,11 @@ set rp2v_ops {
OP_VUpdate
OP_VFilter
OP_Next
- OP_NextIfOpen
OP_SorterNext
OP_Prev
- OP_PrevIfOpen
}
-# Assign small values to opcodes that are processed by resolveP2Values()
+# Assign the smallest values to opcodes that are processed by resolveP2Values()
# to make code generation for the switch() statement smaller and faster.
#
set cnt -1
@@ -177,6 +177,7 @@ for {set i 0} {$i<$nOp} {incr i} {
set def($cnt) $name
}
}
+set mxCase1 $cnt
# Assign the next group of values to JUMP opcodes
#
@@ -311,7 +312,7 @@ for {set i 0} {$i<=$max} {incr i} {
}
puts "\175"
puts ""
-puts "/* The sqlite3P2Values() routine is able to run faster if it knows"
+puts "/* The resolve3P2Values() routine is able to run faster if it knows"
puts "** the value of the largest JUMP opcode. The smaller the maximum"
puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"
puts "** generated this include file strives to group all JUMP opcodes"
diff --git a/tool/omittest.tcl b/tool/omittest.tcl
index 120fc2afdd..9f24d6d3d3 100644
--- a/tool/omittest.tcl
+++ b/tool/omittest.tcl
@@ -206,6 +206,7 @@ proc main {argv} {
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
+ SQLITE_OMIT_DESERIALIZE \
SQLITE_OMIT_DISKIO \
SQLITE_OMIT_EXPLAIN \
SQLITE_OMIT_FLAG_PRAGMAS \
@@ -254,6 +255,7 @@ proc main {argv} {
]
set ::ENABLE_SYMBOLS [list \
+ SQLITE_ALLOW_ROWID_IN_VIEW \
SQLITE_DISABLE_DIRSYNC \
SQLITE_DISABLE_LFS \
SQLITE_ENABLE_ATOMIC_WRITE \
diff --git a/tool/showdb.c b/tool/showdb.c
index 09c4d9de44..5e949939e1 100644
--- a/tool/showdb.c
+++ b/tool/showdb.c
@@ -912,10 +912,19 @@ static void page_usage_btree(
int cellstart = hdr+12;
u32 child;
for(i=0; i= g.pagesize ){
+ printf("ERROR: page %d too many cells (%d)\n", pgno, nCell);
+ break;
+ }
+ ofst = a[cellidx]*256 + a[cellidx+1];
+ if( ofst=g.pagesize ){
+ printf("ERROR: page %d cell %d out of bounds\n", pgno, i);
+ continue;
+ }
child = decodeInt32(a+ofst);
page_usage_btree(child, pgno, i, zName);
}