aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2019-12-31 14:49:10 +0000
committerdrh <drh@noemail.net>2019-12-31 14:49:10 +0000
commit5f6a2ed7f275a201a8ce9fd81b60a2a552c20f6b (patch)
tree0a8359d1c5b0829d9a6292e85665979bf364e076
parentd335bc40a6576d8759466d8efaaaf82b04667aaa (diff)
parent02ff747bc0a6039cddf6108719426d247026fa18 (diff)
downloadsqlite-5f6a2ed7f275a201a8ce9fd81b60a2a552c20f6b.tar.gz
sqlite-5f6a2ed7f275a201a8ce9fd81b60a2a552c20f6b.zip
Merge recent enhancements from trunk.
FossilOrigin-Name: 39d55579376906f212271ce9b2d367e3ad029fb173f22c7253312b467970208a
-rw-r--r--Makefile.in2
-rw-r--r--Makefile.msc15
-rw-r--r--autoconf/Makefile.msc15
-rw-r--r--autoconf/configure.ac2
-rwxr-xr-xconfigure49
-rw-r--r--configure.ac16
-rw-r--r--ext/fts3/fts3.c45
-rw-r--r--ext/fts3/fts3Int.h4
-rw-r--r--ext/fts3/fts3_write.c31
-rw-r--r--ext/fts5/fts5_index.c50
-rw-r--r--ext/fts5/fts5_main.c5
-rw-r--r--ext/fts5/fts5_storage.c15
-rw-r--r--ext/fts5/test/fts5corrupt3.test223
-rw-r--r--ext/fts5/test/fts5integrity.test45
-rw-r--r--ext/fts5/test/fts5misc.test72
-rw-r--r--ext/fts5/test/fts5savepoint.test85
-rw-r--r--ext/misc/regexp.c2
-rw-r--r--ext/misc/zipfile.c22
-rw-r--r--ext/rbu/sqlite3rbu.c2
-rw-r--r--ext/rtree/geopoly.c8
-rw-r--r--ext/rtree/rtree.c27
-rw-r--r--manifest165
-rw-r--r--manifest.uuid2
-rw-r--r--src/alter.c23
-rw-r--r--src/btree.c53
-rw-r--r--src/btree.h2
-rw-r--r--src/btreeInt.h1
-rw-r--r--src/build.c68
-rw-r--r--src/expr.c117
-rw-r--r--src/insert.c172
-rw-r--r--src/os_unix.c3
-rw-r--r--src/pager.c7
-rw-r--r--src/pcache1.c4
-rw-r--r--src/resolve.c4
-rw-r--r--src/select.c56
-rw-r--r--src/sqlite.h.in1
-rw-r--r--src/sqliteInt.h24
-rw-r--r--src/treeview.c5
-rw-r--r--src/update.c13
-rw-r--r--src/upsert.c1
-rw-r--r--src/util.c4
-rw-r--r--src/vdbe.c182
-rw-r--r--src/vdbe.h5
-rw-r--r--src/vdbeInt.h3
-rw-r--r--src/vdbeaux.c30
-rw-r--r--src/vdbemem.c7
-rw-r--r--src/vtab.c4
-rw-r--r--src/where.c97
-rw-r--r--src/whereInt.h3
-rw-r--r--src/wherecode.c60
-rw-r--r--src/whereexpr.c10
-rw-r--r--src/window.c20
-rw-r--r--test/altertab2.test11
-rw-r--r--test/altertab3.test69
-rw-r--r--test/check.test69
-rw-r--r--test/conflict.test22
-rw-r--r--test/conflict3.test12
-rw-r--r--test/exclusive.test18
-rw-r--r--test/filter1.test20
-rw-r--r--test/fts3corrupt4.test54
-rw-r--r--test/fts4langid.test15
-rw-r--r--test/fuzzcheck.c39
-rw-r--r--test/fuzzdata8.dbbin1501184 -> 1620992 bytes
-rw-r--r--test/gencol1.test202
-rw-r--r--test/join.test49
-rw-r--r--test/join2.test14
-rw-r--r--test/nulls1.test50
-rw-r--r--test/pragma3.test29
-rw-r--r--test/rowvalue.test9
-rw-r--r--test/select1.test20
-rw-r--r--test/update.test72
-rw-r--r--test/upsert1.test8
-rw-r--r--test/whereG.test12
-rw-r--r--test/window1.test216
-rw-r--r--test/window2.tcl41
-rw-r--r--test/window2.test43
-rw-r--r--test/windowfault.test19
-rw-r--r--test/zipfile.test41
-rw-r--r--tool/lemon.c10
-rw-r--r--tool/mkmsvcmin.tcl2
80 files changed, 2556 insertions, 491 deletions
diff --git a/Makefile.in b/Makefile.in
index 015796b65..e4b824365 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1177,7 +1177,7 @@ FTS5_SRC = \
$(TOP)/ext/fts5/fts5_varint.c \
$(TOP)/ext/fts5/fts5_vocab.c \
-fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon
+fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon$(BEXE)
cp $(TOP)/ext/fts5/fts5parse.y .
rm -f fts5parse.h
./lemon$(BEXE) $(OPTS) -S fts5parse.y
diff --git a/Makefile.msc b/Makefile.msc
index 1f7cec129..d0b7860d9 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -248,6 +248,12 @@ OPTIMIZATIONS = 2
SESSION = 0
!ENDIF
+# Set this to non-0 to enable support for the rbu extension.
+#
+!IFNDEF RBU
+RBU = 0
+!ENDIF
+
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -364,6 +370,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
+# Should the rbu extension be enabled? If so, add compilation options
+# to enable it.
+#
+!IF $(RBU)!=0
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
+!ENDIF
+
# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
@@ -1742,7 +1755,7 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
- | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@]*)(?:@\d+)?$$" \1 \
| sort >> sqlite3.def
# <</block2>>
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index 52c14c697..37a3c1b18 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -210,6 +210,12 @@ OPTIMIZATIONS = 2
SESSION = 0
!ENDIF
+# Set this to non-0 to enable support for the rbu extension.
+#
+!IFNDEF RBU
+RBU = 0
+!ENDIF
+
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
@@ -295,6 +301,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
+# Should the rbu extension be enabled? If so, add compilation options
+# to enable it.
+#
+!IF $(RBU)!=0
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
+!ENDIF
+
# These are the "extended" SQLite compilation options used when compiling for
# the Windows 10 platform.
#
@@ -977,7 +990,7 @@ Replace.exe:
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
+ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
diff --git a/autoconf/configure.ac b/autoconf/configure.ac
index 82ab43dfa..167626d59 100644
--- a/autoconf/configure.ac
+++ b/autoconf/configure.ac
@@ -161,7 +161,7 @@ AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
[--enable-rtree], [include rtree support [default=yes]])],
[], [enable_rtree=yes])
if test x"$enable_rtree" = "xyes"; then
- BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
fi
#-----------------------------------------------------------------------
diff --git a/configure b/configure
index 299cffa60..1d1a5d242 100755
--- a/configure
+++ b/configure
@@ -906,6 +906,7 @@ enable_amalgamation
enable_load_extension
enable_memsys5
enable_memsys3
+enable_all
enable_fts3
enable_fts4
enable_fts5
@@ -1559,6 +1560,7 @@ Optional Features:
Disable loading of external extensions
--enable-memsys5 Enable MEMSYS5
--enable-memsys3 Enable MEMSYS3
+ --enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
--enable-fts3 Enable the FTS3 extension
--enable-fts4 Enable the FTS4 extension
--enable-fts5 Enable the FTS5 extension
@@ -3934,13 +3936,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:3937: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:3939: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:3942: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:3943: output\"" >&5)
+ (eval echo "\"\$as_me:3945: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5146,7 +5148,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5149 "configure"' > conftest.$ac_ext
+ echo '#line 5151 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6671,11 +6673,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6674: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6676: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6678: \$? = $ac_status" >&5
+ echo "$as_me:6680: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7010,11 +7012,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7013: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7015: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7017: \$? = $ac_status" >&5
+ echo "$as_me:7019: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7115,11 +7117,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7118: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7120: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7122: \$? = $ac_status" >&5
+ echo "$as_me:7124: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7170,11 +7172,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7173: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7175: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7177: \$? = $ac_status" >&5
+ echo "$as_me:7179: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9550,7 +9552,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9553 "configure"
+#line 9555 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9646,7 +9648,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9649 "configure"
+#line 9651 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11450,6 +11452,15 @@ else
$as_echo "no" >&6; }
fi
+########
+# The --enable-extensions argument is short-hand to enable
+# multiple extensions.
+# Check whether --enable-all was given.
+if test "${enable_all+set}" = set; then :
+ enableval=$enable_all;
+fi
+
+
#########
# See whether we should enable Full Text Search extensions
# Check whether --enable-fts3 was given.
@@ -11465,7 +11476,7 @@ if test "${enable_fts4+set}" = set; then :
enableval=$enable_fts4;
fi
-if test "${enable_fts4}" = "yes" ; then
+if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
@@ -11529,7 +11540,7 @@ if test "${enable_fts5+set}" = set; then :
enableval=$enable_fts5;
fi
-if test "${enable_fts5}" = "yes" ; then
+if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
@@ -11596,7 +11607,7 @@ if test "${enable_json1+set}" = set; then :
enableval=$enable_json1;
fi
-if test "${enable_json1}" = "yes" ; then
+if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
@@ -11621,7 +11632,7 @@ else
enable_geopoly=no
fi
-if test "${enable_geopoly}" = "yes" ; then
+if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
enable_rtree=yes
fi
@@ -11644,7 +11655,7 @@ if test "${enable_session+set}" = set; then :
enableval=$enable_session;
fi
-if test "${enable_session}" = "yes" ; then
+if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
diff --git a/configure.ac b/configure.ac
index 9cf87adca..ef70a4f0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -613,6 +613,12 @@ else
AC_MSG_RESULT([no])
fi
+########
+# The --enable-extensions argument is short-hand to enable
+# multiple extensions.
+AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
+ [Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
+
#########
# See whether we should enable Full Text Search extensions
AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
@@ -622,13 +628,13 @@ if test "${enable_fts3}" = "yes" ; then
fi
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
[Enable the FTS4 extension]))
-if test "${enable_fts4}" = "yes" ; then
+if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
AC_SEARCH_LIBS([log],[m])
fi
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
[Enable the FTS5 extension]))
-if test "${enable_fts5}" = "yes" ; then
+if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
AC_SEARCH_LIBS([log],[m])
fi
@@ -636,7 +642,7 @@ fi
#########
# See whether we should enable JSON1
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
-if test "${enable_json1}" = "yes" ; then
+if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
@@ -654,7 +660,7 @@ fi
AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly],
[Enable the GEOPOLY extension]),
[enable_geopoly=yes],[enable_geopoly=no])
-if test "${enable_geopoly}" = "yes" ; then
+if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
enable_rtree=yes
fi
@@ -671,7 +677,7 @@ fi
# See whether we should enable the SESSION extension
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
[Enable the SESSION extension]))
-if test "${enable_session}" = "yes" ; then
+if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index 5067c1cf0..77738eb54 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -308,18 +308,6 @@
SQLITE_EXTENSION_INIT1
#endif
-/*
-** The following are copied from sqliteInt.h.
-**
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#ifndef SQLITE_AMALGAMATION
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
@@ -364,12 +352,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read, or 0 on error.
-** The value is stored in *v.
-*/
-int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
u32 a;
@@ -392,6 +375,15 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
}
/*
+** Read a 64-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+ return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
+}
+
+/*
** Read a 64-bit variable-length integer from memory starting at p[0] and
** not extending past pEnd[-1].
** Return the number of bytes read, or 0 on error.
@@ -2496,12 +2488,12 @@ static void fts3GetDeltaVarint3(
if( *pp>=pEnd ){
*pp = 0;
}else{
- sqlite3_int64 iVal;
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+ u64 iVal;
+ *pp += sqlite3Fts3GetVarintU(*pp, &iVal);
if( bDescIdx ){
- *pVal -= iVal;
+ *pVal = (i64)((u64)*pVal - iVal);
}else{
- *pVal += iVal;
+ *pVal = (i64)((u64)*pVal + iVal);
}
}
}
@@ -2531,10 +2523,10 @@ static void fts3PutDeltaVarint3(
sqlite3_uint64 iWrite;
if( bDescIdx==0 || *pbFirst==0 ){
assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
- iWrite = iVal - *piPrev;
+ iWrite = (u64)iVal - (u64)*piPrev;
}else{
assert_fts3_nc( *piPrev>=iVal );
- iWrite = *piPrev - iVal;
+ iWrite = (u64)*piPrev - (u64)iVal;
}
assert( *pbFirst || *piPrev==0 );
assert_fts3_nc( *pbFirst==0 || iWrite>0 );
@@ -2553,7 +2545,8 @@ static void fts3PutDeltaVarint3(
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
-#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
/*
** This function does an "OR" merge of two doclists (output contains all
@@ -2967,7 +2960,7 @@ static int fts3SegReaderCursor(
** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
- if( iLevel<0 && p->aIndex ){
+ if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index 26b23b66f..50370a910 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -196,6 +196,9 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
# define TESTONLY(X)
#endif
+#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
@@ -578,6 +581,7 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
void sqlite3Fts3ErrMsg(char**,const char*,...);
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
+int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
int sqlite3Fts3GetVarint32(const char *, int *);
int sqlite3Fts3VarintLen(sqlite3_uint64);
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index a6b45aef2..203b48e2d 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -696,7 +696,7 @@ static int fts3PendingListAppend(
assert( !p || p->iLastDocid<=iDocid );
if( !p || p->iLastDocid!=iDocid ){
- sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
+ u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
if( p ){
assert( p->nData<p->nSpace );
assert( p->aData[p->nData]==0 );
@@ -1531,18 +1531,18 @@ static int fts3SegReaderNextDocid(
}else{
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
if( rc==SQLITE_OK ){
- sqlite3_int64 iDelta;
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
+ u64 iDelta;
+ pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
if( pTab->bDescIdx ){
- pReader->iDocid -= iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
}else{
- pReader->iDocid += iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
}
}
}
}
- return SQLITE_OK;
+ return rc;
}
@@ -2281,6 +2281,7 @@ static int fts3SegWriterAdd(
int rc;
/* The current leaf node is full. Write it out to the database. */
+ if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
if( rc!=SQLITE_OK ) return rc;
p->nLeafAdd++;
@@ -2978,10 +2979,10 @@ int sqlite3Fts3SegReaderStep(
sqlite3_int64 iDelta;
if( p->bDescIdx && nDoclist>0 ){
if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
- iDelta = iPrev - iDocid;
+ iDelta = (i64)((u64)iPrev - (u64)iDocid);
}else{
if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
- iDelta = iDocid - iPrev;
+ iDelta = (i64)((u64)iDocid - (u64)iPrev);
}
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
@@ -3264,7 +3265,7 @@ static int fts3SegmentMerge(
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
- assert( pWriter || bIgnoreEmpty );
+ assert_fts3_nc( pWriter || bIgnoreEmpty );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -5190,12 +5191,12 @@ static u64 fts3ChecksumIndex(
i64 iDocid = 0;
i64 iCol = 0;
- i64 iPos = 0;
+ u64 iPos = 0;
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
while( pCsr<pEnd ){
- i64 iVal = 0;
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ u64 iVal = 0;
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( pCsr<pEnd ){
if( iVal==0 || iVal==1 ){
iCol = 0;
@@ -5203,11 +5204,11 @@ static u64 fts3ChecksumIndex(
if( iVal ){
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}else{
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( p->bDescIdx ){
- iDocid -= iVal;
+ iDocid = (i64)((u64)iDocid - iVal);
}else{
- iDocid += iVal;
+ iDocid = (i64)((u64)iDocid + iVal);
}
}
}else{
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 015696f7b..eb20af816 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -5318,10 +5318,13 @@ int sqlite3Fts5IndexCharlenToBytelen(
for(i=0; i<nChar; i++){
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
if( (unsigned char)p[n++]>=0xc0 ){
- if( n>=nByte ) break;
+ if( n>=nByte ) return 0;
while( (p[n] & 0xc0)==0x80 ){
n++;
- if( n>=nByte ) break;
+ if( n>=nByte ){
+ if( i+1==nChar ) break;
+ return 0;
+ }
}
}
}
@@ -5723,6 +5726,37 @@ static int fts5QueryCksum(
return rc;
}
+/*
+** Check if buffer z[], size n bytes, contains as series of valid utf-8
+** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
+** contain valid utf-8, return non-zero.
+*/
+static int fts5TestUtf8(const char *z, int n){
+ assert_nc( n>0 );
+ int i = 0;
+ while( i<n ){
+ if( (z[i] & 0x80)==0x00 ){
+ i++;
+ }else
+ if( (z[i] & 0xE0)==0xC0 ){
+ if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
+ i += 2;
+ }else
+ if( (z[i] & 0xF0)==0xE0 ){
+ if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
+ i += 3;
+ }else
+ if( (z[i] & 0xF8)==0xF0 ){
+ if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
+ if( (z[i+2] & 0xC0)!=0x80 ) return 1;
+ i += 3;
+ }else{
+ return 1;
+ }
+ }
+
+ return 0;
+}
/*
** This function is also purely an internal test. It does not contribute to
@@ -5763,8 +5797,14 @@ static void fts5TestTerm(
** This check may only be performed if the hash table is empty. This
** is because the hash table only supports a single scan query at
** a time, and the multi-iter loop from which this function is called
- ** is already performing such a scan. */
- if( p->nPendingData==0 ){
+ ** is already performing such a scan.
+ **
+ ** Also only do this if buffer zTerm contains nTerm bytes of valid
+ ** utf-8. Otherwise, the last part of the buffer contents might contain
+ ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
+ ** character stored in the main fts index, which will cause the
+ ** test to fail. */
+ if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
if( iIdx>0 && rc==SQLITE_OK ){
int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
ck2 = 0;
@@ -5897,8 +5937,8 @@ static void fts5IndexIntegrityCheckSegment(
i64 iRow; /* Rowid for this leaf */
Fts5Data *pLeaf; /* Data for this leaf */
+ const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
- const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
int iIdxLeaf = sqlite3_column_int(pStmt, 2);
int bIdxDlidx = sqlite3_column_int(pStmt, 3);
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 0980c5b4d..347bf7f23 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -289,7 +289,10 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
assert( iSavepoint>=-1 );
- assert( iSavepoint<=p->ts.iSavepoint );
+ /* The following assert() can fail if another vtab strikes an error
+ ** within an xSavepoint() call then SQLite calls xRollbackTo() - without
+ ** having called xSavepoint() on this vtab. */
+ /* assert( iSavepoint<=p->ts.iSavepoint ); */
p->ts.iSavepoint = iSavepoint;
break;
}
diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c
index c5bf8024d..22f90c0ef 100644
--- a/ext/fts5/fts5_storage.c
+++ b/ext/fts5/fts5_storage.c
@@ -613,10 +613,11 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
+ int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
- sqlite3_column_bytes(pScan, ctx.iCol+1),
+ zText, nText,
(void*)&ctx,
fts5StorageInsertCallback
);
@@ -738,10 +739,11 @@ int sqlite3Fts5StorageIndexInsert(
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
+ const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
+ int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
- sqlite3_value_bytes(apVal[ctx.iCol+2]),
+ zText, nText,
(void*)&ctx,
fts5StorageInsertCallback
);
@@ -910,10 +912,11 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
if( rc==SQLITE_OK ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
+ int nText = sqlite3_column_bytes(pScan, i+1);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, i+1),
- sqlite3_column_bytes(pScan, i+1),
+ zText, nText,
(void*)&ctx,
fts5StorageIntegrityCallback
);
diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test
index 2d6856d05..4e0ae64a9 100644
--- a/ext/fts5/test/fts5corrupt3.test
+++ b/ext/fts5/test/fts5corrupt3.test
@@ -9886,6 +9886,229 @@ do_catchsql_test 67.1 {
), * FROM ttt('e')
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_test 68.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 32768 pagesize 4096 filename crash-41234e232809e7.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 08 .....@ ........
+| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
+| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
+| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
+| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
+| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
+| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
+| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
+| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
+| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
+| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
+| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
+| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
+| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
+| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
+| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
+| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
+| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
+| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
+| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
+| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
+| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
+| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
+| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
+| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
+| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
+| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
+| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
+| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
+| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
+| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
+| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
+| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
+| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
+| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
+| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
+| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
+| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
+| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
+| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
+| page 3 offset 8192
+| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
+| 16: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
+| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
+| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
+| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 00 01 34 01 609...........4.
+| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
+| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
+| 3312: 01 02 04 01 02 03 f1 06 62 69 6e 62 72 79 03 06 ........binbry..
+| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 01 03 16 01 ................
+| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
+| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
+| 3376: 03 04 71 02 02 03 06 11 02 02 01 08 63 6f 6d 70 ..q.........comp
+| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
+| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
+| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
+| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
+| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 03 02 ................
+| 3472: 00 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
+| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
+| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
+| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
+| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
+| 3552: 02 03 01 03 66 63 63 01 02 03 01 02 03 01 02 03 ....fcc.........
+| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
+| 3584: 03 01 05 6a 73 6f 5e 31 13 02 03 01 02 03 01 02 ...jso^1........
+| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
+| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
+| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
+| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n
+| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
+| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 13 06 ................
+| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
+| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
+| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
+| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
+| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 12 02 03 06 ..im............
+| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
+| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
+| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
+| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe....
+| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab.....
+| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
+| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
+| 3888: 01 06 01 01 02 01 06 01 01 02 01 05 f1 01 02 01 ................
+| 3904: 06 01 01 02 01 06 01 5b 02 01 06 01 01 02 01 06 .......[........
+| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
+| 3936: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
+| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
+| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
+| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
+| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
+| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
+| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
+| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
+| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
+| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
+| page 4 offset 12288
+| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0b 01 02 ................
+| page 5 offset 16384
+| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
+| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
+| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
+| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
+| 64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a .......x.W.>.$..
+| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
+| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
+| 3104: 4f 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 OARY.#..%..THREA
+| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
+| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 45 3d ..%..THREADSAFE=
+| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM
+| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
+| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
+| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
+| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
+| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
+| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
+| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
+| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
+| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
+| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
+| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
+| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
+| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
+| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
+| 3392: 4c 45 20 52 54 52 46 45 58 4e 4f 43 41 53 45 17 LE RTRFEXNOCASE.
+| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
+| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
+| 3440: 49 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49 IABLE MEMSYS5XBI
+| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
+| 3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 E MEMSYS5XNOCASE
+| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
+| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
+| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
+| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
+| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
+| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
+| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
+| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 57 42 49 NABLE GEOPOLYWBI
+| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
+| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 42 41 53 45 E GEOPOLYXNOBASE
+| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE
+| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....#
+| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
+| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
+| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
+| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
+| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
+| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
+| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
+| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
+| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
+| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
+| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
+| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
+| 3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d TAT VTABXNOCASE.
+| 3888: 07 05 00 31 0f 17 b7 4e 41 42 4c 45 20 44 42 53 ...1...NABLE DBS
+| 3904: 54 41 54 20 66 54 41 42 58 52 54 52 49 4d 11 06 TAT fTABXRTRIM..
+| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
+| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
+| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
+| 3968: 58 62 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XbTRIM'...C..COM
+| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
+| 4000: 32 30 31 36 30 36 30 39 52 02 4a 4e 41 52 59 27 20160609R.JNARY'
+| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
+| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
+| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
+| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
+| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
+| page 6 offset 20480
+| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
+| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
+| 32: 0f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
+| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
+| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 0e e0 ................
+| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
+| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
+| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
+| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
+| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
+| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
+| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
+| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
+| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
+| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
+| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
+| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
+| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
+| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
+| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
+| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
+| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
+| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
+| page 7 offset 24576
+| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
+| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
+| page 8 offset 28672
+| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e9 0f d6 00 00 ................
+| 4048: 00 00 00 00 00 00 11 04 02 2b 69 6e 74 65 67 72 .........+integr
+| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
+| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 5d 69 71 a5 uild....opti]iq.
+| end crash-41234e232809e7.db
+.testctrl prng_seed 1 db
+}]} {}
+
+do_catchsql_test 68.1 {
+ PRAGMA reverse_unordered_selects=ON;
+ INSERT INTO t1(t1) SELECT x FROM t2;
+} {1 {database disk image is malformed}}
+
+
sqlite3_fts5_may_be_corrupt 0
finish_test
diff --git a/ext/fts5/test/fts5integrity.test b/ext/fts5/test/fts5integrity.test
index 25c727730..72cdeb3e3 100644
--- a/ext/fts5/test/fts5integrity.test
+++ b/ext/fts5/test/fts5integrity.test
@@ -210,4 +210,49 @@ foreach {tn pgsz} {
} {1000}
}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 7.0 {
+ PRAGMA encoding = 'UTF-16';
+ CREATE VIRTUAL TABLE vt0 USING fts5(c0);
+ INSERT INTO vt0 VALUES (x'46f0');
+ SELECT quote(c0) FROM vt0;
+} {X'46F0'}
+do_execsql_test 7.1 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+do_execsql_test 7.2 {
+ INSERT INTO vt0(vt0) VALUES('rebuild');
+}
+do_execsql_test 7.3 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+do_execsql_test 7.4 {
+ UPDATE vt0 SET c0='';
+}
+do_execsql_test 7.5 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+
+#-------------------------------------------------------------------------
+# Ticket 7a458c2a5f4
+#
+reset_db
+do_execsql_test 8.0 {
+ PRAGMA locking_mode = EXCLUSIVE;
+ PRAGMA journal_mode = PERSIST;
+ CREATE VIRTUAL TABLE vt0 USING fts5(c0);
+} {exclusive persist}
+do_execsql_test 8.1 {
+ PRAGMA data_version
+} {1}
+do_execsql_test 8.2 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+ PRAGMA data_version;
+} {1}
+do_execsql_test 8.1 {
+ INSERT INTO vt0(vt0, rank) VALUES('usermerge', 2);
+}
+
finish_test
diff --git a/ext/fts5/test/fts5misc.test b/ext/fts5/test/fts5misc.test
index e2f4b2d09..9abc92b23 100644
--- a/ext/fts5/test/fts5misc.test
+++ b/ext/fts5/test/fts5misc.test
@@ -250,6 +250,78 @@ do_execsql_test 9.2 {
-4764623217061966105 8324454597464624651
}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 10.0 {
+ CREATE VIRTUAL TABLE vt1 USING fts5(c1, c2, prefix = 1, tokenize = "ascii");
+ INSERT INTO vt1 VALUES (x'e4', '䔬');
+}
+
+do_execsql_test 10.1 {
+ SELECT quote(CAST(c1 AS blob)), quote(CAST(c2 AS blob)) FROM vt1
+} {X'E4' X'E494AC'}
+
+do_execsql_test 10.2 {
+ INSERT INTO vt1(vt1) VALUES('integrity-check');
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 11.0 {
+ CREATE VIRTUAL TABLE vt0 USING fts5(
+ c0, prefix = 71, tokenize = "porter ascii", prefix = 9
+ );
+} {}
+do_execsql_test 11.1 {
+ BEGIN;
+ INSERT INTO vt0(c0) VALUES (x'e8');
+}
+do_execsql_test 11.2 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+
+#-------------------------------------------------------------------------
+# Ticket [752fdbf6]
+#
+reset_db
+do_execsql_test 11.0 {
+ PRAGMA encoding = 'UTF-16';
+ CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
+ INSERT INTO vt0(vt0, rank) VALUES('pgsz', '37');
+ INSERT INTO vt0(c0, c1) VALUES (0.66077, 1957391816);
+}
+do_execsql_test 11.1 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+
+#-------------------------------------------------------------------------
+# Ticket [7c0e06b16]
+#
+do_execsql_test 12.0 {
+ CREATE TABLE t1(a, b, rank);
+ INSERT INTO t1 VALUES('a', 'hello', '');
+ INSERT INTO t1 VALUES('b', 'world', '');
+
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ INSERT INTO ft VALUES('b');
+ INSERT INTO ft VALUES('y');
+
+ CREATE TABLE t2(x, y, ft);
+ INSERT INTO t2 VALUES(1, 2, 'x');
+ INSERT INTO t2 VALUES(3, 4, 'b');
+}
+
+do_execsql_test 12.1 {
+ SELECT * FROM t1 NATURAL JOIN ft WHERE ft MATCH('b')
+} {b world {}}
+do_execsql_test 12.2 {
+ SELECT * FROM ft NATURAL JOIN t1 WHERE ft MATCH('b')
+} {b world {}}
+do_execsql_test 12.3 {
+ SELECT * FROM t2 JOIN ft USING (ft)
+} {3 4 b b}
finish_test
diff --git a/ext/fts5/test/fts5savepoint.test b/ext/fts5/test/fts5savepoint.test
new file mode 100644
index 000000000..e431f9f5f
--- /dev/null
+++ b/ext/fts5/test/fts5savepoint.test
@@ -0,0 +1,85 @@
+# 2019 Dec 26
+#
+# 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.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5savepoint
+
+# If SQLITE_ENABLE_FTS5 is defined, omit this file.
+ifcapable !fts5 {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(c);
+ BEGIN;
+ SAVEPOINT one;
+ INSERT INTO ft VALUES('a');
+ SAVEPOINT two;
+ INSERT INTO ft VALUES('b');
+ RELEASE two;
+ SAVEPOINT four;
+ INSERT INTO ft VALUES('c');
+ RELEASE four;
+ SAVEPOINT three;
+ INSERT INTO ft VALUES('d');
+ ROLLBACK TO three;
+ COMMIT;
+ SELECT * FROM ft
+} {a b c}
+
+reset_db
+do_catchsql_test 2.0 {
+ CREATE VIRTUAL TABLE ft1 USING fts5(c);
+ CREATE VIRTUAL TABLE ft2 USING fts5(c);
+ DROP TABLE ft2_idx;
+ BEGIN;
+ INSERT INTO ft2 VALUES('a');
+ INSERT INTO ft1 VALUES('a');
+ SAVEPOINT two;
+ INSERT INTO ft1 VALUES('b');
+ COMMIT;
+} {1 {SQL logic error}}
+
+reset_db
+ifcapable fts3 {
+ do_execsql_test 3.0 {
+ CREATE VIRTUAL TABLE vt0 USING fts5(c0);
+ CREATE VIRTUAL TABLE vt1 USING fts4(c0);
+ INSERT INTO vt1(c0) VALUES(0);
+ }
+
+ do_execsql_test 3.1 {
+ BEGIN;
+ UPDATE vt1 SET c0 = 0;
+ INSERT INTO vt1(c0) VALUES (0), (0);
+ UPDATE vt0 SET c0 = 0;
+ INSERT INTO vt1(c0) VALUES (0);
+ UPDATE vt1 SET c0 = 0;
+ INSERT INTO vt1(vt1) VALUES('automerge=1');
+ UPDATE vt1 SET c0 = 0;
+ }
+
+ do_catchsql_test 3.2 {
+ DROP TABLE vt1;
+ } {1 {SQL logic error}}
+
+ do_execsql_test 3.3 {
+ SAVEPOINT x;
+ INSERT INTO vt0 VALUES('x');
+ COMMIT;
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+ }
+}
+
+finish_test
+
diff --git a/ext/misc/regexp.c b/ext/misc/regexp.c
index 3359109ab..a97290511 100644
--- a/ext/misc/regexp.c
+++ b/ext/misc/regexp.c
@@ -156,7 +156,7 @@ static unsigned re_next_char(ReInput *p){
&& (p->z[p->i+1]&0xc0)==0x80 ){
c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
p->i += 2;
- if( c<=0x3ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
+ if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
}else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c
index 0d66f6a6f..326228337 100644
--- a/ext/misc/zipfile.c
+++ b/ext/misc/zipfile.c
@@ -999,7 +999,6 @@ static int zipfileDeflate(
int res;
str.next_out = aOut;
str.avail_out = nAlloc;
- deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
res = deflate(&str, Z_FINISH);
if( res==Z_STREAM_END ){
*ppOut = aOut;
@@ -1434,8 +1433,8 @@ static int zipfileGetMode(
** identical, ignoring any trailing '/' character in either path. */
static int zipfileComparePath(const char *zA, const char *zB, int nB){
int nA = (int)strlen(zA);
- if( zA[nA-1]=='/' ) nA--;
- if( zB[nB-1]=='/' ) nB--;
+ if( nA>0 && zA[nA-1]=='/' ) nA--;
+ if( nB>0 && zB[nB-1]=='/' ) nB--;
if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
return 1;
}
@@ -1619,6 +1618,7 @@ static int zipfileUpdate(
if( rc==SQLITE_OK ){
zPath = (const char*)sqlite3_value_text(apVal[2]);
+ if( zPath==0 ) zPath = "";
nPath = (int)strlen(zPath);
mTime = zipfileGetTime(apVal[4]);
}
@@ -1628,11 +1628,15 @@ static int zipfileUpdate(
** '/'. This appears to be required for compatibility with info-zip
** (the unzip command on unix). It does not create directories
** otherwise. */
- if( zPath[nPath-1]!='/' ){
+ if( nPath<=0 || zPath[nPath-1]!='/' ){
zFree = sqlite3_mprintf("%s/", zPath);
- if( zFree==0 ){ rc = SQLITE_NOMEM; }
zPath = (const char*)zFree;
- nPath++;
+ if( zFree==0 ){
+ rc = SQLITE_NOMEM;
+ nPath = 0;
+ }else{
+ nPath = (int)strlen(zPath);
+ }
}
}
@@ -2025,19 +2029,19 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
** at the end of the path. Or, if this is not a directory and the path
** ends in '/' it is an error. */
if( bIsDir==0 ){
- if( zName[nName-1]=='/' ){
+ if( nName>0 && zName[nName-1]=='/' ){
zErr = sqlite3_mprintf("non-directory name must not end with /");
rc = SQLITE_ERROR;
goto zipfile_step_out;
}
}else{
- if( zName[nName-1]!='/' ){
+ if( nName==0 || zName[nName-1]!='/' ){
zName = zFree = sqlite3_mprintf("%s/", zName);
- nName++;
if( zName==0 ){
rc = SQLITE_NOMEM;
goto zipfile_step_out;
}
+ nName = (int)strlen(zName);
}else{
while( nName>1 && zName[nName-2]=='/' ) nName--;
}
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index 5c2ae9545..b2e23b165 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -4959,7 +4959,7 @@ static const char *rbuMainToWal(const char *zName, int flags){
}else{
while( *z==0 ) z++;
}
- z += (n + 8 + 1);
+ z += (n + 8 + 2);
return z;
}
diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c
index fa58838a3..312f337b1 100644
--- a/ext/rtree/geopoly.c
+++ b/ext/rtree/geopoly.c
@@ -1345,17 +1345,11 @@ static int geopolyFilter(
RtreeNode *pRoot = 0;
int rc = SQLITE_OK;
int iCell = 0;
- sqlite3_stmt *pStmt;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
- freeCursorConstraints(pCsr);
- sqlite3_free(pCsr->aPoint);
- pStmt = pCsr->pReadAux;
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
- pCsr->pReadAux = pStmt;
+ resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index b4d15f6cb..1eef1a1b5 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -1065,9 +1065,12 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
/*
-** Free the RtreeCursor.aConstraint[] array and its contents.
+** Reset a cursor back to its initial state.
*/
-static void freeCursorConstraints(RtreeCursor *pCsr){
+static void resetCursor(RtreeCursor *pCsr){
+ Rtree *pRtree = (Rtree *)(pCsr->base.pVtab);
+ int ii;
+ sqlite3_stmt *pStmt;
if( pCsr->aConstraint ){
int i; /* Used to iterate through constraint array */
for(i=0; i<pCsr->nConstraint; i++){
@@ -1080,6 +1083,13 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
sqlite3_free(pCsr->aConstraint);
pCsr->aConstraint = 0;
}
+ for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
+ sqlite3_free(pCsr->aPoint);
+ pStmt = pCsr->pReadAux;
+ memset(pCsr, 0, sizeof(RtreeCursor));
+ pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
+ pCsr->pReadAux = pStmt;
+
}
/*
@@ -1087,13 +1097,10 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
Rtree *pRtree = (Rtree *)(cur->pVtab);
- int ii;
RtreeCursor *pCsr = (RtreeCursor *)cur;
assert( pRtree->nCursor>0 );
- freeCursorConstraints(pCsr);
+ resetCursor(pCsr);
sqlite3_finalize(pCsr->pReadAux);
- sqlite3_free(pCsr->aPoint);
- for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
sqlite3_free(pCsr);
pRtree->nCursor--;
nodeBlobReset(pRtree);
@@ -1799,17 +1806,11 @@ static int rtreeFilter(
int ii;
int rc = SQLITE_OK;
int iCell = 0;
- sqlite3_stmt *pStmt;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
- freeCursorConstraints(pCsr);
- sqlite3_free(pCsr->aPoint);
- pStmt = pCsr->pReadAux;
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
- pCsr->pReadAux = pStmt;
+ resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
diff --git a/manifest b/manifest
index 16e83f5bd..d7ccb2fbc 100644
--- a/manifest
+++ b/manifest
@@ -1,11 +1,11 @@
-C Change\sthe\sdefault\slookaside\sconfiguration\sto\s40\sslots\sof\s1200-bytes\seach.\nThis\sactually\sworks\sout\sto\s30\sbig\sslots\sand\s93\ssmall\sslots\susing\sthe\s\nmini-lookaside\sallocator.\s\sWe\sget\sthe\ssame\s(or\sbetter)\slookaside\scoverage\nbut\swith\s72KB\sless\smemory\sper\sconnection.
-D 2019-12-13T16:04:52.502
+C Merge\srecent\senhancements\sfrom\strunk.
+D 2019-12-31T14:49:10.816
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in d3a862c9742f5a08230a3b295c0a47fd3067f19356dc39935280135f90474b04
+F Makefile.in 9dfc7936f675785309b74d09202bb656732325e65df889e5aaa18cc8932e5b0c
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc 0b0acbf34bb238170bdf1fd343a1fd37bc81c042ce029c1cc53fe15b5d4ed07b
+F Makefile.msc fab23c6b10cb6f06a7e9c407fc2e35cb184a6d653f1b793bda87fcee2eafa4f6
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
F VERSION 081500f0aeaadc989d85aafbc717af45512018aebc73d89e5c2368fe62a600ff
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -15,10 +15,10 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc 492ea431c411378094593a5225b9a02645455a5d87a26d018b5461b723e52125
+F autoconf/Makefile.msc 1d1e4af61289c62b94aa65a93afcd3dfa4b53e4195908980e0b138203e71e1c9
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
-F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
+F autoconf/configure.ac 3cd933b959fe514eebd1ca1717dfddbf2c9b825b6bc2c5f744deaf5d63af9288
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -34,8 +34,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure fdc9f8d53360170679349d8f72fb2e5c79f511424891b7bb8a2f48de41c7a6ef x
-F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
+F configure aae28230005acf833d466c8a160bd4c70cf42984f5a6756fa327e15e7f473477 x
+F configure.ac 798a24cee2879325ca5b688a618199eb32cc77ed8136edbaa43d9137b470d54e
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3
@@ -81,9 +81,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 9a69143c94195d9342dd4a704021009fb9e45dff9bff775dae024d47e363bab8
+F ext/fts3/fts3.c 52c09f459364732b5df73eff0373f991fd6af8f0f60fcdbb4b649205e88a7568
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h ba4e5445a0daf4a251345d4704259268fd98a3e0282fedfcaedb9fc6da9f250c
+F ext/fts3/fts3Int.h f091030b976045e7df91af2337935952b477cdbd9f48058c44c965684484cb50
F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
F ext/fts3/fts3_expr.c b132af223e90e35b9f9efa9fe63d6ae737d34153a3b6066736086df8abc78a1f
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
@@ -99,7 +99,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
-F ext/fts3/fts3_write.c fa971df91b7c9c317ccb76e73de425de372f854cbed16be2d98f42f61be6c0fb
+F ext/fts3/fts3_write.c 51e0a4e3782ee17b6dd5e89949b7095fc98e36e87725c53de631734535507498
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
@@ -116,9 +116,9 @@ F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6
F ext/fts5/fts5_config.c b447948f35ad3354e8fe5e242e0a7e7b5b941555400b9404259944e3aa570037
F ext/fts5/fts5_expr.c 2be456484786333d559dc2987a00f2750981fab91d52db8452a8046278c5f22e
F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
-F ext/fts5/fts5_index.c 99b77ae1f503978ca76985bcfff7345c822aed8bbaa8edb3747f804f614685b5
-F ext/fts5/fts5_main.c 9db1f173d299466aeff89bd949fb1eb0a181265726fb56f11e07ea292dcc9a73
-F ext/fts5/fts5_storage.c 167e3d8f8052a71032d498e32a2f2ed5ffe489e5d4d47e298adfa02ed55c7882
+F ext/fts5/fts5_index.c e3573c88ce8238f7a5892c777a9ddf646c1355012780337d783fb2dfc3dca650
+F ext/fts5/fts5_main.c e881a2ea0bf01b3a3ff0bc1b31373c58fd54b6c9f3c43ea3d431bea4e5d4025e
+F ext/fts5/fts5_storage.c 3ecda8edadc1f62a355d6789776be0da609f8658c50d72e422674093ab7e1528
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7
@@ -157,7 +157,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test 5aaa2f8b44a85246a2ea76db1695bde38a75802979f3961702afa8f322d331c8
+F ext/fts5/test/fts5corrupt3.test fab4ea761b2df254fb3909423989320772a3a757de4d151ddcfa2a40a3b93328
F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91
F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
@@ -182,14 +182,14 @@ F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b99
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
-F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b
+F ext/fts5/test/fts5integrity.test c354fd693d9fb14018b33113aa2331265d915d51f67067a2cfa7873894c9ecf0
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5matchinfo.test 50d86da66ec5b27603dcd90ba0227f5d9deb10351cbc52974a88e24f6fc9b076
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
-F ext/fts5/test/fts5misc.test a5b53328b5b79275915de8f67ae85905eb2133d8dbcc808411f67c094b1bd347
+F ext/fts5/test/fts5misc.test 088ac5f0f5de1ad45b0f83197ab5263bcae8130156cdc901bff2375ff2b8af86
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
@@ -205,6 +205,7 @@ F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6
+F ext/fts5/test/fts5savepoint.test fc02929f238d02a22df4172625704e029f7c1e0e92e332d654375690f8e6e43f
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
@@ -304,7 +305,7 @@ F ext/misc/nextchar.c 279f80fe8ef5ba413242e2704e246503ac601f005eefb180d19e6c9203
F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c
F ext/misc/percentile.c 148dd07286b16e50f232bb638a47850085ad37d51f270429905bd865e595d1ca
F ext/misc/prefixes.c 7be86d17525cfae6ed462fc3c519efc44488ac329890f77491c8f82871f57e17
-F ext/misc/regexp.c 653b6ab5e89bcb5d45f9ebe0747d7f8f3f5706cac963fcbc9a3ddbe5fdc1efa2
+F ext/misc/regexp.c be064ad9478361e40c7b8ca460f78b3d3c9b96080d5f391126c95e14bd362fae
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
@@ -324,7 +325,7 @@ F ext/misc/vfsstat.c 77b5b4235c9f7f11eddf82487c0a422944ac2f132dafd5af3be7a68a057
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c 7ad29133e304e40c8fe239bea10e101580ed56bc68c16d992af514cce19572d0
+F ext/misc/zipfile.c 185d060a595c79ebbec904e9d73b97b400dca94d2f910d351d6a8b5fcfe2c3d0
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
@@ -366,7 +367,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 f3a3e09f575157052813be667d6ab3b54f47fb02e6e1c9f767ad7bb8f1fb90b3
+F ext/rbu/sqlite3rbu.c 4e9a59aa80c03350a0ca5faa454dec894906537fbd98b3231604cc33baf174c8
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -379,8 +380,8 @@ 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 c591164125808f8bba9659e92665b78412cd263e654b6f05294f3a8da7cdd9fb
-F ext/rtree/rtree.c 26fcb3f7a92fda9afcf5eee684cc3188b7367da69bc9c374492d844fb8ed4e25
+F ext/rtree/geopoly.c 4f176fa4d954997e8880f8b75e15b578765b4f471e359b73020b3d4e1defe958
+F ext/rtree/rtree.c 84b939a9a558edd0461bb976b98f60012e3e574b3b17a0f44533d6f2a9aa2f2e
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 4092a8bd2b5eafc4fafe4fe9024249c12b13e4bab23c2c3eaff57412fdf805fa
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -461,17 +462,17 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c accee2f80a2db2cb0ca253a62704ab9fad0e8355b0e4b372f0d3bfdf7737a8e3
+F src/alter.c 92604dd52bd73dbc4f0cc4f4a1b1fdd366e53cb0503494291e5798524beb74ec
F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c
F src/attach.c b30c44333d55a68c0a12920b5b9d40b254cbd3d4509bda77417209eeed8b3d80
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c d22498af716953400e314d2d98d1dac3ea5c3b01e0fd243ef9e9b132c74114ec
-F src/btree.h f27a33c49280209a93385e218306c4ee5f46ba8d7649d2f81a7166b282232484
-F src/btreeInt.h 91806f01fd1145a9a86ba3042f25c38d8faf6002701bf5e780742cf88bcff437
-F src/build.c ec3332b5ff5871a5e134889392e7d9340a2c274b292b1674b595a7835c4908ad
+F src/btree.c f191aa4d99597a1ad77cb15a9473f1183f2a12a7f1650a7705eaac9085e493bb
+F src/btree.h 6111552f19ed7a40f029cf4b33badc6fef9880314fffd80a945f0b7f43ab7471
+F src/btreeInt.h 6794084fad08c9750b45145743c0e3e5c27c94dee89f26dd8df7073314934fd2
+F src/build.c 9b7153d93308783c801c5c36d9b4b3189ab4f00cd9ad6bf4d6c9750378a56be9
F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
@@ -479,7 +480,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c 6c407e549406c10fde9ac3987f6d734459205239ad370369bc5fcd683084a4fa
F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4
-F src/expr.c a4c16d4eed1508377bb8aba71471f3f023edb2ebd79fb7ba3bf379b1e54a6cb7
+F src/expr.c 8d4b6ac02f69e60b185cba0e38a76ba3f6f2122ee767e7de0f933fddec423e4a
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847
F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12
@@ -488,7 +489,7 @@ 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 276463aa7a26ee73958b9f4bcbef4eaec516f22bf6b8d7d2428f39c8dea90840
+F src/insert.c e43c6475b302d094ffa01d76b784c719001c9cf24c0b5af96b78e5b25dc54b83
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
F src/main.c 34d73303ac76015d3c8961f16d49ab44a56cbc998f178b27ca07847db4cf9273
@@ -511,28 +512,28 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 3e0e519f27683083a465e948e056759a8340728c222b5c394a135e0c57c220bc
+F src/os_unix.c ad7640c04eed946052a3b12856362a773d0a717696707313037186df0e2b59f2
F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 30f20d2263d3717f41a0d9a40f7a3d0f48ce1cfab461b875c6187ead9d6ad1c7
+F src/pager.c b08541016855b06956cb34c4cddd8c9fa97793f3bfdc4f7809f09fda24702435
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
F src/parse.y c8d2de64db469fd56e0fa24da46cd8ec8523eb98626567d2708df371b47fdc3f
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848
+F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
F src/pragma.c 26e9ee514138b9697d4be6d8f9ca84655053026390cf10de838862238aa4aba9
F src/pragma.h ec3b31eac9b1df040f1cc8cb3d89bc06605c3b4cb3d76f833de8d6d6c3f77f04
F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c da68e9e68e60aa786a4a7b67c6e3ca2b8186df1ed1830ba230c94889aa8ac15f
+F src/resolve.c a76b7ac9848ae226f8dd718e607a830eb6ce9140d8c314735379ab560ad48df6
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 3590f0641817f0d3af4211315ff91abd197f7c03ba8d20129388af8dcdb707f3
+F src/select.c bf8e7222602afe1fbce0c09e4300756b5ca5118f7224f414dd58debe6eb80b5e
F src/shell.c.in 4a3a9e1c11847b1904f2b01d087af1c052f660902755abab457cab1756817ded
-F src/sqlite.h.in 2a23e8161775253d9cf383c2c6aa559005dc787d350dcb0be67a6c4cc3bd1d19
+F src/sqlite.h.in 51f69c62ba3e980aca1e39badcaf9ad13f008774fe1bb8e7f57e3e456c656670
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
-F src/sqliteInt.h 4948c2046c921461d2021e52ac8cec5b65cd56ab0c58aa7150313abace90153c
+F src/sqliteInt.h b5784a17e5ad158a759b2ed0a0d2ded1e1c3e9cf4cf51e4da21783790b9d0567
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c baf38f521ac079be616dab1ff13f60c6ce0703c7f0429a65238c695197a56935
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -592,32 +593,32 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
-F src/treeview.c b36e832d4d17ba1abe7739a7a91f1432012c5ada762fb47bfec6fc9ab969af60
+F src/treeview.c 74d4fb2b6a2eaced4c0a6e22a9caf6e4a975577774456575065c5c921bdb3381
F src/trigger.c a40d50e88bd3355f1d2a73f0a3b2d6b42eae26ca4219001b82ef0d064439badc
-F src/update.c c66576a821d4821eda6b40c6aabc646cac5c9eb80f4987cc901db8657549c782
-F src/upsert.c b445315c8958d8f17ec3297d06842e61dacaad0633ccaec1e4e160de7e562212
+F src/update.c 9ad19af96aff95dc02a923a99f97c1bc0b909009a29a2914b796f786b9ac0c60
+F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
-F src/util.c 66b22af7b359ce6493c34fef28c87d5c2d1765f212d6e4cd5e08d99ac30b89bb
+F src/util.c 2c92bc706bbdb1c45a25180291e7e05a56e297aa5dd7b2bcd2b1c47e8bb05b17
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
-F src/vdbe.c 30fc70ea7f1a47f50cd6557d8073b57fcf2275b537b896ba7e8d602065bc5648
-F src/vdbe.h fdbc0a11e5768a702b46ce63286f60e22e71351a29bd98b3666405e1fccc7802
-F src/vdbeInt.h bd589b8b7273286858950717e0e1ec5c88b18af45079a3366dc1371865cea704
+F src/vdbe.c 119ddfe16b35fbaaf5460c9b58a8eeb0cc5d43058342af36925411dfc73f9862
+F src/vdbe.h 3f068f00b23aebf392df142312ab5874588371c6d83e60d953f6d6b6453491c5
+F src/vdbeInt.h e02ccac0334f7c71c952210657e6e18de1917605887c7bc6167a80a17f62da18
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
-F src/vdbeaux.c ede199fe272656338741dd831da86362a3b60e42fb12ef5389ea1325823e9686
+F src/vdbeaux.c 0a9716e47012ef018038c2e1dab9f701a6fb4429bb3ee1d4d0f49497519ace74
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
-F src/vdbemem.c 2eb00a4d1a7d2c97510a4d1ccaf4e12c9143f2ced1c6b96b5eddc372183c9121
+F src/vdbemem.c fa083086758379b52f8771d69424b273c7bd0f94413802404ee32cd5cc7cd870
F src/vdbesort.c a3be032cc3fee0e3af31773af4a7a6f931b7230a34f53282ccf1d9a2a72343be
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
-F src/vtab.c 2736f853a1bd270581f76bae8e5d2e840b6258f3d85c1fa382e9454b3c414d1d
+F src/vtab.c a2fead3e97fca54fcf3f3db784e17c9ee2d39a0c5ad323e9d514855106300a86
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 15a2845769f51ba132f9cf0b2c7a6887a91fc8437892dbcce9fcdc68b66d60a1
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c a137468bf36c92e64d2275caa80c83902e3a0fc59273591b96c6416d3253d05d
-F src/where.c c51ebd505c8417285ca1db8f94933a12224bf636ad93f27d821c07f93d59c035
-F src/whereInt.h 4a296fd4fa79fdcbc2b5e8c1b898901617655811223e1082b899c23ecb092217
-F src/wherecode.c 7efa97f4dc2f95548611deba68f0210ab357725899a9bae5391a525e48271875
-F src/whereexpr.c 39b6a538804c6e1248c22b33e09d00f89ae6a099c849c4d841ce3995562287b4
-F src/window.c a77f12078dd4b10e655d4ba5a73ca32dbe00e0206018305185c7e86445d3f429
+F src/where.c 602e5093556bbd9090c0a9bd834fec0717e3a4b0377a021d38091a6d554a1177
+F src/whereInt.h a727b32260e12707a8c1bc29d7f7e9b6dc1a44551a45093d5968fbe570ff0c56
+F src/wherecode.c a987d22b42e09b06f3a49596e0953b1cd28e568cc656681776edc0026cfac0cc
+F src/whereexpr.c 4b34be1434183e7bb8a05d4bf42bd53ea53021b0b060936fbd12062b4ff6b396
+F src/window.c 87795bb8293179cb8a92529264d49bd66b5bcad5e91cfc17dd8d3e66a2a77f88
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -636,8 +637,8 @@ F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altertab.test 4d8b79b0b88b62b90b710390df14fe99e0a3578345526886eaa550e28e3065dc
-F test/altertab2.test 8883693952f6d7fb5f754dbf1d694ed780aa883027bef04cb1fb99a3b88c9272
-F test/altertab3.test 231881a8e9c4905a84213476c64c174a119e1ab75ce17d986dcbbacc07b2b544
+F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
+F test/altertab3.test 155b8dc225ce484454a7fb4c8ba745680b6fa0fc3e08919cbbc19f9309d128ff
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
F test/analyze3.test 01f0b122e3e54ad2544f14f7cc7dcb4c2cb8753cad5e88c6b8d49615b3fd6a2b
@@ -728,7 +729,7 @@ F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bc
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 3619f0c58c2e4b2a94aa86e75607e497d34ef40ab74418e71aef7b4ca5155895
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
-F test/check.test 25c6035302c846c7ff8e681cf8284473f6f01be94d327de60a688ad84ab01f8b
+F test/check.test b21a76546c2115af2674280566a8eba577e72adfec330c3d9a8a466d41f8eb0d
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
@@ -747,9 +748,9 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
-F test/conflict.test c7cc007e2af151516ddf38f7412fe10d473a694f55e3df437e2c7b31c2590e8d
+F test/conflict.test 58857e2533fb9f2e0358ea7cb191215657846be1dd9da3b3d6df3e750c02ae03
F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
-F test/conflict3.test f62a2d0cad9162a60e6458fc913dff3a2208feca924120c21737cfee65a6a74a
+F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
@@ -850,7 +851,7 @@ F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 84879b63e3110552bf8ce648a3507dc3ceb72109ecec83c2aef0db37a27f6382
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
-F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
+F test/exclusive.test d6ccc6acc5d660544f8e0cacaec2c620f8ebb42a764d783ab53430e26057a185
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
@@ -861,7 +862,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
-F test/filter1.test fe7fcfeff48ca399fbc9577f55b60c8be8ccfdffc5e3b4ace21dc3c3e59f0f6a
+F test/filter1.test 8a6f047a000ef391db2ca17b6beecc0006f4e0f9ca8bbe272b2443c7316e66b1
F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a
F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
@@ -939,7 +940,7 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
F test/fts3corrupt.test ce7f7b5eaeee5f1804584d061b978d85e64abf2af9adaa7577589fac6f7eae01
F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test bc90c0f6ee73df4c6bd20f1b32fefdfc00b44cc577d67ebca43b157fc3efd422
+F test/fts3corrupt4.test 5ac8c0378dab68808f080d03d8525d2262879cb23db1bc5eb138e141a4f2010c
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
@@ -981,7 +982,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
-F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714
+F test/fts4langid.test 89e623218935507bca69d076ca254a7a8969dfc681c282b6374feaea8c7de784
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
F test/fts4merge.test e2b2ec21e287d54ec09824ccfb41e66896eeca568fc818ba0e0eb2efd94c35d2
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
@@ -1009,7 +1010,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c e8cf694f71a1ee39a59f7c2a38c0f8660db0656ce47c8a334b6e9a11f1e66c6d
+F test/fuzzcheck.c 0df68e0df3b93a8c8fc24c9873127c7d78024b51444193545f985dbc90ac024e
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1017,12 +1018,12 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac640639711
-F test/fuzzdata8.db b45368bbe9f86d40d30603e8f780ac29807cbcc951a18d7a7fd9d0c0e904706e
+F test/fuzzdata8.db a0b7151bf505ee9735f6e5a3f7851ecb35121f1cd731ac677a77ee540f358939
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
-F test/gencol1.test aab394862d6c14a57ff488b0ef3413ed9f3067a56955ede25b5e059188a66a41
+F test/gencol1.test e89eafdf03245e2609ddf6e9b0add37a17ce229095836c409131764c3a5282a5
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
@@ -1084,8 +1085,8 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a
-F test/join.test f787ee2716efe5beeb9888d10630f917b112c32b6b3e612e48a17ea8aed3a8eb
-F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
+F test/join.test 0e8d3f4092897c717abcaf64e2e7b298e1cb143e2436010c57cfed5596bf6d30
+F test/join2.test 659bc6193f5c3fe20fa444dd2c91713db8c33e376b098b860644e175e87b8dbc
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
@@ -1190,7 +1191,7 @@ F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
-F test/nulls1.test a325e2f2148fb5c82cd5f734e7b60f5fa28f9394c318edf3140f36f57d39930a
+F test/nulls1.test fe4153fd59a3786b4b9f3663a3e65a3aa43a318c7b4d7dcb3f6c3ed5652c9095
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
@@ -1229,7 +1230,7 @@ F test/permutations.test 8587800fe1a0eb01456a3f4500b821e54e3347e78acf11dbf05f499
F test/pg_common.tcl 222a1bad1c41c308fa366313cd7b51b3be7e9b21c8736a421b974ac941693b54
F test/pragma.test 59becdfd720b80d463ab750f69f7118fde10dfd556aa5d554f3bf6b7e5ea7533
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
-F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
+F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
F test/pragma4.test 10c624e45a83c0096a82a7579a5ff658542391d3b77355192da6572c8c17c00b
F test/pragma5.test 2be6a44c91e8585ccb4c71c5f221ccebe0692a49557215a912916ed391188959
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
@@ -1264,7 +1265,7 @@ F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3
-F test/rowvalue.test c39cc0be5e33f5294fc9224216198d6709d713ea948fdf8f42d89568e97912c9
+F test/rowvalue.test 8964f95b253d3b5cc8dc1cfd0cdb7529bce3ecc6b6259e23c5f829f80f4d51cd
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
@@ -1294,7 +1295,7 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce
F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e
F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 703154cbf66d0a9fbbd5b771dc3d2c4d3700121d133d695958d4a9c5a33251e8
+F test/select1.test b887331202618dbdabed92446b661ebd95a55ef3923700af56ed71266e9c1157
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 3905450067c28766bc83ee397f6d87342de868baa60f2bcfd00f286dfbd62cb9
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
@@ -1604,9 +1605,9 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
-F test/update.test 6a1193fbcb4546b4467d24635b1504b8e746b41d3b66dc6ace07581a62ce58fb
+F test/update.test e906ca7cb1dc6f52af1ea243e08f727edfa79f924c2691f2f9e72481f847310d
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
-F test/upsert1.test 0b740c8488fd2f5a06ac317c9913f7ef1eda8282f2db58b544b89480c51efab3
+F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@ -1699,7 +1700,7 @@ F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 4cda56de49f0c7d9a4f2590a3ddc5f79a7f2a03d2229d0f5bb5d3981ce57f293
+F test/whereG.test c9378b285828754377ef47fbece7264018c0a3743e7eb686e89917bb9df10885
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
@@ -1713,9 +1714,9 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test b3567fde130dd65fedf56da66a3916cc992e61f910a56b7dac3f71608809faac
-F test/window2.tcl 66db96fd9fd202bc31ee7f8ce7904cb469564864cff3f74e009bfef8102333f4
-F test/window2.test af2a001ded703bb8f2474fb0edfef170d5aba00f5c1f2aa9f65935b5da13df90
+F test/window1.test cd6e2dafaa14ae26c995547013a9765356d910f473664497c926ea3f47510997
+F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
+F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb
F test/window4.tcl d732df0e81beedc0ba8a563ade68611d322d27303ad0c0c8e4444107c39e84ec
@@ -1731,7 +1732,7 @@ F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af
F test/windowB.test 7a983ea1cc1cf72be7f378e4b32f6cb2d73014c5cd8b25aaee825164cd4269e5
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
-F test/windowfault.test a90b397837209f15e54afa62e8be39b2759a0101fae04e05a08bcc50e243a452
+F test/windowfault.test 8e3b69abe0eea9595ba3940afd9c63644e11966ed8815734b67f1479a8e9891a
F test/with1.test d32792084dcb5f6c047d77bb8a032822ef9fe050ade07d0aeffa37753a05e3c9
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 7de8dff2891aca0f9453463e4a2d6eb995baf137827d5596116fee53e22a4e29
@@ -1748,7 +1749,7 @@ F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912ade
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test b3b558639f7a103e095713ad0f57fec1fce1b7d60c8054df5789b98f7547a395
+F test/zipfile.test aab99dc488586842bed415a1ce1a2327948064aa660c00243e3f14a1ff1cf282
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
@@ -1771,7 +1772,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 50f9d1896ba141bffca6929317f54f63709d00d3ac82bc5c189d9c9c0a83e832
+F tool/lemon.c a361b85fa230560b783006ac002a6a8bad214c3b9d7fa48980aecc2b691ddcad
F tool/lempar.c e8899b28488f060d0ff931539ea6311b16b22dce068c086c788a06d5e8d01ab7
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -1781,7 +1782,7 @@ F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c7
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c 27ffc6f6e7e3ecbfc5bca1f1f11a09fc5badf6d67557a5fb2d3b069dbed90617
-F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
+F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
@@ -1852,7 +1853,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 74805668430051032ae9b256c84e252755ee03075fc08293c948675ed40ec280
-R be744340ad93a72a39e7a253bc678105
+P 47b71a84d1262c4bf6ad4f4a91820fd63593f08ae9efa144199d44972225e073 1dc83c5d54ca2890112e735e336c209adb8d067d2f647e9f8ae5d58f84a52461
+R 8dbc460e590e85bbe19d4191ea7ea91a
U drh
-Z cd1e4565dc6a4c9271072cb91752ff19
+Z ac3eece56ae65a72ceccf8b58e31752f
diff --git a/manifest.uuid b/manifest.uuid
index 5fd4b1824..47ee9f350 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-47b71a84d1262c4bf6ad4f4a91820fd63593f08ae9efa144199d44972225e073 \ No newline at end of file
+39d55579376906f212271ce9b2d367e3ad029fb173f22c7253312b467970208a \ No newline at end of file
diff --git a/src/alter.c b/src/alter.c
index 3bc779a1e..f3caba4c1 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -740,15 +740,17 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
- if( pSelect->pWith ){
+ With *pWith = pSelect->pWith;
+ if( pWith ){
int i;
- for(i=0; i<pSelect->pWith->nCte; i++){
- Select *p = pSelect->pWith->a[i].pSelect;
+ for(i=0; i<pWith->nCte; i++){
+ Select *p = pWith->a[i].pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pWalker->pParse;
sqlite3SelectPrep(sNC.pParse, p, &sNC);
sqlite3WalkSelect(pWalker, p);
+ sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols);
}
}
}
@@ -773,6 +775,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
+ if( sqlite3WalkExpr(pWalker, pSrc->a[i].pOn) ) return WRC_Abort;
}
}
@@ -987,7 +990,6 @@ static void renameColumnIdlistNames(
static int renameParseSql(
Parse *p, /* Memory to use for Parse object */
const char *zDb, /* Name of schema SQL belongs to */
- int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL to parse */
int bTemp /* True if SQL is from temp schema */
@@ -1308,7 +1310,7 @@ static void renameColumnFunc(
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = 0;
#endif
- rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
/* Find tokens that need to be replaced. */
memset(&sWalker, 0, sizeof(Walker));
@@ -1512,7 +1514,7 @@ static void renameTableFunc(
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
@@ -1529,8 +1531,11 @@ static void renameTableFunc(
assert( pSelect->selFlags & SF_View );
pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
- if( sParse.nErr ) rc = sParse.rc;
- sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ if( sParse.nErr ){
+ rc = sParse.rc;
+ }else{
+ sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ }
}
}else{
/* Modify any FK definitions to point to the new table. */
@@ -1651,7 +1656,7 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
diff --git a/src/btree.c b/src/btree.c
index d0eed5dd4..a137da3c7 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -699,6 +699,9 @@ static int saveCursorPosition(BtCursor *pCur){
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
+ if( pCur->curFlags & BTCF_Pinned ){
+ return SQLITE_CONSTRAINT_PINNED;
+ }
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
}else{
@@ -4562,6 +4565,18 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
return pCur->info.nKey;
}
+/*
+** Pin or unpin a cursor.
+*/
+void sqlite3BtreeCursorPin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)==0 );
+ pCur->curFlags |= BTCF_Pinned;
+}
+void sqlite3BtreeCursorUnpin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)!=0 );
+ pCur->curFlags &= ~BTCF_Pinned;
+}
+
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
@@ -5718,8 +5733,11 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure. */
- testcase( idx>pPage->nCell );
+ ** page into more than one b-tree structure.
+ **
+ ** Update 2019-12-23: appears to long longer be possible after the
+ ** addition of anotherValidCursor() condition on balance_deeper(). */
+ harmless( idx>pPage->nCell );
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
@@ -8309,6 +8327,30 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
}
/*
+** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
+** on the same B-tree as pCur.
+**
+** This can if a database is corrupt with two or more SQL tables
+** pointing to the same b-tree. If an insert occurs on one SQL table
+** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
+** table linked to the same b-tree. If the secondary insert causes a
+** rebalance, that can change content out from under the cursor on the
+** first SQL table, violating invariants on the first insert.
+*/
+static int anotherValidCursor(BtCursor *pCur){
+ BtCursor *pOther;
+ for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
+ if( pOther!=pCur
+ && pOther->eState==CURSOR_VALID
+ && pOther->pPage==pCur->pPage
+ ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
** tree needs to be balanced, and if so calls the appropriate balancing
@@ -8335,7 +8377,7 @@ static int balance(BtCursor *pCur){
if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
break;
}else if( (iPage = pCur->iPage)==0 ){
- if( pPage->nOverflow ){
+ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
@@ -8631,7 +8673,6 @@ int sqlite3BtreeInsert(
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
assert( pX->nKey==pCur->info.nKey );
- assert( pCur->info.nSize!=0 );
assert( loc==0 );
}
#endif
@@ -8706,7 +8747,9 @@ int sqlite3BtreeInsert(
}
}
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+ assert( pCur->eState==CURSOR_VALID
+ || (pCur->eState==CURSOR_INVALID && loc)
+ || CORRUPT_DB );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 );
diff --git a/src/btree.h b/src/btree.h
index 4fd281dec..4bd41f7f3 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -306,6 +306,8 @@ int sqlite3BtreeNext(BtCursor*, int flags);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int flags);
i64 sqlite3BtreeIntegerKey(BtCursor*);
+void sqlite3BtreeCursorPin(BtCursor*);
+void sqlite3BtreeCursorUnpin(BtCursor*);
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
i64 sqlite3BtreeOffset(BtCursor*);
#endif
diff --git a/src/btreeInt.h b/src/btreeInt.h
index 72d877f33..7687a0f1e 100644
--- a/src/btreeInt.h
+++ b/src/btreeInt.h
@@ -542,6 +542,7 @@ struct BtCursor {
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
+#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
/*
** Potential values for BtCursor.eState.
diff --git a/src/build.c b/src/build.c
index 196b35acf..23d7e7910 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1547,6 +1547,7 @@ void sqlite3AddPrimaryKey(
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
+ (void)sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -2242,6 +2243,12 @@ void sqlite3EndTable(
*/
if( p->pCheck ){
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
+ if( pParse->nErr ){
+ /* If errors are seen, delete the CHECK constraints now, else they might
+ ** actually be used if PRAGMA writable_schema=ON is set. */
+ sqlite3ExprListDelete(db, p->pCheck);
+ p->pCheck = 0;
+ }
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
@@ -2252,10 +2259,19 @@ void sqlite3EndTable(
for(ii=0; ii<p->nCol; ii++){
u32 colFlags = p->aCol[ii].colFlags;
if( (colFlags & COLFLAG_GENERATED)!=0 ){
+ Expr *pX = p->aCol[ii].pDflt;
testcase( colFlags & COLFLAG_VIRTUAL );
testcase( colFlags & COLFLAG_STORED );
- sqlite3ResolveSelfReference(pParse, p, NC_GenCol,
- p->aCol[ii].pDflt, 0);
+ if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
+ /* If there are errors in resolving the expression, change the
+ ** expression to a NULL. This prevents code generators that operate
+ ** on the expression from inserting extra parts into the expression
+ ** tree that have been allocated from lookaside memory, which is
+ ** illegal in a schema and will lead to errors heap corruption when
+ ** the database connection closes. */
+ sqlite3ExprDelete(db, pX);
+ p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
+ }
}else{
nNG++;
}
@@ -2609,7 +2625,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = n;
- if( pTable->pCheck ){
+ if( pSelTab==0 ){
+ pTable->nCol = 0;
+ nErr++;
+ }else if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
@@ -2619,13 +2638,13 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
if( db->mallocFailed==0
- && pParse->nErr==0
+ && ALWAYS(pParse->nErr==0)
&& pTable->nCol==pSel->pEList->nExpr
){
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
- }else if( pSelTab ){
+ }else{
/* CREATE VIEW name AS... without an argument list. Construct
** the column names from the SELECT statement that defines the view.
*/
@@ -2635,9 +2654,6 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
- }else{
- pTable->nCol = 0;
- nErr++;
}
pTable->nNVCol = pTable->nCol;
sqlite3DeleteTable(db, pSelTab);
@@ -3912,26 +3928,9 @@ void sqlite3CreateIndex(
sqlite3VdbeJumpHere(v, pIndex->tnum);
}
}
-
- /* When adding an index to the list of indices for a table, make
- ** sure all indices labeled OE_Replace come after all those labeled
- ** OE_Ignore. This is necessary for the correct constraint check
- ** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
- */
if( db->init.busy || pTblName==0 ){
- if( onError!=OE_Replace || pTab->pIndex==0
- || pTab->pIndex->onError==OE_Replace){
- pIndex->pNext = pTab->pIndex;
- pTab->pIndex = pIndex;
- }else{
- Index *pOther = pTab->pIndex;
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
- pOther = pOther->pNext;
- }
- pIndex->pNext = pOther->pNext;
- pOther->pNext = pIndex;
- }
+ pIndex->pNext = pTab->pIndex;
+ pTab->pIndex = pIndex;
pIndex = 0;
}
else if( IN_RENAME_OBJECT ){
@@ -3943,6 +3942,21 @@ void sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqlite3FreeIndex(db, pIndex);
+ if( pTab ){ /* Ensure all REPLACE indexes are at the end of the list */
+ Index **ppFrom = &pTab->pIndex;
+ Index *pThis;
+ for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
+ Index *pNext;
+ if( pThis->onError!=OE_Replace ) continue;
+ while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){
+ *ppFrom = pNext;
+ pThis->pNext = pNext->pNext;
+ pNext->pNext = pThis;
+ ppFrom = &pNext->pNext;
+ }
+ break;
+ }
+ }
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
diff --git a/src/expr.c b/src/expr.c
index 150e34a2c..9b2cb2657 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -376,6 +376,7 @@ static int codeCompare(
int addr;
CollSeq *p4;
+ if( pParse->nErr ) return 0;
if( isCommuted ){
p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
}else{
@@ -593,6 +594,7 @@ static void codeVectorCompare(
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
+ if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
@@ -931,9 +933,11 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
return pRight;
}else if( pRight==0 ){
return pLeft;
- }else if( ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight) ){
- sqlite3ExprUnmapAndDelete(pParse, pLeft);
- sqlite3ExprUnmapAndDelete(pParse, pRight);
+ }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
+ && !IN_RENAME_OBJECT
+ ){
+ sqlite3ExprDelete(db, pLeft);
+ sqlite3ExprDelete(db, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
@@ -2207,7 +2211,9 @@ int sqlite3ExprCanBeNull(const Expr *p){
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
+ (p->iColumn>=0
+ && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */
+ && p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -2289,7 +2295,7 @@ static Select *isCandidateForInOpt(Expr *pX){
testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
return 0; /* No DISTINCT keyword and no aggregate functions */
}
- assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
+ if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
if( p->pWhere ) return 0; /* Has no WHERE clause */
pSrc = p->pSrc;
@@ -2684,8 +2690,10 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
** "sub-select returns N columns - expected M"
*/
void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
- const char *zFmt = "sub-select returns %d columns - expected %d";
- sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
+ if( pParse->nErr==0 ){
+ const char *zFmt = "sub-select returns %d columns - expected %d";
+ sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
+ }
}
#endif
@@ -3187,15 +3195,21 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
}
if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
- sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
+ int op = rLhs!=r2 ? OP_Eq : OP_NotNull;
+ sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2,
(void*)pColl, P4_COLLSEQ);
- VdbeCoverageIf(v, ii<pList->nExpr-1);
- VdbeCoverageIf(v, ii==pList->nExpr-1);
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_Eq);
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq);
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_NotNull);
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull);
sqlite3VdbeChangeP5(v, zAff[0]);
}else{
+ int op = rLhs!=r2 ? OP_Ne : OP_IsNull;
assert( destIfNull==destIfFalse );
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2,
- (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
+ sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2,
+ (void*)pColl, P4_COLLSEQ);
+ VdbeCoverageIf(v, op==OP_Ne);
+ VdbeCoverageIf(v, op==OP_IsNull);
sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL);
}
sqlite3ReleaseTempReg(pParse, regToFree);
@@ -3218,6 +3232,7 @@ static void sqlite3ExprCodeIN(
}else{
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
+ if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( sqlite3ExprCanBeNull(p) ){
@@ -3409,11 +3424,20 @@ void sqlite3ExprCodeGeneratedColumn(
Column *pCol,
int regOut
){
+ int iAddr;
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ assert( pParse->iSelfTab!=0 );
+ if( pParse->iSelfTab>0 ){
+ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
+ }else{
+ iAddr = 0;
+ }
sqlite3ExprCode(pParse, pCol->pDflt, regOut);
if( pCol->affinity>=SQLITE_AFF_TEXT ){
- sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, regOut, 1, 0,
- &pCol->affinity, 1);
+ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
+ if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
@@ -3488,7 +3512,8 @@ int sqlite3ExprCodeGetColumn(
assert( pParse->pVdbe!=0 );
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
if( p5 ){
- sqlite3VdbeChangeP5(pParse->pVdbe, p5);
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
+ if( pOp->opcode==OP_Column ) pOp->p5 = p5;
}
return iReg;
}
@@ -3498,7 +3523,6 @@ int sqlite3ExprCodeGetColumn(
** over to iTo..iTo+nReg-1.
*/
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
- assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
}
@@ -3600,6 +3624,7 @@ expr_code_doover:
}
case TK_COLUMN: {
int iTab = pExpr->iTable;
+ int iReg;
if( ExprHasProperty(pExpr, EP_FixedCol) ){
/* This COLUMN expression is really a constant due to WHERE clause
** constraints, and that constant is coded by the pExpr->pLeft
@@ -3607,8 +3632,8 @@ expr_code_doover:
** datatype by applying the Affinity of the table column to the
** constant.
*/
- int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff;
+ iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
if( pExpr->y.pTab ){
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
@@ -3641,7 +3666,7 @@ expr_code_doover:
int iCol = pExpr->iColumn;
assert( pTab!=0 );
assert( iCol>=XN_ROWID );
- assert( iCol<pExpr->y.pTab->nCol );
+ assert( iCol<pTab->nCol );
if( iCol<0 ){
return -1-pParse->iSelfTab;
}
@@ -3676,9 +3701,13 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
- return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
+ iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
+ if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
+ }
+ return iReg;
}
case TK_INTEGER: {
codeInteger(pParse, pExpr, 0, target);
@@ -3700,7 +3729,12 @@ expr_code_doover:
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
return target;
}
- case TK_NULL: {
+ default: {
+ /* Make NULL the default case so that if a bug causes an illegal
+ ** 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 );
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
@@ -3727,7 +3761,7 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
- assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
+ assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
}
@@ -4040,8 +4074,12 @@ expr_code_doover:
sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
pDef, pExpr->op2);
}
- if( nFarg && constMask==0 ){
- sqlite3ReleaseTempRange(pParse, r1, nFarg);
+ if( nFarg ){
+ if( constMask==0 ){
+ sqlite3ReleaseTempRange(pParse, r1, nFarg);
+ }else{
+ sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask);
+ }
}
return target;
}
@@ -4211,7 +4249,7 @@ expr_code_doover:
** or if there is no matching Ei, the ELSE term Y, or if there is
** no ELSE term, NULL.
*/
- default: assert( op==TK_CASE ); {
+ case TK_CASE: {
int endLabel; /* GOTO label for end of CASE stmt */
int nextCase; /* GOTO label for next WHEN clause */
int nExpr; /* 2x number of WHEN terms */
@@ -5268,7 +5306,10 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
return WRC_Prune;
case TK_BETWEEN:
- sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){
+ assert( pWalker->eCode );
+ return WRC_Abort;
+ }
return WRC_Prune;
/* Virtual tables are allowed to use constraints like x=NULL. So
@@ -5411,12 +5452,13 @@ struct SrcCount {
** Count the number of references to columns.
*/
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
- /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
- ** is always called before sqlite3ExprAnalyzeAggregates() and so the
- ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
- ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
- ** NEVER() will need to be removed. */
- if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
+ /* There was once a NEVER() on the second term on the grounds that
+ ** sqlite3FunctionUsesThisSrc() was always called before
+ ** sqlite3ExprAnalyzeAggregates() and so the TK_COLUMNs have not yet
+ ** been converted into TK_AGG_COLUMN. But this is no longer true due
+ ** to window functions - sqlite3WindowRewrite() may now indirectly call
+ ** FunctionUsesThisSrc() when creating a new sub-select. */
+ if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
int i;
struct SrcCount *p = pWalker->u.pSrcCount;
SrcList *pSrc = p->pSrc;
@@ -5454,6 +5496,11 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
cnt.nThis = 0;
cnt.nOther = 0;
sqlite3WalkExprList(&w, pExpr->x.pList);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
+ }
+#endif
return cnt.nThis>0 || cnt.nOther==0;
}
@@ -5682,8 +5729,11 @@ int sqlite3GetTempReg(Parse *pParse){
** purpose.
*/
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
- if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- pParse->aTempReg[pParse->nTempReg++] = iReg;
+ if( iReg ){
+ sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0);
+ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
+ pParse->aTempReg[pParse->nTempReg++] = iReg;
+ }
}
}
@@ -5709,6 +5759,7 @@ void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ReleaseTempReg(pParse, iReg);
return;
}
+ sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0);
if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg;
diff --git a/src/insert.c b/src/insert.c
index 75db13177..56d70c00d 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -1020,6 +1020,7 @@ void sqlite3Insert(
** goto C
** D: ...
*/
+ sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0);
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
if( ipkColumn>=0 ){
@@ -1280,6 +1281,15 @@ void sqlite3Insert(
sqlite3VdbeAddOp1(v, OP_Close, srcTab);
}else if( pSelect ){
sqlite3VdbeGoto(v, addrCont);
+#ifdef SQLITE_DEBUG
+ /* If we are jumping back to an OP_Yield that is preceded by an
+ ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the
+ ** OP_ReleaseReg will be included in the loop. */
+ if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){
+ assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield );
+ sqlite3VdbeChangeP5(v, 1);
+ }
+#endif
sqlite3VdbeJumpHere(v, addrInsTop);
}
@@ -1502,7 +1512,6 @@ void sqlite3GenerateConstraintChecks(
int ix; /* Index loop counter */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
- int addr1; /* Address of jump instruction */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
Index *pUpIdx = 0; /* Index to which to apply the upsert */
@@ -1546,71 +1555,100 @@ void sqlite3GenerateConstraintChecks(
/* Test all NOT NULL constraints.
*/
if( pTab->tabFlags & TF_HasNotNull ){
- for(i=0; i<nCol; i++){
- int iReg;
- onError = pTab->aCol[i].notNull;
- if( onError==OE_None ) continue; /* No NOT NULL on this column */
- if( i==pTab->iPKey ){
- continue; /* ROWID is never NULL */
- }
- if( aiChng && aiChng[i]<0 ){
- /* Don't bother checking for NOT NULL on columns that do not change */
- continue;
- }
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
- if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
- onError = OE_Abort;
- }
- assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
- || onError==OE_Ignore || onError==OE_Replace );
- addr1 = 0;
- testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
- testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
- testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
- iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
- switch( onError ){
- case OE_Replace: {
- assert( onError==OE_Replace );
- addr1 = sqlite3VdbeMakeLabel(pParse);
- sqlite3VdbeAddOp2(v, OP_NotNull, iReg, addr1);
- VdbeCoverage(v);
- if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ){
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
- sqlite3VdbeAddOp2(v, OP_NotNull, iReg, addr1);
- VdbeCoverage(v);
- }
- onError = OE_Abort;
- /* Fall through into the OE_Abort case to generate code that runs
- ** if both the input and the default value are NULL */
+ int b2ndPass = 0; /* True if currently running 2nd pass */
+ int nSeenReplace = 0; /* Number of ON CONFLICT REPLACE operations */
+ int nGenerated = 0; /* Number of generated columns with NOT NULL */
+ while(1){ /* Make 2 passes over columns. Exit loop via "break" */
+ for(i=0; i<nCol; i++){
+ int iReg; /* Register holding column value */
+ Column *pCol = &pTab->aCol[i]; /* The column to check for NOT NULL */
+ int isGenerated; /* non-zero if column is generated */
+ onError = pCol->notNull;
+ if( onError==OE_None ) continue; /* No NOT NULL on this column */
+ if( i==pTab->iPKey ){
+ continue; /* ROWID is never NULL */
}
- case OE_Abort:
- sqlite3MayAbort(pParse);
- /* Fall through */
- case OE_Rollback:
- case OE_Fail: {
- char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
- pTab->aCol[i].zName);
- sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
- onError, iReg);
- sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
- sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
- VdbeCoverage(v);
- if( addr1 ) sqlite3VdbeResolveLabel(v, addr1);
- break;
+ isGenerated = pCol->colFlags & COLFLAG_GENERATED;
+ if( isGenerated && !b2ndPass ){
+ nGenerated++;
+ continue; /* Generated columns processed on 2nd pass */
}
- default: {
- assert( onError==OE_Ignore );
- sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
- VdbeCoverage(v);
- break;
+ if( aiChng && aiChng[i]<0 && !isGenerated ){
+ /* Do not check NOT NULL on columns that do not change */
+ continue;
}
+ if( overrideError!=OE_Default ){
+ onError = overrideError;
+ }else if( onError==OE_Default ){
+ onError = OE_Abort;
+ }
+ if( onError==OE_Replace ){
+ if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
+ || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
+ ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ testcase( pCol->colFlags & COLFLAG_GENERATED );
+ onError = OE_Abort;
+ }else{
+ assert( !isGenerated );
+ }
+ }else if( b2ndPass && !isGenerated ){
+ continue;
+ }
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
+ testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
+ iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
+ switch( onError ){
+ case OE_Replace: {
+ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
+ VdbeCoverage(v);
+ assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
+ nSeenReplace++;
+ sqlite3ExprCode(pParse, pCol->pDflt, iReg);
+ sqlite3VdbeJumpHere(v, addr1);
+ break;
+ }
+ case OE_Abort:
+ sqlite3MayAbort(pParse);
+ /* Fall through */
+ case OE_Rollback:
+ case OE_Fail: {
+ char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
+ pCol->zName);
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
+ onError, iReg);
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
+ VdbeCoverage(v);
+ break;
+ }
+ default: {
+ assert( onError==OE_Ignore );
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
+ VdbeCoverage(v);
+ break;
+ }
+ } /* end switch(onError) */
+ } /* end loop i over columns */
+ if( nGenerated==0 && nSeenReplace==0 ){
+ /* If there are no generated columns with NOT NULL constraints
+ ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single
+ ** pass is sufficient */
+ break;
}
- }
- }
+ if( b2ndPass ) break; /* Never need more than 2 passes */
+ b2ndPass = 1;
+ if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
+ /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the
+ ** first pass, recomputed values for all generated columns, as
+ ** those values might depend on columns affected by the REPLACE.
+ */
+ sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab);
+ }
+ } /* end of 2-pass loop */
+ } /* end if( has-not-null-constraints ) */
/* Test all CHECK constraints
*/
@@ -2091,9 +2129,15 @@ void sqlite3GenerateConstraintChecks(
sqlite3MultiWrite(pParse);
nReplaceTrig++;
}
+ if( pTrigger && isUpdate ){
+ sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur);
+ }
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
+ if( pTrigger && isUpdate ){
+ sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur);
+ }
if( regTrigCnt ){
int addrBypass; /* Jump destination to bypass recheck logic */
@@ -2250,6 +2294,10 @@ void sqlite3CompleteInsertion(
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ /* All REPLACE indexes are at the end of the list */
+ assert( pIdx->onError!=OE_Replace
+ || pIdx->pNext==0
+ || pIdx->pNext->onError==OE_Replace );
if( aRegIdx[i]==0 ) continue;
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
diff --git a/src/os_unix.c b/src/os_unix.c
index 18f2afcb6..07ae4bc03 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -6259,7 +6259,8 @@ static int unixAccess(
if( flags==SQLITE_ACCESS_EXISTS ){
struct stat buf;
- *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
+ *pResOut = 0==osStat(zPath, &buf) &&
+ (!S_ISREG(buf.st_mode) || buf.st_size>0);
}else{
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
}
diff --git a/src/pager.c b/src/pager.c
index 9d4922c4a..0fae9ae3d 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -1172,6 +1172,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
}
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
}
+ pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
return rc;
}
@@ -1893,7 +1894,6 @@ static void pager_unlock(Pager *pPager){
** code is cleared and the cache reset in the block below.
*/
assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
- pPager->changeCountDone = 0;
pPager->eState = PAGER_OPEN;
}
@@ -2157,7 +2157,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
- pPager->changeCountDone = 0;
}
pPager->eState = PAGER_READER;
pPager->setMaster = 0;
@@ -4813,7 +4812,7 @@ int sqlite3PagerOpen(
z += strlen(z)+1;
nUri++;
}
- nUriByte = (int)(&z[2] - zUri);
+ nUriByte = (int)(&z[1] - zUri);
assert( nUriByte>=1 );
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
@@ -6627,6 +6626,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** But if (due to a coding error elsewhere in the system) it does get
** called, just return the same error code without doing anything. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
+ pPager->iDataVersion++;
assert( pPager->eState==PAGER_WRITER_LOCKED
|| pPager->eState==PAGER_WRITER_FINISHED
@@ -6655,7 +6655,6 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
}
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
- pPager->iDataVersion++;
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
return pager_error(pPager, rc);
}
diff --git a/src/pcache1.c b/src/pcache1.c
index d0051433d..ed762ebf7 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -448,13 +448,15 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
}
#else
pPg = pcache1Alloc(pCache->szAlloc);
- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
pcache1EnterMutex(pCache->pGroup);
#endif
if( pPg==0 ) return 0;
+#ifndef SQLITE_PCACHE_SEPARATE_HEADER
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+#endif
p->page.pBuf = pPg;
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
diff --git a/src/resolve.c b/src/resolve.c
index 92a937d45..3e445fa9a 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -465,7 +465,9 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
return WRC_Abort;
}
- if( (pNC->ncFlags&NC_AllowWin)==0 && ExprHasProperty(pOrig, EP_Win) ){
+ if( ExprHasProperty(pOrig, EP_Win)
+ && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC )
+ ){
sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs);
return WRC_Abort;
}
diff --git a/src/select.c b/src/select.c
index 11c25e787..3e81beb39 100644
--- a/src/select.c
+++ b/src/select.c
@@ -84,7 +84,10 @@ struct SortCtx {
/*
** Delete all the content of a Select structure. Deallocate the structure
-** itself only if bFree is true.
+** itself depending on the value of bFree
+**
+** If bFree==1, call sqlite3DbFree() on the p object.
+** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
while( p ){
@@ -189,6 +192,20 @@ void sqlite3SelectDelete(sqlite3 *db, Select *p){
}
/*
+** Delete all the substructure for p, but keep p allocated. Redefine
+** p to be a single SELECT where every column of the result set has a
+** value of NULL.
+*/
+void sqlite3SelectReset(Parse *pParse, Select *p){
+ if( ALWAYS(p) ){
+ clearSelect(pParse->db, p, 0);
+ memset(&p->iLimit, 0, sizeof(Select) - offsetof(Select,iLimit));
+ p->pEList = sqlite3ExprListAppend(pParse, 0,
+ sqlite3ExprAlloc(pParse->db,TK_NULL,0,0));
+ }
+}
+
+/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
static Select *findRightmost(Select *p){
@@ -296,7 +313,8 @@ static int tableAndColumnIndex(
int N, /* Number of tables in pSrc->a[] to search */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
- int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int bIgnoreHidden /* True to ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
@@ -304,7 +322,9 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; i<N; i++){
iCol = columnIndex(pSrc->a[i].pTab, zCol);
- if( iCol>=0 ){
+ if( iCol>=0
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ ){
if( piTab ){
*piTab = i;
*piCol = iCol;
@@ -469,10 +489,11 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iLeft; /* Matching left table */
int iLeftCol; /* Matching column in the left table */
+ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
zName = pRightTab->aCol[j].zName;
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
- isOuter, &p->pWhere);
+ isOuter, &p->pWhere);
}
}
}
@@ -512,7 +533,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
zName = pList->a[j].zName;
iRightCol = columnIndex(pRightTab, zName);
if( iRightCol<0
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
@@ -2711,9 +2732,9 @@ static int multiSelect(
** it is that we currently need.
*/
assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
- if( dest.eDest!=priorOp ){
+ assert( p->pEList || db->mallocFailed );
+ if( dest.eDest!=priorOp && db->mallocFailed==0 ){
int iCont, iBreak, iStart;
- assert( p->pEList );
iBreak = sqlite3VdbeMakeLabel(pParse);
iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
@@ -2809,6 +2830,7 @@ static int multiSelect(
}
#endif
}
+ if( pParse->nErr ) goto multi_select_end;
/* Compute collating sequences used by
** temporary tables needed to implement the compound select.
@@ -3600,6 +3622,7 @@ static void substSelect(
** (3b) the FROM clause of the subquery may not contain a virtual
** table and
** (3c) the outer query may not be an aggregate.
+** (3d) the outer query may not be DISTINCT.
**
** (4) The subquery can not be DISTINCT.
**
@@ -3650,6 +3673,7 @@ static void substSelect(
** (17d1) aggregate, or
** (17d2) DISTINCT, or
** (17d3) a join.
+** (17e) the subquery may not contain window functions
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -3796,8 +3820,11 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
isLeftJoin = 1;
- if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
- /* (3a) (3c) (3b) */
+ if( pSubSrc->nSrc>1 /* (3a) */
+ || isAgg /* (3b) */
+ || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
+ || (p->selFlags & SF_Distinct)!=0 /* (3d) */
+ ){
return 0;
}
}
@@ -3831,6 +3858,7 @@ static int flattenSubquery(
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
|| pSub1->pSrc->nSrc<1 /* (17c) */
+ || pSub1->pWin /* (17e) */
){
return 0;
}
@@ -4956,7 +4984,7 @@ static int selectExpander(Walker *pWalker, Select *p){
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
return WRC_Abort;
}
@@ -5062,7 +5090,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( i>0 && zTName==0 ){
if( (pFrom->fg.jointype & JT_NATURAL)!=0
- && tableAndColumnIndex(pTabList, i, zName, 0, 0)
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1)
){
/* In a NATURAL join, omit the join columns from the
** table to the right of the join */
@@ -5733,7 +5761,9 @@ int sqlite3Select(
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( sqlite3WindowRewrite(pParse, p) ){
+ rc = sqlite3WindowRewrite(pParse, p);
+ if( rc ){
+ assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 944b5be3e..50976ee16 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -536,6 +536,7 @@ int sqlite3_exec(
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b18f05c85..463cfcefc 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -447,6 +447,26 @@
#endif
/*
+** The harmless(X) macro indicates that expression X is usually false
+** but can be true without causing any problems, but we don't know of
+** any way to cause X to be true.
+**
+** In debugging and testing builds, this macro will abort if X is ever
+** true. In this way, developers are alerted to a possible test case
+** that causes X to be true. If a harmless macro ever fails, that is
+** an opportunity to change the macro into a testcase() and add a new
+** test case to the test suite.
+**
+** For normal production builds, harmless(X) is a no-op, since it does
+** not matter whether expression X is true or false.
+*/
+#ifdef SQLITE_DEBUG
+# define harmless(X) assert(!(X));
+#else
+# define harmless(X)
+#endif
+
+/*
** Some conditionals are optimizations only. In other words, if the
** conditionals are replaced with a constant 1 (true) or 0 (false) then
** the correct answer is still obtained, though perhaps not as quickly.
@@ -2942,13 +2962,13 @@ struct Upsert {
** sequences for the ORDER BY clause.
*/
struct Select {
- ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
+ ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -4116,6 +4136,7 @@ int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
+void sqlite3SelectReset(Parse*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -4138,6 +4159,7 @@ int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
+int sqlite3WhereUsesDeferredSeek(WhereInfo*);
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
diff --git a/src/treeview.c b/src/treeview.c
index ac0e92a08..e6ec4161b 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -432,8 +432,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
pExpr->iColumn, zFlgs, zOp2);
}else{
- sqlite3TreeViewLine(pView, "{%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
+ sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
+ pExpr->iTable, pExpr->iColumn,
+ pExpr->y.pTab, zFlgs);
}
if( ExprHasProperty(pExpr, EP_FixedCol) ){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
diff --git a/src/update.c b/src/update.c
index f4e8f696d..61b1740b4 100644
--- a/src/update.c
+++ b/src/update.c
@@ -191,6 +191,7 @@ void sqlite3Update(
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
+ int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -524,6 +525,7 @@ void sqlite3Update(
pWInfo = 0;
eOnePass = ONEPASS_SINGLE;
sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
+ bFinishSeek = 0;
}else{
/* Begin the database scan.
**
@@ -550,6 +552,7 @@ void sqlite3Update(
** strategy that uses an index for which one or more columns are being
** updated. */
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
if( eOnePass!=ONEPASS_SINGLE ){
sqlite3MultiWrite(pParse);
if( eOnePass==ONEPASS_MULTI ){
@@ -713,6 +716,7 @@ void sqlite3Update(
testcase( i==31 );
testcase( i==32 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
+ bFinishSeek = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}
@@ -800,6 +804,15 @@ void sqlite3Update(
/* Delete the index entries associated with the current record. */
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
+ /* We must run the OP_FinishSeek opcode to resolve a prior
+ ** OP_DeferredSeek if there is any possibility that there have been
+ ** no OP_Column opcodes since the OP_DeferredSeek was issued. But
+ ** we want to avoid the OP_FinishSeek if possible, as running it
+ ** costs CPU cycles. */
+ if( bFinishSeek ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
+ }
+
/* If changing the rowid value, or if there are foreign key constraints
** to process, delete the old record. Otherwise, add a noop OP_Delete
** to invoke the pre-update hook.
diff --git a/src/upsert.c b/src/upsert.c
index 5db4f5fc9..9a33f75d0 100644
--- a/src/upsert.c
+++ b/src/upsert.c
@@ -236,6 +236,7 @@ void sqlite3UpsertDoUpdate(
VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
"corrupt database", P4_STATIC);
+ sqlite3MayAbort(pParse);
sqlite3VdbeJumpHere(v, i);
}
}
diff --git a/src/util.c b/src/util.c
index 2c14911b6..f7a993a76 100644
--- a/src/util.c
+++ b/src/util.c
@@ -389,7 +389,7 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
int incr;
- const char *zEnd = z + length;
+ const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
i64 s = 0; /* significand */
@@ -403,9 +403,11 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
+ if( length==0 ) return 0;
if( enc==SQLITE_UTF8 ){
incr = 1;
+ zEnd = z + length;
}else{
int i;
incr = 2;
diff --git a/src/vdbe.c b/src/vdbe.c
index f4520c608..cc999a3eb 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -845,6 +845,20 @@ int sqlite3VdbeExec(
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
+
+#ifdef SQLITE_DEBUG
+ /* In debuggging mode, when the p5 flags is set on an OP_Goto, that
+ ** means we should really jump back to the preceeding OP_ReleaseReg
+ ** instruction. */
+ if( pOp->p5 ){
+ assert( pOp->p2 < (int)(pOp - aOp) );
+ assert( pOp->p2 > 1 );
+ pOp = &aOp[pOp->p2 - 2];
+ assert( pOp[1].opcode==OP_ReleaseReg );
+ goto check_for_interrupt;
+ }
+#endif
+
jump_to_p2_and_check_for_interrupt:
pOp = &aOp[pOp->p2 - 1];
@@ -1463,6 +1477,14 @@ case OP_ResultRow: {
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
+#ifdef SQLITE_DEBUG
+ /* The registers in the result will not be used again when the
+ ** prepared statement restarts. This is because sqlite3_column()
+ ** APIs might have caused type conversions of made other changes to
+ ** the register values. Therefore, we can go ahead and break any
+ ** OP_SCopy dependencies. */
+ pMem[i].pScopyFrom = 0;
+#endif
}
if( db->mallocFailed ) goto no_mem;
@@ -1470,6 +1492,7 @@ case OP_ResultRow: {
db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
}
+
/* Return SQLITE_ROW
*/
p->pc = (int)(pOp - aOp) + 1;
@@ -1866,9 +1889,11 @@ case OP_Cast: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
rc = ExpandBlob(pIn1);
- sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
- UPDATE_MAX_BLOBSIZE(pIn1);
if( rc ) goto abort_due_to_error;
+ rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
+ if( rc ) goto abort_due_to_error;
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ REGISTER_TRACE(pOp->p1, pIn1);
break;
}
#endif /* SQLITE_OMIT_CAST */
@@ -2027,12 +2052,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
- assert( flags3==pIn3->flags );
- /* testcase( flags3!=pIn3->flags );
- ** this used to be possible with pIn1==pIn3, but not since
- ** the column cache was removed. The following assignment
- ** is essentially a no-op. But, it provides defense-in-depth
- ** in case our analysis is incorrect, so it is left in. */
+ testcase( flags3!=pIn3->flags );
flags3 = pIn3->flags;
}
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
@@ -2055,7 +2075,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
sqlite3VdbeMemStringify(pIn1, encoding, 1);
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
- assert( pIn1!=pIn3 );
+ if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str;
}
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
@@ -2090,10 +2110,10 @@ compare_op:
}
/* Undo any changes made by applyAffinity() to the input registers. */
- assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
- pIn1->flags = flags1;
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
pIn3->flags = flags3;
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
+ pIn1->flags = flags1;
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
@@ -2129,16 +2149,31 @@ compare_op:
/* Opcode: ElseNotEq * P2 * * *
**
-** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
-** If result of an OP_Eq comparison on the same two operands
-** would have be 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.
+** 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.
+**
+** 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.
*/
case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
- assert( pOp>aOp );
- assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
- assert( pOp[-1].p5 & SQLITE_STOREP2 );
+
+#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 */
+ 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;
break;
@@ -2549,7 +2584,9 @@ case OP_Column: {
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
p2 = pOp->p2;
/* If the cursor cache is stale (meaning it is not currently point at
@@ -2561,7 +2598,6 @@ case OP_Column: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pC!=0 );
assert( p2<pC->nField );
aOffset = pC->aOffset;
@@ -3264,8 +3300,12 @@ case OP_Savepoint: {
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
- db->isTransactionSavepoint = 0;
rc = p->rc;
+ if( rc ){
+ db->autoCommit = 0;
+ }else{
+ db->isTransactionSavepoint = 0;
+ }
}else{
int isSchemaChange;
iSavepoint = db->nSavepoint - iSavepoint - 1;
@@ -3293,6 +3333,7 @@ case OP_Savepoint: {
db->mDbFlags |= DBFLAG_SchemaChange;
}
}
+ if( rc ) goto abort_due_to_error;
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
@@ -3788,6 +3829,7 @@ case OP_OpenDup: {
VdbeCursor *pCx; /* The new cursor */
pOrig = p->apCsr[pOp->p2];
+ assert( pOrig );
assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
@@ -4794,6 +4836,7 @@ case OP_Insert: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
+ assert( pC->deferredMoveto==0 );
assert( pC->uc.pCursor!=0 );
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
@@ -5667,6 +5710,24 @@ case OP_IdxRowid: { /* out2 */
break;
}
+/* Opcode: FinishSeek P1 * * * *
+**
+** If cursor P1 was previously moved via OP_DeferredSeek, complete that
+** seek operation now, without further delay. If the cursor seek has
+** already occurred, this instruction is a no-op.
+*/
+case OP_FinishSeek: {
+ VdbeCursor *pC; /* The P1 index cursor */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ if( pC->deferredMoveto ){
+ rc = sqlite3VdbeFinishMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ }
+ break;
+}
+
/* Opcode: IdxGE P1 P2 P3 P4 P5
** Synopsis: key=r[P3@P4]
**
@@ -6973,6 +7034,36 @@ case OP_Expire: {
break;
}
+/* Opcode: CursorLock P1 * * * *
+**
+** Lock the btree to which cursor P1 is pointing so that the btree cannot be
+** written by an other cursor.
+*/
+case OP_CursorLock: {
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ sqlite3BtreeCursorPin(pC->uc.pCursor);
+ break;
+}
+
+/* Opcode: CursorUnlock P1 * * * *
+**
+** Unlock the btree to which cursor P1 is pointing so that it can be
+** written by other cursors.
+*/
+case OP_CursorUnlock: {
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ sqlite3BtreeCursorUnpin(pC->uc.pCursor);
+ break;
+}
+
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
** Synopsis: iDb=P1 root=P2 write=P3
@@ -7217,7 +7308,7 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
- testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
+ assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
@@ -7678,6 +7769,53 @@ case OP_Abortable: {
}
#endif
+#ifdef SQLITE_DEBUG
+/* Opcode: ReleaseReg P1 P2 P3 * *
+** Synopsis: release r[P1@P2] mask P3
+**
+** Release registers from service. Any content that was in the
+** the registers is unreliable after this opcode completes.
+**
+** The registers released will be the P2 registers starting at P1,
+** except if bit ii of P3 set, then do not release register P1+ii.
+** In other words, P3 is a mask of registers to preserve.
+**
+** Releasing a register clears the Mem.pScopyFrom pointer. That means
+** that if the content of the released register was set using OP_SCopy,
+** a change to the value of the source register for the OP_SCopy will no longer
+** generate an assertion fault in sqlite3VdbeMemAboutToChange().
+**
+** TODO: Released registers ought to also have their datatype set to
+** MEM_Undefined so that any subsequent attempt to read the released
+** register (before it is reinitialized) will generate an assertion fault.
+** However, there are places in the code generator which release registers
+** before their are used, under the (valid) assumption that the registers
+** will not be reallocated for some other purpose before they are used and
+** hence are safe to release.
+**
+** This opcode is only available in testing and debugging builds. It is
+** not generated for release builds. The purpose of this opcode is to help
+** validate the generated bytecode. This opcode does not actually contribute
+** to computing an answer.
+*/
+case OP_ReleaseReg: {
+ Mem *pMem;
+ int i;
+ u32 constMask;
+ assert( pOp->p1>0 );
+ assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
+ pMem = &aMem[pOp->p1];
+ constMask = pOp->p3;
+ for(i=0; i<pOp->p2; i++, pMem++){
+ if( i>=32 || (constMask & MASKBIT32(i))==0 ){
+ pMem->pScopyFrom = 0;
+ /* MemSetTypeFlag(pMem, MEM_Undefined); // See the TODO */
+ }
+ }
+ break;
+}
+#endif
+
/* Opcode: Noop * * * * *
**
** Do nothing. This instruction is often useful as a jump
diff --git a/src/vdbe.h b/src/vdbe.h
index 3214d5bce..9b25452e2 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -232,6 +232,11 @@ void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+#ifdef SQLITE_DEBUG
+ void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask);
+#else
+# define sqlite3VdbeReleaseRegisters(P,A,N,M)
+#endif
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 4775f406c..138377def 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -483,6 +483,7 @@ struct PreUpdate {
void sqlite3VdbeError(Vdbe*, const char *, ...);
void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
+int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
int sqlite3VdbeCursorRestore(VdbeCursor*);
u32 sqlite3VdbeSerialTypeLen(u32);
@@ -529,7 +530,7 @@ int sqlite3VdbeBooleanValue(Mem*, int ifNull);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemNumerify(Mem*);
-void sqlite3VdbeMemCast(Mem*,u8,u8);
+int sqlite3VdbeMemCast(Mem*,u8,u8);
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 311be9af9..9d04c160a 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1186,6 +1186,29 @@ int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
}
}
+#ifdef SQLITE_DEBUG
+/*
+** Generate an OP_ReleaseReg opcode to indicate that a range of
+** registers, except any identified by mask, are no longer in use.
+*/
+void sqlite3VdbeReleaseRegisters(Parse *pParse, int iFirst, int N, u32 mask){
+ assert( pParse->pVdbe );
+ while( N>0 && (mask&1)!=0 ){
+ mask >>= 1;
+ iFirst++;
+ N--;
+ }
+ while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){
+ mask &= ~MASKBIT32(N-1);
+ N--;
+ }
+ if( N>0 ){
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask);
+ }
+}
+#endif /* SQLITE_DEBUG */
+
+
/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
@@ -1303,7 +1326,8 @@ void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
+ || p->pParse->nErr>0 );
if( p->nOp ){
assert( p->aOp );
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
@@ -3390,7 +3414,7 @@ void sqlite3VdbeDelete(Vdbe *p){
** carried out. Seek the cursor now. If an error occurs, return
** the appropriate error code.
*/
-static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
+int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
int res, rc;
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
@@ -3462,7 +3486,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
*piCol = iMap - 1;
return SQLITE_OK;
}
- return handleDeferredMoveto(p);
+ return sqlite3VdbeFinishMoveto(p);
}
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
return handleMovedCursor(p);
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 8ef5a5133..c64901e44 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -747,8 +747,8 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
** affinity even if that results in loss of data. This routine is
** used (for example) to implement the SQL "cast()" operator.
*/
-void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
- if( pMem->flags & MEM_Null ) return;
+int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
+ if( pMem->flags & MEM_Null ) return SQLITE_OK;
switch( aff ){
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
if( (pMem->flags & MEM_Blob)==0 ){
@@ -779,9 +779,10 @@ void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
- break;
+ return sqlite3VdbeChangeEncoding(pMem, encoding);
}
}
+ return SQLITE_OK;
}
/*
diff --git a/src/vtab.c b/src/vtab.c
index 64125e769..082b56edb 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -484,13 +484,13 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
zStmt,
pParse->regRowid
);
- sqlite3DbFree(db, zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp0(v, OP_Expire);
- zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
+ zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
sqlite3VdbeLoadString(v, iReg, pTab->zName);
diff --git a/src/where.c b/src/where.c
index 6a05d0c4d..7c05a58e4 100644
--- a/src/where.c
+++ b/src/where.c
@@ -120,7 +120,7 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
/*
** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
-** operate directly on the rowis returned by a WHERE clause. Return
+** operate directly on the rowids returned by a WHERE clause. Return
** ONEPASS_SINGLE (1) if the statement can operation directly because only
** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
** optimization can be used on multiple
@@ -148,6 +148,14 @@ int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
}
/*
+** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
+** the data cursor to the row selected by the index cursor.
+*/
+int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){
+ return pWInfo->bDeferredSeek;
+}
+
+/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
@@ -605,7 +613,7 @@ static void translateColumnToCopy(
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
-static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
+static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
@@ -623,7 +631,7 @@ static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
p->aOrderBy[i].desc);
}
}
-static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
+static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
@@ -639,8 +647,8 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
}
#else
-#define TRACE_IDX_INPUTS(A)
-#define TRACE_IDX_OUTPUTS(A)
+#define whereTraceIndexInfoInputs(A)
+#define whereTraceIndexInfoOutputs(A)
#endif
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -801,7 +809,8 @@ static void constructAutomaticIndex(
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
- pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : sqlite3StrBINARY;
+ assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
+ pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
}
}
@@ -869,8 +878,8 @@ static void constructAutomaticIndex(
pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
+ sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
}
- sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
@@ -949,23 +958,14 @@ static sqlite3_index_info *allocateIndexInfo(
sqlite3ErrorMsg(pParse, "out of memory");
return 0;
}
-
- /* Initialize the structure. The sqlite3_index_info structure contains
- ** many fields that are declared "const" to prevent xBestIndex from
- ** changing them. We have to do some funky casting in order to
- ** initialize those fields.
- */
pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1];
pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
- *(int*)&pIdxInfo->nConstraint = nTerm;
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
- *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
- *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
- *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
- pUsage;
-
+ pIdxInfo->nOrderBy = nOrderBy;
+ pIdxInfo->aConstraint = pIdxCons;
+ pIdxInfo->aOrderBy = pIdxOrderBy;
+ pIdxInfo->aConstraintUsage = pUsage;
pHidden->pWC = pWC;
pHidden->pParse = pParse;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -1025,6 +1025,7 @@ static sqlite3_index_info *allocateIndexInfo(
j++;
}
+ pIdxInfo->nConstraint = j;
for(i=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -1055,9 +1056,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int rc;
- TRACE_IDX_INPUTS(p);
+ whereTraceIndexInfoInputs(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
- TRACE_IDX_OUTPUTS(p);
+ whereTraceIndexInfoOutputs(p);
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
@@ -1738,16 +1739,17 @@ static int whereInScanEst(
/*
** Print the content of a WhereTerm object
*/
-static void whereTermPrint(WhereTerm *pTerm, int iTerm){
+void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm==0 ){
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
- char zType[4];
+ char zType[8];
char zLeft[50];
- memcpy(zType, "...", 4);
+ memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
+ if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.leftColumn);
@@ -1758,14 +1760,21 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
sqlite3DebugPrintf(
- "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
- iTerm, pTerm, zType, zLeft, pTerm->truthProb,
- pTerm->eOperator, pTerm->wtFlags);
+ "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
+ iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
+ /* The 0x10000 .wheretrace flag causes extra information to be
+ ** shown about each Term */
+ if( sqlite3WhereTrace & 0x10000 ){
+ sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
+ pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
+ }
if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
- }else{
- sqlite3DebugPrintf("\n");
+ sqlite3DebugPrintf(" iField=%d", pTerm->iField);
}
+ if( pTerm->iParent>=0 ){
+ sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
+ }
+ sqlite3DebugPrintf("\n");
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
@@ -1778,7 +1787,7 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
void sqlite3WhereClausePrint(WhereClause *pWC){
int i;
for(i=0; i<pWC->nTerm; i++){
- whereTermPrint(&pWC->a[i], i);
+ sqlite3WhereTermPrint(&pWC->a[i], i);
}
}
#endif
@@ -1787,7 +1796,7 @@ void sqlite3WhereClausePrint(WhereClause *pWC){
/*
** Print a WhereLoop object for debugging purposes
*/
-static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
+void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
@@ -1829,7 +1838,7 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
int i;
for(i=0; i<p->nLTerm; i++){
- whereTermPrint(p->aLTerm[i], i);
+ sqlite3WhereTermPrint(p->aLTerm[i], i);
}
}
}
@@ -2134,6 +2143,8 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
}
pBuilder->iPlanLimit--;
+ whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
+
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
@@ -2148,7 +2159,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
}
@@ -2157,7 +2168,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
/* Look for an existing WhereLoop to replace with pTemplate
*/
- whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
if( ppPrev==0 ){
@@ -2166,7 +2176,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" skip: ");
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
return SQLITE_OK;
@@ -2182,12 +2192,12 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
if( sqlite3WhereTrace & 0x8 ){
if( p!=0 ){
sqlite3DebugPrintf("replace: ");
- whereLoopPrint(p, pBuilder->pWC);
+ sqlite3WhereLoopPrint(p, pBuilder->pWC);
sqlite3DebugPrintf(" with: ");
}else{
sqlite3DebugPrintf(" add: ");
}
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
if( p==0 ){
@@ -2211,7 +2221,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" delete: ");
- whereLoopPrint(pToDel, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pToDel, pBuilder->pWC);
}
#endif
whereLoopDelete(db, pToDel);
@@ -3499,7 +3509,8 @@ static int whereLoopAddOr(
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
- assert( rc==SQLITE_OK || sCur.n==0 );
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
+ testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
break;
@@ -4829,7 +4840,7 @@ WhereInfo *sqlite3WhereBegin(
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
p->cId = zLabel[i%(sizeof(zLabel)-1)];
- whereLoopPrint(p, sWLB.pWC);
+ sqlite3WhereLoopPrint(p, sWLB.pWC);
}
}
#endif
@@ -4869,7 +4880,7 @@ WhereInfo *sqlite3WhereBegin(
}
sqlite3DebugPrintf("\n");
for(ii=0; ii<pWInfo->nLevel; ii++){
- whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
+ sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
}
}
#endif
diff --git a/src/whereInt.h b/src/whereInt.h
index e63ca46d5..f500e01d4 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -459,6 +459,7 @@ struct WhereInfo {
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 sorted; /* True if really sorted (not just grouped) */
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
+ u8 bDeferredSeek; /* Uses OP_DeferredSeek */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
@@ -479,6 +480,8 @@ struct WhereInfo {
Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
#ifdef WHERETRACE_ENABLED
void sqlite3WhereClausePrint(WhereClause *pWC);
+void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm);
+void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC);
#endif
WhereTerm *sqlite3WhereFindTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
diff --git a/src/wherecode.c b/src/wherecode.c
index 59546c43c..96c2971a5 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -415,7 +415,8 @@ static Expr *removeUnindexableInClauseTerms(
Expr *pX /* The IN expression to be reduced */
){
sqlite3 *db = pParse->db;
- Expr *pNew = sqlite3ExprDup(db, pX, 0);
+ Expr *pNew;
+ pNew = sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed==0 ){
ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
@@ -1044,6 +1045,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
+ pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
@@ -1127,6 +1129,9 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->y.pTab = 0;
+ testcase( ExprHasProperty(pExpr, EP_Skip) );
+ testcase( ExprHasProperty(pExpr, EP_Unlikely) );
+ ExprClearProperty(pExpr, EP_Skip|EP_Unlikely);
return WRC_Prune;
}else{
return WRC_Continue;
@@ -1188,9 +1193,20 @@ static void whereIndexExprTrans(
if( iRef==XN_EXPR ){
assert( aColExpr->a[iIdxCol].pExpr!=0 );
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
+ if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
w.xExprCallback = whereIndexExprTransNode;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- }else if( iRef>=0 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0 ){
+ }else if( iRef>=0
+ && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
+ && (pTab->aCol[iRef].zColl==0
+ || sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlite3StrBINARY)==0)
+ ){
+ /* Check to see if there are direct references to generated columns
+ ** that are contained in the index. Pulling the generated column
+ ** out of the index is an optimization only - the main table is always
+ ** available if the index cannot be used. To avoid unnecessary
+ ** complication, omit this optimization if the collating sequence for
+ ** the column is non-standard */
x.iTabCol = iRef;
w.xExprCallback = whereIndexExprTransColumn;
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
@@ -1269,6 +1285,21 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
+#if WHERETRACE_ENABLED /* 0x20800 */
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
+ iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom);
+ sqlite3WhereLoopPrint(pLoop, pWC);
+ }
+ if( sqlite3WhereTrace & 0x20000 ){
+ if( iLevel==0 ){
+ sqlite3DebugPrintf("WHERE clause being coded:\n");
+ sqlite3TreeViewExpr(0, pWInfo->pWhere, 0);
+ }
+ sqlite3DebugPrintf("All WHERE-clause terms before coding:\n");
+ sqlite3WhereClausePrint(pWC);
+ }
+#endif
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -1655,7 +1686,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
){
assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
assert( pRangeEnd==0 && pRangeStart==0 );
- assert( pLoop->nSkip==0 );
+ testcase( pLoop->nSkip>0 );
nExtraReg = 1;
bSeekPastNull = 1;
pLevel->regBignull = regBignull = ++pParse->nMem;
@@ -2324,6 +2355,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
pWC->nTerm-j, pTerm, iLoop));
}
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding auxiliary constraint:\n");
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
+ }
#endif
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
@@ -2347,8 +2382,14 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
- if( pLevel->iLeftJoin ) continue;
+ if( pTabItem->fg.jointype & JT_LEFT ) continue;
pE = pTerm->pExpr;
+#ifdef WHERETRACE_ENABLED /* 0x800 */
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding transitive constraint:\n");
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
+ }
+#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
@@ -2391,5 +2432,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
}
+#if WHERETRACE_ENABLED /* 0x20800 */
+ if( sqlite3WhereTrace & 0x20000 ){
+ sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
+ iLevel);
+ sqlite3WhereClausePrint(pWC);
+ }
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n",
+ iLevel, (u64)pLevel->notReady);
+ }
+#endif
return pLevel->notReady;
}
diff --git a/src/whereexpr.c b/src/whereexpr.c
index 16bbf4468..cec0aefd8 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -1298,6 +1298,7 @@ static void exprAnalyze(
0, sqlite3ExprDup(db, pRight, 0));
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
ExprSetProperty(pNewExpr, EP_FromJoin);
+ pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
}
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
@@ -1354,11 +1355,15 @@ static void exprAnalyze(
** expression). The WhereTerm.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
- ** This only works if the RHS is a simple SELECT, not a compound
+ ** This only works if the RHS is a simple SELECT (not a compound) that does
+ ** not use window functions.
*/
if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ && pExpr->x.pSelect->pWin==0
+#endif
){
int i;
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
@@ -1516,9 +1521,10 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( p->op==TK_FUNCTION && p->y.pWin ){
+ if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && p->y.pWin ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
+ mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
}
#endif
return mask;
diff --git a/src/window.c b/src/window.c
index 06a341d27..15a49f442 100644
--- a/src/window.c
+++ b/src/window.c
@@ -799,6 +799,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
}
if( iCol<0 ){
Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
+ if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION;
p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
}
if( p->pSub ){
@@ -894,10 +895,13 @@ static ExprList *exprListAppendList(
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; i<pAppend->nExpr; i++){
+ int iDummy;
Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
- if( bIntToNull && pDup && pDup->op==TK_INTEGER ){
+ assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
+ if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
pDup->op = TK_NULL;
pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
+ pDup->u.zToken = 0;
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
@@ -932,7 +936,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
- return SQLITE_NOMEM;
+ return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
p->pSrc = 0;
@@ -945,7 +949,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
/* Create the ORDER BY clause for the sub-select. This is the concatenation
** of the window PARTITION and ORDER BY clauses. Then, if this makes it
** redundant, remove the ORDER BY from the parent SELECT. */
- pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
+ pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1);
pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
int nSave = pSort->nExpr;
@@ -1019,6 +1023,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
if( pTab2==0 ){
+ /* Might actually be some other kind of error, but in that case
+ ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
+ ** the correct error message regardless. */
rc = SQLITE_NOMEM;
}else{
memcpy(pTab, pTab2, sizeof(Table));
@@ -1037,6 +1044,13 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
sqlite3DbFree(db, pTab);
}
+ if( rc ){
+ if( pParse->nErr==0 ){
+ assert( pParse->db->mallocFailed );
+ sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
+ }
+ sqlite3SelectReset(pParse, p);
+ }
return rc;
}
diff --git a/test/altertab2.test b/test/altertab2.test
index f14dc13ff..9c1ad5813 100644
--- a/test/altertab2.test
+++ b/test/altertab2.test
@@ -343,22 +343,21 @@ do_execsql_test 8.4 {
CREATE VIEW v4 AS SELECT * FROM t4 WHERE (a=1 AND 0) OR b=2;
}
-# Do not rename branches of an expression tree that is optimized out by
-# the AND optimization.
+# Branches of an expression tree that are optimized out by the AND
+# optimization are renamed.
#
do_execsql_test 8.5 {
ALTER TABLE t4 RENAME a TO c;
SELECT sql FROM sqlite_master WHERE name = 'v4'
-} {{CREATE VIEW v4 AS SELECT * FROM t4 WHERE (a=1 AND 0) OR b=2}}
-# "a" is not renamed to "c" ---^
+} {{CREATE VIEW v4 AS SELECT * FROM t4 WHERE (c=1 AND 0) OR b=2}}
# 2019-06-10 https://www.sqlite.org/src/info/533010b8cacebe82
reset_db
-do_execsql_test 8.6 {
+do_catchsql_test 8.6 {
CREATE TABLE t0(c0);
CREATE INDEX i0 ON t0(LIKELIHOOD(1,2) AND 0);
ALTER TABLE t0 RENAME TO t1;
SELECT sql FROM sqlite_master WHERE name='i0';
-} {{CREATE INDEX i0 ON "t1"(LIKELIHOOD(1,2) AND 0)}}
+} {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}}
finish_test
diff --git a/test/altertab3.test b/test/altertab3.test
index 88d882fcb..b39065589 100644
--- a/test/altertab3.test
+++ b/test/altertab3.test
@@ -517,5 +517,74 @@ do_catchsql_test 22.6 {
ALTER TABLE t1 RENAME TO t4;
} {0 {}}
+#------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 23.1 {
+ CREATE TABLE t1(x);
+ CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
+ UPDATE t1 SET (c,d)=((SELECT 1 FROM t1 JOIN t2 ON b=x),1);
+ END;
+}
+
+do_catchsql_test 23.2 {
+ ALTER TABLE t1 RENAME TO t1x;
+} {1 {error in trigger r1: no such table: main.t2}}
+
+#------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 23.1 {
+ CREATE TABLE v0 (a);
+ CREATE VIEW v2 (v3) AS
+ WITH x1 AS (SELECT * FROM v2)
+ SELECT v3 AS x, v3 AS y FROM v2;
+}
+
+do_catchsql_test 23.2 {
+ SELECT * FROM v2
+} {1 {view v2 is circularly defined}}
+
+db close
+sqlite3 db test.db
+
+do_catchsql_test 23.3 {
+ ALTER TABLE v0 RENAME TO t3 ;
+} {1 {error in view v2: view v2 is circularly defined}}
+
+#------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 24.1 {
+ CREATE TABLE v0 (v1);
+ CREATE TABLE v2 (v3 INTEGER UNIQUE ON CONFLICT ABORT);
+ CREATE TRIGGER x AFTER INSERT ON v2 WHEN (
+ ( SELECT v1 AS PROMO_REVENUE FROM v2 JOIN v0 USING ( VALUE ) ) AND 0 )
+ BEGIN
+ DELETE FROM v2;
+ END;
+}
+do_catchsql_test 24.2 {
+ ALTER TABLE v0 RENAME TO x ;
+} {1 {error in trigger x: cannot join using column VALUE - column not present in both tables}}
+
+do_execsql_test 24.3 {
+ DROP TRIGGER x;
+ CREATE TRIGGER x AFTER INSERT ON v2 WHEN (
+ 0 AND (SELECT rowid FROM v0)
+ ) BEGIN
+ DELETE FROM v2;
+ END;
+}
+
+do_execsql_test 24.4 {
+ ALTER TABLE v0 RENAME TO xyz;
+ SELECT sql FROM sqlite_master WHERE type='trigger'
+} {{CREATE TRIGGER x AFTER INSERT ON v2 WHEN (
+ 0 AND (SELECT rowid FROM "xyz")
+ ) BEGIN
+ DELETE FROM v2;
+ END}}
finish_test
+
diff --git a/test/check.test b/test/check.test
index ac0a9ac6b..3e16b9dcf 100644
--- a/test/check.test
+++ b/test/check.test
@@ -11,7 +11,6 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing CHECK constraints
#
-# $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -536,7 +535,71 @@ do_execsql_test 11.6 {
INSERT INTO t2(b, a) VALUES(2, 'abc');
}
-finish_test
-
+# 2019-12-24 ticket b383b90278186263
+#
+reset_db
+do_execsql_test 12.10 {
+ CREATE TABLE t1(a TEXT, CHECK(a=+a));
+ INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL 'xyz' '5' X'303132' '4.75'}
+do_execsql_test 12.20 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(a<>+a));
+ INSERT INTO t1(a) VALUES(NULL);
+} {}
+do_catchsql_test 12.21 {
+ INSERT INTO t1(a) VALUES('xyz');
+} {1 {CHECK constraint failed: t1}}
+do_catchsql_test 12.22 {
+ INSERT INTO t1(a) VALUES(123);
+} {1 {CHECK constraint failed: t1}}
+do_execsql_test 12.30 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(NOT(a=+a)));
+ INSERT INTO t1(a) VALUES(NULL);
+} {}
+do_catchsql_test 12.31 {
+ INSERT INTO t1(a) VALUES('xyz');
+} {1 {CHECK constraint failed: t1}}
+do_catchsql_test 12.32 {
+ INSERT INTO t1(a) VALUES(123);
+} {1 {CHECK constraint failed: t1}}
+do_execsql_test 12.40 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(NOT(a<>+a)));
+ INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL 'xyz' '5' X'303132' '4.75'}
+do_execsql_test 12.50 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(a BETWEEN 0 AND +a));
+ INSERT INTO t1(a) VALUES(NULL),('xyz'),(5),(x'303132'),(4.75);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL 'xyz' '5' X'303132' '4.75'}
+do_execsql_test 12.60 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(a NOT BETWEEN 0 AND +a));
+ INSERT INTO t1(a) VALUES(NULL);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL}
+do_catchsql_test 12.61 {
+ INSERT INTO t1(a) VALUES(456);
+} {1 {CHECK constraint failed: t1}}
+do_execsql_test 12.70 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(a BETWEEN +a AND 999999));
+ INSERT INTO t1(a) VALUES(NULL),(5);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL '5'}
+do_execsql_test 12.80 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a TEXT, CHECK(a NOT BETWEEN +a AND 999999));
+ INSERT INTO t1(a) VALUES(NULL);
+ SELECT quote(a) FROM t1 ORDER BY rowid;
+} {NULL}
+do_catchsql_test 12.81 {
+ INSERT INTO t1(a) VALUES(456);
+} {1 {CHECK constraint failed: t1}}
finish_test
diff --git a/test/conflict.test b/test/conflict.test
index 136bc3fec..b86f86022 100644
--- a/test/conflict.test
+++ b/test/conflict.test
@@ -834,5 +834,27 @@ do_catchsql_test conflict-14.1 {
REPLACE INTO t1 DEFAULT VALUES;
} {1 {NOT NULL constraint failed: t1.x}}
+# 2019-12-15 gramfuzz1 find
+# Three UNIQUE constraints, where the third would is a duplicate except
+# that it adds ON CONFLICT REPLACE. Verify that the indexes end up
+# sorted in the correct order (REPLACE last) so that constraint processing
+# works correctly.
+#
+reset_db
+do_execsql_test conflict-15.10 {
+ CREATE TABLE t1(
+ x PRIMARY KEY,
+ UNIQUE(x,x),
+ UNIQUE(x,x) ON CONFLICT REPLACE
+ );
+ INSERT INTO t1(x) VALUES(1);
+ SELECT * FROM t1;
+} {1}
+do_catchsql_test conflict-15.20 {
+ INSERT INTO t1(x) VALUES(1);
+} {1 {UNIQUE constraint failed: t1.x}}
+do_execsql_test conflict-15.30 {
+ SELECT * FROM t1;
+} {1}
finish_test
diff --git a/test/conflict3.test b/test/conflict3.test
index cc3a51b85..8eb4c1b0f 100644
--- a/test/conflict3.test
+++ b/test/conflict3.test
@@ -380,15 +380,15 @@ ifcapable trigger {
INSERT INTO t0 VALUES(0, NULL);
}
- do_execsql_test 13.1.1 {
+ do_catchsql_test 13.1.1 {
UPDATE OR REPLACE t0 SET c1 = 1;
- }
+ } {1 {constraint failed}}
integrity_check 13.1.2
do_execsql_test 13.1.3 {
SELECT * FROM t0
- } {}
+ } {1 {} 0 {}}
do_execsql_test 13.2.0 {
CREATE TABLE t2 (a PRIMARY KEY, b UNIQUE, c UNIQUE) WITHOUT ROWID;
@@ -400,15 +400,15 @@ ifcapable trigger {
INSERT INTO t2 VALUES(2, 2, 2);
}
- do_execsql_test 13.2.1 {
+ do_catchsql_test 13.2.1 {
UPDATE OR REPLACE t2 SET c = 0;
- }
+ } {1 {constraint failed}}
integrity_check 13.2.2
do_execsql_test 13.2.3 {
SELECT * FROM t2
- } {}
+ } {1 1 1 2 2 2}
do_execsql_test 13.3.0 {
CREATE TABLE t1(a, b);
diff --git a/test/exclusive.test b/test/exclusive.test
index 04de52913..5168fa748 100644
--- a/test/exclusive.test
+++ b/test/exclusive.test
@@ -511,6 +511,24 @@ do_execsql_test exclusive-6.5 {
SELECT * FROM sqlite_master;
} {exclusive}
+# 2019-12-26 ticket fb3b3024ea238d5c
+do_test exclusive-7.1 {
+ db close
+ forcedelete test.db test.db-journal test.db-wal
+ sqlite3 db test.db
+ # The following sequence of pragmas would trigger an assert()
+ # associated with Pager.changeCountDone inside of assert_pager_state(),
+ # prior to the fix.
+ db eval {
+ PRAGMA locking_mode = EXCLUSIVE;
+ PRAGMA journal_mode = WAL;
+ PRAGMA locking_mode = NORMAL;
+ PRAGMA user_version;
+ PRAGMA journal_mode = DELETE;
+ }
+} {exclusive wal normal 0 delete}
+
+
} ;# atomic_batch_write==0
finish_test
diff --git a/test/filter1.test b/test/filter1.test
index eb5096347..ee17099d9 100644
--- a/test/filter1.test
+++ b/test/filter1.test
@@ -184,4 +184,24 @@ do_execsql_test 5.3 {
SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1)
} {0 1}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 6.0 {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,1);
+ INSERT INTO t1 VALUES(2,2);
+ CREATE TABLE t2(x,y);
+ INSERT INTO t2 VALUES(1,1);
+}
+
+do_execsql_test 6.1 {
+ SELECT (SELECT COUNT(a) FILTER(WHERE x) FROM t2) FROM t1;
+} {1 1}
+do_execsql_test 6.2 {
+ SELECT (SELECT COUNT(a+x) FROM t2) FROM t1;
+} {1 1}
+do_execsql_test 6.3 {
+ SELECT (SELECT COUNT(a) FROM t2) FROM t1;
+} {2}
+
finish_test
diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test
index 2334907f8..c244076c5 100644
--- a/test/fts3corrupt4.test
+++ b/test/fts3corrupt4.test
@@ -5759,25 +5759,57 @@ do_test 32.0 {
| end crash-74fdbc96edbc04.db
}]} {}
-do_execsql_test 32.1 {
+do_catchsql_test 32.1 {
UPDATE t1 SET b=quote(zeroblob(6.51158946e+5)) WHERE a MATCH '*t*';
-} {}
-
-do_catchsql_test 32.2 {
- UPDATE t1 SET b=((- '' )) WHERE a MATCH '0*t';
} {1 {database disk image is malformed}}
+#do_catchsql_test 32.2 {
+# UPDATE t1 SET b=((- '' )) WHERE a MATCH '0*t';
+#} {1 {database disk image is malformed}}
+
+#-------------------------------------------------------------------------
+#
+ifcapable icu {
+ reset_db
+ do_catchsql_test 33.0 {
+ CREATE VIRTUAL TABLE f USING fts3(a,b,tokenize=icu);
+ CREATE TABLE 'f_docsize'(docid INTEGER PRIMARY KEY, size BLOB);
+ CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
+ INSERT INTO f VALUES (1, '1234');
+ INSERT INTO f_stat VALUES (1,x'0000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003bc502fffffffffb8b2afbfb6565f0740100650000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003b8b00c5c5c5c5c5bfc5');
+ INSERT INTO f(f) VALUES ('merge=198,49');
+ } {1 {database disk image is malformed}}
+}
+
#-------------------------------------------------------------------------
#
reset_db
-do_catchsql_test 32.0 {
- CREATE VIRTUAL TABLE f USING fts3(a,b,tokenize=icu);
- CREATE TABLE 'f_docsize'(docid INTEGER PRIMARY KEY, size BLOB);
- CREATE TABLE 'f_stat'(id INTEGER PRIMARY KEY, value BLOB);
+do_execsql_test 34.0 {
+ CREATE VIRTUAL TABLE f USING fts3(a,b);
INSERT INTO f VALUES (1, '1234');
- INSERT INTO f_stat VALUES (1,x'0000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003bc502fffffffffb8b2afbfb6565f0740100650000000165656565db6569746565c5c52bc5c5c53e3a003bc502ffffffffc5c5c53e3a003b8b00c5c5c5c5c5bfc5');
- INSERT INTO f(f) VALUES ('merge=198,49');
+ INSERT INTO f_segdir VALUES (1,255,0,0,'1 255',x'00');
+ UPDATE f_segdir SET level = 0 WHERE level IN (
+ SELECT level FROM f_segdir LIMIT 1 OFFSET 1
+ );
+ INSERT INTO f_segdir VALUES (255,249,0,121,'0 0',x'00');
+ INSERT INTO f_content VALUES (255,0,x'ff');
+ INSERT INTO f_segdir VALUES (1,255,16,0,'1 255',x'00');
+}
+
+do_catchsql_test 34.1 {
+ UPDATE f SET b = x'00' WHERE b IN (SELECT b FROM f LIMIT 1 OFFSET 0);
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 35.0 {
+ CREATE VIRTUAL TABLE f USING fts3(a,b);
+ INSERT INTO f_segdir VALUES (1,255,0,0,'1 255',x'0001ff000001ff000001ff000001ff000001ff00c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5bec5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5');
+}
+
+do_catchsql_test 35.1 {
+ INSERT INTO f(f) VALUES ('integrity-check');
+} {1 {database disk image is malformed}}
finish_test
diff --git a/test/fts4langid.test b/test/fts4langid.test
index 9fffe9521..45e851f94 100644
--- a/test/fts4langid.test
+++ b/test/fts4langid.test
@@ -489,4 +489,19 @@ foreach lid [list 4 [expr 1<<30]] {
SELECT count(*) FROM t6_segments;
} {1 2}
}
+
+reset_db
+do_execsql_test 6.0 {
+ CREATE VIRTUAL TABLE vt0 USING fts4(c0, languageid="lid");
+ INSERT INTO vt0 VALUES ('a'), ('b');
+ BEGIN;
+ UPDATE vt0 SET lid = 1 WHERE lid=0;
+}
+do_execsql_test 6.1 {
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
+do_execsql_test 6.2 {
+ COMMIT;
+ INSERT INTO vt0(vt0) VALUES('integrity-check');
+}
finish_test
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index f1d2415de..4f3321f0a 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -134,6 +134,7 @@ struct Blob {
*/
static struct GlobalVars {
const char *zArgv0; /* Name of program */
+ const char *zDbFile; /* Name of database file */
VFile aFile[MX_FILE]; /* The virtual filesystem */
int nDb; /* Number of template databases */
Blob *pFirstDb; /* Content of first template database */
@@ -148,11 +149,10 @@ static struct GlobalVars {
*/
static void fatalError(const char *zFormat, ...){
va_list ap;
- if( g.zTestName[0] ){
- fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
- }else{
- fprintf(stderr, "%s: ", g.zArgv0);
- }
+ fprintf(stderr, "%s", g.zArgv0);
+ if( g.zDbFile ) fprintf(stderr, " %s", g.zDbFile);
+ if( g.zTestName[0] ) fprintf(stderr, " (%s)", g.zTestName);
+ fprintf(stderr, ": ");
va_start(ap, zFormat);
vfprintf(stderr, zFormat, ap);
va_end(ap);
@@ -161,12 +161,21 @@ static void fatalError(const char *zFormat, ...){
}
/*
-** Timeout handler
+** signal handler
*/
#ifdef __unix__
-static void timeoutHandler(int NotUsed){
- (void)NotUsed;
- fatalError("timeout\n");
+static void signalHandler(int signum){
+ const char *zSig;
+ if( signum==SIGABRT ){
+ zSig = "abort";
+ }else if( signum==SIGALRM ){
+ zSig = "timeout";
+ }else if( signum==SIGSEGV ){
+ zSig = "segfault";
+ }else{
+ zSig = "signal";
+ }
+ fatalError(zSig);
}
#endif
@@ -1311,6 +1320,7 @@ static void showHelp(void){
" --sqlid N Use only SQL where sqlid=N\n"
" --timeout N Abort if any single test needs more than N seconds\n"
" -v|--verbose Increased output. Repeat for more output.\n"
+" --vdbe-debug Activate VDBE debugging.\n"
);
}
@@ -1360,7 +1370,9 @@ int main(int argc, char **argv){
sqlite3_initialize();
iBegin = timeOfDay();
#ifdef __unix__
- signal(SIGALRM, timeoutHandler);
+ signal(SIGALRM, signalHandler);
+ signal(SIGSEGV, signalHandler);
+ signal(SIGABRT, signalHandler);
#endif
g.zArgv0 = argv[0];
openFlags4Data = SQLITE_OPEN_READONLY;
@@ -1464,6 +1476,9 @@ int main(int argc, char **argv){
fatalError("timeout is not available on non-unix systems");
#endif
}else
+ if( strcmp(z,"vdbe-debug")==0 ){
+ bVdbeDebug = 1;
+ }else
if( strcmp(z,"verbose")==0 ){
quietFlag = 0;
verboseFlag++;
@@ -1506,6 +1521,7 @@ int main(int argc, char **argv){
/* Process each source database separately */
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
+ g.zDbFile = azSrcDb[iSrcDb];
rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
openFlags4Data, pDfltVfs->zName);
if( rc ){
@@ -1809,6 +1825,9 @@ int main(int argc, char **argv){
#ifdef SQLITE_TESTCTRL_PRNG_SEED
sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);
#endif
+ if( bVdbeDebug ){
+ sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
+ }
do{
runSql(db, (char*)pSql->a, runFlags);
}while( timeoutTest );
diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db
index 820ff08a2..e103ef27e 100644
--- a/test/fuzzdata8.db
+++ b/test/fuzzdata8.db
Binary files differ
diff --git a/test/gencol1.test b/test/gencol1.test
index dbcfefe61..5276d9694 100644
--- a/test/gencol1.test
+++ b/test/gencol1.test
@@ -211,16 +211,81 @@ do_catchsql_test gencol1-6.10 {
REPLACE INTO t0(c1) VALUES(NULL);
} {1 {NOT NULL constraint failed: t0.c0}}
-# 2019-11-06 ticket b13b7dce76e9352b34e7
+# 2019-11-06 ticket https://www.sqlite.org/src/info/2399f5986134f79c
+# 2019-12-27 ticket https://www.sqlite.org/src/info/5fbc159eeb092130
+# 2019-12-27 ticket https://www.sqlite.org/src/info/37823501c68a09f9
+#
+# All of the above tickets deal with NOT NULL ON CONFLICT REPLACE
+# constraints on tables that have generated columns.
+#
+reset_db
do_execsql_test gencol1-7.10 {
- DROP TABLE IF EXISTS t0;
CREATE TABLE t0 (c0 GENERATED ALWAYS AS (1), c1 UNIQUE, c2 UNIQUE);
INSERT INTO t0(c1) VALUES (1);
SELECT quote(0 = t0.c2 OR t0.c1 BETWEEN t0.c2 AND 1) FROM t0;
} {NULL}
+do_execsql_test gencol1-7.11 {
+ DROP TABLE t0;
+ CREATE TABLE t0(c0 NOT NULL DEFAULT 'xyz', c1 AS(c0) NOT NULL);
+ REPLACE INTO t0(c0) VALUES(NULL);
+ SELECT * FROM t0;
+} {xyz xyz}
+do_execsql_test gencol1-7.12 {
+ DROP TABLE t0;
+ CREATE TABLE t0(c0 NOT NULL DEFAULT 'xyz', c1 AS(c0) STORED NOT NULL);
+ REPLACE INTO t0(c0) VALUES(NULL);
+ SELECT * FROM t0;
+} {xyz xyz}
do_execsql_test gencol1-7.20 {
- SELECT 99 FROM t0 WHERE 0 = t0.c2 OR t0.c1 BETWEEN t0.c2 AND 1;
-} {}
+ CREATE TABLE t1(
+ a NOT NULL DEFAULT 'aaa',
+ b AS(c) NOT NULL,
+ c NOT NULL DEFAULT 'ccc');
+ REPLACE INTO t1(a,c) VALUES(NULL,NULL);
+ SELECT * FROM t1;
+} {aaa ccc ccc}
+do_execsql_test gencol1-7.21 {
+ DROP TABLE t1;
+ CREATE TABLE t1(
+ a NOT NULL DEFAULT 'aaa',
+ b AS(c) STORED NOT NULL,
+ c NOT NULL DEFAULT 'ccc');
+ REPLACE INTO t1(a,c) VALUES(NULL,NULL);
+ SELECT * FROM t1;
+} {aaa ccc ccc}
+do_execsql_test gencol1-7.30 {
+ CREATE TABLE t2(
+ a NOT NULL DEFAULT 'aaa',
+ b AS(a) NOT NULL,
+ c NOT NULL DEFAULT 'ccc');
+ REPLACE INTO t2(a,c) VALUES(NULL,NULL);
+ SELECT * FROM t2;
+} {aaa aaa ccc}
+do_execsql_test gencol1-7.31 {
+ DROP TABLE t2;
+ CREATE TABLE t2(
+ a NOT NULL DEFAULT 'aaa',
+ b AS(a) STORED NOT NULL,
+ c NOT NULL DEFAULT 'ccc');
+ REPLACE INTO t2(a,c) VALUES(NULL,NULL);
+ SELECT * FROM t2;
+} {aaa aaa ccc}
+do_execsql_test gencol1-7.40 {
+ CREATE TABLE t3(a NOT NULL DEFAULT 123, b AS(a) UNIQUE);
+ REPLACE INTO t3 VALUES(NULL);
+ SELECT * FROM t3;
+} {123 123}
+do_execsql_test gencol1-7.41 {
+ SELECT * FROM t3 WHERE b=123;
+} {123 123}
+do_execsql_test gencol1-7.50 {
+ CREATE TABLE t4(a NOT NULL DEFAULT 123, b AS(a*10+4) STORED UNIQUE);
+ REPLACE INTO t4 VALUES(NULL);
+ SELECT * FROM t4;
+} {123 1234}
+do_execsql_test gencol1-7.51 {
+ SELECT * FROM t4 WHERE b=1234;
+} {123 1234}
# 2019-11-06 ticket 4fc08501f4e56692
do_execsql_test gencol1-8.10 {
@@ -245,9 +310,9 @@ do_catchsql_test gencol1-8.20 {
# 2019-11-21 Problems in the new generated column logic
# reported by Yongheng Chen and Rui Zhong
+reset_db
do_execsql_test gencol1-9.10 {
PRAGMA foreign_keys=OFF;
- DROP TABLE t1;
CREATE TABLE t1(aa , bb AS (17) UNIQUE);
INSERT INTO t1 VALUES(17);
CREATE TABLE t2(cc);
@@ -342,7 +407,7 @@ do_execsql_test gencol1-12.10 {
PRAGMA integrity_check;
} {ok}
-# 2019-12-09 but report from Yongheng Chen
+# 2019-12-09 bug report from Yongheng Chen
# Ensure that the SrcList_item.colUsed field is set correctly when a
# generated column appears in the USING clause of a join.
#
@@ -369,5 +434,130 @@ do_execsql_test gencol1-13.22 {
SELECT 456 FROM t1 JOIN t1 USING (x,x);
} {456}
+# 2019-12-14 ticket b439bfcfb7deedc6
+#
+sqlite3 db :memory:
+do_execsql_test gencol1-14.10 {
+ CREATE TABLE t0(c0 AS(1 >= 1), c1 UNIQUE AS(TYPEOF(c0)), c2);
+ INSERT INTO t0 VALUES(0);
+ REINDEX;
+ SELECT * FROM t0;
+} {1 integer 0}
+do_catchsql_test gencol1-14.10 {
+ INSERT INTO t0 VALUES(2);
+} {1 {UNIQUE constraint failed: t0.c1}}
+
+# 2019-12-14 gramfuzz1 find
+# The schema is malformed in that it has a subquery on a generated
+# column expression. This will be loaded if writable_schema=ON. SQLite
+# must not use such an expression during code generation as the code generator
+# will add bits of content to the expression tree that might be allocated
+# from lookaside. But the schema is not tied to a particular database
+# connection, so the use of lookaside memory is prohibited. The fix
+# is to change the generated column expression to NULL before adding it
+# to the schema.
+#
+reset_db
+do_test gencol1-15.10 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 8192 pagesize 4096 filename c27.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 01 00 00 00 02 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
+| 96: 00 2e 3f d8 0d 00 00 00 01 0f ba 00 0f ba 00 00 ..?.............
+| 4016: 00 00 00 00 00 00 00 00 00 00 44 01 06 17 11 11 ..........D.....
+| 4032: 01 75 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .utablet1t1.CREA
+| 4048: 54 45 20 54 41 42 4c 45 20 74 31 28 61 20 49 4e TE TABLE t1(a IN
+| 4064: 54 2c 20 62 20 41 53 28 28 56 41 4c 55 45 53 28 T, b AS((VALUES(
+| 4080: 31 29 29 20 49 53 20 75 6e 6b 6e 6f 77 6e 29 29 1)) IS unknown))
+| page 2 offset 4096
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| end c27.db
+}]} {}
+do_execsql_test gencol1-15.20 {
+ PRAGMA writable_schema=ON;
+ REPLACE INTO t1 VALUES(9);
+ SELECT a, quote(b) FROM t1
+} {9 NULL}
+
+# 2019-12-16 ticket 3b84b42943644d6f
+# When a table is the right table of a LEFT JOIN and the ON clause is
+# false, make sure any generated columns evaluate to NULL.
+reset_db
+do_execsql_test gencol1-16.10 {
+ CREATE TABLE t0(c0);
+ CREATE TABLE t1(c1, c2 AS(1));
+ INSERT INTO t0 VALUES(0);
+ SELECT c0, c1, c2 FROM t0 LEFT JOIN t1;
+} {0 {} {}}
+do_execsql_test gencol1-16.20 {
+ DROP TABLE t1;
+ CREATE TABLE t1(c1, c2 AS (c1 ISNULL));
+ SELECT c0, c1, c2 FROM t0 LEFT JOIN t1;
+} {0 {} {}}
+do_execsql_test gencol1-16.30 {
+ INSERT INTO t1(c1) VALUES(1),(NULL);
+ SELECT * FROM t1;
+} {1 0 {} 1}
+do_execsql_test gencol1-16.40 {
+ SELECT c0, c1, c2 FROM t0 LEFT JOIN t1 ON c0=c1;
+} {0 {} {}}
+
+# 2019-12-20 ticket e0a8120553f4b082
+# Generated columns with REAL affinity need to have an OP_RealAffinity
+# opcode applied, even when the column value is extracted from an index.
+#
+reset_db
+do_execsql_test gencol1-17.10 {
+ CREATE TABLE t0(c0 REAL AS(1) UNIQUE, c1 INT);
+ INSERT INTO t0 VALUES('');
+ SELECT quote(c0), quote(c1) from t0;
+} {1.0 ''}
+do_execsql_test gencol1-17.20 {
+ SELECT *, (1 BETWEEN CAST(t0.c0 AS TEXT) AND t0.c0) FROM t0;
+} {1.0 {} 0}
+do_execsql_test gencol1-17.30 {
+ SELECT * FROM t0 WHERE (1 BETWEEN CAST(t0.c0 AS TEXT) AND t0.c0);
+} {}
+do_execsql_test gencol1-17.40 {
+ CREATE TABLE t1(a TEXT AS(b) COLLATE nocase, b TEXT, c INT, d DEFAULT 1);
+ INSERT INTO t1(b,c) VALUES('abc',11),('DEF',22),('ghi',33);
+ SELECT a FROM t1 WHERE b='DEF' AND a='def';
+} {DEF}
+do_execsql_test gencol1-17.50 {
+ CREATE INDEX t1bca ON t1(b,c,a);
+ SELECT a FROM t1 WHERE b='DEF' AND a='def';
+} {DEF}
+
+# 2019-12-26 ticket ec8abb025e78f40c
+# An index on a virtual column with a constant value (why would anybody
+# ever do such a thing?) can cause problems for a one-pass DELETE.
+#
+reset_db
+do_execsql_test gencol1-18.10 {
+ CREATE TABLE t0(c0 UNIQUE AS(0), c1, c2);
+ INSERT INTO t0(c1) VALUES(0);
+ SELECT * FROM t0;
+} {0 0 {}}
+do_execsql_test gencol1-18.20 {
+ UPDATE t0 SET c1=0, c2=0 WHERE c0>=0;
+ SELECT * FROM t0;
+} {0 0 0}
+
+# 2019-12-27 ticket de4b04149b9fdeae
+#
+reset_db
+do_catchsql_test gencol1-19.10 {
+ CREATE TABLE t0(
+ c0 INT AS(2) UNIQUE,
+ c1 TEXT UNIQUE,
+ FOREIGN KEY(c0) REFERENCES t0(c1)
+ );
+ INSERT INTO t0(c1) VALUES(0.16334143182538696), (0);
+} {1 {UNIQUE constraint failed: t0.c0}}
finish_test
diff --git a/test/join.test b/test/join.test
index 19a061d46..391e0681c 100644
--- a/test/join.test
+++ b/test/join.test
@@ -975,4 +975,53 @@ do_execsql_test join-21.10 {
SELECT 24, * FROM t1 LEFT JOIN t0 ON +aa ISNULL;
} {13 1 {} 14 1 {} 23 1 {} 24 1 {}}
+# 2019-12-18 problem with a LEFT JOIN where the RHS is a view.
+# Detected by Yongheng and Rui.
+# Follows from the optimization attempt of check-in 41c27bc0ff1d3135
+# on 2017-04-18
+#
+reset_db
+do_execsql_test join-22.10 {
+ CREATE TABLE t0(a, b);
+ CREATE INDEX t0a ON t0(a);
+ INSERT INTO t0 VALUES(10,10),(10,11),(10,12);
+ SELECT DISTINCT c FROM t0 LEFT JOIN (SELECT a+1 AS c FROM t0) ORDER BY c ;
+} {11}
+
+# 2019-12-22 ticket 7929c1efb2d67e98
+#
+reset_db
+do_execsql_test join-23.10 {
+ CREATE TABLE t0(c0);
+ INSERT INTO t0(c0) VALUES(123);
+ CREATE VIEW v0(c0) AS SELECT 0 GROUP BY 1;
+ SELECT t0.c0, v0.c0, vt0.name
+ FROM v0, t0 LEFT JOIN pragma_table_info('t0') AS vt0
+ ON vt0.name LIKE 'c0'
+ WHERE v0.c0 == 0;
+} {123 0 c0}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test join-24.1 {
+ CREATE TABLE t1(a PRIMARY KEY, x);
+ CREATE TABLE t2(b INT);
+ CREATE INDEX t1aa ON t1(a, a);
+
+ INSERT INTO t1 VALUES('abc', 'def');
+ INSERT INTO t2 VALUES(1);
+}
+
+do_execsql_test join-24.2 {
+ SELECT * FROM t2 JOIN t1 WHERE a='abc' AND x='def';
+} {1 abc def}
+do_execsql_test join-24.3 {
+ SELECT * FROM t2 JOIN t1 WHERE a='abc' AND x='abc';
+} {}
+
+do_execsql_test join-24.2 {
+ SELECT * FROM t2 LEFT JOIN t1 ON a=0 WHERE (x='x' OR x IS NULL);
+} {1 {} {}}
+
finish_test
+
diff --git a/test/join2.test b/test/join2.test
index 5a70573e0..bfcecda29 100644
--- a/test/join2.test
+++ b/test/join2.test
@@ -279,5 +279,19 @@ do_execsql_test 7.0 {
SELECT * FROM test;
} {3 4 {} {} {} x 5 6 {} {} {} x}
+#-------------------------------------------------------------------------
+# Ticket [dfd66334].
+#
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE t0(c0);
+ CREATE TABLE t1(c0);
+}
+
+do_execsql_test 8.1 {
+ SELECT * FROM t0 LEFT JOIN t1
+ WHERE (t1.c0 BETWEEN 0 AND 0) > ('' AND t0.c0);
+}
+
finish_test
diff --git a/test/nulls1.test b/test/nulls1.test
index fb059a674..9f4402f91 100644
--- a/test/nulls1.test
+++ b/test/nulls1.test
@@ -248,4 +248,54 @@ do_execsql_test 7.0 {
SELECT * FROM t71 ORDER BY a DESC NULLS FIRST;
}
+# 2019-12-18 gramfuzz1 find
+# NULLS LAST not allows on an INTEGER PRIMARY KEY.
+#
+do_catchsql_test 8.0 {
+ CREATE TABLE t80(a, b INTEGER, PRIMARY KEY(b NULLS LAST)) WITHOUT ROWID;
+} {1 {unsupported use of NULLS LAST}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 9.0 {
+ CREATE TABLE v0 (c1, c2, c3);
+ CREATE INDEX v3 ON v0 (c1, c2, c3);
+}
+do_execsql_test 9.1 {
+ ANALYZE sqlite_master;
+ INSERT INTO sqlite_stat1 VALUES('v0','v3','648 324 81');
+ ANALYZE sqlite_master;
+}
+
+do_execsql_test 9.2 {
+ INSERT INTO v0 VALUES
+ (1, 10, 'b'),
+ (1, 10, 'd'),
+ (1, 10, NULL),
+ (2, 10, 'a'),
+ (2, 10, NULL),
+ (1, 10, 'c'),
+ (2, 10, 'b'),
+ (1, 10, 'a'),
+ (1, 10, NULL),
+ (2, 10, NULL),
+ (2, 10, 'd'),
+ (2, 10, 'c');
+}
+
+do_execsql_test 9.3 {
+ SELECT c1, c2, ifnull(c3, 'NULL') FROM v0
+ WHERE c2=10 ORDER BY c1, c3 NULLS LAST
+} {
+ 1 10 a 1 10 b 1 10 c 1 10 d 1 10 NULL 1 10 NULL
+ 2 10 a 2 10 b 2 10 c 2 10 d 2 10 NULL 2 10 NULL
+}
+
+do_eqp_test 9.4 {
+ SELECT c1, c2, ifnull(c3, 'NULL') FROM v0
+ WHERE c2=10 ORDER BY c1, c3 NULLS LAST
+} {SEARCH TABLE v0 USING COVERING INDEX v3 (ANY(c1) AND c2=?)}
+
+
+
finish_test
diff --git a/test/pragma3.test b/test/pragma3.test
index eebbcbb9c..c4794c743 100644
--- a/test/pragma3.test
+++ b/test/pragma3.test
@@ -255,4 +255,33 @@ if {[permutation]!="inmemory_journal"} {
}
}
+#-------------------------------------------------------------------------
+# Check that empty write transactions do not cause the return of "PRAGMA
+# data_version" to be decremented with journal_mode=PERSIST and
+# locking_mode=EXCLUSIVE
+#
+foreach {tn sql} {
+ A {
+ }
+ B {
+ PRAGMA journal_mode = PERSIST;
+ PRAGMA locking_mode = EXCLUSIVE;
+ }
+} {
+ reset_db
+ execsql $sql
+
+ do_execsql_test pragma3-510$tn {
+ CREATE TABLE t1(x, y);
+ INSERT INTO t1 VALUES(1, 2);
+ PRAGMA data_version;
+ } {1}
+
+ do_execsql_test pragma3-520$tn {
+ BEGIN EXCLUSIVE;
+ COMMIT;
+ PRAGMA data_version;
+ } {1}
+}
+
finish_test
diff --git a/test/rowvalue.test b/test/rowvalue.test
index f0a32b18c..e3b66a109 100644
--- a/test/rowvalue.test
+++ b/test/rowvalue.test
@@ -636,7 +636,12 @@ do_execsql_test 26.30 {
SELECT 3 FROM t1 LEFT JOIN t0 WHERE (c0, x'') != (NULL, 0);
} {3}
-
-
+# 2019-12-30 ticket 892575cdba4e1e36
+#
+reset_db
+do_catchsql_test 27.10 {
+ CREATE TABLE t0(c0 CHECK(((0, 0) > (0, c0))));
+ INSERT INTO t0(c0) VALUES(0) ON CONFLICT(c0) DO UPDATE SET c0 = 3;
+} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
finish_test
diff --git a/test/select1.test b/test/select1.test
index 27191caf6..47dcd0fe4 100644
--- a/test/select1.test
+++ b/test/select1.test
@@ -1165,4 +1165,24 @@ do_execsql_test select1-18.4 {
);
} {1}
+# 2019-12-17 gramfuzz find
+#
+do_execsql_test select-19.10 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(x);
+} {}
+do_catchsql_test select-19.20 {
+ INSERT INTO t1
+ SELECT 1,2,3,4,5,6,7
+ UNION ALL SELECT 1,2,3,4,5,6,7
+ ORDER BY 1;
+} {1 {table t1 has 1 columns but 7 values were supplied}}
+do_catchsql_test select-19.21 {
+ INSERT INTO t1
+ SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ UNION ALL SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ ORDER BY 1;
+} {1 {table t1 has 1 columns but 15 values were supplied}}
+
+
finish_test
diff --git a/test/update.test b/test/update.test
index 76aba65cd..dd96124b4 100644
--- a/test/update.test
+++ b/test/update.test
@@ -656,6 +656,78 @@ do_execsql_test update-17.10 {
SELECT * FROM t1;
} {2 3}
+# 2019-12-22 ticket 5ad2aa6921faa1ee
+# Make a hard-copy of values that need to be run through OP_RealAffinity
+# rather than a soft-copy. This is not strictly necessary, but it avoids
+# a memory-accounting assert().
+#
+reset_db
+do_execsql_test update-18.10 {
+ PRAGMA encoding = 'UTF16';
+ CREATE TABLE t0(c0 REAL, c1);
+ INSERT INTO t0(c0,c1) VALUES('xyz',11),('uvw',22);
+ CREATE INDEX i0 ON t0(c1) WHERE c0 GLOB 3;
+ CREATE INDEX i1 ON t0(c0,c1) WHERE typeof(c0)='text' AND typeof(c1)='integer';
+ UPDATE t0 SET c1=345;
+ SELECT * FROM t0;
+} {xyz 345 uvw 345}
+
+# 2019-12-22 ticket c62c5e58524b204d
+# This is really the same underlying problem as 5ad2aa6921faa1ee
+#
+reset_db
+do_execsql_test update-18.20 {
+ PRAGMA encoding = 'utf16';
+ CREATE TABLE t0(c0 TEXT);
+ CREATE INDEX i0 ON t0(0 LIKE COALESCE(c0, 0));
+ INSERT INTO t0(c0) VALUES (0), (0);
+ SELECT * FROM t0;
+} {0 0}
+
+# 2019-12-28 assertion fault reported by Yongheng
+# Similar to ticket ec8abb025e78f40c
+# An UPDATE was reaching the OP_Delete after running OP_DeferredSeek
+# without ever hitting an OP_Column. The enhanced solution is to
+# fix OP_Delete so that it can do the seek itself.
+#
+reset_db
+do_execsql_test update-19.10 {
+ CREATE TABLE t1(
+ a TEXT,
+ b INTEGER PRIMARY KEY UNIQUE
+ );
+ INSERT INTO t1 VALUES(1,2);
+ UPDATE t1 SET a = quote(b) WHERE b>=2;
+ SELECT * FROM t1;
+} {2 2}
+# 2019-12-29 ticket https://www.sqlite.org/src/info/314cc133e5ada126
+# REPLACE conflict resolution during an UPDATE causes a DELETE trigger
+# to fire. If that DELETE trigger subsequently modifies the row
+# being updated, bad things can happen. Prevent this by prohibiting
+# triggers from making changes to the table being updated while doing
+# REPLACE conflict resolution on the UPDATE.
+#
+# See also tickets:
+# https://www.sqlite.org/src/info/c1e19e12046d23fe 2019-10-25
+# https://www.sqlite.org/src/info/a8a4847a2d96f5de 2019-10-16
+#
+reset_db
+do_execsql_test update-20.10 {
+ PRAGMA recursive_triggers = true;
+ CREATE TABLE t1(a UNIQUE ON CONFLICT REPLACE, b);
+ INSERT INTO t1(a,b) VALUES(4,12),(9,13);
+ CREATE INDEX i0 ON t1(b);
+ CREATE TRIGGER tr0 DELETE ON t1 BEGIN
+ UPDATE t1 SET b = a;
+ END;
+ PRAGMA integrity_check;
+} {ok}
+do_catchsql_test update-20.20 {
+ UPDATE t1 SET a=0;
+} {1 {constraint failed}}
+do_execsql_test update-20.30 {
+ PRAGMA integrity_check;
+} {ok}
finish_test
diff --git a/test/upsert1.test b/test/upsert1.test
index 6b5be23b7..5250a5d2f 100644
--- a/test/upsert1.test
+++ b/test/upsert1.test
@@ -233,4 +233,12 @@ do_catchsql_test upsert1-910 {
INSERT INTO t1 VALUES(3) ON CONFLICT(x) DO NOTHING;
} {1 {cannot UPSERT a view}}
+# 2019-12-26 ticket 7c13db5c3bf74001
+reset_db
+do_catchsql_test upsert1-1000 {
+ CREATE TABLE t0(c0 PRIMARY KEY, c1, c2 UNIQUE) WITHOUT ROWID;
+ INSERT OR FAIL INTO t0(c2) VALUES (0), (NULL)
+ ON CONFLICT(c2) DO UPDATE SET c1 = c0;
+} {1 {NOT NULL constraint failed: t0.c0}}
+
finish_test
diff --git a/test/whereG.test b/test/whereG.test
index 595de116a..9d4cde7b4 100644
--- a/test/whereG.test
+++ b/test/whereG.test
@@ -306,7 +306,15 @@ do_execsql_test 8.10 {
SELECT * FROM t0 WHERE likelihood(t0.rowid <= '0', 0.5);
} {}
-
-
+# 2019-12-31: assertion fault discovered by Yongheng's fuzzer.
+# Harmless memIsValid() due to the code generators failure to
+# release the registers used by OP_ResultRow.
+#
+do_execsql_test 9.10 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a, b FLOAT);
+ INSERT INTO t1(a) VALUES(''),(NULL),('X'),(NULL);
+ SELECT coalesce(max(quote(a)),10) FROM t1 GROUP BY a;
+} {NULL '' 'X'}
finish_test
diff --git a/test/window1.test b/test/window1.test
index b4542891b..0b7884784 100644
--- a/test/window1.test
+++ b/test/window1.test
@@ -1314,5 +1314,221 @@ do_execsql_test 36.40 {
VALUES(2),(3),(count(*)OVER()),(4),(5);
} {2 3 1 4 5}
+# 2019-12-17 crash test case found by Yongheng and Rui
+# See check-in 1ca0bd982ab1183b
+#
+reset_db
+do_execsql_test 37.10 {
+ CREATE TABLE t0(a UNIQUE, b PRIMARY KEY);
+ CREATE VIEW v0(c) AS SELECT max((SELECT count(a)OVER(ORDER BY 1))) FROM t0;
+ SELECT c FROM v0 WHERE c BETWEEN 10 AND 20;
+} {}
+do_execsql_test 37.20 {
+ DROP VIEW v0;
+ CREATE VIEW v0(c) AS SELECT max((SELECT count(a)OVER(ORDER BY 1234))) FROM t0;
+ SELECT c FROM v0 WHERE c BETWEEN -10 AND 20;
+} {}
+
+# 2019-12-20 mrigger reported problem with a FILTER clause on an aggregate
+# in a join.
+#
+reset_db
+do_catchsql_test 38.10 {
+ CREATE TABLE t0(c0);
+ CREATE TABLE t1(c0, c1 UNIQUE);
+ INSERT INTO t0(c0) VALUES(1);
+ INSERT INTO t1(c0,c1) VALUES(2,3);
+ SELECT COUNT(*) FROM t0, t1 WHERE (SELECT AVG(0) FILTER(WHERE t1.c1));
+} {1 {misuse of aggregate: AVG()}}
+do_execsql_test 38.20 {
+ SELECT COUNT(*), AVG(1) FILTER(WHERE t1.c1) FROM t0, t1;
+} {1 1.0}
+do_catchsql_test 38.30 {
+ SELECT COUNT(*) FROM t0, t1 WHERE (SELECT AVG(1) FILTER(WHERE t1.c1));
+} {1 {misuse of aggregate: AVG()}}
+
+reset_db
+do_execsql_test 39.1 {
+ CREATE TABLE t0(c0 UNIQUE);
+}
+do_execsql_test 39.2 {
+ SELECT FIRST_VALUE(0) OVER();
+} {0}
+do_execsql_test 39.3 {
+ SELECT * FROM t0 WHERE(c0, 0) IN(SELECT FIRST_VALUE(0) OVER(), 0);
+}
+do_execsql_test 39.4 {
+ SELECT * FROM t0 WHERE (t0.c0, 1) IN(SELECT NTILE(1) OVER(), 0 FROM t0);
+}
+
+ifcapable rtree {
+ # 2019-12-25 ticket d87336c81c7d0873
+ #
+ reset_db
+ do_catchsql_test 40.1 {
+ CREATE VIRTUAL TABLE t0 USING rtree(c0, c1, c2);
+ SELECT * FROM t0
+ WHERE ((0,0) IN (SELECT COUNT(*),LAG(5)OVER(PARTITION BY 0) FROM t0),0)<=(c1,0);
+ } {0 {}}
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 41.1 {
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(NULL,'bb',355);
+ INSERT INTO t1 VALUES('CC','aa',158);
+ INSERT INTO t1 VALUES('GG','bb',929);
+ INSERT INTO t1 VALUES('FF','Rb',574);
+}
+
+do_execsql_test 41.2 {
+ SELECT min(c) OVER (
+ ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
+ ) FROM t1
+} {355 158 574 929}
+
+do_execsql_test 41.2 {
+ SELECT min(c) OVER (
+ ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
+ ) << 100 FROM t1
+} {0 0 0 0}
+
+do_execsql_test 41.3 {
+ SELECT
+ min(c) OVER win3 << first_value(c) OVER win3,
+ min(c) OVER win3 << first_value(c) OVER win3
+ FROM t1
+ WINDOW win3 AS (
+ PARTITION BY 6 ORDER BY a RANGE BETWEEN 5.2 PRECEDING AND 0.1 PRECEDING
+ );
+} {0 0 0 0 0 0 0 0}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 42.1 {
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(2, 2, 2);
+}
+do_execsql_test 42.2 {
+ SELECT * FROM t1 WHERE (0, 0) IN ( SELECT count(*), 0 FROM t1 )
+} {}
+do_execsql_test 42.3 {
+ SELECT * FROM t1 WHERE (2, 0) IN ( SELECT count(*), 0 FROM t1 )
+} {1 1 1 2 2 2}
+
+do_execsql_test 42.3 {
+ SELECT count(*), max(a) OVER () FROM t1 GROUP BY c;
+} {1 2 1 2}
+
+do_execsql_test 42.4 {
+ SELECT sum(a), max(b) OVER () FROM t1;
+} {3 1}
+
+do_execsql_test 42.5 {
+ CREATE TABLE t2(a, b);
+ INSERT INTO t2 VALUES('a', 1);
+ INSERT INTO t2 VALUES('a', 2);
+ INSERT INTO t2 VALUES('a', 3);
+ INSERT INTO t2 VALUES('b', 4);
+ INSERT INTO t2 VALUES('b', 5);
+ INSERT INTO t2 VALUES('b', 6);
+}
+
+do_execsql_test 42.6 {
+ SELECT a, sum(b), sum( sum(b) ) OVER (ORDER BY a) FROM t2 GROUP BY a;
+} {a 6 6 b 15 21}
+
+do_execsql_test 42.7 {
+ SELECT sum(b), sum( sum(b) ) OVER (ORDER BY a) FROM t2;
+} {21 21}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 43.1.1 {
+ CREATE TABLE t1(x INTEGER PRIMARY KEY);
+ INSERT INTO t1 VALUES (10);
+}
+do_catchsql_test 43.1.2 {
+ SELECT count() OVER() AS m FROM t1 ORDER BY (SELECT m);
+} {1 {misuse of aliased window function m}}
+
+reset_db
+do_execsql_test 43.2.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);
+ INSERT INTO t1(a, b) VALUES(1, 10); -- 10
+ INSERT INTO t1(a, b) VALUES(2, 15); -- 25
+ INSERT INTO t1(a, b) VALUES(3, -5); -- 20
+ INSERT INTO t1(a, b) VALUES(4, -5); -- 15
+ INSERT INTO t1(a, b) VALUES(5, 20); -- 35
+ INSERT INTO t1(a, b) VALUES(6, -11); -- 24
+}
+
+do_execsql_test 43.2.2 {
+ SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY 2
+} {
+ 1 10 4 15 3 20 6 24 2 25 5 35
+}
+
+do_execsql_test 43.2.3 {
+ SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY abc
+} {
+ 1 10 4 15 3 20 6 24 2 25 5 35
+}
+
+do_execsql_test 43.2.4 {
+ SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY abc+5
+} {
+ 1 10 4 15 3 20 6 24 2 25 5 35
+}
+
+do_catchsql_test 43.2.5 {
+ SELECT a, sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY (SELECT abc)
+} {1 {misuse of aliased window function abc}}
+
+do_catchsql_test 43.2.6 {
+ SELECT a, 1+sum(b) OVER (ORDER BY a) AS abc FROM t1 ORDER BY (SELECT abc)
+} {1 {misuse of aliased window function abc}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 44.1 {
+ CREATE TABLE t0(c0);
+}
+
+do_catchsql_test 44.2.1 {
+ SELECT ntile(0) OVER ();
+} {1 {argument of ntile must be a positive integer}}
+do_catchsql_test 44.2.2 {
+ SELECT (0, 0) IN(SELECT MIN(c0), NTILE(0) OVER()) FROM t0;
+} {1 {argument of ntile must be a positive integer}}
+
+do_execsql_test 44.3.1 {
+ SELECT ntile(1) OVER ();
+} {1}
+do_execsql_test 44.3.2 {
+ SELECT (0, 0) IN(SELECT MIN(c0), NTILE(1) OVER()) FROM t0;
+} {0}
+
+do_execsql_test 44.4.2 {
+ INSERT INTO t0 VALUES(2), (1), (0);
+ SELECT (0, 1) IN(SELECT MIN(c0), NTILE(1) OVER()) FROM t0;
+} {1}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 45.1 {
+ CREATE TABLE t0(x);
+ CREATE TABLE t1(a);
+ INSERT INTO t1 VALUES(1000);
+ INSERT INTO t1 VALUES(1000);
+ INSERT INTO t0 VALUES(10000);
+}
+do_execsql_test 45.2 {
+ SELECT * FROM (
+ SELECT sum (a) OVER() FROM t1 UNION ALL SELECT x FROM t0
+ );
+} {2000 2000 10000}
finish_test
diff --git a/test/window2.tcl b/test/window2.tcl
index 5edc53680..4c18b7970 100644
--- a/test/window2.tcl
+++ b/test/window2.tcl
@@ -448,6 +448,47 @@ execsql_float_test 5.1 {
SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;
}
+==========
+
+execsql_test 6.0 {
+ DROP TABLE IF EXISTS t0;
+ CREATE TABLE t0(c0 INTEGER UNIQUE);
+ INSERT INTO t0 VALUES(0);
+}
+execsql_test 6.1 {
+ SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
+}
+execsql_test 6.2 {
+ SELECT * FROM t0 WHERE
+ (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
+}
+
+==========
+
+execsql_test 7.0 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER);
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(1, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3);
+ INSERT INTO t1 VALUES(3, 4, 4);
+}
+
+execsql_test 7.1 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (ORDER BY b)
+}
+
+execsql_test 7.2 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (PARTITION BY 1 ORDER BY b)
+}
+
+execsql_test 7.3 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (ORDER BY 1)
+}
+
finish_test
diff --git a/test/window2.test b/test/window2.test
index 5f028eb72..e241d5964 100644
--- a/test/window2.test
+++ b/test/window2.test
@@ -930,4 +930,47 @@ do_test 5.1 {
set {} {}
} {}
+#==========================================================================
+
+do_execsql_test 6.0 {
+ DROP TABLE IF EXISTS t0;
+ CREATE TABLE t0(c0 INTEGER UNIQUE);
+ INSERT INTO t0 VALUES(0);
+} {}
+
+do_execsql_test 6.1 {
+ SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
+} {1 {}}
+
+do_execsql_test 6.2 {
+ SELECT * FROM t0 WHERE
+ (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
+} {}
+
+#==========================================================================
+
+do_execsql_test 7.0 {
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1(a INTEGER, b INTEGER, c INTEGER);
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(1, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3);
+ INSERT INTO t1 VALUES(3, 4, 4);
+} {}
+
+do_execsql_test 7.1 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (ORDER BY b)
+} {1 1 2 3 3 6 4 10}
+
+do_execsql_test 7.2 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (PARTITION BY 1 ORDER BY b)
+} {1 1 2 3 3 6 4 10}
+
+do_execsql_test 7.3 {
+ SELECT c, sum(c) OVER win1 FROM t1
+ WINDOW win1 AS (ORDER BY 1)
+} {1 10 2 10 3 10 4 10}
+
finish_test
diff --git a/test/windowfault.test b/test/windowfault.test
index e037c467b..e97544f4c 100644
--- a/test/windowfault.test
+++ b/test/windowfault.test
@@ -230,7 +230,7 @@ do_execsql_test 10.0 {
CREATE TABLE t2(a, b, c, d);
}
-do_faultsim_test 1 -faults oom* -prep {
+do_faultsim_test 10 -faults oom* -prep {
} -body {
execsql {
SELECT row_number() OVER win
@@ -246,4 +246,21 @@ do_faultsim_test 1 -faults oom* -prep {
faultsim_test_result {0 {}}
}
+reset_db
+do_execsql_test 11.0 {
+ DROP TABLE IF EXISTS t0;
+ CREATE TABLE t0(c0 INTEGER UNIQUE);
+ INSERT INTO t0 VALUES(0);
+} {}
+
+do_faultsim_test 11 -faults oom* -prep {
+} -body {
+ execsql {
+ SELECT * FROM t0 WHERE
+ (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
finish_test
diff --git a/test/zipfile.test b/test/zipfile.test
index 2bab066df..6ea9ac6a0 100644
--- a/test/zipfile.test
+++ b/test/zipfile.test
@@ -795,4 +795,45 @@ if {$tcl_platform(platform)!="windows"} {
} {. ./x1.txt ./x2.txt}
}
+# 2019-12-18 Yongheng and Rui fuzzer
+#
+do_execsql_test 13.10 {
+ DROP TABLE IF EXISTS t0;
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t0(a,b,c,d,e,f,g);
+ REPLACE INTO t0(c,b,f) VALUES(10,10,10);
+ CREATE VIRTUAL TABLE t1 USING zipfile('h.zip');
+ REPLACE INTO t1 SELECT * FROM t0;
+ SELECT quote(name),quote(mode),quote(mtime),quote(sz),quote(rawdata),
+ quote(data),quote(method) FROM t1;
+} {'' 10 10 2 X'3130' X'3130' 0}
+
+# 2019-12-23 Yongheng and Rui fuzzer
+# Run using valgrind to see the problem.
+#
+do_execsql_test 14.10 {
+ DROP TABLE t1;
+ CREATE TABLE t1(x char);
+ INSERT INTO t1(x) VALUES('1');
+ INSERT INTO t1(x) SELECT zipfile(x, 'xyz') FROM t1;
+ INSERT INTO t1(x) SELECT zipfile(x, 'uvw') FROM t1;
+ SELECT count(*) FROM t1;
+ PRAGMA integrity_check;
+} {3 ok}
+
+# 2019-12-26 More problems in zipfile from the Yongheng and Rui fuzzer
+#
+do_execsql_test 15.10 {
+ DROP TABLE IF EXISTS t1;
+ CREATE VIRTUAL TABLE t1 USING zipfile(null);
+ REPLACE INTO t1 VALUES(null,null,0,null,null,null,null);
+} {}
+do_execsql_test 15.20 {
+ DROP TABLE IF EXISTS t2;
+ CREATE VIRTUAL TABLE t2 USING zipfile(null);
+ REPLACE INTO t2 values(null,null,null,null,null,10,null);
+} {}
+
+
+
finish_test
diff --git a/tool/lemon.c b/tool/lemon.c
index 0e717e1af..8dcf65179 100644
--- a/tool/lemon.c
+++ b/tool/lemon.c
@@ -4222,7 +4222,8 @@ void ReportTable(
fprintf(sql,
"CREATE TABLE rule(\n"
" ruleid INTEGER PRIMARY KEY,\n"
- " lhs INTEGER REFERENCES symbol(id)\n"
+ " lhs INTEGER REFERENCES symbol(id),\n"
+ " txt TEXT\n"
");\n"
"CREATE TABLE rulerhs(\n"
" ruleid INTEGER REFERENCES rule(ruleid),\n"
@@ -4232,13 +4233,12 @@ void ReportTable(
);
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
assert( i==rp->iRule );
- fprintf(sql, "-- ");
- writeRuleText(sql, rp);
- fprintf(sql, "\n");
fprintf(sql,
- "INSERT INTO rule(ruleid,lhs)VALUES(%d,%d);\n",
+ "INSERT INTO rule(ruleid,lhs,txt)VALUES(%d,%d,'",
rp->iRule, rp->lhs->index
);
+ writeRuleText(sql, rp);
+ fprintf(sql,"');\n");
for(j=0; j<rp->nrhs; j++){
struct symbol *sp = rp->rhs[j];
if( sp->type!=MULTITERMINAL ){
diff --git a/tool/mkmsvcmin.tcl b/tool/mkmsvcmin.tcl
index 764641fae..ef948a05c 100644
--- a/tool/mkmsvcmin.tcl
+++ b/tool/mkmsvcmin.tcl
@@ -83,7 +83,7 @@ Replace.exe:
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \\
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
+ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
| sort >> sqlite3.def
}]]