From 84ecc5f798589a0592294b5b7e295d3df93a4236 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Mon, 8 Mar 2021 10:21:02 -0500
Subject: [PATCH 001/340] remove use of += in configure per issue #382
---
configure | 16 ++++++++--------
configure.ac | 16 ++++++++--------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/configure b/configure
index 55102b042..b152d3abd 100755
--- a/configure
+++ b/configure
@@ -11997,14 +11997,14 @@ if test "$crypto_lib" = "none"; then
$as_echo "none" >&6; }
else
if test "$crypto_lib" = "commoncrypto"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_CC"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_CC"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_CC"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: commoncrypto" >&5
$as_echo "commoncrypto" >&6; }
else
if test "$crypto_lib" = "libtomcrypt"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: libtomcrypt" >&5
$as_echo "libtomcrypt" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for register_cipher in -ltomcrypt" >&5
@@ -12056,8 +12056,8 @@ fi
else
if test "$crypto_lib" = "nss"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_NSS"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_NSS"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_NSS"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_NSS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: nss3" >&5
$as_echo "nss3" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PK11_Decrypt in -lnss3" >&5
@@ -12108,8 +12108,8 @@ else
fi
else
- CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_OPENSSL"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_OPENSSL"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: openssl" >&5
$as_echo "openssl" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_Init_ex in -lcrypto" >&5
diff --git a/configure.ac b/configure.ac
index ef212983a..b55c93516 100644
--- a/configure.ac
+++ b/configure.ac
@@ -203,26 +203,26 @@ if test "$crypto_lib" = "none"; then
AC_MSG_RESULT([none])
else
if test "$crypto_lib" = "commoncrypto"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_CC"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_CC"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_CC"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_CC"
AC_MSG_RESULT([commoncrypto])
else
if test "$crypto_lib" = "libtomcrypt"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_LIBTOMCRYPT"
AC_MSG_RESULT([libtomcrypt])
AC_CHECK_LIB([tomcrypt], [register_cipher], ,
AC_MSG_ERROR([Library crypto not found. Install libtomcrypt!"]))
else
if test "$crypto_lib" = "nss"; then
- CFLAGS+=" -DSQLCIPHER_CRYPTO_NSS"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_NSS"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_NSS"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_NSS"
AC_MSG_RESULT([nss3])
AC_CHECK_LIB([nss3], [PK11_Decrypt], ,
AC_MSG_ERROR([Library crypto not found. Install nss!"]))
else
- CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL"
- BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL"
+ CFLAGS="$CFLAGS -DSQLCIPHER_CRYPTO_OPENSSL"
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLCIPHER_CRYPTO_OPENSSL"
AC_MSG_RESULT([openssl])
AC_CHECK_LIB([crypto], [HMAC_Init_ex], ,
AC_MSG_ERROR([Library crypto not found. Install openssl!"]))
From 20c087553300d3c92b9dd398f3c21dec30a2fa3c Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Tue, 16 Mar 2021 11:07:32 -0400
Subject: [PATCH 002/340] fix build when OMIT_MEMLOCK defined per #384
---
src/crypto_impl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/crypto_impl.c b/src/crypto_impl.c
index c7214ed54..0baff69d3 100644
--- a/src/crypto_impl.c
+++ b/src/crypto_impl.c
@@ -35,10 +35,10 @@
#include "crypto.h"
#ifndef OMIT_MEMLOCK
#if defined(__unix__) || defined(__APPLE__) || defined(_AIX)
-#include
-#include
-#include
-#include
+#include /* amalgamator: dontcache */
+#include /* amalgamator: dontcache */
+#include /* amalgamator: dontcache */
+#include /* amalgamator: dontcache */
#elif defined(_WIN32)
#include
#endif
From a646b5ceddbd487f9a1ff49496ce264d59bcbda8 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Tue, 16 Mar 2021 11:29:10 -0400
Subject: [PATCH 003/340] restores usage note on sqlite3_rekey behavior for
#301 and #383
---
src/sqlite.h.in | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index c69a0e894..9b959e22d 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -5976,6 +5976,19 @@ int sqlite3_key_v2(
** The code to implement this API is not available in the public release
** of SQLite.
*/
+/* SQLCipher usage note:
+
+ If the current database is plaintext SQLCipher will NOT encrypt it.
+ If the current database is encrypted and pNew==0 or nNew==0, SQLCipher
+ will NOT decrypt it.
+
+ This routine will ONLY work on an already encrypted database in order
+ to change the key.
+
+ Conversion from plaintext-to-encrypted or encrypted-to-plaintext should
+ use an ATTACHed database and the sqlcipher_export() convenience function
+ as per the SQLCipher Documentation.
+*/
int sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
From 3399ace24662a076353932b8c2b1f168ebf4bf42 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Mon, 2 Aug 2021 16:49:37 -0400
Subject: [PATCH 004/340] add new amalgamation_line_macros option missing from
configure.ac
---
configure | 25 ++++++++++++++++++++++++-
configure.ac | 18 ++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index b152d3abd..c6167ed83 100755
--- a/configure
+++ b/configure
@@ -634,6 +634,8 @@ BUILD_CFLAGS
USE_GCOV
OPT_FEATURE_FLAGS
HAVE_ZLIB
+AMALGAMATION_LINE_MACROS
+amalgamation_line_macros
USE_AMALGAMATION
TARGET_DEBUG
TARGET_HAVE_EDITLINE
@@ -797,7 +799,8 @@ LIBS
CPPFLAGS
LT_SYS_LIBRARY_PATH
CPP
-TCLLIBDIR'
+TCLLIBDIR
+amalgamation_line_macros'
# Initialize some variables set by options.
@@ -1484,6 +1487,8 @@ Some influential environment variables:
User-defined run-time library search path.
CPP C preprocessor
TCLLIBDIR Where to install tcl plugin
+ amalgamation_line_macros
+
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -12873,6 +12878,24 @@ if test "${enable_amalgamation}" = "no" ; then
fi
+#########
+# By default, amalgamation sqlite3.c will have #line directives.
+# This is a build option not shown by ./configure --help
+# To control it, use configure option: amalgamation_line_macros=?
+# where ? is no to suppress #line directives or yes to create them.
+AMALGAMATION_LINE_MACROS=--linemacros=1
+
+
+if test "${amalgamation_line_macros+set}" = set; then :
+ enableval=$amalgamation_line_macros;
+fi
+if test "${amalgamation_line_macros}" = "yes" ; then
+ AMALGAMATION_LINE_MACROS=--linemacros=1
+fi
+if test "${amalgamation_line_macros}" = "no" ; then
+ AMALGAMATION_LINE_MACROS=--linemacros=0
+fi
+
#########
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
for ac_header in zlib.h
diff --git a/configure.ac b/configure.ac
index b55c93516..31ca12310 100644
--- a/configure.ac
+++ b/configure.ac
@@ -624,6 +624,24 @@ if test "${enable_amalgamation}" = "no" ; then
fi
AC_SUBST(USE_AMALGAMATION)
+#########
+# By default, amalgamation sqlite3.c will have #line directives.
+# This is a build option not shown by ./configure --help
+# To control it, use configure option: amalgamation_line_macros=?
+# where ? is no to suppress #line directives or yes to create them.
+AMALGAMATION_LINE_MACROS=--linemacros=1
+AC_ARG_VAR(amalgamation_line_macros,)
+AC_SUBST(AMALGAMATION_LINE_MACROS)
+if test "${amalgamation_line_macros+set}" = set; then :
+ enableval=$amalgamation_line_macros;
+fi
+if test "${amalgamation_line_macros}" = "yes" ; then
+ AMALGAMATION_LINE_MACROS=--linemacros=1
+fi
+if test "${amalgamation_line_macros}" = "no" ; then
+ AMALGAMATION_LINE_MACROS=--linemacros=0
+fi
+
#########
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
AC_CHECK_HEADERS(zlib.h)
From 5db049f916832d8b527145fd1de77211adce0d89 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Tue, 7 Sep 2021 13:53:53 -0400
Subject: [PATCH 005/340] alter realloc logic to allocate and lock new segment
with memory security on
---
src/crypto_impl.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/crypto_impl.c b/src/crypto_impl.c
index 0baff69d3..cf06cf61d 100644
--- a/src/crypto_impl.c
+++ b/src/crypto_impl.c
@@ -95,8 +95,20 @@ static void sqlcipher_mem_free(void *p) {
default_mem_methods.xFree(p);
}
static void *sqlcipher_mem_realloc(void *p, int n) {
- return default_mem_methods.xRealloc(p, n);
+ void *new = NULL;
+ if(mem_security_on) {
+ new = sqlcipher_mem_malloc(n);
+ if(new == NULL) {
+ return NULL;
+ }
+ memcpy(new, p, n);
+ sqlcipher_mem_free(p);
+ return new;
+ } else {
+ return default_mem_methods.xRealloc(p, n);
+ }
}
+
static int sqlcipher_mem_roundup(int n) {
return default_mem_methods.xRoundup(n);
}
From 7b54c31180e837d1feb99e78d33fee65904a8c7b Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Wed, 8 Sep 2021 10:20:23 -0400
Subject: [PATCH 006/340] fix and expand sqlcipher_mem_realloc implementation
---
src/crypto_impl.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/crypto_impl.c b/src/crypto_impl.c
index cf06cf61d..f20d1101c 100644
--- a/src/crypto_impl.c
+++ b/src/crypto_impl.c
@@ -96,14 +96,24 @@ static void sqlcipher_mem_free(void *p) {
}
static void *sqlcipher_mem_realloc(void *p, int n) {
void *new = NULL;
+ int orig_sz = 0;
if(mem_security_on) {
- new = sqlcipher_mem_malloc(n);
- if(new == NULL) {
+ orig_sz = sqlcipher_mem_size(p);
+ if (n==0) {
+ sqlcipher_mem_free(p);
return NULL;
+ } else if (!p) {
+ return sqlcipher_mem_malloc(n);
+ } else if(n <= orig_sz) {
+ return p;
+ } else {
+ new = sqlcipher_mem_malloc(n);
+ if(new) {
+ memcpy(new, p, orig_sz);
+ sqlcipher_mem_free(p);
+ }
+ return new;
}
- memcpy(new, p, n);
- sqlcipher_mem_free(p);
- return new;
} else {
return default_mem_methods.xRealloc(p, n);
}
From 07ca482e4e675bc50cea6003b501c080a0c55e89 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Wed, 8 Sep 2021 10:26:36 -0400
Subject: [PATCH 007/340] disable memory security feature by default; once it
is turned on it can't be turned off
---
src/crypto_impl.c | 9 ++++++---
test/sqlcipher-core.test | 14 +++++++-------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/src/crypto_impl.c b/src/crypto_impl.c
index f20d1101c..e798b65db 100644
--- a/src/crypto_impl.c
+++ b/src/crypto_impl.c
@@ -51,7 +51,7 @@ static volatile int default_page_size = 4096;
static volatile int default_plaintext_header_sz = 0;
static volatile int default_hmac_algorithm = SQLCIPHER_HMAC_SHA512;
static volatile int default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA512;
-static volatile int mem_security_on = 1;
+static volatile int mem_security_on = 0;
static volatile int mem_security_initialized = 0;
static volatile int mem_security_activated = 0;
static volatile unsigned int sqlcipher_activate_count = 0;
@@ -836,8 +836,11 @@ int sqlcipher_get_default_pagesize() {
}
void sqlcipher_set_mem_security(int on) {
- mem_security_on = on;
- mem_security_activated = 0;
+ /* memory security can only be enabled, not disabled */
+ if(on) {
+ mem_security_on = on;
+ mem_security_activated = 0;
+ }
}
int sqlcipher_get_mem_security() {
diff --git a/test/sqlcipher-core.test b/test/sqlcipher-core.test
index cc3683397..185a0ff8b 100644
--- a/test/sqlcipher-core.test
+++ b/test/sqlcipher-core.test
@@ -730,20 +730,20 @@ db close
file delete -force test.db
# verify memory security behavior
-# initially should report ON
-# then disable, check that it is off
-# turn it back on, then check.
+# initially should report OFF
+# then enable, check that it is ON
+# try to turn if off, but verify that it
+# can't be unset.
do_test verify-memory-security {
sqlite_orig db test.db
execsql {
- PRAGMA cipher_memory_security;
- PRAGMA cipher_memory_security = OFF;
PRAGMA cipher_memory_security;
PRAGMA cipher_memory_security = ON;
PRAGMA cipher_memory_security;
-
+ PRAGMA cipher_memory_security = OFF;
+ PRAGMA cipher_memory_security;
}
-} {1 0 1}
+} {0 1 1}
db close
file delete -force test.db
From 3cfbe7934bacb04fbadb55e2a573bd0769cb3887 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Wed, 8 Sep 2021 13:03:59 -0400
Subject: [PATCH 008/340] format pointer for key material with trace logging
enabled per #398
---
src/crypto.c | 12 ++++++------
src/crypto_impl.c | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/crypto.c b/src/crypto.c
index 428b9a58c..5a181a885 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -82,7 +82,7 @@ static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ct
static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx);
+ CODEC_TRACE("codec_set_pass_key: entered db=%p nDb=%d zKey=%p nKey=%d for_ctx=%d\n", db, nDb, zKey, nKey, for_ctx);
if(pDb->pBt) {
codec_ctx *ctx = (codec_ctx*) sqlite3PagerGetCodec(pDb->pBt->pBt->pPager);
@@ -770,7 +770,7 @@ static void sqlite3FreeCodecArg(void *pCodecArg) {
int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE("sqlite3CodecAttach: entered db=%p, nDb=%d zKey=%s, nKey=%d\n", db, nDb, (char *)zKey, nKey);
+ CODEC_TRACE("sqlite3CodecAttach: entered db=%p, nDb=%d zKey=%p, nKey=%d\n", db, nDb, zKey, nKey);
if(nKey && zKey && pDb->pBt) {
@@ -858,12 +858,12 @@ void sqlite3_activate_see(const char* in) {
}
int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
+ CODEC_TRACE("sqlite3_key entered: db=%p pKey=%p nKey=%d\n", db, pKey, nKey);
return sqlite3_key_v2(db, "main", pKey, nKey);
}
int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey);
+ CODEC_TRACE("sqlite3_key_v2: entered db=%p zDb=%s pKey=%p nKey=%d\n", db, zDb, pKey, nKey);
/* attach key if db and pKey are not null and nKey is > 0 */
if(db && pKey && nKey) {
int db_index = sqlcipher_find_db_index(db, zDb);
@@ -873,7 +873,7 @@ int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
}
int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
+ CODEC_TRACE("sqlite3_rekey entered: db=%p pKey=%p nKey=%d\n", db, pKey, nKey);
return sqlite3_rekey_v2(db, "main", pKey, nKey);
}
@@ -888,7 +888,7 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
** 3. If there is a key present, re-encrypt the database with the new key
*/
int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey);
+ CODEC_TRACE("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%p, nKey=%d\n", db, zDb, pKey, nKey);
if(db && pKey && nKey) {
int db_index = sqlcipher_find_db_index(db, zDb);
struct Db *pDb = &db->aDb[db_index];
diff --git a/src/crypto_impl.c b/src/crypto_impl.c
index e798b65db..93c44079a 100644
--- a/src/crypto_impl.c
+++ b/src/crypto_impl.c
@@ -1117,7 +1117,7 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
*/
static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
int rc;
- CODEC_TRACE("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
+ CODEC_TRACE("cipher_ctx_key_derive: entered c_ctx->pass=%p, c_ctx->pass_sz=%d \
ctx->kdf_salt=%p ctx->kdf_salt_sz=%d ctx->kdf_iter=%d \
ctx->hmac_kdf_salt=%p, ctx->fast_kdf_iter=%d ctx->key_sz=%d\n",
c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, ctx->kdf_iter,
From a422e6d25664625c285e7450cae423270d6f543a Mon Sep 17 00:00:00 2001
From: Jeremy Lin
Date: Mon, 4 Oct 2021 13:41:03 -0700
Subject: [PATCH 009/340] Fix some formatting and grammar in README.md
---
README.md | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 608cb8dc5..945f43e90 100644
--- a/README.md
+++ b/README.md
@@ -32,9 +32,9 @@ The SQLCipher team welcomes contributions to the core library. All contributions
## Compiling
-Building SQLCipher is similar to compiling a regular version of SQLite from source a couple small exceptions:
+Building SQLCipher is similar to compiling a regular version of SQLite from source, with a couple of small exceptions:
- 1. You *must* define `SQLITE_HAS_CODEC` and either `SQLITE_TEMP_STORE=2` or SQLITE_TEMP_STORE=3`
+ 1. You *must* define `SQLITE_HAS_CODEC` and either `SQLITE_TEMP_STORE=2` or `SQLITE_TEMP_STORE=3`
2. You will need to link against a support cryptographic provider (OpenSSL, LibTomCrypt, CommonCrypto/Security.framework, or NSS)
The following examples demonstrate linking against OpenSSL, which is a readily available provider on most Unix-like systems.
@@ -43,17 +43,17 @@ Example 1. Static linking (replace /opt/local/lib with the path to libcrypto.a).
example, `--enable-tempstore=yes` is setting `SQLITE_TEMP_STORE=2` for the build.
```
- $ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
- LDFLAGS="/opt/local/lib/libcrypto.a"
- $ make
+$ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
+ LDFLAGS="/opt/local/lib/libcrypto.a"
+$ make
```
Example 2. Dynamic linking
```
- $ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
- LDFLAGS="-lcrypto"
- $ make
+$ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
+ LDFLAGS="-lcrypto"
+$ make
```
## Testing
@@ -65,10 +65,10 @@ As a result, the SQLCipher package includes it's own independent tests that exer
To run SQLCipher specific tests, configure as described here and run the following to execute the tests and receive a report of the results:
```
- $ ./configure --enable-tempstore=yes --enable-fts5 CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_TEST" \
- LDFLAGS="-lcrypto"
- $ make testfixture
- $ ./testfixture test/sqlcipher.test
+$ ./configure --enable-tempstore=yes --enable-fts5 CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_TEST" \
+ LDFLAGS="-lcrypto"
+$ make testfixture
+$ ./testfixture test/sqlcipher.test
```
## Encrypting a database
From 328a4c84379d87de81e14d8ddd1d99b77f0979d7 Mon Sep 17 00:00:00 2001
From: Stephen Lombardo
Date: Tue, 5 Oct 2021 16:25:47 -0400
Subject: [PATCH 010/340] Snapshot of upstream SQLite 3.36.0
---
Makefile.in | 20 +-
Makefile.msc | 14 +-
README.md | 24 +-
VERSION | 2 +-
autoconf/Makefile.msc | 5 +-
autoconf/configure.ac | 48 +-
autoconf/tea/win/nmakehlp.c | 183 +-
configure | 214 +-
configure.ac | 68 +-
doc/lemon.html | 38 +-
ext/expert/expert1.test | 85 +-
ext/expert/sqlite3expert.c | 2 +-
ext/fts3/fts3.c | 35 +-
ext/fts3/fts3Int.h | 2 +-
ext/fts3/fts3_aux.c | 1 +
ext/fts3/fts3_expr.c | 5 +
ext/fts3/fts3_snippet.c | 24 +-
ext/fts3/fts3_test.c | 2 +
ext/fts3/fts3_unicode.c | 1 +
ext/fts3/fts3_write.c | 17 +-
ext/fts5/fts5_buffer.c | 22 +-
ext/fts5/fts5_config.c | 2 +-
ext/fts5/fts5_expr.c | 11 +-
ext/fts5/fts5_index.c | 567 ++--
ext/fts5/fts5_main.c | 19 +-
ext/fts5/fts5_tcl.c | 4 +
ext/fts5/fts5_test_tok.c | 2 +-
ext/fts5/test/fts5corrupt3.test | 4629 ++++++++++++++++++++++++++++++-
ext/fts5/test/fts5corrupt4.test | 2 +
ext/fts5/test/fts5delete.test | 23 +-
ext/fts5/test/fts5doclist.test | 21 +
ext/fts5/test/fts5plan.test | 14 +-
ext/fts5/test/fts5prefix2.test | 57 +
ext/fts5/test/fts5trigram.test | 3 +-
ext/misc/appendvfs.c | 333 ++-
ext/misc/cksumvfs.c | 70 +-
ext/misc/decimal.c | 9 +-
ext/misc/ieee754.c | 8 +
ext/misc/json1.c | 21 +-
ext/misc/memvfs.c | 1 +
ext/misc/regexp.c | 37 +-
ext/misc/series.c | 16 +-
ext/misc/shathree.c | 3 +
ext/misc/vfslog.c | 1 +
ext/misc/vfsstat.c | 1 +
ext/misc/wholenumber.c | 2 +-
ext/misc/zipfile.c | 67 +-
ext/rbu/rbu.c | 9 +-
ext/rbu/rbu1.test | 5 +
ext/rbu/rbudiff.test | 8 +
ext/rbu/sqlite3rbu.c | 46 +-
ext/rtree/geopoly.c | 6 +-
ext/rtree/rtree.c | 7 +-
ext/rtree/rtree6.test | 24 +-
ext/rtree/rtreeC.test | 88 +-
ext/rtree/rtreefuzz001.test | 162 ++
ext/session/session2.test | 58 +-
ext/session/sessionbig.test | 108 +
ext/session/sessionmem.test | 57 +
ext/session/sessionnoop.test | 187 ++
ext/session/sessionsize.test | 131 +
ext/session/sessionwor.test | 25 +-
ext/session/sqlite3session.c | 685 +++--
ext/session/sqlite3session.h | 81 +-
ext/session/test_session.c | 45 +-
main.mk | 25 +-
manifest | 643 +++--
manifest.uuid | 2 +-
src/alter.c | 611 +++-
src/attach.c | 212 +-
src/auth.c | 17 +-
src/btree.c | 306 +-
src/btree.h | 3 +
src/btreeInt.h | 3 +-
src/build.c | 359 ++-
src/ctime.c | 66 +-
src/date.c | 1 +
src/delete.c | 40 +-
src/expr.c | 271 +-
src/fkey.c | 21 +-
src/func.c | 260 +-
src/global.c | 37 +-
src/insert.c | 370 ++-
src/loadext.c | 38 +-
src/main.c | 73 +-
src/malloc.c | 1 -
src/memdb.c | 349 ++-
src/memjournal.c | 41 +-
src/os.c | 13 +-
src/os.h | 6 +
src/os_unix.c | 61 +-
src/pager.c | 22 +-
src/parse.y | 123 +-
src/pcache1.c | 1 +
src/pragma.c | 2 +-
src/prepare.c | 165 +-
src/printf.c | 39 +-
src/random.c | 7 +-
src/resolve.c | 276 +-
src/select.c | 1200 +++++---
src/shell.c.in | 244 +-
src/sqlite.h.in | 97 +-
src/sqliteInt.h | 436 ++-
src/tclsqlite.c | 4 +-
src/test1.c | 84 +-
src/test8.c | 6 +
src/test_config.c | 21 +-
src/tokenize.c | 89 +-
src/treeview.c | 29 +-
src/trigger.c | 290 +-
src/update.c | 14 +-
src/upsert.c | 232 +-
src/util.c | 10 +
src/vdbe.c | 415 +--
src/vdbe.h | 2 +-
src/vdbeInt.h | 9 +-
src/vdbeapi.c | 35 +-
src/vdbeaux.c | 63 +-
src/vdbeblob.c | 3 +-
src/vdbemem.c | 20 +-
src/vdbesort.c | 5 +-
src/vdbetrace.c | 2 +-
src/vtab.c | 6 +-
src/wal.c | 5 +-
src/walker.c | 45 +-
src/where.c | 215 +-
src/whereInt.h | 26 +-
src/wherecode.c | 70 +-
src/whereexpr.c | 192 +-
src/window.c | 145 +-
test/alter.test | 12 +
test/alter4.test | 8 +-
test/alterauth2.test | 20 +
test/altercol.test | 60 +-
test/altercorrupt.test | 175 ++
test/alterdropcol.test | 339 +++
test/alterdropcol2.test | 222 ++
test/alterlegacy.test | 4 +-
test/altermalloc2.test | 21 +
test/altermalloc3.test | 47 +
test/alterqf.test | 111 +
test/altertab.test | 258 +-
test/altertab3.test | 2 +-
test/analyze3.test | 30 +-
test/analyze4.test | 2 +-
test/analyze6.test | 24 +-
test/analyze7.test | 32 +-
test/analyze8.test | 22 +-
test/analyze9.test | 30 +-
test/analyzeC.test | 2 +-
test/analyzeD.test | 8 +-
test/analyzeE.test | 88 +-
test/analyzeF.test | 4 +-
test/analyzeG.test | 32 +-
test/attach.test | 15 +
test/attach4.test | 1 -
test/auth.test | 16 +-
test/autoindex1.test | 30 +-
test/autoindex3.test | 8 +-
test/autoindex5.test | 6 +-
test/avfs.test | 395 +++
test/backup2.test | 5 +-
test/bestindex1.test | 10 +-
test/bestindex2.test | 30 +-
test/bestindex3.test | 16 +-
test/bestindex4.test | 8 +-
test/bestindex7.test | 1 -
test/between.test | 6 +-
test/bigmmap.test | 4 +-
test/busy2.test | 1 -
test/columncount.test | 56 +
test/corrupt4.test | 69 +-
test/corruptL.test | 88 +
test/corruptN.test | 228 ++
test/cost.test | 46 +-
test/count.test | 8 +-
test/coveridxscan.test | 4 +-
test/crash5.test | 75 +-
test/date2.test | 7 +
test/dbfuzz2.c | 19 +-
test/delete.test | 2 +-
test/delete4.test | 12 +-
test/distinct.test | 15 +-
test/distinctagg.test | 157 +-
test/e_createtable.test | 6 +-
test/e_fkey.test | 22 +-
test/e_select.test | 9 +-
test/eqp.test | 324 ++-
test/exprfault.test | 35 +
test/external_reader.test | 74 +
test/fts3aux1.test | 34 +-
test/fts3corrupt4.test | 510 ++++
test/fts3corrupt6.test | 26 +-
test/fts3join.test | 8 +-
test/fts3query.test | 16 +-
test/fts3snippet2.test | 1 -
test/fts4rename.test | 2 +-
test/fts4unicode.test | 18 +
test/fts4upfrom.test | 1 -
test/func.test | 7 +
test/func7.test | 245 ++
test/fuzzcheck.c | 117 +-
test/fuzzdata8.db | Bin 1616896 -> 2398208 bytes
test/fuzzerfault.test | 19 +
test/having.test | 13 +
test/hook.test | 57 +
test/in4.test | 107 +-
test/in6.test | 19 +
test/incrvacuum.test | 58 +-
test/index6.test | 22 +-
test/index7.test | 14 +-
test/index8.test | 2 +-
test/indexedby.test | 68 +-
test/indexexpr1.test | 4 +-
test/indexexpr2.test | 10 +-
test/intpkey.test | 2 +-
test/join2.test | 34 +-
test/join5.test | 10 +-
test/like.test | 29 +-
test/like3.test | 24 +-
test/limit.test | 23 +
test/mallocK.test | 2 +-
test/memdb1.test | 10 +
test/memjournal.test | 48 +
test/minmax.test | 15 +-
test/minmax2.test | 15 +-
test/misc2.test | 25 +-
test/misc7.test | 6 +-
test/misc8.test | 4 +-
test/notnull2.test | 112 +
test/notnullfault.test | 55 +
test/nulls1.test | 10 +-
test/optfuzz.c | 1 -
test/orderby1.test | 2 +-
test/pager1.test | 9 +
test/permutations.test | 19 +-
test/quote.test | 45 +-
test/regexp1.test | 35 +-
test/regexp2.test | 20 +
test/releasetest.tcl | 4 +-
test/releasetest_data.tcl | 32 +-
test/returning1.test | 321 +++
test/rollback2.test | 4 +-
test/rowvalue.test | 60 +-
test/rowvalue4.test | 34 +-
test/rowvalue9.test | 13 +
test/scanstatus.test | 86 +-
test/select1.test | 12 +-
test/select4.test | 14 +
test/select5.test | 11 +-
test/select9.test | 6 +-
test/selectA.test | 19 +-
test/selectC.test | 6 +-
test/selectD.test | 2 +-
test/shell1.test | 4 +-
test/shell4.test | 2 +-
test/skipscan1.test | 4 +-
test/skipscan2.test | 2 +-
test/skipscan5.test | 24 +-
test/skipscan6.test | 4 +-
test/speedtest1.c | 132 +-
test/sqllimits1.test | 4 +-
test/startup.c | 628 +++++
test/tabfunc01.test | 44 +
test/tester.tcl | 17 +-
test/threadtest5.c | 339 +++
test/tkt-385a5b56b9.test | 8 +-
test/tkt-78e04e52ea.test | 6 +-
test/tkt-b75a9ca6b0.test | 4 +-
test/tkt3442.test | 6 +-
test/tpch01.test | 14 +-
test/trace3.test | 79 +
test/transitive1.test | 31 +-
test/trigger2.test | 21 +-
test/trigger9.test | 11 +-
test/triggerE.test | 2 +
test/triggerupfrom.test | 1 -
test/unionall.test | 367 +++
test/unionall2.test | 58 +
test/unionallfault.test | 36 +
test/unordered.test | 28 +-
test/upfrom1.test | 32 +
test/upfrom2.test | 2 -
test/upfrom3.test | 1 -
test/upfromfault.test | 1 -
test/upsert5.test | 411 +++
test/vacuum2.test | 2 +-
test/vacuum6.test | 112 +
test/view.test | 7 +-
test/view2.test | 49 +
test/vtab1.test | 1 +
test/wal.test | 31 +
test/walsetlk.test | 1 -
test/walvfs.test | 9 +-
test/where.test | 20 +-
test/where2.test | 10 +-
test/where3.test | 50 +-
test/where7.test | 6 +-
test/where9.test | 39 +-
test/whereE.test | 8 +-
test/whereF.test | 6 +-
test/whereG.test | 79 +-
test/whereI.test | 8 +-
test/whereJ.test | 6 +-
test/whereK.test | 10 +-
test/whereL.test | 21 +-
test/whereM.test | 112 +
test/wherefault.test | 24 +
test/wherelimit.test | 22 +-
test/window1.test | 179 +-
test/window8.tcl | 70 +
test/window8.test | 71 +
test/window9.test | 17 +
test/windowB.test | 21 +
test/windowfault.test | 22 +-
test/windowpushd.test | 236 ++
test/with1.test | 64 +-
test/with2.test | 196 ++
test/with3.test | 76 +-
test/with6.test | 255 ++
test/without_rowid1.test | 13 +
test/without_rowid6.test | 8 +-
test/zipfile.test | 12 +
tool/lemon.c | 14 +-
tool/lempar.c | 101 +-
tool/merge-test.tcl | 99 +
tool/mkctimec.tcl | 160 +-
tool/mkkeywordhash.c | 32 +-
tool/mkopcodeh.tcl | 14 +-
tool/mkshellc.tcl | 1 +
tool/omittest.tcl | 2 +
tool/showdb.c | 17 +-
tool/sqldiff.c | 14 +-
333 files changed, 22890 insertions(+), 4623 deletions(-)
create mode 100644 ext/fts5/test/fts5prefix2.test
create mode 100644 ext/session/sessionbig.test
create mode 100644 ext/session/sessionmem.test
create mode 100644 ext/session/sessionnoop.test
create mode 100644 ext/session/sessionsize.test
create mode 100644 test/altercorrupt.test
create mode 100644 test/alterdropcol.test
create mode 100644 test/alterdropcol2.test
create mode 100644 test/altermalloc3.test
create mode 100644 test/alterqf.test
create mode 100644 test/avfs.test
create mode 100644 test/columncount.test
create mode 100644 test/corruptN.test
create mode 100644 test/exprfault.test
create mode 100644 test/external_reader.test
create mode 100644 test/func7.test
create mode 100644 test/memjournal.test
create mode 100644 test/notnull2.test
create mode 100644 test/notnullfault.test
create mode 100644 test/returning1.test
create mode 100644 test/startup.c
create mode 100644 test/threadtest5.c
create mode 100644 test/unionall.test
create mode 100644 test/unionall2.test
create mode 100644 test/unionallfault.test
create mode 100644 test/upsert5.test
create mode 100644 test/vacuum6.test
create mode 100644 test/view2.test
create mode 100644 test/whereM.test
create mode 100644 test/windowpushd.test
create mode 100644 test/with6.test
create mode 100644 tool/merge-test.tcl
diff --git a/Makefile.in b/Makefile.in
index 6ab49dbe9..2795ffa9e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -432,7 +432,7 @@ TESTSRC = \
$(TOP)/ext/fts3/fts3_term.c \
$(TOP)/ext/fts3/fts3_test.c \
$(TOP)/ext/session/test_session.c \
- $(TOP)/ext/rbu/test_rbu.c
+ $(TOP)/ext/rbu/test_rbu.c
# Statically linked extensions
#
@@ -440,6 +440,7 @@ TESTSRC += \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/test_expert.c \
$(TOP)/ext/misc/amatch.c \
+ $(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/carray.c \
$(TOP)/ext/misc/cksumvfs.c \
$(TOP)/ext/misc/closure.c \
@@ -520,7 +521,8 @@ TESTSRC2 = \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/misc/stmt.c
+ $(TOP)/ext/misc/stmt.c \
+ fts5.c
# Header files used by all library source files.
#
@@ -614,12 +616,10 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
-SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
@@ -693,7 +693,6 @@ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -1087,6 +1086,7 @@ SHELL_SRC = \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
+ $(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/sqlar.c \
@@ -1233,7 +1233,6 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
-TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
@@ -1267,7 +1266,7 @@ fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuz
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
- valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
+ valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
# The veryquick.test TCL tests.
@@ -1378,6 +1377,9 @@ wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
+startup$(TEXE): $(TOP)/test/startup.c sqlite3.c
+ $(CC) -Os -g -DSQLITE_THREADSAFE=0 -o $@ $(TOP)/test/startup.c sqlite3.c $(TLIBS)
+
KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
@@ -1426,6 +1428,9 @@ threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
threadtest: threadtest3$(TEXE)
./threadtest3$(TEXE)
+threadtest5: sqlite3.c $(TOP)/test/threadtest5.c
+ $(LTLINK) $(TOP)/test/threadtest5.c sqlite3.c -o $@ $(TLIBS)
+
releasetest:
$(TCLSH_CMD) $(TOP)/test/releasetest.tcl
@@ -1479,6 +1484,7 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f dbhash dbhash.exe
rm -f fts5.* fts5parse.*
+ rm -f threadtest5
distclean: clean
rm -f config.h config.log config.status libtool Makefile sqlite3.pc
diff --git a/Makefile.msc b/Makefile.msc
index 404e3b236..4f20c0c0c 100644
--- a/Makefile.msc
+++ b/Makefile.msc
@@ -367,7 +367,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -380,6 +379,9 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
+# Always enable math functions on Windows
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
+
# Should the rbu extension be enabled? If so, add compilation options
# to enable it.
#
@@ -1549,7 +1551,7 @@ TESTSRC = \
$(TOP)\ext\fts3\fts3_term.c \
$(TOP)\ext\fts3\fts3_test.c \
$(TOP)\ext\rbu\test_rbu.c \
- $(TOP)\ext\session\test_session.c
+ $(TOP)\ext\session\test_session.c
# Statically linked extensions.
#
@@ -1557,6 +1559,7 @@ TESTEXT = \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\test_expert.c \
$(TOP)\ext\misc\amatch.c \
+ $(TOP)\ext\misc\appendvfs.c \
$(TOP)\ext\misc\carray.c \
$(TOP)\ext\misc\cksumvfs.c \
$(TOP)\ext\misc\closure.c \
@@ -1581,7 +1584,8 @@ TESTEXT = \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\unionvtab.c \
- $(TOP)\ext\misc\wholenumber.c
+ $(TOP)\ext\misc\wholenumber.c \
+ fts5.c
# If use of zlib is enabled, add the "zipfile.c" source file.
#
@@ -1684,7 +1688,6 @@ FUZZDATA = \
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
# <>
@@ -1693,7 +1696,6 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
@@ -2209,6 +2211,7 @@ SHELL_SRC = \
$(TOP)\ext\misc\decimal.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\ieee754.c \
+ $(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\uint.c \
@@ -2387,7 +2390,6 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
-TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
diff --git a/README.md b/README.md
index c12b77c1b..b79fc67f1 100644
--- a/README.md
+++ b/README.md
@@ -55,11 +55,11 @@ a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.)
Then run commands like this:
- mkdir ~/sqlite
+ mkdir -p ~/sqlite ~/Fossils
cd ~/sqlite
- fossil clone https://www.sqlite.org/src sqlite.fossil
- fossil open sqlite.fossil
-
+ fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
+ fossil open ~/Fossils/sqlite.fossil
+
After setting up a repository using the steps above, you can always
update to the lastest version using:
@@ -68,7 +68,7 @@ update to the lastest version using:
Or type "fossil ui" to get a web-based user interface.
-## Compiling
+## Compiling for Unix-like systems
First create a directory in which to place
the build products. It is recommended, but not required, that the
@@ -94,22 +94,22 @@ script does not work out for you, there is a generic makefile named
can copy and edit to suit your needs. Comments on the generic makefile
show what changes are needed.
-## Using MSVC
+## Using MSVC for Windows systems
On Windows, all applicable build products can be compiled with MSVC.
First open the command prompt window associated with the desired compiler
version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE
with the provided "Makefile.msc" to build one of the supported targets.
-For example:
+For example, from the parent directory of the source subtree named "sqlite":
mkdir bld
cd bld
- nmake /f Makefile.msc TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
- nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
- nmake /f Makefile.msc test TOP=..\sqlite
+ nmake /f ..\sqlite\Makefile.msc TOP=..\sqlite
+ nmake /f ..\sqlite\Makefile.msc sqlite3.c TOP=..\sqlite
+ nmake /f ..\sqlite\Makefile.msc sqlite3.dll TOP=..\sqlite
+ nmake /f ..\sqlite\Makefile.msc sqlite3.exe TOP=..\sqlite
+ nmake /f ..\sqlite\Makefile.msc test TOP=..\sqlite
There are several build options that can be set via the NMAKE command
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
diff --git a/VERSION b/VERSION
index 62d286466..0b477b458 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.34.1
+3.36.0
diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc
index 746162a00..40d0e8113 100644
--- a/autoconf/Makefile.msc
+++ b/autoconf/Makefile.msc
@@ -290,7 +290,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -303,6 +302,9 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
+# Always enable math functions on Windows
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
+
# Should the rbu extension be enabled? If so, add compilation options
# to enable it.
#
@@ -957,7 +959,6 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
diff --git a/autoconf/configure.ac b/autoconf/configure.ac
index 167626d59..e050786bd 100644
--- a/autoconf/configure.ac
+++ b/autoconf/configure.ac
@@ -87,7 +87,9 @@ AC_SUBST(READLINE_LIBS)
AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
[--enable-threadsafe], [build a thread-safe library [default=yes]])],
[], [enable_threadsafe=yes])
-if test x"$enable_threadsafe" != "xno"; then
+if test x"$enable_threadsafe" == "xno"; then
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0"
+else
BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
AC_SEARCH_LIBS(pthread_create, pthread)
AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
@@ -109,14 +111,34 @@ AC_MSG_CHECKING([for whether to support dynamic extensions])
AC_MSG_RESULT($enable_dynamic_extensions)
#-----------------------------------------------------------------------
+#-----------------------------------------------------------------------
+# --enable-math
+#
+AC_ARG_ENABLE(math, [AS_HELP_STRING(
+ [--enable-math], [SQL math functions [default=yes]])],
+ [], [enable_math=yes])
+AC_MSG_CHECKING([SQL math functions])
+if test x"$enable_math" = "xyes"; then
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS"
+ AC_MSG_RESULT([enabled])
+ AC_SEARCH_LIBS(ceil, m)
+else
+ AC_MSG_RESULT([disabled])
+fi
+#-----------------------------------------------------------------------
+
#-----------------------------------------------------------------------
# --enable-fts4
#
AC_ARG_ENABLE(fts4, [AS_HELP_STRING(
[--enable-fts4], [include fts4 support [default=yes]])],
[], [enable_fts4=yes])
+AC_MSG_CHECKING([FTS4 extension])
if test x"$enable_fts4" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4"
+ AC_MSG_RESULT([enabled])
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -126,8 +148,12 @@ fi
AC_ARG_ENABLE(fts3, [AS_HELP_STRING(
[--enable-fts3], [include fts3 support [default=no]])],
[], [])
+AC_MSG_CHECKING([FTS3 extension])
if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3"
+ AC_MSG_RESULT([enabled])
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -137,9 +163,13 @@ fi
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
[--enable-fts5], [include fts5 support [default=yes]])],
[], [enable_fts5=yes])
+AC_MSG_CHECKING([FTS5 extension])
if test x"$enable_fts5" = "xyes"; then
+ AC_MSG_RESULT([enabled])
AC_SEARCH_LIBS(log, m)
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5"
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -149,8 +179,12 @@ fi
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
[--enable-json1], [include json1 support [default=yes]])],
[],[enable_json1=yes])
+AC_MSG_CHECKING([JSON functions])
if test x"$enable_json1" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1"
+ AC_MSG_RESULT([enabled])
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -160,8 +194,12 @@ fi
AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
[--enable-rtree], [include rtree support [default=yes]])],
[], [enable_rtree=yes])
+AC_MSG_CHECKING([RTREE extension])
if test x"$enable_rtree" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
+ AC_MSG_RESULT([enabled])
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -171,8 +209,12 @@ fi
AC_ARG_ENABLE(session, [AS_HELP_STRING(
[--enable-session], [enable the session extension [default=no]])],
[], [])
+AC_MSG_CHECKING([Session extension])
if test x"$enable_session" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
+ AC_MSG_RESULT([enabled])
+else
+ AC_MSG_RESULT([disabled])
fi
#-----------------------------------------------------------------------
@@ -182,9 +224,13 @@ fi
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
[--enable-debug], [build with debugging features enabled [default=no]])],
[], [])
+AC_MSG_CHECKING([Build type])
if test x"$enable_debug" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
CFLAGS="-g -O0"
+ AC_MSG_RESULT([debug])
+else
+ AC_MSG_RESULT([release])
fi
#-----------------------------------------------------------------------
diff --git a/autoconf/tea/win/nmakehlp.c b/autoconf/tea/win/nmakehlp.c
index e00f1b499..7536edee3 100644
--- a/autoconf/tea/win/nmakehlp.c
+++ b/autoconf/tea/win/nmakehlp.c
@@ -14,13 +14,8 @@
#define _CRT_SECURE_NO_DEPRECATE
#include
-#define NO_SHLWAPI_GDI
-#define NO_SHLWAPI_STREAM
-#define NO_SHLWAPI_REG
-#include
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
-#pragma comment (lib, "shlwapi.lib")
#include
#include
@@ -39,15 +34,15 @@
#endif
-
/* protos */
static int CheckForCompilerFeature(const char *option);
-static int CheckForLinkerFeature(const char *option);
+static int CheckForLinkerFeature(const char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
-static const char *GetVersionFromFile(const char *filename, const char *match);
+static int LocateDependency(const char *keyfile);
+static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);
/* globals */
@@ -74,6 +69,7 @@ main(
char msg[300];
DWORD dwWritten;
int chars;
+ const char *s;
/*
* Make sure children (cl.exe and link.exe) are kept quiet.
@@ -102,16 +98,16 @@ main(
}
return CheckForCompilerFeature(argv[2]);
case 'l':
- if (argc != 3) {
+ if (argc < 3) {
chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -l \n"
+ "usage: %s -l ? ...?\n"
"Tests for whether link.exe supports an option\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
- return CheckForLinkerFeature(argv[2]);
+ return CheckForLinkerFeature(&argv[2], argc-2);
case 'f':
if (argc == 2) {
chars = snprintf(msg, sizeof(msg) - 1,
@@ -153,8 +149,13 @@ main(
&dwWritten, NULL);
return 0;
}
- printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
- return 0;
+ s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
+ if (s && *s) {
+ printf("%s\n", s);
+ return 0;
+ } else
+ return 1; /* Version not found. Return non-0 exit code */
+
case 'Q':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
@@ -166,6 +167,18 @@ main(
return 2;
}
return QualifyPath(argv[2]);
+
+ case 'L':
+ if (argc != 3) {
+ chars = snprintf(msg, sizeof(msg) - 1,
+ "usage: %s -L keypath\n"
+ "Emit the fully qualified path of directory containing keypath\n"
+ "exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+ &dwWritten, NULL);
+ return 2;
+ }
+ return LocateDependency(argv[2]);
}
}
chars = snprintf(msg, sizeof(msg) - 1,
@@ -313,7 +326,8 @@ CheckForCompilerFeature(
static int
CheckForLinkerFeature(
- const char *option)
+ const char **options,
+ int count)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -322,7 +336,8 @@ CheckForLinkerFeature(
char msg[300];
BOOL ok;
HANDLE hProcess, h, pipeThreads[2];
- char cmdline[100];
+ int i;
+ char cmdline[255];
hProcess = GetCurrentProcess();
@@ -368,7 +383,11 @@ CheckForLinkerFeature(
* Append our option for testing.
*/
- lstrcat(cmdline, option);
+ for (i = 0; i < count; i++) {
+ lstrcat(cmdline, " \"");
+ lstrcat(cmdline, options[i]);
+ lstrcat(cmdline, "\"");
+ }
ok = CreateProcess(
NULL, /* Module name. */
@@ -433,7 +452,9 @@ CheckForLinkerFeature(
return !(strstr(Out.buffer, "LNK1117") != NULL ||
strstr(Err.buffer, "LNK1117") != NULL ||
strstr(Out.buffer, "LNK4044") != NULL ||
- strstr(Err.buffer, "LNK4044") != NULL);
+ strstr(Err.buffer, "LNK4044") != NULL ||
+ strstr(Out.buffer, "LNK4224") != NULL ||
+ strstr(Err.buffer, "LNK4224") != NULL);
}
static DWORD WINAPI
@@ -479,7 +500,8 @@ IsIn(
static const char *
GetVersionFromFile(
const char *filename,
- const char *match)
+ const char *match,
+ int numdots)
{
size_t cbBuffer = 100;
static char szBuffer[100];
@@ -497,9 +519,10 @@ GetVersionFromFile(
p = strstr(szBuffer, match);
if (p != NULL) {
/*
- * Skip to first digit.
+ * Skip to first digit after the match.
*/
+ p += strlen(match);
while (*p && !isdigit(*p)) {
++p;
}
@@ -509,7 +532,8 @@ GetVersionFromFile(
*/
q = p;
- while (*q && (isalnum(*q) || *q == '.')) {
+ while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
+ && (!strchr("ab", q[-1])) || --numdots))) {
++q;
}
@@ -619,7 +643,7 @@ SubstituteFile(
}
/* debug: dump the list */
-#ifdef _DEBUG
+#ifndef NDEBUG
{
int n = 0;
list_item_t *p = NULL;
@@ -628,11 +652,11 @@ SubstituteFile(
}
}
#endif
-
+
/*
* Run the substitutions over each line of the input
*/
-
+
while (fgets(szBuffer, cbBuffer, fp) != NULL) {
list_item_t *p = NULL;
for (p = substPtr; p != NULL; p = p->nextPtr) {
@@ -652,13 +676,24 @@ SubstituteFile(
}
printf(szBuffer);
}
-
+
list_free(&substPtr);
}
fclose(fp);
return 0;
}
+BOOL FileExists(LPCTSTR szPath)
+{
+#ifndef INVALID_FILE_ATTRIBUTES
+ #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+ DWORD pathAttr = GetFileAttributes(szPath);
+ return (pathAttr != INVALID_FILE_ATTRIBUTES &&
+ !(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
+}
+
+
/*
* QualifyPath --
*
@@ -672,17 +707,103 @@ QualifyPath(
const char *szPath)
{
char szCwd[MAX_PATH + 1];
- char szTmp[MAX_PATH + 1];
- char *p;
- GetCurrentDirectory(MAX_PATH, szCwd);
- while ((p = strchr(szPath, '/')) && *p)
- *p = '\\';
- PathCombine(szTmp, szCwd, szPath);
- PathCanonicalize(szCwd, szTmp);
+
+ GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
printf("%s\n", szCwd);
return 0;
}
+/*
+ * Implements LocateDependency for a single directory. See that command
+ * for an explanation.
+ * Returns 0 if found after printing the directory.
+ * Returns 1 if not found but no errors.
+ * Returns 2 on any kind of error
+ * Basically, these are used as exit codes for the process.
+ */
+static int LocateDependencyHelper(const char *dir, const char *keypath)
+{
+ HANDLE hSearch;
+ char path[MAX_PATH+1];
+ int dirlen, keylen, ret;
+ WIN32_FIND_DATA finfo;
+
+ if (dir == NULL || keypath == NULL)
+ return 2; /* Have no real error reporting mechanism into nmake */
+ dirlen = strlen(dir);
+ if ((dirlen + 3) > sizeof(path))
+ return 2;
+ strncpy(path, dir, dirlen);
+ strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
+ keylen = strlen(keypath);
+
+#if 0 /* This function is not available in Visual C++ 6 */
+ /*
+ * Use numerics 0 -> FindExInfoStandard,
+ * 1 -> FindExSearchLimitToDirectories,
+ * as these are not defined in Visual C++ 6
+ */
+ hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
+#else
+ hSearch = FindFirstFile(path, &finfo);
+#endif
+ if (hSearch == INVALID_HANDLE_VALUE)
+ return 1; /* Not found */
+
+ /* Loop through all subdirs checking if the keypath is under there */
+ ret = 1; /* Assume not found */
+ do {
+ int sublen;
+ /*
+ * We need to check it is a directory despite the
+ * FindExSearchLimitToDirectories in the above call. See SDK docs
+ */
+ if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+ continue;
+ sublen = strlen(finfo.cFileName);
+ if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
+ continue; /* Path does not fit, assume not matched */
+ strncpy(path+dirlen+1, finfo.cFileName, sublen);
+ path[dirlen+1+sublen] = '\\';
+ strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
+ if (FileExists(path)) {
+ /* Found a match, print to stdout */
+ path[dirlen+1+sublen] = '\0';
+ QualifyPath(path);
+ ret = 0;
+ break;
+ }
+ } while (FindNextFile(hSearch, &finfo));
+ FindClose(hSearch);
+ return ret;
+}
+
+/*
+ * LocateDependency --
+ *
+ * Locates a dependency for a package.
+ * keypath - a relative path within the package directory
+ * that is used to confirm it is the correct directory.
+ * The search path for the package directory is currently only
+ * the parent and grandparent of the current working directory.
+ * If found, the command prints
+ * name_DIRPATH=
+ * and returns 0. If not found, does not print anything and returns 1.
+ */
+static int LocateDependency(const char *keypath)
+{
+ int i, ret;
+ static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
+
+ for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
+ ret = LocateDependencyHelper(paths[i], keypath);
+ if (ret == 0)
+ return ret;
+ }
+ return ret;
+}
+
+
/*
* Local variables:
* mode: c
diff --git a/configure b/configure
index ff6029b73..5df138630 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.34.1.
+# Generated by GNU Autoconf 2.69 for sqlite 3.36.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.34.1'
-PACKAGE_STRING='sqlite 3.34.1'
+PACKAGE_VERSION='3.36.0'
+PACKAGE_STRING='sqlite 3.36.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -903,9 +903,10 @@ with_readline_inc
enable_debug
enable_amalgamation
enable_load_extension
+enable_math
+enable_all
enable_memsys5
enable_memsys3
-enable_all
enable_fts3
enable_fts4
enable_fts5
@@ -1466,7 +1467,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.34.1 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.36.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1532,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.34.1:";;
+ short | recursive ) echo "Configuration of sqlite 3.36.0:";;
esac
cat <<\_ACEOF
@@ -1557,9 +1558,10 @@ Optional Features:
separately
--disable-load-extension
Disable loading of external extensions
+ --disable-math Disable math functions
+ --enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
--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
@@ -1658,7 +1660,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.34.1
+sqlite configure 3.36.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2077,7 +2079,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.34.1, which was
+It was created by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3935,13 +3937,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:3938: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:3940: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:3941: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:3943: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:3944: output\"" >&5)
+ (eval echo "\"\$as_me:3946: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5147,7 +5149,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5150 "configure"' > conftest.$ac_ext
+ echo '#line 5152 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6672,11 +6674,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:6675: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6677: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6679: \$? = $ac_status" >&5
+ echo "$as_me:6681: \$? = $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.
@@ -7011,11 +7013,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:7014: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7016: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7018: \$? = $ac_status" >&5
+ echo "$as_me:7020: \$? = $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.
@@ -7116,11 +7118,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:7119: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7121: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7123: \$? = $ac_status" >&5
+ echo "$as_me:7125: \$? = $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
@@ -7171,11 +7173,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:7174: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7176: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7178: \$? = $ac_status" >&5
+ echo "$as_me:7180: \$? = $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
@@ -9551,7 +9553,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9554 "configure"
+#line 9556 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9647,7 +9649,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9650 "configure"
+#line 9652 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10364,8 +10366,10 @@ fi
if test "x${TCLLIBDIR+set}" != "xset" ; then
TCLLIBDIR='$(libdir)'
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
- TCLLIBDIR=$i
- break
+ if test -d $i ; then
+ TCLLIBDIR=$i
+ break
+ fi
done
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi
@@ -11247,10 +11251,16 @@ if test "${enable_debug+set}" = set; then :
enableval=$enable_debug;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build type" >&5
+$as_echo_n "checking build type... " >&6; }
if test "${enable_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
+$as_echo "debug" >&6; }
else
TARGET_DEBUG="-DNDEBUG"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5
+$as_echo "release" >&6; }
fi
@@ -11411,6 +11421,91 @@ else
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi
+##########
+# Do we want to support math functions
+#
+# Check whether --enable-math was given.
+if test "${enable_math+set}" = set; then :
+ enableval=$enable_math;
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support math functions" >&5
+$as_echo_n "checking whether to support math functions... " >&6; }
+if test "$enable_math" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ceil" >&5
+$as_echo_n "checking for library containing ceil... " >&6; }
+if ${ac_cv_search_ceil+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ceil ();
+int
+main ()
+{
+return ceil ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' m; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_ceil=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ceil+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ceil+:} false; then :
+
+else
+ ac_cv_search_ceil=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ceil" >&5
+$as_echo "$ac_cv_search_ceil" >&6; }
+ac_res=$ac_cv_search_ceil
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+
+########
+# The --enable-all 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
+
+
##########
# Do we want to support memsys3 and/or memsys5
#
@@ -11445,15 +11540,6 @@ 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.
@@ -11461,15 +11547,26 @@ if test "${enable_fts3+set}" = set; then :
enableval=$enable_fts3;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS3" >&5
+$as_echo_n "checking whether to support FTS3... " >&6; }
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
# Check whether --enable-fts4 was given.
if test "${enable_fts4+set}" = set; then :
enableval=$enable_fts4;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS4" >&5
+$as_echo_n "checking whether to support FTS4... " >&6; }
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
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; }
@@ -11527,13 +11624,20 @@ if test "$ac_res" != no; then :
fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
# Check whether --enable-fts5 was given.
if test "${enable_fts5+set}" = set; then :
enableval=$enable_fts5;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support FTS5" >&5
+$as_echo_n "checking whether to support FTS5... " >&6; }
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
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; }
@@ -11591,6 +11695,9 @@ if test "$ac_res" != no; then :
fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -11600,8 +11707,15 @@ if test "${enable_json1+set}" = set; then :
enableval=$enable_json1;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON" >&5
+$as_echo_n "checking whether to support JSON... " >&6; }
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -11612,8 +11726,15 @@ if test "${enable_update_limit+set}" = set; then :
enableval=$enable_update_limit;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support LIMIT on UPDATE and DELETE statements" >&5
+$as_echo_n "checking whether to support LIMIT on UPDATE and DELETE statements... " >&6; }
if test "${enable_update_limit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -11625,9 +11746,16 @@ else
enable_geopoly=no
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support GEOPOLY" >&5
+$as_echo_n "checking whether to support GEOPOLY... " >&6; }
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
enable_rtree=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -11637,8 +11765,15 @@ if test "${enable_rtree+set}" = set; then :
enableval=$enable_rtree;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support RTREE" >&5
+$as_echo_n "checking whether to support RTREE... " >&6; }
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -11648,9 +11783,16 @@ if test "${enable_session+set}" = set; then :
enableval=$enable_session;
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support SESSION" >&5
+$as_echo_n "checking whether to support SESSION... " >&6; }
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"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
#########
@@ -12236,7 +12378,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.34.1, which was
+This file was extended by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12302,7 +12444,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.34.1
+sqlite config.status 3.36.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index bb8f4bd56..70664dd41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -134,8 +134,10 @@ AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
if test "x${TCLLIBDIR+set}" != "xset" ; then
TCLLIBDIR='$(libdir)'
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
- TCLLIBDIR=$i
- break
+ if test -d $i ; then
+ TCLLIBDIR=$i
+ break
+ fi
done
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
fi
@@ -553,10 +555,13 @@ AC_SEARCH_LIBS(fdatasync, [rt])
#########
# check for debug enabled
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
+AC_MSG_CHECKING([build type])
if test "${enable_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+ AC_MSG_RESULT([debug])
else
TARGET_DEBUG="-DNDEBUG"
+ AC_MSG_RESULT([release])
fi
AC_SUBST(TARGET_DEBUG)
@@ -586,6 +591,27 @@ else
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi
+##########
+# Do we want to support math functions
+#
+AC_ARG_ENABLE(math,
+AC_HELP_STRING([--disable-math],[Disable math functions]))
+AC_MSG_CHECKING([whether to support math functions])
+if test "$enable_math" = "no"; then
+ AC_MSG_RESULT([no])
+else
+ AC_MSG_RESULT([yes])
+ OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
+ AC_SEARCH_LIBS(ceil, m)
+fi
+
+
+########
+# The --enable-all argument is short-hand to enable
+# multiple extensions.
+AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all],
+ [Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions]))
+
##########
# Do we want to support memsys3 and/or memsys5
#
@@ -608,37 +634,47 @@ 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],
[Enable the FTS3 extension]))
+AC_MSG_CHECKING([whether to support FTS3])
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
[Enable the FTS4 extension]))
+AC_MSG_CHECKING([whether to support FTS4])
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
+ AC_MSG_RESULT([yes])
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
AC_SEARCH_LIBS([log],[m])
+else
+ AC_MSG_RESULT([no])
fi
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
[Enable the FTS5 extension]))
+AC_MSG_CHECKING([whether to support FTS5])
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
+ AC_MSG_RESULT([yes])
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
AC_SEARCH_LIBS([log],[m])
+else
+ AC_MSG_RESULT([no])
fi
#########
# See whether we should enable JSON1
AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension]))
+AC_MSG_CHECKING([whether to support JSON])
if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
#########
@@ -646,8 +682,12 @@ fi
# statements.
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
[Enable the UPDATE/DELETE LIMIT clause]))
+AC_MSG_CHECKING([whether to support LIMIT on UPDATE and DELETE statements])
if test "${enable_update_limit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
#########
@@ -655,26 +695,38 @@ fi
AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly],
[Enable the GEOPOLY extension]),
[enable_geopoly=yes],[enable_geopoly=no])
+AC_MSG_CHECKING([whether to support GEOPOLY])
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
enable_rtree=yes
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
#########
# See whether we should enable RTREE
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
[Enable the RTREE extension]))
+AC_MSG_CHECKING([whether to support RTREE])
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
#########
# See whether we should enable the SESSION extension
AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
[Enable the SESSION extension]))
+AC_MSG_CHECKING([whether to support SESSION])
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"
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
fi
#########
diff --git a/doc/lemon.html b/doc/lemon.html
index bd078c8ec..324b3f331 100644
--- a/doc/lemon.html
+++ b/doc/lemon.html
@@ -697,6 +697,7 @@ 4.4 Special Directives
%stack_size
%start_symbol
%syntax_error
+%token
%token_class
%token_destructor
%token_prefix
@@ -1077,16 +1078,39 @@ 4.4.18 The %start_symbol directive
4.4.19 The %syntax_error directive
-See Error Processing.
+See Error Processing.
+
+
+4.4.20 The %token directive
+
+Tokens are normally created automatically, the first time they are used.
+Any identifier that begins with an upper-case letter is a token.
+
+
Sometimes it is useful to declare tokens in advance, however. The
+integer values assigned to each token determined by the order in which
+the tokens are seen. So by declaring tokens in advance, it is possible to
+cause some tokens to have low-numbered values, which might be desirable in
+some grammers, or to have sequential values assigned to a sequence of
+related tokens. For this reason, the %token directive is provided to
+declare tokens in advance. The syntax is as follows:
+
+
+%token TOKEN TOKEN... .
+
+
+The %token directive is followed by zero or more token symbols and
+terminated by a single ".". Each token named is created if it does not
+already exist. Tokens are created in order.
+
-
4.4.20 The %token_class directive
+4.4.21 The %token_class directive
Undocumented. Appears to be related to the MULTITERMINAL concept.
Implementation.
-4.4.21 The %token_destructor directive
+4.4.22 The %token_destructor directive
The %destructor directive assigns a destructor to a non-terminal
symbol. (See the description of the
@@ -1102,7 +1126,7 @@
4.4.21 The %token_destructor directive
destructors.
-4.4.22 The %token_prefix directive
+4.4.23 The %token_prefix directive
Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
@@ -1129,7 +1153,7 @@
4.4.22 The %token_prefix directive
-4.4.23 The %token_type and %type directives
+4.4.24 The %token_type and %type directives
These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
@@ -1166,7 +1190,7 @@
4.4.23 The %token_type and %type directives
and able to pay that price, fine. You just need to know.
-4.4.24 The %wildcard directive
+4.4.25 The %wildcard directive
The %wildcard directive is followed by a single token name and a
period. This directive specifies that the identified token should
@@ -1176,7 +1200,7 @@
4.4.24 The %wildcard directive
the wildcard token and some other token, the other token is always used.
The wildcard token is only matched if there are no alternatives.
-
+
5.0 Error Processing
After extensive experimentation over several years, it has been
diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test
index f49f1f5e5..3987d0c91 100644
--- a/ext/expert/expert1.test
+++ b/ext/expert/expert1.test
@@ -28,6 +28,7 @@ if {[info commands sqlite3_expert_new]==""} {
return
}
+
set CLI [test_binary_name sqlite3]
set CMD [test_binary_name sqlite3_expert]
@@ -102,7 +103,7 @@ do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
SELECT * FROM t1
} {
(no new indexes)
- SCAN TABLE t1
+ SCAN t1
}
do_setup_rec_test $tn.2 {
@@ -111,7 +112,7 @@ do_setup_rec_test $tn.2 {
SELECT * FROM t1 WHERE b>?;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
- SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
+ SEARCH t1 USING INDEX t1_idx_00000062 (b>?)
}
do_setup_rec_test $tn.3 {
@@ -120,7 +121,7 @@ do_setup_rec_test $tn.3 {
SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
} {
CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
- SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b)
+ SEARCH t1 USING INDEX t1_idx_3e094c27 (b>? AND b)
}
do_setup_rec_test $tn.4 {
@@ -129,7 +130,7 @@ do_setup_rec_test $tn.4 {
SELECT a FROM t1 ORDER BY b;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
- SCAN TABLE t1 USING INDEX t1_idx_00000062
+ SCAN t1 USING INDEX t1_idx_00000062
}
do_setup_rec_test $tn.5 {
@@ -138,7 +139,7 @@ do_setup_rec_test $tn.5 {
SELECT a FROM t1 WHERE a=? ORDER BY b;
} {
CREATE INDEX t1_idx_000123a7 ON t1(a, b);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
+ SEARCH t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
}
if 0 {
@@ -148,7 +149,7 @@ do_setup_rec_test $tn.6 {
SELECT min(a) FROM t1
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
+ SEARCH t1 USING COVERING INDEX t1_idx_00000061
}
}
@@ -158,7 +159,7 @@ do_setup_rec_test $tn.7 {
SELECT * FROM t1 ORDER BY a, b, c;
} {
CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
+ SCAN t1 USING COVERING INDEX t1_idx_033e95fe
}
#do_setup_rec_test $tn.1.8 {
@@ -167,7 +168,7 @@ do_setup_rec_test $tn.7 {
# SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
#} {
# CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
-# 0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
+# 0|0|0|SCAN t1 USING COVERING INDEX t1_idx_5be6e222
#}
do_setup_rec_test $tn.8.1 {
@@ -176,7 +177,7 @@ do_setup_rec_test $tn.8.1 {
SELECT * FROM t1 WHERE a=?
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
- SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
+ SEARCH t1 USING INDEX t1_idx_00000061 (a=?)
}
do_setup_rec_test $tn.8.2 {
CREATE TABLE t1(a, b COLLATE nocase, c);
@@ -184,7 +185,7 @@ do_setup_rec_test $tn.8.2 {
SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
} {
CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
- SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
+ SCAN t1 USING COVERING INDEX t1_idx_5cb97285
}
@@ -196,7 +197,7 @@ do_setup_rec_test $tn.9.1 {
SELECT * FROM "t t" WHERE a=?
} {
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
- SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
+ SEARCH t t USING INDEX t t_idx_00000061 (a=?)
}
do_setup_rec_test $tn.9.2 {
@@ -205,7 +206,7 @@ do_setup_rec_test $tn.9.2 {
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
} {
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
- SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b)
+ SEARCH t t USING INDEX t t_idx_00000062 (b>? AND b)
}
# Columns with names that require quotes.
@@ -216,7 +217,7 @@ do_setup_rec_test $tn.10.1 {
SELECT * FROM t3 WHERE "b b" = ?
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
+ SEARCH t3 USING INDEX t3_idx_00050c52 (b b=?)
}
do_setup_rec_test $tn.10.2 {
@@ -225,7 +226,7 @@ do_setup_rec_test $tn.10.2 {
SELECT * FROM t3 ORDER BY "b b"
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
- SCAN TABLE t3 USING INDEX t3_idx_00050c52
+ SCAN t3 USING INDEX t3_idx_00050c52
}
# Transitive constraints
@@ -238,8 +239,8 @@ do_setup_rec_test $tn.11.1 {
} {
CREATE INDEX t5_idx_000123a7 ON t5(a, b);
CREATE INDEX t6_idx_00000063 ON t6(c);
- SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
- SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
+ SEARCH t6 USING INDEX t6_idx_00000063 (c=?)
+ SEARCH t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
}
# OR terms.
@@ -253,9 +254,9 @@ do_setup_rec_test $tn.12.1 {
CREATE INDEX t7_idx_00000061 ON t7(a);
MULTI-INDEX OR
INDEX 1
- SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
+ SEARCH t7 USING INDEX t7_idx_00000061 (a=?)
INDEX 2
- SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
+ SEARCH t7 USING INDEX t7_idx_00000062 (b=?)
}
# rowid terms.
@@ -266,7 +267,7 @@ do_setup_rec_test $tn.13.1 {
SELECT * FROM t8 WHERE rowid=?
} {
(no new indexes)
- SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
+ SEARCH t8 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.13.2 {
CREATE TABLE t8(a, b);
@@ -274,7 +275,7 @@ do_setup_rec_test $tn.13.2 {
SELECT * FROM t8 ORDER BY rowid
} {
(no new indexes)
- SCAN TABLE t8
+ SCAN t8
}
do_setup_rec_test $tn.13.3 {
CREATE TABLE t8(a, b);
@@ -282,7 +283,7 @@ do_setup_rec_test $tn.13.3 {
SELECT * FROM t8 WHERE a=? ORDER BY rowid
} {
CREATE INDEX t8_idx_00000061 ON t8(a);
- SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
+ SEARCH t8 USING INDEX t8_idx_00000061 (a=?)
}
# Triggers
@@ -297,7 +298,7 @@ do_setup_rec_test $tn.14 {
INSERT INTO t9 VALUES(?, ?, ?);
} {
CREATE INDEX t10_idx_00000062 ON t10(b);
- SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
+ SEARCH t10 USING INDEX t10_idx_00000062 (b=?)
}
do_setup_rec_test $tn.15 {
@@ -313,8 +314,8 @@ do_setup_rec_test $tn.15 {
SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
} {
CREATE INDEX t2_idx_00000064 ON t2(d);
- SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
- SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ SEARCH t2 USING INDEX t2_idx_00000064 (d=?)
+ SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.16 {
@@ -323,7 +324,7 @@ do_setup_rec_test $tn.16 {
SELECT * FROM t1 WHERE b IS NOT NULL;
} {
(no new indexes)
- SCAN TABLE t1
+ SCAN t1
}
do_setup_rec_test $tn.17.1 {
@@ -332,7 +333,7 @@ do_setup_rec_test $tn.17.1 {
SELECT * FROM example WHERE a=?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=?)
}
do_setup_rec_test $tn.17.2 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -340,7 +341,7 @@ do_setup_rec_test $tn.17.2 {
SELECT * FROM example WHERE b=?
} {
CREATE INDEX example_idx_00000042 ON example(B);
- SEARCH TABLE example USING INDEX example_idx_00000042 (B=?)
+ SEARCH example USING INDEX example_idx_00000042 (B=?)
}
do_setup_rec_test $tn.17.3 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -348,7 +349,7 @@ do_setup_rec_test $tn.17.3 {
SELECT * FROM example WHERE a=? AND b=?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
}
do_setup_rec_test $tn.17.4 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -356,7 +357,7 @@ do_setup_rec_test $tn.17.4 {
SELECT * FROM example WHERE a=? AND b>?
} {
(no new indexes)
- SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
+ SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
}
do_setup_rec_test $tn.17.5 {
CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
@@ -364,7 +365,30 @@ do_setup_rec_test $tn.17.5 {
SELECT * FROM example WHERE a>? AND b=?
} {
CREATE INDEX example_idx_0000cb3f ON example(B, A);
- SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
+ SEARCH example USING INDEX example_idx_0000cb3f (B=? AND A>?)
+}
+
+do_setup_rec_test $tn.18.0 {
+ CREATE TABLE SomeObject (
+ a INTEGER PRIMARY KEY,
+ x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
+ );
+} {
+ SELECT x FROM SomeObject;
+} {
+ (no new indexes)
+ SCAN SomeObject
+}
+do_setup_rec_test $tn.18.1 {
+ CREATE TABLE SomeObject (
+ a INTEGER PRIMARY KEY,
+ x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
+ );
+} {
+ SELECT * FROM SomeObject WHERE x=?;
+} {
+ CREATE INDEX SomeObject_idx_00000078 ON SomeObject(x);
+ SEARCH SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
}
}
@@ -430,5 +454,4 @@ do_execsql_test 5.3 {
t2 t2_idx_0001295b {100 20 5}
}
-
finish_test
diff --git a/ext/expert/sqlite3expert.c b/ext/expert/sqlite3expert.c
index 5c1342320..863c6a340 100644
--- a/ext/expert/sqlite3expert.c
+++ b/ext/expert/sqlite3expert.c
@@ -687,7 +687,7 @@ static int idxGetTableInfo(
char *pCsr = 0;
int nPk = 0;
- rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
+ rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
nByte += 1 + STRLEN(zCol);
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index 79dc5c88c..9c5703d3f 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -326,7 +326,9 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
int sqlite3_fts3_may_be_corrupt = 1;
+#endif
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
@@ -1897,7 +1899,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -1913,8 +1915,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -1967,20 +1969,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
@@ -3586,14 +3588,20 @@ static int fts3SetHasStat(Fts3Table *p){
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
+ int rc;
UNUSED_PARAMETER(pVtab);
assert( p->pSegments==0 );
assert( p->nPendingData==0 );
assert( p->inTransaction!=1 );
- TESTONLY( p->inTransaction = 1 );
- TESTONLY( p->mxSavepoint = -1; );
p->nLeafAdd = 0;
- return fts3SetHasStat(p);
+ rc = fts3SetHasStat(p);
+#ifdef SQLITE_DEBUG
+ if( rc==SQLITE_OK ){
+ p->inTransaction = 1;
+ p->mxSavepoint = -1;
+ }
+#endif
+ return rc;
}
/*
@@ -5122,16 +5130,15 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
- Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
- apOr = (Fts3Expr **)&aTC[nToken];
if( !aTC ){
rc = SQLITE_NOMEM;
}else{
+ Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
int ii;
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
@@ -5212,9 +5219,9 @@ static int fts3EvalNearTrim(
);
if( res ){
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
- if( nNew>=0 ){
+ assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
+ if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
assert( pPhrase->doclist.pList[nNew]=='\0' );
- assert( nNew<=pPhrase->doclist.nList && nNew>0 );
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
pPhrase->doclist.nList = nNew;
}
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index b3e0ec85f..8c2579166 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -134,7 +134,7 @@ SQLITE_EXTENSION_INIT3
** is used for assert() conditions that are true only if it can be
** guranteed that the database is not corrupt.
*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+#ifdef SQLITE_DEBUG
extern int sqlite3_fts3_may_be_corrupt;
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
#else
diff --git a/ext/fts3/fts3_aux.c b/ext/fts3/fts3_aux.c
index 08edc00f4..b6e651853 100644
--- a/ext/fts3/fts3_aux.c
+++ b/ext/fts3/fts3_aux.c
@@ -406,6 +406,7 @@ static int fts3auxFilterMethod(
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->aStat);
+ sqlite3_free(pCsr->zStop);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c
index e19137a03..7a69a935f 100644
--- a/ext/fts3/fts3_expr.c
+++ b/ext/fts3/fts3_expr.c
@@ -493,6 +493,11 @@ static int getNextNode(
if( *zInput=='(' ){
int nConsumed = 0;
pParse->nNest++;
+#if !defined(SQLITE_MAX_EXPR_DEPTH)
+ if( pParse->nNest>1000 ) return SQLITE_ERROR;
+#elif SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR;
+#endif
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c
index ebc771fd6..613d3e5f1 100644
--- a/ext/fts3/fts3_snippet.c
+++ b/ext/fts3/fts3_snippet.c
@@ -17,6 +17,10 @@
#include
#include
+#ifndef SQLITE_AMALGAMATION
+typedef sqlite3_int64 i64;
+#endif
+
/*
** Characters that may appear in the second argument to matchinfo().
*/
@@ -67,9 +71,9 @@ struct SnippetIter {
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
- int iHead; /* Next value in position list */
+ i64 iHead; /* Next value in position list */
char *pHead; /* Position list data following iHead */
- int iTail; /* Next value in trailing position list */
+ i64 iTail; /* Next value in trailing position list */
char *pTail; /* Position list data following iTail */
};
@@ -234,7 +238,7 @@ void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
-static void fts3GetDeltaPosition(char **pp, int *piPos){
+static void fts3GetDeltaPosition(char **pp, i64 *piPos){
int iVal;
*pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
@@ -343,10 +347,10 @@ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
-static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
+static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
- int iIter = *piIter;
+ i64 iIter = *piIter;
while( iIteraPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
- int iCsr = pPhrase->iTail;
+ i64 iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
@@ -475,7 +479,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( pCsr ){
- int iFirst = 0;
+ i64 iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
if( iFirst<0 ){
@@ -1539,8 +1543,8 @@ typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
- int iPos; /* Position just read from pList */
- int iOff; /* Offset of this term from read positions */
+ i64 iPos; /* Position just read from pList */
+ i64 iOff; /* Offset of this term from read positions */
};
struct TermOffsetCtx {
@@ -1559,7 +1563,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
int nTerm; /* Number of tokens in phrase */
int iTerm; /* For looping through nTerm phrase terms */
char *pList; /* Pointer to position list for phrase */
- int iPos = 0; /* First position in position-list */
+ i64 iPos = 0; /* First position in position-list */
int rc;
UNUSED_PARAMETER(iPhrase);
diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c
index fa0f00a6c..49a8476bf 100644
--- a/ext/fts3/fts3_test.c
+++ b/ext/fts3/fts3_test.c
@@ -585,6 +585,7 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifdef SQLITE_DEBUG
int bOld = sqlite3_fts3_may_be_corrupt;
if( objc!=2 && objc!=1 ){
@@ -598,6 +599,7 @@ static int SQLITE_TCLAPI fts3_may_be_corrupt(
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
+#endif
return TCL_OK;
}
diff --git a/ext/fts3/fts3_unicode.c b/ext/fts3/fts3_unicode.c
index b06d99214..2fd4b39fb 100644
--- a/ext/fts3/fts3_unicode.c
+++ b/ext/fts3/fts3_unicode.c
@@ -285,6 +285,7 @@ static int unicodeOpen(
pCsr->aInput = (const unsigned char *)aInput;
if( aInput==0 ){
pCsr->nInput = 0;
+ pCsr->aInput = (const unsigned char*)"";
}else if( nInput<0 ){
pCsr->nInput = (int)strlen(aInput);
}else{
diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
index 092cad9ac..56c59ce3a 100644
--- a/ext/fts3/fts3_write.c
+++ b/ext/fts3/fts3_write.c
@@ -1807,7 +1807,7 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
if( rc==0 ){
rc = pRhs->iIdx - pLhs->iIdx;
}
- assert( rc!=0 );
+ assert_fts3_nc( rc!=0 );
return rc;
}
@@ -2003,8 +2003,8 @@ static int fts3PrefixCompress(
int nNext /* Size of buffer zNext in bytes */
){
int n;
- UNUSED_PARAMETER(nNext);
- for(n=0; nkey, reader.term.n, &rc);
if( rc==SQLITE_OK ){
- memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
+ if( reader.term.n>0 ){
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ }
pNode->key.n = reader.term.n;
if( i>0 ){
char *aBlock = 0;
int nBlock = 0;
pNode = &pWriter->aNodeWriter[i-1];
pNode->iBlock = reader.iChild;
- rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
+ rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
blobGrowBuffer(&pNode->block,
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
- );
+ );
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c
index cb768ebb1..a8f3bee33 100644
--- a/ext/fts5/fts5_buffer.c
+++ b/ext/fts5/fts5_buffer.c
@@ -178,6 +178,7 @@ int sqlite3Fts5PoslistNext64(
i64 iOff = *piOff;
int iVal;
fts5FastGetVarint32(a, i, iVal);
+ assert( iVal>=0 );
if( iVal<=1 ){
if( iVal==0 ){
*pi = i;
@@ -191,9 +192,12 @@ int sqlite3Fts5PoslistNext64(
*piOff = -1;
return 1;
}
+ *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
+ }else{
+ *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
}
- *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
*pi = i;
+ assert( *piOff>=iOff );
return 0;
}
}
@@ -232,14 +236,16 @@ void sqlite3Fts5PoslistSafeAppend(
i64 *piPrev,
i64 iPos
){
- static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
- if( (iPos & colmask) != (*piPrev & colmask) ){
- pBuf->p[pBuf->n++] = 1;
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
- *piPrev = (iPos & colmask);
+ if( iPos>=*piPrev ){
+ static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
+ if( (iPos & colmask) != (*piPrev & colmask) ){
+ pBuf->p[pBuf->n++] = 1;
+ pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
+ *piPrev = (iPos & colmask);
+ }
+ pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
+ *piPrev = iPos;
}
- pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
- *piPrev = iPos;
}
int sqlite3Fts5PoslistWriterAppend(
diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c
index 6c02d2b35..32335c937 100644
--- a/ext/fts5/fts5_config.c
+++ b/ext/fts5/fts5_config.c
@@ -537,7 +537,7 @@ int sqlite3Fts5ConfigParse(
nByte = nArg * (sizeof(char*) + sizeof(u8));
pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
- pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
+ pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0;
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
pRet->bColumnsize = 1;
diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c
index 392dde3ab..f3cec00be 100644
--- a/ext/fts5/fts5_expr.c
+++ b/ext/fts5/fts5_expr.c
@@ -1500,8 +1500,8 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
}
/* If the iterator is not at a real match, skip forward until it is. */
- while( pRoot->bNomatch ){
- assert( pRoot->bEof==0 && rc==SQLITE_OK );
+ while( pRoot->bNomatch && rc==SQLITE_OK ){
+ assert( pRoot->bEof==0 );
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
}
return rc;
@@ -2412,6 +2412,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
return pRet;
}
+#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
@@ -2778,12 +2779,14 @@ static void fts5ExprFold(
sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
}
}
+#endif /* ifdef SQLITE_TEST */
/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
+#ifdef SQLITE_TEST
struct Fts5ExprFunc {
const char *z;
void (*x)(sqlite3_context*,int,sqlite3_value**);
@@ -2801,6 +2804,10 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
+#else
+ int rc = SQLITE_OK;
+ UNUSED_PARAM2(pGlobal,db);
+#endif
/* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
** sqlite3Fts5ParserFallback() are unused */
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index f83488e2f..7cc0d46ac 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -431,7 +431,7 @@ struct Fts5SegIter {
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
- int iLeafOffset; /* Byte offset within current leaf */
+ i64 iLeafOffset; /* Byte offset within current leaf */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
@@ -1611,7 +1611,7 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset;
+ i64 iOff = pIter->iLeafOffset;
ASSERT_SZLEAF_OK(pIter->pLeaf);
if( iOff>=pIter->pLeaf->szLeaf ){
@@ -1644,7 +1644,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset; /* Offset to read at */
+ i64 iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
@@ -2070,14 +2070,9 @@ static void fts5SegIterNext(
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
- ** code is inlined.
- **
- ** Later: Switched back to fts5SegIterLoadNPos() because it supports
- ** detail=none mode. Not ideal.
- */
+ ** code is inlined. */
int nSz;
- assert( p->rc==SQLITE_OK );
- assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
+ assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -3069,7 +3064,7 @@ static void fts5ChunkIterate(
int pgno = pSeg->iLeafPgno;
int pgnoSave = 0;
- /* This function does notmwork with detail=none databases. */
+ /* This function does not work with detail=none databases. */
assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
@@ -3082,6 +3077,9 @@ static void fts5ChunkIterate(
fts5DataRelease(pData);
if( nRem<=0 ){
break;
+ }else if( pSeg->pSeg==0 ){
+ p->rc = FTS5_CORRUPT;
+ return;
}else{
pgno++;
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
@@ -3133,66 +3131,72 @@ static void fts5SegiterPoslist(
}
/*
-** IN/OUT parameter (*pa) points to a position list n bytes in size. If
-** the position list contains entries for column iCol, then (*pa) is set
-** to point to the sub-position-list for that column and the number of
-** bytes in it returned. Or, if the argument position list does not
-** contain any entries for column iCol, return 0.
+** Parameter pPos points to a buffer containing a position list, size nPos.
+** This function filters it according to pColset (which must be non-NULL)
+** and sets pIter->base.pData/nData to point to the new position list.
+** If memory is required for the new position list, use buffer pIter->poslist.
+** Or, if the new position list is a contiguous subset of the input, set
+** pIter->base.pData/nData to point directly to it.
+**
+** This function is a no-op if *pRc is other than SQLITE_OK when it is
+** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
+** before returning.
*/
-static int fts5IndexExtractCol(
- const u8 **pa, /* IN/OUT: Pointer to poslist */
- int n, /* IN: Size of poslist in bytes */
- int iCol /* Column to extract from poslist */
-){
- int iCurrent = 0; /* Anything before the first 0x01 is col 0 */
- const u8 *p = *pa;
- const u8 *pEnd = &p[n]; /* One byte past end of position list */
-
- while( iCol>iCurrent ){
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint. Note that it is not possible for a negative
- ** or extremely large varint to occur within an uncorrupted position
- ** list. So the last byte of each varint may be assumed to have a clear
- ** 0x80 bit. */
- while( *p!=0x01 ){
- while( *p++ & 0x80 );
- if( p>=pEnd ) return 0;
- }
- *pa = p++;
- iCurrent = *p++;
- if( iCurrent & 0x80 ){
- p--;
- p += fts5GetVarint32(p, iCurrent);
- }
- }
- if( iCol!=iCurrent ) return 0;
-
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint */
- while( pnCol; i++){
- const u8 *pSub = pPos;
- int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
- if( nSub ){
- fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
+ const u8 *p = pPos;
+ const u8 *aCopy = p;
+ const u8 *pEnd = &p[nPos]; /* One byte past end of position list */
+ int i = 0;
+ int iCurrent = 0;
+
+ if( pColset->nCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
+ return;
+ }
+
+ while( 1 ){
+ while( pColset->aiCol[i]nCol ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ }
+
+ /* Advance pointer p until it points to pEnd or an 0x01 byte that is
+ ** not part of a varint */
+ while( paiCol[i]==iCurrent ){
+ if( pColset->nCol==1 ){
+ pIter->base.pData = aCopy;
+ pIter->base.nData = p-aCopy;
+ return;
+ }
+ fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
+ }
+ if( p>=pEnd ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ aCopy = p++;
+ iCurrent = *p++;
+ if( iCurrent & 0x80 ){
+ p--;
+ p += fts5GetVarint32(p, iCurrent);
}
}
}
+
}
/*
@@ -3312,16 +3316,9 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- if( pColset->nCol==1 ){
- pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
- pIter->base.pData = a;
- }else{
- int *pRc = &pIter->pIndex->rc;
- fts5BufferZero(&pIter->poslist);
- fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
- }
+ int *pRc = &pIter->pIndex->rc;
+ fts5BufferZero(&pIter->poslist);
+ fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
@@ -4543,14 +4540,14 @@ static void fts5FlushOneHash(Fts5Index *p){
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
}else{
i64 iRowid = 0;
- i64 iDelta = 0;
+ u64 iDelta = 0;
int iOff = 0;
/* The entire doclist will not fit on this leaf. The following
** loop iterates through the poslists that make up the current
** doclist. */
while( p->rc==SQLITE_OK && iOffaPoslist + pIter->nSize + pIter->nPoslist;
- assert( pIter->aPoslist );
+ assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
if( p>=pIter->aEof ){
pIter->aPoslist = 0;
}else{
@@ -4824,6 +4821,9 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
}
pIter->aPoslist = p;
+ if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
+ pIter->aPoslist = 0;
+ }
}
}
@@ -4832,9 +4832,11 @@ static void fts5DoclistIterInit(
Fts5DoclistIter *pIter
){
memset(pIter, 0, sizeof(*pIter));
- pIter->aPoslist = pBuf->p;
- pIter->aEof = &pBuf->p[pBuf->n];
- fts5DoclistIterNext(pIter);
+ if( pBuf->n>0 ){
+ pIter->aPoslist = pBuf->p;
+ pIter->aEof = &pBuf->p[pBuf->n];
+ fts5DoclistIterNext(pIter);
+ }
}
#if 0
@@ -4888,16 +4890,20 @@ static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
static void fts5MergeRowidLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
+ int nBuf, /* Number of entries in apBuf[] */
+ Fts5Buffer *aBuf /* Array of other lists to merge into p1 */
){
int i1 = 0;
int i2 = 0;
i64 iRowid1 = 0;
i64 iRowid2 = 0;
i64 iOut = 0;
-
+ Fts5Buffer *p2 = &aBuf[0];
Fts5Buffer out;
+
+ (void)nBuf;
memset(&out, 0, sizeof(out));
+ assert( nBuf==1 );
sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
if( p->rc ) return;
@@ -4924,180 +4930,214 @@ static void fts5MergeRowidLists(
fts5BufferFree(&out);
}
+typedef struct PrefixMerger PrefixMerger;
+struct PrefixMerger {
+ Fts5DoclistIter iter; /* Doclist iterator */
+ i64 iPos; /* For iterating through a position list */
+ int iOff;
+ u8 *aPos;
+ PrefixMerger *pNext; /* Next in docid/poslist order */
+};
+
+static void fts5PrefixMergerInsertByRowid(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iter.aPoslist ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+static void fts5PrefixMergerInsertByPosition(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iPos>=0 ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iPos>(*pp)->iPos ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+
/*
-** Buffers p1 and p2 contain doclists. This function merges the content
-** of the two doclists together and sets buffer p1 to the result before
-** returning.
-**
-** If an error occurs, an error code is left in p->rc. If an error has
-** already occurred, this function is a no-op.
+** Array aBuf[] contains nBuf doclists. These are all merged in with the
+** doclist in buffer p1.
*/
static void fts5MergePrefixLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
+ int nBuf, /* Number of buffers in array aBuf[] */
+ Fts5Buffer *aBuf /* Other lists to merge in */
){
- if( p2->n ){
- i64 iLastRowid = 0;
- Fts5DoclistIter i1;
- Fts5DoclistIter i2;
- Fts5Buffer out = {0, 0, 0};
- Fts5Buffer tmp = {0, 0, 0};
-
- /* The maximum size of the output is equal to the sum of the two
- ** input sizes + 1 varint (9 bytes). The extra varint is because if the
- ** first rowid in one input is a large negative number, and the first in
- ** the other a non-negative number, the delta for the non-negative
- ** number will be larger on disk than the literal integer value
- ** was.
- **
- ** Or, if the input position-lists are corrupt, then the output might
- ** include up to 2 extra 10-byte positions created by interpreting -1
- ** (the value PoslistNext64() uses for EOF) as a position and appending
- ** it to the output. This can happen at most once for each input
- ** position-list, hence two 10 byte paddings. */
- if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9+10+10) ) return;
- fts5DoclistIterInit(p1, &i1);
- fts5DoclistIterInit(p2, &i2);
-
- while( 1 ){
- if( i1.iRowidp) + (i2.aPoslist-p2->p)+9+10+10) );
- }
- else if( i2.iRowid!=i1.iRowid ){
- /* Copy entry from i2 */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
- fts5DoclistIterNext(&i2);
- if( i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
+#define fts5PrefixMergerNextPosition(p) \
+ sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos)
+#define FTS5_MERGE_NLIST 16
+ PrefixMerger aMerger[FTS5_MERGE_NLIST];
+ PrefixMerger *pHead = 0;
+ int i;
+ int nOut = 0;
+ Fts5Buffer out = {0, 0, 0};
+ Fts5Buffer tmp = {0, 0, 0};
+ i64 iLastRowid = 0;
+
+ /* Initialize a doclist-iterator for each input buffer. Arrange them in
+ ** a linked-list starting at pHead in ascending order of rowid. Avoid
+ ** linking any iterators already at EOF into the linked list at all. */
+ assert( nBuf+1<=sizeof(aMerger)/sizeof(aMerger[0]) );
+ memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
+ pHead = &aMerger[nBuf];
+ fts5DoclistIterInit(p1, &pHead->iter);
+ for(i=0; in + 9 + 10*nBuf;
+
+ /* The maximum size of the output is equal to the sum of the
+ ** input sizes + 1 varint (9 bytes). The extra varint is because if the
+ ** first rowid in one input is a large negative number, and the first in
+ ** the other a non-negative number, the delta for the non-negative
+ ** number will be larger on disk than the literal integer value
+ ** was.
+ **
+ ** Or, if the input position-lists are corrupt, then the output might
+ ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
+ ** (the value PoslistNext64() uses for EOF) as a position and appending
+ ** it to the output. This can happen at most once for each input
+ ** position-list, hence (nBuf+1) 10 byte paddings. */
+ if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
+
+ while( pHead ){
+ fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
+
+ if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
+ /* Merge data from two or more poslists */
+ i64 iPrev = 0;
+ int nTmp = FTS5_DATA_ZERO_PADDING;
+ int nMerge = 0;
+ PrefixMerger *pSave = pHead;
+ PrefixMerger *pThis = 0;
+ int nTail = 0;
+
+ pHead = 0;
+ while( pSave && pSave->iter.iRowid==iLastRowid ){
+ PrefixMerger *pNext = pSave->pNext;
+ pSave->iOff = 0;
+ pSave->iPos = 0;
+ pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
+ fts5PrefixMergerNextPosition(pSave);
+ nTmp += pSave->iter.nPoslist + 10;
+ nMerge++;
+ fts5PrefixMergerInsertByPosition(&pHead, pSave);
+ pSave = pNext;
}
- else{
- /* Merge the two position lists. */
- i64 iPos1 = 0;
- i64 iPos2 = 0;
- int iOff1 = 0;
- int iOff2 = 0;
- u8 *a1 = &i1.aPoslist[i1.nSize];
- u8 *a2 = &i2.aPoslist[i2.nSize];
- int nCopy;
- u8 *aCopy;
-
- i64 iPrev = 0;
- Fts5PoslistWriter writer;
- memset(&writer, 0, sizeof(writer));
-
- /* See the earlier comment in this function for an explanation of why
- ** corrupt input position lists might cause the output to consume
- ** at most 20 bytes of unexpected space. */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp,
- i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
- );
- if( p->rc ) break;
- sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- assert_nc( iPos1>=0 && iPos2>=0 );
+ if( pHead==0 || pHead->pNext==0 ){
+ p->rc = FTS5_CORRUPT;
+ break;
+ }
- if( iPos1=0 && iPos2>=0 ){
- while( 1 ){
- if( iPos1rc, &tmp, nTmp+nMerge*10) ){
+ break;
+ }
+ fts5BufferZero(&tmp);
+
+ pThis = pHead;
+ pHead = pThis->pNext;
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
+ fts5PrefixMergerNextPosition(pThis);
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
+
+ while( pHead->pNext ){
+ pThis = pHead;
+ if( pThis->iPos!=iPrev ){
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
}
+ fts5PrefixMergerNextPosition(pThis);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
+ }
- if( iPos1>=0 ){
- if( iPos1!=iPrev ){
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- aCopy = &a1[iOff1];
- nCopy = i1.nPoslist - iOff1;
- }else{
- assert_nc( iPos2>=0 && iPos2!=iPrev );
- sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- aCopy = &a2[iOff2];
- nCopy = i2.nPoslist - iOff2;
- }
- if( nCopy>0 ){
- fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
- }
+ if( pHead->iPos!=iPrev ){
+ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
+ }
+ nTail = pHead->iter.nPoslist - pHead->iOff;
- /* WRITEPOSLISTSIZE */
- assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
- assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
- if( tmp.n>i1.nPoslist+i2.nPoslist ){
- if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
- break;
+ /* WRITEPOSLISTSIZE */
+ assert_nc( tmp.n+nTail<=nTmp );
+ assert( tmp.n+nTail<=nTmp+nMerge*10 );
+ if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
+ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
+ break;
+ }
+ fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
+ fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
+ if( nTail>0 ){
+ fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
+ }
+
+ pHead = pSave;
+ for(i=0; iiter.aPoslist && pX->iter.iRowid==iLastRowid ){
+ fts5DoclistIterNext(&pX->iter);
+ fts5PrefixMergerInsertByRowid(&pHead, pX);
}
- fts5BufferSafeAppendVarint(&out, tmp.n * 2);
- fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
- fts5DoclistIterNext(&i1);
- fts5DoclistIterNext(&i2);
- assert_nc( out.n<=(p1->n+p2->n+9) );
- if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
- }
- if( i1.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
- }
- else if( i2.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
+ }else{
+ /* Copy poslist from pHead to output */
+ PrefixMerger *pThis = pHead;
+ Fts5DoclistIter *pI = &pThis->iter;
+ fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
+ fts5DoclistIterNext(pI);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByRowid(&pHead, pThis);
}
- assert_nc( out.n<=(p1->n+p2->n+9) );
-
- fts5BufferFree(p1);
- fts5BufferFree(&tmp);
- memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
- *p1 = out;
}
+
+ fts5BufferFree(p1);
+ fts5BufferFree(&tmp);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
- const u8 *pToken, /* Buffer containing prefix to match */
+ int iIdx, /* Index to scan for data */
+ u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
Fts5Buffer *aBuf;
- const int nBuf = 32;
+ int nBuf = 32;
+ int nMerge = 1;
- void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid;
}else{
+ nMerge = FTS5_MERGE_NLIST-1;
+ nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
xMerge = fts5MergePrefixLists;
xAppend = fts5AppendPoslist;
}
@@ -5117,6 +5157,27 @@ static void fts5SetupPrefixIter(
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
+ if( iIdx!=0 ){
+ int dummy = 0;
+ const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
+ pToken[0] = FTS5_MAIN_PREFIX;
+ fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
+ for(;
+ fts5MultiIterEof(p, p1)==0;
+ fts5MultiIterNext2(p, p1, &dummy)
+ ){
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
+ p1->xSetOutputs(p1, pSeg);
+ if( p1->base.nData ){
+ xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
+ iLastRowid = p1->base.iRowid;
+ }
+ }
+ fts5MultiIterFree(p1);
+ }
+
+ pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
@@ -5137,13 +5198,21 @@ static void fts5SetupPrefixIter(
if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
- assert( ibase.iRowid;
}
- for(i=0; irc==SQLITE_OK ){
- xMerge(p, &doclist, &aBuf[i]);
+ xMerge(p, &doclist, nMerge, &aBuf[i]);
+ }
+ for(iFree=i; iFreerc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
+ int iPrefixIdx = 0; /* +1 prefix index */
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
@@ -5433,7 +5507,9 @@ int sqlite3Fts5IndexQuery(
if( flags & FTS5INDEX_QUERY_PREFIX ){
int nChar = fts5IndexCharlen(pToken, nToken);
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
- if( pConfig->aPrefix[iIdx-1]==nChar ) break;
+ int nIdxChar = pConfig->aPrefix[iIdx-1];
+ if( nIdxChar==nChar ) break;
+ if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
@@ -5450,8 +5526,7 @@ int sqlite3Fts5IndexQuery(
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
- buf.p[0] = FTS5_MAIN_PREFIX;
- fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
+ fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
fts5IterSetOutputCb(&p->rc, pRet);
if( p->rc==SQLITE_OK ){
@@ -5524,8 +5599,9 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
int n;
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
+ assert_nc( z || n<=1 );
*pn = n-1;
- return &z[1];
+ return (z ? &z[1] : 0);
}
/*
@@ -6150,6 +6226,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
** function only.
*/
+#ifdef SQLITE_TEST
/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
@@ -6172,7 +6249,9 @@ static void fts5DecodeRowid(
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -6190,7 +6269,9 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugStructure(
int *pRc, /* IN/OUT: error code */
Fts5Buffer *pBuf,
@@ -6212,7 +6293,9 @@ static void fts5DebugStructure(
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -6237,7 +6320,9 @@ static void fts5DecodeStructure(
fts5DebugStructure(pRc, pBuf, p);
fts5StructureRelease(p);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -6260,7 +6345,9 @@ static void fts5DecodeAverages(
zSpace = " ";
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
@@ -6277,7 +6364,9 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
}
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
@@ -6310,7 +6399,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is
** only ever used with detail=none tables.
@@ -6351,7 +6442,9 @@ static void fts5DecodeRowidList(
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_decode().
*/
@@ -6560,7 +6653,9 @@ static void fts5DecodeFunction(
}
fts5BufferFree(&s);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
@@ -6594,6 +6689,7 @@ static void fts5RowidFunction(
}
}
}
+#endif /* SQLITE_TEST */
/*
** This is called as part of registering the FTS5 module with database
@@ -6604,6 +6700,7 @@ static void fts5RowidFunction(
** SQLite error code is returned instead.
*/
int sqlite3Fts5IndexInit(sqlite3 *db){
+#ifdef SQLITE_TEST
int rc = sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
@@ -6621,6 +6718,10 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
);
}
return rc;
+#else
+ return SQLITE_OK;
+ UNUSED_PARAM(db);
+#endif
}
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 788821e6b..3dea6cafc 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -22,7 +22,9 @@
** assert() conditions in the fts5 code are activated - conditions that are
** only true if it is guaranteed that the fts5 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
int sqlite3_fts5_may_be_corrupt = 1;
+#endif
typedef struct Fts5Auxdata Fts5Auxdata;
@@ -1947,13 +1949,15 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
nInst++;
if( nInst>=pCsr->nInstAlloc ){
- pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
+ int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
aInst = (int*)sqlite3_realloc64(
- pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
+ pCsr->aInst, nNewSize*sizeof(int)*3
);
if( aInst ){
pCsr->aInst = aInst;
+ pCsr->nInstAlloc = nNewSize;
}else{
+ nInst--;
rc = SQLITE_NOMEM;
break;
}
@@ -2177,7 +2181,8 @@ static int fts5ApiPhraseFirst(
int n;
int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
*piOff = 0;
fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
@@ -2236,7 +2241,8 @@ static int fts5ApiPhraseFirstColumn(
rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
}
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
}
@@ -2244,7 +2250,8 @@ static int fts5ApiPhraseFirstColumn(
int n;
rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
if( n<=0 ){
*piCol = -1;
}else if( pIter->a[0]==0x01 ){
@@ -2722,7 +2729,7 @@ int sqlite3Fts5GetTokenizer(
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
rc = pMod->x.xCreate(
- pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
);
pConfig->pTokApi = &pMod->x;
if( rc!=SQLITE_OK ){
diff --git a/ext/fts5/fts5_tcl.c b/ext/fts5/fts5_tcl.c
index f33dcae03..80c600dbb 100644
--- a/ext/fts5/fts5_tcl.c
+++ b/ext/fts5/fts5_tcl.c
@@ -29,7 +29,9 @@
#include
#include
+#ifdef SQLITE_DEBUG
extern int sqlite3_fts5_may_be_corrupt;
+#endif
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*);
@@ -1011,6 +1013,7 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifdef SQLITE_DEBUG
int bOld = sqlite3_fts5_may_be_corrupt;
if( objc!=2 && objc!=1 ){
@@ -1024,6 +1027,7 @@ static int SQLITE_TCLAPI f5tMayBeCorrupt(
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
+#endif
return TCL_OK;
}
diff --git a/ext/fts5/fts5_test_tok.c b/ext/fts5/fts5_test_tok.c
index b5d4162fa..a5d839da6 100644
--- a/ext/fts5/fts5_test_tok.c
+++ b/ext/fts5/fts5_test_tok.c
@@ -211,7 +211,7 @@ static int fts5tokConnectMethod(
rc = pApi->xFindTokenizer(pApi, zModule, &pTokCtx, &pTab->tok);
if( rc==SQLITE_OK ){
- const char **azArg = (const char **)&azDequote[1];
+ const char **azArg = (nDequote>1 ? (const char **)&azDequote[1] : 0);
int nArg = nDequote>0 ? nDequote-1 : 0;
rc = pTab->tok.xCreate(pTokCtx, azArg, nArg, &pTab->pTok);
}
diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test
index 1b7b0c9d8..5604bca76 100644
--- a/ext/fts5/test/fts5corrupt3.test
+++ b/ext/fts5/test/fts5corrupt3.test
@@ -8346,6 +8346,7 @@ do_catchsql_test 58.1 {
#-------------------------------------------------------------------------
do_test 59.0 {
sqlite3 db {}
+ sqlite3_fts5_register_matchinfo db
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-96b136358d01ec.db
@@ -8544,11 +8545,12 @@ do_test 59.0 {
do_catchsql_test 59.1 {
SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*e'
-} {1 {database disk image is malformed}}
+} {0 {}}
#-------------------------------------------------------------------------
do_test 60.0 {
sqlite3 db {}
+ sqlite3_fts5_register_matchinfo db
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-c77b90b929dc92.db
@@ -10507,6 +10509,4631 @@ do_catchsql_test 71.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+reset_db
+do_test 72.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 24576 pagesize 4096 filename crash-77b86d070d0ac6.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 06 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j
+| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .....=..........
+| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet
+| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con
+| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE
+| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k
+| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v)
+| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^..
+| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d
+| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz
+| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE '
+| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id
+| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)]..
+| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c
+| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten
+| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
+| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id
+| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l...
+| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id
+| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE
+| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'(
+| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn
+| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s
+| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT
+| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX.....
+| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data
+| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE
+| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data'
+| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
+| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B
+| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl
+| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI
+| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt
+| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
+| page 2 offset 4096
+| 0: 0d 0f 44 00 05 0e 81 00 0f e7 0e 81 0f af 0f 58 ..D............X
+| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0..........
+| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$......
+| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e.....
+| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................
+| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................
+| 3792: 08 03 03 02 01 65 03 1e 03 05 05 04 05 05 01 01 .....e..........
+| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 05 05 04 ........6.......
+| 3824: 05 05 04 05 05 01 01 03 06 04 04 06 04 04 06 04 ................
+| 3840: 04 06 04 03 03 01 65 03 14 04 05 07 05 05 01 01 ......e.........
+| 3856: 02 08 0a 01 20 04 05 07 05 07 05 07 05 05 01 01 .... ...........
+| 3872: 02 08 0a 09 fa 04 01 65 03 02 0a 01 06 0a 1a 0a .......e........
+| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e.............
+| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*.......
+| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P.......
+| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e......
+| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e....
+| 3968: 05 04 05 05 01 01 03 06 04 04 06 04 03 03 01 65 ...............e
+| 3984: 02 14 04 05 07 05 05 01 01 02 08 0a 04 01 65 02 ..............e.
+| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1
+| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e
+| 4032: 01 10 02 05 05 01 01 04 03 9f 02 01 65 01 12 03 ............e...
+| 4048: 05 05 01 01 03 06 04 03 03 01 65 01 0e 14 05 05 ..........e.....
+| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL.
+| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
+| page 3 offset 8192
+| 0: 0a 00 00 00 03 0f 00 00 00 00 00 00 00 00 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
+| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
+| page 4 offset 12288
+| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R....
+| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee
+| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 65 20 65 eee e ee eeee e
+| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
+| 3664: 20 65 65 20 65 65 55 65 20 65 65 20 65 65 65 20 ee eeUe ee eee
+| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee
+| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e
+| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e
+| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 85 65 20 65 e e e e ee e.e e
+| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 20 65 e eeeee ee e e e
+| 3760: 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 65 ee eee ee eeeee
+| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee
+| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 20 65 ee eeeee ee e e
+| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej
+| 3824: 03 04 00 75 71 65 20 65 65 20 65 65 65 20 65 20 ...uqe ee eee e
+| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee
+| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee
+| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee
+| 3888: 65 20 65 20 65 20 65 64 20 65 65 65 20 65 65 20 e e e ed eee ee
+| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 10 65 eeeee ee e e e.e
+| 3920: 65 20 65 65 65 10 65 65 20 65 65 6a 02 04 00 75 e eee.ee eej...u
+| 3936: 71 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 qe ee eee e ee e
+| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee
+| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e
+| 3984: 65 20 65 65 65 66 65 65 20 65 65 20 65 20 65 20 e eeefee ee e e
+| 4000: 65 88 65 65 20 65 65 65 30 65 65 20 65 65 65 65 e.ee eee0ee eeee
+| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee
+| 4032: 65 20 65 65 20 65 65 37 01 04 00 41 3f 65 20 65 e ee ee7...A?e e
+| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
+| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e
+| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee
+| page 5 offset 16384
+| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 03 03 00 10 .........!!.....
+| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................
+| page 6 offset 20480
+| 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.
+| end crash-77b86d070d0ac6.db
+}]} {}
+
+do_catchsql_test 72.1 {
+ INSERT INTO ttt(ttt) VALUES('integrity-check');
+} {1 {database disk image is malformed}}
+
+do_catchsql_test 72.1 {
+ SELECT 1 FROM ttt('e* NOT ee*');
+} {1 {database disk image is malformed}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_test 73.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 24576 pagesize 4096 filename crash-b02ca2cc4d7dda.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 06 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j
+| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .....=..........
+| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet
+| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con
+| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE
+| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k
+| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v)
+| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^..
+| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d
+| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz
+| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE '
+| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id
+| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)]..
+| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c
+| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten
+| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
+| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id
+| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l...
+| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id
+| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE
+| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'(
+| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn
+| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s
+| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT
+| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX.....
+| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data
+| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE
+| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data'
+| 4000: 28 69 65 20 49 4e 54 45 47 45 52 20 50 52 49 4d (ie INTEGER PRIM
+| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B
+| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl
+| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI
+| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt
+| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
+| page 2 offset 4096
+| 0: 0d 0f 44 00 05 0e 81 00 0f e7 0e 81 0f af 0f 58 ..D............X
+| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0..........
+| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$......
+| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e.....
+| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................
+| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................
+| 3792: 08 03 03 02 01 65 03 1e 03 05 05 04 05 05 01 01 .....e..........
+| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 05 05 04 ........6.......
+| 3824: 05 04 f4 04 05 01 01 03 06 04 04 06 04 04 06 04 ................
+| 3840: 04 06 04 db 03 01 65 03 14 04 05 07 05 05 01 01 ......e.........
+| 3856: 02 08 0a 01 20 04 05 07 05 07 05 07 05 05 01 01 .... ...........
+| 3872: 02 08 0a 0a 0a 04 01 65 03 02 0a 01 06 0a 0a 0a .......e........
+| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e.............
+| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*.......
+| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P.......
+| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e......
+| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e....
+| 3968: 05 04 05 05 01 01 03 06 09 14 06 04 03 03 01 65 ...............e
+| 3984: 02 14 04 05 07 05 05 01 01 02 08 ed 04 01 65 02 ..............e.
+| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1
+| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e
+| 4032: 01 10 02 05 05 01 01 04 03 03 02 01 55 01 12 03 ............U...
+| 4048: 05 05 01 01 03 06 05 03 03 01 65 01 0e 04 05 05 ..........e.....
+| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL.
+| 4080: 00 00 11 24 00 00 00 00 01 0f c1 00 01 01 01 01 ...$............
+| page 3 offset 8192
+| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
+| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
+| page 4 offset 12288
+| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R....
+| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee
+| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 65 20 65 eee e ee eeee e
+| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
+| 3664: 20 65 65 20 65 65 65 65 20 65 65 20 65 65 65 20 ee eeee ee eee
+| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee
+| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e
+| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e
+| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 65 65 20 65 e e e e ee eee e
+| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 20 65 e eeeee ee e e e
+| 3760: 20 65 65 20 65 62 d5 20 65 65 20 65 65 65 65 65 ee eb. ee eeeee
+| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee
+| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 21 65 ee eeeee ee e!e
+| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej
+| 3824: 03 04 00 75 71 65 20 65 65 10 65 65 65 20 65 20 ...uqe ee.eee e
+| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee
+| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee
+| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee
+| 3888: 65 20 65 20 65 20 65 65 20 65 65 65 20 62 55 20 e e e ee eee bU
+| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 20 65 eeeee ee e e e e
+| 3920: 65 20 65 65 65 20 55 65 20 65 65 6a 02 04 00 75 e eee Ue eej...u
+| 3936: 71 65 20 65 65 20 65 65 65 20 65 10 65 65 20 65 qe ee eee e.ee e
+| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee
+| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e
+| 3984: 65 20 65 65 65 65 65 65 20 65 65 20 65 20 65 20 e eeeeee ee e e
+| 4000: 65 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 e ee eee ee eeee
+| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee
+| 4032: 65 20 65 65 21 65 65 37 0a 04 00 41 3f 65 20 65 e ee!ee7...A?e e
+| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
+| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e
+| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee
+| page 5 offset 16384
+| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 13 03 00 10 .........!!.....
+| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................
+| page 6 offset 20480
+| 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.
+| end crash-b02ca2cc4d7dda.db
+}]} {}
+
+do_catchsql_test 73.1 {
+ SELECT snippet(ttt,ttt, NOT 54 ),
+ * FROM ttt('e* NOT ee*e* NOT ee* NOT ee*e* NOT e*') ;
+} {1 {database disk image is malformed}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_test 74.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 106496 pagesize 4096 filename x.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 1a .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
+| 96: 00 2e 4f 78 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ..Ox...........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 d6 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 2 offset 4096
+| 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 01 2f 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 00 00 00 00 00 .......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: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
+| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 8f 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 59 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMYT 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 57 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000WBINARY....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 45 45 59 4e 4f 43 41 53 45 17 LE RTREEYNOCASE.
+| 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: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49 NABLE 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 58 42 49 NABLE GEOPOLYXBI
+| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4f 41 42 4c NARY....)..EOABL
+| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 51 53 45 E GEOPOLYXNOCQSE
+| 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 1d 05 E FTS5XNOCASE...
+| 3728: 00 23 0f a4 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 55 53 34 58 42 49 4e 41 52 59 17 0b LE FUS4XBINARY..
+| 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 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
+| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
+| 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 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...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 58 42 49 4e 41 52 59 27 20160609XBINARY'
+| 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 53 49 4d 0 20160609XRTSIM
+| page 3 offset 8192
+| 0: 05 00 00 00 07 0f ba 00 00 00 00 1a 0f f6 0f ec ................
+| 16: 0f e2 0f d8 0f ce 0f c4 0f ba 00 00 00 00 00 00 ................
+| 3200: 00 00 00 00 00 00 00 00 00 00 08 01 03 00 16 2e ................
+| 3216: b1 7d 24 24 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 01 01 34 00 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 3d ......0000000..=
+| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
+| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 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 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............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 07 65 ebug...........e
+| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 d3 02 01 02 nable...........
+| 3456: 02 01 02 02 02 02 02 01 02 02 01 02 02 01 02 02 ................
+| 3472: 01 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 67 63 63 01 02 54 01 02 03 01 02 03 ....gcc..T......
+| 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 6e 31 13 02 03 01 02 03 01 02 ...json1........
+| 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 13 06 01 02 02 03 06 01 02 02 03 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 02 02 03 06 ..im............
+| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
+| 3792: 02 01 f3 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 08 ................
+| 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 06 01 01 02 01 ................
+| 3904: 06 01 01 02 01 06 01 01 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 ad 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 01 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 00 00 00 19 88 80 ................
+| 4032: 80 80 80 06 00 00 00 18 88 80 80 80 80 05 00 00 ................
+| 4048: 00 17 88 80 80 80 80 04 00 00 00 16 88 80 80 80 ................
+| 4064: 80 03 00 00 00 15 88 80 80 80 80 02 00 00 00 14 ................
+| 4080: 88 80 80 80 80 01 00 00 00 13 84 80 80 80 80 01 ................
+| page 4 offset 12288
+| 0: 0a 00 00 00 08 0e bd 00 00 00 0e f9 0e ef 0e e5 ................
+| 16: 0e db 0e d1 0e c7 0e bd 00 00 00 00 00 00 00 00 ................
+| 3760: 00 00 00 00 00 00 00 00 00 00 00 00 00 09 04 01 ................
+| 3776: 12 01 02 30 f4 a3 0e 09 04 01 12 01 02 30 cf 8c ...0.........0..
+| 3792: 0c 09 04 01 12 01 02 30 7a 34 0a 09 04 01 12 01 .......0z4......
+| 3808: 02 30 72 64 08 09 04 01 12 01 02 30 6b 30 06 09 .0rd.......0k0..
+| 3824: 04 01 12 01 02 30 63 33 04 06 04 01 0c 01 02 02 .....0c3........
+| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
+| page 5 offset 16384
+| 0: 05 00 00 00 0a 0f ce 00 00 00 00 12 0f fb 0f f6 ................
+| 16: 0f f1 0f ec 0f e7 0f e2 0f dd 0f d8 0f d3 0f ce ................
+| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 01 2f 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 00 00 00 00 00 .......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: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
+| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 8f 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 59 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMYT 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 57 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000WBINARY....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 45 45 59 4e 4f 43 41 53 45 17 LE RTREEYNOCASE.
+| 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: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49 NABLE 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 58 42 49 NABLE GEOPOLYXBI
+| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4f 41 42 4c NARY....)..EOABL
+| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 51 53 45 E GEOPOLYXNOCQSE
+| 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 1d 05 E FTS5XNOCASE...
+| 3728: 00 23 0f a4 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 55 53 34 58 42 49 4e 41 52 59 17 0b LE FUS4XBINARY..
+| 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 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
+| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
+| 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 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...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 58 42 49 4e 41 52 59 27 20160609XBINARY'
+| 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 00 00 cc-5.4.0 20160..
+| 4048: 00 11 09 00 00 00 10 08 00 00 00 0f 07 00 00 00 ................
+| 4064: 0e 06 00 00 00 0d 05 00 00 00 0c 04 00 00 00 0b ................
+| 4080: 03 00 00 00 0a 02 00 00 00 09 01 00 00 00 02 00 ................
+| page 6 offset 20480
+| 0: 0d 0f b0 00 25 0e bc 03 0e d7 0e ce 0f f0 0e c5 ....%...........
+| 16: 0f e7 0f de 0f d5 0f cc 0f c3 0e bc 0f b7 0f a8 ................
+| 32: 0f a0 0f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 ...........x.p.h
+| 48: 0f 60 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 .`.X.P.H.@.8.0.(
+| 64: 0f 20 0f 18 0f 10 0f 08 0f 00 0e f8 0e 00 00 00 . ..............
+| 3760: 00 00 00 00 00 00 00 00 00 00 00 00 07 09 03 00 ................
+| 3776: 14 84 6b 00 00 07 03 03 00 14 84 5b 00 00 07 02 ..k........[....
+| 3792: 03 00 14 84 63 00 00 07 01 03 00 14 85 07 00 00 ....c...........
+| 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 00 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: 0f f8 00 07 12 02 01 07 0a 03 00 14 85 05 00 00 ................
+| 4032: 0f f8 00 07 08 03 00 14 84 73 00 00 07 07 03 00 .........s......
+| 4048: 14 85 0b 00 00 07 06 03 00 14 85 02 00 00 07 05 ................
+| 4064: 03 00 14 84 70 00 00 07 04 03 00 14 84 7e 00 00 ....p........~..
+| 4080: 06 de 03 00 12 06 01 01 00 00 00 08 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 01 ................
+| 4048: 00 00 00 00 00 00 11 03 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 00 00 00 00 uild....opti....
+| page 9 offset 32768
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 01 06 00 ae 7c 00 00 ee a4 ad af cf 26 bc c7 >....|.......&..
+| 1104: a8 a1 59 d7 43 c2 93 4f ad 82 19 2e 25 e1 97 f9 ..Y.C..O....%...
+| 1120: 21 59 34 ce e8 b2 e2 3c 4b f2 b4 ee 6b 35 84 c3 !Y4.....@..r...
+| 1792: 8d 30 50 e6 54 9d 62 0d 11 b0 80 ad 64 44 7f 82 .0P.T.b.....dD..
+| 1808: 9a 61 c7 d5 f1 6b 34 2b ec bf 1a ee 5f bf 10 fe .a...k4+...._...
+| 1824: 0f 9e 42 3d 34 1e ff 00 82 db 52 e0 65 d1 d7 0d ..B=4.....R.e...
+| 1840: 77 fb 84 5c ec c3 b7 72 cf 21 26 40 85 20 f4 78 w......r.!&@. .x
+| 1856: 6a f2 f4 52 8a c8 cd d9 99 73 8f 65 f5 f5 a8 af j..R.....s.e....
+| 1872: 75 bd a0 c6 ff 1a bf 64 53 01 4e ed be 22 95 1a u......dS.N.....
+| 1888: 57 06 21 1d f3 f3 97 4f c7 de 83 ab 80 40 c4 02 W.!....O.....@..
+| 1904: 12 65 0d d5 55 87 6f 33 a1 b9 45 86 56 aa df fc .e..U.o3..E.V...
+| 1920: 24 e6 70 37 c3 e8 bc b6 b6 e1 02 29 dc ba 7e 16 $.p7.......)..~.
+| 1936: e9 52 3b 9d e7 f8 d9 d1 5c b2 db 4c 18 29 56 80 .R;........L.)V.
+| 1952: f0 f1 b4 07 34 30 2c 2f ee f6 a5 80 f7 a0 b6 7c ....40,/.......|
+| 1968: 43 e7 6f e2 a9 87 21 a2 96 82 d7 17 55 4d 33 ff C.o...!.....UM3.
+| 1984: 78 75 40 fe db de 63 c3 b5 45 c8 37 40 97 f8 68 xu@...c..E.7@..h
+| 2000: b3 03 46 2d 50 1e 2b b0 90 23 09 47 f5 05 db 9c ..F-P.+..#.G....
+| 2016: 23 71 b1 12 e4 b2 ff 41 b4 1f e3 bb 3c 50 d2 ab #q.....A......
+| 2096: 24 2d b9 ba ec 3d e0 88 60 b2 9d 02 07 86 97 13 $-...=..`.......
+| 2112: e9 c5 64 c8 0f 03 e1 1b 12 0b ff 39 e1 49 95 fa ..d........9.I..
+| 2128: 6f c3 63 4a 7c 86 38 66 95 b3 57 0b 95 96 c5 e5 o.cJ|.8f..W.....
+| 2144: 55 3b 4b 58 d2 59 89 fa 70 40 b5 59 a1 b9 9e 46 U;KX.Y..p@.Y...F
+| 2160: ec 3a 5a c8 6d fb ac da d0 62 f6 fb 8c 26 ff 3e .:Z.m....b...&.>
+| 2176: fb 54 69 ca 27 4b b5 a3 d1 27 f4 f5 2e d4 26 5a .Ti.'K...'....&Z
+| 2192: 0b 3e d6 f4 11 b9 ae fd 42 65 08 6f c1 83 51 1a .>......Be.o..Q.
+| 2208: 98 bc ad a9 77 8c da ef 70 dd 9b 6e e6 89 a0 75 ....w...p..n...u
+| 2224: 5b c5 14 70 9c 3c 8d 99 b5 83 59 1e 77 0f 16 5e [..p.<....Y.w..^
+| 2240: 38 44 b9 da 9c c0 f0 61 23 5a 67 0e 43 48 81 ff 8D.....a#Zg.CH..
+| 2256: 50 9b 2a 36 d1 18 7e bb d2 4e 83 45 07 f8 35 5f P.*6..~..N.E..5_
+| 2272: a4 8a af 12 ab 91 3e 4f 4f 40 32 3f 7e fc 06 6a ......>OO@2?~..j
+| 2288: c4 de 5e aa 2a a5 21 ba 14 51 28 65 c9 9e ef 7c ..^.*.!..Q(e...|
+| 2304: 6a 65 67 fc 11 23 1d 76 e3 be e3 10 7a 34 b8 ef jeg..#.v....z4..
+| 2320: 37 b8 ba 9c 1a 13 c7 e1 91 c9 06 ad 98 3c 4b ea 7................
+| 2576: 93 1b 7c 28 fb 53 bc b2 13 2d 8e 22 50 97 4c cf ..|(.S...-..P.L.
+| 2592: 06 f1 ac 55 9d c8 ce cd 59 74 9c af 7b bd 6f 7c ...U....Yt....o|
+| 2608: a5 b3 a4 87 6a 67 22 f1 82 5b 3e 9e 76 b0 2f d6 ....jg...[>.v./.
+| 2624: f6 6d 7a c0 f5 8f 06 c2 5b 09 0f b5 df b9 d7 c2 .mz.....[.......
+| 2640: be 51 e0 5e 5a 0a 79 62 3a 3c c8 a1 50 0d a3 36 .Q.^Z.yb:<..P..6
+| 2656: e1 7d 61 4a 1b af f0 42 20 dc 10 a9 13 3d 2b 46 ..aJ...B ....=+F
+| 2672: 16 98 d1 24 a8 a1 1a c8 88 0d 63 23 2b 23 b3 8d ...$......c#+#..
+| 2688: 19 13 f9 4c 76 0b 48 40 bb 02 db 1a 54 e8 ea f4 ...Lv.H@....T...
+| 2704: f4 57 25 0d 50 1d 31 af 74 00 d8 f4 22 d9 53 e8 .W%.P.1.t.....S.
+| 2720: 35 ae 1c c6 82 18 06 4f b6 f3 e8 2c 15 1c 38 1c 5......O...,..8.
+| 2736: 5c 47 24 f4 49 44 ef a6 cc de 85 0d 61 aa f6 4f .G$.ID......a..O
+| 2752: 18 4b 23 7e ca dd 04 7a 7f 6c d0 70 59 05 0f 31 .K#~...z.l.pY..1
+| 2768: de 19 71 96 7a 1b 93 a2 20 18 d6 a6 f2 8d 28 1d ..q.z... .....(.
+| 2784: c0 f3 a9 20 87 f7 dc 10 eb bf bc 1e cf 7a 54 a2 ... .........zT.
+| 2800: 7f 96 0d 32 a9 30 30 5c 6d 31 3c 76 4d 65 1f d0 ...2.00.m1..=......USJ
+| 2928: 53 80 b1 9e 23 83 49 1a e0 22 9f 5c f3 df 87 d8 S...#.I.........
+| 2944: 6f 45 ff 9b 8a 69 80 95 f8 ca bc 5c 0c b1 46 04 oE...i........F.
+| 2960: 7e d7 61 72 d8 bf a1 b6 bc b3 48 c7 c2 b3 9d 7c ~.ar......H....|
+| 2976: de fb a4 0a 04 2f 97 99 eb ca 8c b5 39 fc 2b 45 ...../......9.+E
+| 2992: 69 7f a9 70 c6 73 a1 22 71 b0 0d 53 0c f4 c7 68 i..p.s..q..S...h
+| 3008: 85 ec 11 44 0b f9 b7 3b ff b7 91 1b fb bd bf e1 ...D...;........
+| 3024: 01 90 4c 74 35 f3 ac 5a 70 bd e1 4e bb fd a8 dc ..Lt5..Zp..N....
+| 3040: 4d 38 c4 68 a8 e1 8f d1 69 b8 7a 20 b6 5c ed 2b M8.h....i.z ...+
+| 3056: e8 20 dc 0f 7e 29 3e 5f 83 76 e2 d9 b1 c0 07 66 . ..~)>_.v.....f
+| 3072: cd a2 d4 57 bc 27 ff 1d 16 7a 11 d6 3d df 04 89 ...W.'...z..=...
+| 3088: 45 91 e5 37 62 51 5a e6 0f 0d b8 e9 1a 43 e4 c3 E..7bQZ......C..
+| 3104: 47 94 bf 16 fb 8c e2 f7 b8 c8 7f 7f 34 3b a3 fa G...........4;..
+| 3120: 4f 39 b3 89 ee 7a 1b 80 a6 04 46 24 7f 0c d2 48 O9...z....F$...H
+| 3136: b4 cb a2 df 5c af 55 11 a5 c6 f6 de 6a a4 0f dc ......U.....j...
+| 3152: ae 12 98 11 9e 95 e2 b1 a6 c2 67 bb 37 ea e8 8e ..........g.7...
+| 3168: d1 6f 6c 7a 3a 13 5e 1c 31 92 7e 24 72 b0 f5 b6 .olz:.^.1.~$r...
+| 3184: f5 db 3e b9 3b 2a 18 da 93 29 da 2c be 4a de c6 ..>.;*...).,.J..
+| 3200: 6c 55 a0 3e 47 25 76 5c 73 08 99 17 87 e9 30 0e lU.>G%v.s.....0.
+| 3216: 91 a8 cd da 9a cd 90 8b 2d 5f 0e 88 7c a7 00 42 ........-_..|..B
+| 3232: 84 bd 59 1b ce fa 76 27 33 78 c1 a4 0d 29 98 45 ..Y...v'3x...).E
+| 3248: d1 7f b6 7d 56 f6 67 fe 78 ae 83 03 39 66 ce 5a ....V.g.x...9f.Z
+| 3264: 62 a1 e3 c5 fd 29 53 06 6e cd ff 0e 5a 95 ca 91 b....)S.n...Z...
+| 3280: 1b 24 0d 42 ec e2 24 8a 01 ff 12 0b bf b1 18 74 .$.B..$........t
+| 3296: 77 2d f5 9e 0a 74 e6 d4 7d 1c c1 53 d9 f5 65 9c w-...t.....S..e.
+| 3312: 40 6d 8f a9 f6 7b b0 96 37 71 c2 96 8c 90 f8 29 @m......7q.....)
+| 3328: 07 10 c7 2d f5 1d 80 dc 96 b7 25 65 a6 a2 ff ba ...-......%e....
+| 3344: 5d 1e c1 0d ed b1 6a 83 20 6d 06 28 6d 54 8c 88 ].....j. m.(mT..
+| 3360: 08 02 3d cf f6 79 81 f1 36 3b f0 6e e6 80 39 43 ..=..y..6;.n..9C
+| 3376: 64 d6 4a 24 8b 3d 21 41 a9 48 d2 36 65 2f 5a 71 d.J$.=!A.H.6e/Zq
+| 3392: eb 6f 2b 47 78 2d 8c 28 91 60 25 3c 35 81 5b 1d .o+Gx-.(.`%<5.[.
+| 3408: b7 36 34 71 4c 38 f2 29 7e f5 a8 45 71 95 78 19 .64qL8.)~..Eq.x.
+| 3424: 00 e8 87 4d da 50 78 5e f7 dc aa 2d 15 92 49 d8 ...M.Px^...-..I.
+| 3440: 4e af 77 30 bd ad 22 1b 6a 84 ff 78 6d 37 cf 1b N.w0....j..xm7..
+| 3456: 8a d9 81 dd 34 15 a7 3a c0 53 d6 ab 5a 38 ec 69 ....4..:.S..Z8.i
+| 3472: 6a 88 64 8c a6 ce 50 12 45 a1 7f a2 aa 3a a8 cf j.d...P.E....:..
+| 3488: d6 a0 80 4e d6 7a b6 50 90 64 c0 52 30 51 04 6f ...N.z.P.d.R0Q.o
+| 3504: 89 25 02 b3 54 0b fb 24 89 cf f7 98 bd 8e fc 9f .%..T..$........
+| 3520: 62 0c cd fd 57 fd ac 64 b9 2a 94 62 94 38 c6 01 b...W..d.*.b.8..
+| 3536: 0c f1 b9 75 f4 3c 5d 0e d4 1f 96 b3 74 3f 96 03 ...u.<].....t?..
+| 3552: 13 b6 76 32 07 e0 1f 82 d8 27 f3 e7 2e f4 60 d0 ..v2.....'....`.
+| 3568: 56 a5 8f 04 37 bd 5c 17 1e 33 94 75 d8 30 59 0d V...7....3.u.0Y.
+| 3584: e5 90 f5 09 ee 5c 01 88 14 ca 69 27 08 fa e7 3c ..........i'...<
+| 3600: a2 69 df e2 be 35 44 96 b5 06 69 5c 01 3f 52 67 .i...5D...i..?Rg
+| 3616: 18 d2 c9 64 a7 ba 0b 59 d8 b8 53 21 74 de 2b 21 ...d...Y..S!t.+!
+| 3632: 8a 53 3d 97 14 92 77 ed 51 21 4b f0 2d 69 93 09 .S=...w.Q!K.-i..
+| 3648: 57 3e 92 9f 3e 20 6c 4d bf 8b fd 4f 75 4b 19 5d W>..> lM...OuK.]
+| 3664: 48 ef 23 1e 53 11 ee 76 b7 04 08 5a c4 9a 1f 6c H.#.S..v...Z...l
+| 3680: 24 cb 15 7f 0b f7 86 8e 60 a4 8d 3c 2a fe 14 13 $.......`..<*...
+| 3696: 03 28 80 fa 6b d7 1b 02 a7 0d 9e 88 4d 1f b2 a4 .(..k.......M...
+| 3712: 63 c7 65 56 14 df 51 7e d3 d4 3b e3 45 e1 7a 49 c.eV..Q~..;.E.zI
+| 3728: 1e 71 40 fe b7 ae 65 10 b1 27 3a 02 31 21 47 11 .q@...e..':.1!G.
+| 3744: d9 fc 9c 32 e5 c8 40 0d b6 4b 02 ed bc da 4c 98 ...2..@..K....L.
+| 3760: 35 2c d5 9e 6f b3 42 c7 8e 0a c7 fa ae ff 36 5b 5,..o.B.......6[
+| 3776: 76 08 69 3e 3c cd 4d eb 6f 0c a0 f6 23 93 a6 bb v.i><.M.o...#...
+| 3792: 2f ed 44 64 22 df e8 6b 21 68 5b 35 d6 8f 68 c5 /.Dd...k!h[5..h.
+| 3808: 15 1f 46 fd 12 bc b5 b5 3e a7 e4 9b b2 83 f4 12 ..F.....>.......
+| 3824: ea bb 50 84 f4 40 96 c4 64 30 d8 fe 74 5b f2 ba ..P..@..d0..t[..
+| 3840: 9a 64 23 67 4a 3d 7e 54 da 8f 39 18 df 31 88 23 .d#gJ=~T..9..1.#
+| 3856: d6 80 5f e9 10 9f 37 22 6f 4a 21 13 20 13 fc 66 .._...7.oJ!. ..f
+| 3872: fc 4b db a8 d9 aa 55 01 48 3e 8c ac bf 16 fc 62 .K....U.H>.....b
+| 3888: 95 2c 44 1f 27 bf 7b 45 7d 28 55 14 1f ed 56 ed .,D.'..E.(U...V.
+| 3904: 24 5b 11 ff be a0 7a 20 3b 3e 9c 2c e6 d6 b0 ef $[....z ;>.,....
+| 3920: b4 df 16 73 f2 d3 a9 90 2b 54 c7 7a fa 25 e7 ee ...s....+T.z.%..
+| 3936: da 99 8d d7 b5 7d 0f 72 c7 61 75 d1 d7 23 dd 41 .......r.au..#.A
+| 3952: 1e 46 ee ef 41 86 00 9f 1c 47 36 75 95 f6 1d 89 .F..A....G6u....
+| 3968: 13 c0 75 f8 cc 5e 08 93 e4 de a8 ee d2 ce c2 32 ..u..^.........2
+| 3984: e4 16 b0 c8 82 c1 2a 74 ed 5c 5f c1 99 f7 07 a7 ......*t.._.....
+| 4000: b3 50 21 87 a1 43 dc 17 4f 2d 47 e0 be 53 ad 17 .P!..C..O-G..S..
+| 4016: f9 09 67 d1 4f 1f 72 17 62 b7 03 fa cd de 3e a7 ..g.O.r.b.....>.
+| 4032: 25 a9 e7 a0 e2 3d a3 6b 2b 34 3f 55 46 18 df ef %....=.k+4?UF...
+| 4048: 16 0a ce c8 67 58 eb 64 eb 7e a3 5b 4e 85 49 64 ....gX.d.~.[N.Id
+| 4064: d7 f9 ec 0d 4d b6 1d 49 bb 93 e9 79 3d e1 f9 ad ....M..I...y=...
+| 4080: 6d c0 45 9c 46 26 21 41 10 dd 4a 12 fc 28 f4 cc m.E.F&!A..J..(..
+| page 10 offset 36864
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 02 06 00 ae 7c 00 00 9a 84 85 31 87 79 cc e4 >....|.....1.y..
+| 1104: 12 98 6f 2c 46 b6 5d 4e d9 5c ba 21 2f cf 51 9d ..o,F.]N...!/.Q.
+| 1120: 9f 8c 48 7d 5a 15 ae 1c 54 d7 f0 7f a2 e6 cc fd ..H.Z...T.......
+| 1136: ad e6 3c d5 e5 98 5d f2 64 82 5b 9e 6c d6 05 8f ..<...].d.[.l...
+| 1152: de fb 33 3a 37 b3 1d 58 04 47 13 cd d9 39 17 a9 ..3:7..X.G...9..
+| 1168: a7 14 f1 fe c8 3b 21 40 a8 22 f5 3b 64 74 14 dc .....;!@...;dt..
+| 1184: c5 9e 99 8b f3 d4 5f 1a e8 1d 93 98 9e 00 7d ee ......_.........
+| 1200: 9f 0f 49 b5 af 12 7e 47 8e fe 5f 70 a1 9c 32 ae ..I...~G.._p..2.
+| 1216: d1 23 33 d1 c0 65 b6 8e 5a 4a 03 2f 74 27 0f 3d .#3..e..ZJ./t'.=
+| 1232: 3f 42 0d 03 5f 6c ef 2c 54 6a bd ec 88 eb cd 1f ?B.._l.,Tj......
+| 1248: dd 03 9c 06 18 8e a4 c1 a5 3c ec 9d 68 da d9 d3 .........<..h...
+| 1264: d8 8f ba 16 95 fd 94 ed 19 2b 2f 5e 0e a5 fa de .........+/^....
+| 1280: dc c5 a0 a2 d4 31 0f dc f5 8b 4a 28 4f 6f 9f ff .....1....J(Oo..
+| 1296: 7f e6 d4 d0 08 7e 5c 76 9a 3a ea 0e ea b4 9d 45 .....~.v.:.....E
+| 1312: 4b db 96 ed 27 ad a8 09 63 3c d0 1d d9 b1 dc 94 K...'...c<......
+| 1328: 6a 8e e7 6a 9b 6e d1 8b f7 c8 60 1c 85 e9 a2 3e j..j.n....`....>
+| 1344: 0c b6 2f 40 b0 2e b6 53 8f 94 74 6b 39 13 fd c9 ../@...S..tk9...
+| 1360: 44 77 64 7c 62 e0 51 2e 04 0f 6a 99 5e 68 6f 72 Dwd|b.Q...j.^hor
+| 1376: 08 92 02 bf 36 78 0c 98 c3 3f 3d e3 ac a4 2d 3b ....6x...?=...-;
+| 1392: d7 51 cf f9 25 72 59 36 b0 ea 51 a1 9c bf 13 f1 .Q..%rY6..Q.....
+| 1408: dc f5 36 f0 d9 83 fe 0a ff b5 00 ab 5b 4e 0b 33 ..6.........[N.3
+| 1424: 0a a1 fa c1 02 c8 7a af 00 30 54 d3 6e a8 37 b4 ......z..0T.n.7.
+| 1440: 02 88 16 41 95 86 1f 36 e0 98 43 d5 55 57 c6 5e ...A...6..C.UW.^
+| 1456: 0d 10 40 fd 3d 85 a1 5f 19 3f 18 87 11 d9 6a ca ..@.=.._.?....j.
+| 1472: 8b 5c 14 cc 64 48 b9 42 71 61 30 ca 0d 2c a5 67 ....dH.Bqa0..,.g
+| 1488: 6b 4f 5b 34 1b f3 7b a1 1f ed e4 3b ef 68 27 00 kO[4.......;.h'.
+| 1504: f3 8a 27 ff de 2e 07 ab 03 b1 5b b9 c3 84 53 f1 ..'.......[...S.
+| 1520: d0 c5 8c 65 50 4b 7a 35 06 0c d5 2a ce 4c b9 02 ...ePKz5...*.L..
+| 1536: 7f cf 2a d9 0d 2a 1c c1 5f 94 cb 5c 05 4d 3a 7a ..*..*.._....M:z
+| 1552: aa c5 3e 4e 26 93 8a 4d 1d fc 75 23 9f b5 27 87 ..>N&..M..u#..'.
+| 1568: fc f7 3d aa a6 3e 5d c3 55 63 e2 a8 2a 7b 2e 26 ..=..>].Uc..*..&
+| 1584: e9 64 59 1f 2a e7 ff 7c d4 69 a6 34 bb d9 23 81 .dY.*..|.i.4..#.
+| 1600: de 4b ba f3 91 cd 9a 8b 98 56 f0 b8 73 7b 83 f1 .K.......V..s...
+| 1616: fc e9 5c 01 7e 74 66 d0 0c 01 79 c0 b2 49 0f 78 ....~tf...y..I.x
+| 1632: 79 ef 20 96 ec cb 63 67 fe 43 a7 ea 5d af 68 12 y. ...cg.C..].h.
+| 1648: 84 dc 0c 5c 31 6a 1d d6 a1 1e d4 25 a3 f0 7c 19 ....1j.....%..|.
+| 1664: dc 84 4f 7b e4 5a e5 40 23 07 b3 5b 92 92 4b 3a ..O..Z.@#..[..K:
+| 1680: 0e 11 9c b4 ba d4 d1 ff 22 af cd 7d e8 86 c3 0a ................
+| 1696: 14 eb 01 13 f8 99 56 8c c6 26 55 8d a7 cc cc 00 ......V..&U.....
+| 1712: 4c 16 7a 07 de 6c 69 02 e2 a1 e6 e1 d5 ff 12 f5 L.z..li.........
+| 1728: ee d7 8f 90 e1 78 99 09 de 27 b8 b3 e1 7a df 8a .....x...'...z..
+| 1744: 08 cb c0 67 ff d4 48 bd 0b 4c 65 56 5a ed 02 47 ...g..H..LeVZ..G
+| 1760: 1c de b7 58 7c cf 68 a4 7f e6 db 74 26 55 9c 14 ...X|.h....t&U..
+| 1776: 76 5a bf f3 e1 79 23 5e 33 f8 65 13 bb 36 cc ed vZ...y#^3.e..6..
+| 1792: 9e 12 63 b2 c2 14 3f 6a 4d e3 a4 63 bf 30 0f cb ..c...?jM..c.0..
+| 1808: f2 f0 d1 81 a7 26 d7 c0 92 9f 06 79 bd a7 a0 8d .....&.....y....
+| 1824: 74 21 7b c6 46 49 5c fd 01 a6 92 56 3b eb e6 d5 t!..FI.....V;...
+| 1840: b4 4d 76 2a e8 00 98 3b a3 67 a9 7d 02 25 96 3b .Mv*...;.g...%.;
+| 1856: 45 19 a0 d4 b5 67 88 cf 48 eb 1a b6 0e f3 2d 62 E....g..H.....-b
+| 1872: 3e 0c fa b3 e7 a4 f1 76 d4 d7 f5 19 6f b2 9e e8 >......v....o...
+| 1888: e1 a1 b7 be 3a ff 69 db eb 75 1c 0c 91 7f 02 4f ....:.i..u.....O
+| 1904: df 15 af 09 48 2c d0 86 bd b0 80 82 e7 7b 1d a6 ....H,..........
+| 1920: 38 f1 24 79 d0 8e 4c 07 9f ed 9f fb 90 a1 7e fd 8.$y..L.......~.
+| 1936: 50 c6 fe d3 61 04 a1 03 34 30 bd 98 db 5c 18 e3 P...a...40......
+| 1952: 94 d9 ba 8f 64 f8 6b c1 21 3b 22 b7 3e 71 5a 66 ....d.k.!;..>qZf
+| 1968: cf 9f 51 c4 a2 36 c8 ba c3 2a 95 2e 67 e4 87 3e ..Q..6...*..g..>
+| 1984: 07 ae 66 ad ec af c6 17 62 11 be 5f 15 fc 61 53 ..f.....b.._..aS
+| 2000: 76 eb f5 78 da 32 8c fa 4e d3 cc 27 19 dc 89 fc v..x.2..N..'....
+| 2016: 37 4f 74 61 f7 5e 97 0f fe fc af aa 12 ee ea f2 7Ota.^..........
+| 2032: 68 36 36 cd 7e 57 41 75 48 be cd 46 e3 cd 3a 99 h66.~WAuH..F..:.
+| 2048: 31 33 9a 84 8a 83 a2 fc 85 85 3c bc cf 07 b4 6d 13........<....m
+| 2064: 57 d2 c9 63 a2 9d 42 07 4e cd 65 2e 65 0a af 03 W..c..B.N.e.e...
+| 2080: dc a9 98 57 b6 7f da 1d b7 3c e0 ef aa 18 eb 3f ...W.....<.....?
+| 2096: 78 f1 34 e6 bf c7 28 34 11 a7 bc b3 34 79 f2 85 x.4...(4....4y..
+| 2112: ed 7d fe 38 a5 48 b3 b4 8a 0d 75 12 65 04 f8 88 ...8.H....u.e...
+| 2128: 71 b9 d4 86 48 c7 ea 2f af 4d 50 b9 50 a7 17 f6 q...H../.MP.P...
+| 2144: 1f a2 e1 b8 aa ed 6d 85 3a e2 91 be 94 c8 fc db ......m.:.......
+| 2160: 93 50 0e 50 7c cf 52 f7 55 81 3e 1a 59 4d a8 36 .P.P|.R.U.>.YM.6
+| 2176: ee 07 f1 9e 26 4a 1e d3 0b 7d 52 e3 bc 7c 91 78 ....&J....R..|.x
+| 2192: 02 48 7e b5 4c 32 1e a3 ba db 93 61 94 3b d7 22 .H~.L2.....a.;..
+| 2208: 7b cb 46 5b c0 a5 1e e6 5a ed c9 82 07 48 17 d6 ..F[....Z....H..
+| 2224: de 85 ca 47 e1 16 5c c8 dc 30 5e 27 65 60 a5 41 ...G.....0^'e`.A
+| 2240: 46 0a 12 0e 97 63 3f 05 5f 62 83 e0 cb 72 b6 61 F....c?._b...r.a
+| 2256: 6a 4c 1d 7b 09 28 75 54 1c cd 29 bc f8 71 34 56 jL...(uT..)..q4V
+| 2272: d6 ac 77 34 44 0d 5f c3 0e f1 d7 b3 dc 0d 1f 85 ..w4D._.........
+| 2288: e3 db 45 88 fd db ab bf a6 ff bc 08 f3 3c 00 f0 ..E..........<..
+| 2304: 9f 3b 07 36 cc 37 f0 6d 14 a8 6b 69 d6 e4 3a ab .;.6.7.m..ki..:.
+| 2320: 4f 5a b5 ad 3a e5 e3 d6 1c e1 6b 15 97 69 b0 41 OZ..:.....k..i.A
+| 2336: 91 09 50 02 6a 5c c1 9e fe e7 38 7e 19 8a 36 44 ..P.j.....8~..6D
+| 2352: 51 04 8d 61 d9 a3 12 34 00 b2 b1 60 f3 35 eb 8a Q..a...4...`.5..
+| 2368: dc bb a1 67 48 b6 95 81 91 fe 20 dd 03 74 bb 3b ...gH..... ..t.;
+| 2384: 8c 33 58 b2 d8 55 7e 04 ea 42 6c 02 e8 26 18 19 .3X..U~..Bl..&..
+| 2400: 23 15 21 a5 73 ca 08 7b dd db fb b2 12 df 6a 5a #.!.s.........jZ
+| 2416: d7 ac e4 57 61 ac 3f 81 77 df f6 a3 97 5c 69 47 ...Wa.?.w.....iG
+| 2432: 5a b7 75 23 6c 60 be 97 ee b5 5d a0 c3 60 15 4a Z.u#l`....]..`.J
+| 2448: 79 eb 81 9f 2a 74 22 13 7e ca 4d 3b 19 13 62 58 y...*t..~.M;..bX
+| 2464: 78 25 ca 21 c3 10 1e 96 34 82 37 6b 08 b5 9b f6 x%.!....4.7k....
+| 2480: 7b 87 97 cd bf 64 67 b4 10 f6 84 16 62 74 a5 b0 .....dg.....bt..
+| 2496: 1f d4 c7 1d 8c 2d b5 10 36 5b fb 06 80 fe 97 59 .....-..6[.....Y
+| 2512: b6 5a 08 0f 1e ff 0f 5f bf 28 46 4b d8 84 6c ad .Z....._.(FK..l.
+| 2528: 05 c0 25 89 a9 cd 6a be a3 59 84 f0 17 1c 37 8a ..%...j..Y....7.
+| 2544: 8d 09 17 bf 7d fe 47 b4 d6 d6 56 1f d8 04 66 59 ......G...V...fY
+| 2560: 2c c4 b4 91 a9 ff da 4a 9c b1 29 ff 92 db 6f 19 ,......J..)...o.
+| 2576: ef eb 99 ba 6e 65 2f 6a 7f 1a cf ad a3 96 8c 1d ....ne/j........
+| 2592: 62 86 42 3e a3 64 fc e0 40 4c 7c 60 77 b5 42 68 b.B>.d..@L|`w.Bh
+| 2608: 3f 09 37 68 02 75 2c 22 83 d5 04 17 eb a7 e2 71 ?.7h.u,........q
+| 2624: 29 36 b7 1b c5 1f 11 ce 8d 91 5a 25 39 50 16 2b )6........Z%9P.+
+| 2640: 60 29 50 9f 17 55 b0 9b a5 92 92 f8 1b e3 9c a3 `)P..U..........
+| 2656: e2 a4 cd 90 1e 21 ac 30 ac 35 de 25 30 88 6c 2c .....!.0.5.%0.l,
+| 2672: 79 ea b5 0d 58 a5 37 2b ac af 7d 1f af 32 ca 58 y...X.7+.....2.X
+| 2688: 27 17 68 f2 a3 ca a6 cc b2 be 12 c1 a0 43 1e 7d '.h..........C..
+| 2704: 11 ec 8e 23 22 0a ca cd 70 d1 05 fd c0 68 92 e9 ...#....p....h..
+| 2720: 1c 55 85 48 10 37 7c 02 69 bf 3f 86 cf d6 40 38 .U.H.7|.i.?...@8
+| 2736: a3 9c 83 40 b8 4b 83 51 50 0d d2 b9 c3 32 09 f8 ...@.K.QP....2..
+| 2752: bc 7b 9b b8 d7 2e 4f a0 96 48 a7 5a 1b c9 71 fb ......O..H.Z..q.
+| 2768: f4 2b ff 05 54 89 26 b9 6f 25 4a b9 e2 2b e8 86 .+..T.&.o%J..+..
+| 2784: 43 22 f6 20 28 a9 39 d9 09 a2 dc 60 14 09 d6 0d C.. (.9....`....
+| 2800: 61 7c 15 5a 8f 3f cc 00 12 f5 e0 45 fe 14 1a cc a|.Z.?.....E....
+| 2816: 98 c4 de 48 75 12 02 2b 79 a1 4a 33 a5 7c 3d cd ...Hu..+y.J3.|=.
+| 2832: b0 5c dd 77 15 5f d9 24 b7 6b 62 80 cb 35 5c e6 ...w._.$.kb..5..
+| 2848: a6 57 2e e9 00 9e 20 a9 c6 f0 63 a2 0e eb 9d f3 .W.... ...c.....
+| 2864: bb 2c 56 03 68 35 53 5a fb 4f 44 8e 0f a4 9c 9a .,V.h5SZ.OD.....
+| 2880: 0d b7 2c a9 03 14 8c 51 23 21 fb fd 46 07 68 a7 ..,....Q#!..F.h.
+| 2896: f3 09 25 e4 98 55 24 da 72 ee 50 00 95 04 7c 74 ..%..U$.r.P...|t
+| 2912: d0 07 8b 92 f9 27 11 3e 41 b4 3e 6c aa 56 ed 54 .....'.>A.>l.V.T
+| 2928: e3 40 4d 67 8b 7b 63 cd 62 37 ec e2 1b b4 f9 eb .@Mg..c.b7......
+| 2944: ca c7 6e 8a d3 7e f5 e9 e1 33 84 31 05 cb f8 e4 ..n..~...3.1....
+| 2960: 02 76 c2 2c b9 00 32 5f be b5 f1 c8 78 e8 cf 22 .v.,..2_....x...
+| 2976: 65 d8 2b 43 2c 2e 5d fb 2e 58 92 d2 3e 9b 7e 67 e.+C,.]..X..>.~g
+| 2992: a7 3b 59 18 84 5d 61 92 ec 57 97 b6 bd e3 7b f2 .;Y..]a..W......
+| 3008: ff 3b 9f 48 39 ad 10 81 51 85 7c 6b 5c b0 53 10 .;.H9...Q.|k..S.
+| 3024: 60 9b 4e 0d 86 c0 31 b9 a1 95 05 f4 54 13 52 6a `.N...1.....T.Rj
+| 3040: 96 50 1b e5 f5 54 98 63 8f 07 28 cf b4 ba 9c 3b .P...T.c..(....;
+| 3056: dd 85 3c a6 15 a6 31 f6 aa 1c 3b 31 3e d9 6e c3 ..<...1...;1>.n.
+| 3072: 09 74 b9 8e 59 a1 50 10 e0 f0 48 a9 f1 dd a1 ab .t..Y.P...H.....
+| 3088: b6 fc 53 9f bb 38 69 78 07 50 8c 77 cb d1 89 e2 ..S..8ix.P.w....
+| 3104: cb b9 51 dc c7 2e 8a 56 47 14 67 80 eb 7a 16 f8 ..Q....VG.g..z..
+| 3120: 87 89 58 d1 55 58 c5 bd 62 24 4d ef 46 9f 68 94 ..X.UX..b$M.F.h.
+| 3136: 61 9a 08 81 dd dd f1 51 c6 40 63 9b a1 3c 3e 5a a......Q.@c..<>Z
+| 3152: 78 b2 10 7c a2 47 45 57 ef 98 85 82 7e 21 3b 77 x..|.GEW....~!;w
+| 3168: 1e d2 fd 0d bf a5 41 6f f5 ee 4c ed 82 f3 15 ea ......Ao..L.....
+| 3184: 2e 57 5e 78 7c 22 2e a4 a6 9c 3f 50 e9 4b 02 11 .W^x|.....?P.K..
+| 3200: a0 7c 5a 19 82 9b 34 13 39 32 07 f1 46 4c ad fa .|Z...4.92..FL..
+| 3216: a7 5a fa 22 5c 84 4d 8d 07 1f 17 1f 1a 49 5f fa .Z....M......I_.
+| 3232: df 22 56 ac ce 27 4d 00 a9 b0 c0 77 d8 10 56 cb ..V..'M....w..V.
+| 3248: 76 e0 c8 4a 8a d1 37 c1 cc b8 74 d3 e9 61 1b 0c v..J..7...t..a..
+| 3264: 81 7b be 3d e3 17 43 75 5c ba 6f 61 74 d4 a4 e9 ...=..Cu..oat...
+| 3280: d7 0f 2f d2 bc 7d 0b 6e 32 ae fc 20 db 08 39 b5 ../....n2.. ..9.
+| 3296: 8f 78 1f d6 4e 84 46 05 a3 a1 15 e8 9d 36 b1 96 .x..N.F......6..
+| 3312: 3e e3 12 1b 72 28 28 e8 a5 0f e1 16 a2 31 22 48 >...r((......1.H
+| 3328: 4b 77 c6 e5 3f b8 f5 bb 29 13 e1 c1 da 79 81 72 Kw..?...)....y.r
+| 3344: fa 12 ab 62 da 63 ac 95 2a 1b 4a a4 4f 96 95 c0 ...b.c..*.J.O...
+| 3360: 30 38 3b af 2d c5 cd aa 56 ef e4 35 1d 97 9c 3f 08;.-...V..5...?
+| 3376: 57 30 2a 7a 1a 0f 4d 9e be 82 a6 fc 5e a7 9d 0d W0*z..M.....^...
+| 3392: a8 11 12 39 b5 e7 5f 8d 18 1d bb a0 2b 02 10 d3 ...9.._.....+...
+| 3408: 08 3a 47 de a1 93 f3 7b b7 07 21 c2 62 22 f2 b3 .:G.......!.b...
+| 3424: dd 67 9c 8c 87 59 7d 87 75 46 0c 85 64 f3 09 7f .g...Y..uF..d...
+| 3440: e2 7f ee ca c8 d2 2e 96 14 50 30 89 86 f6 ed 07 .........P0.....
+| 3456: ee 9d 78 0c 84 c8 80 ee 2f d4 59 22 12 92 e9 80 ..x...../.Y.....
+| 3472: 04 f5 ed aa 7a f5 cd 53 d7 de 45 a5 c3 e1 4e 9d ....z..S..E...N.
+| 3488: fb 78 98 4d cb 5b 0b bf 1b 6a bc 50 ba 45 e5 ff .x.M.[...j.P.E..
+| 3504: d7 d0 7b 39 3d 5b eb 92 46 7f bb 21 7f 81 8b da ...9=[..F..!....
+| 3520: e7 c1 e2 12 41 82 19 7a bd 78 de bc e0 51 cf a7 ....A..z.x...Q..
+| 3536: 0e 20 0b 74 cb c8 fe e9 26 64 6e c4 e1 cc 3f b8 . .t....&dn...?.
+| 3552: 62 a1 9b 79 bd 9f 05 21 b1 d6 93 66 6f 38 e5 df b..y...!...fo8..
+| 3568: 56 0c 57 c3 3b 57 04 79 f7 f4 b5 20 16 65 18 dc V.W.;W.y... .e..
+| 3584: a8 88 ce 1c bd 7f 40 c8 05 46 17 d7 99 a7 8e 07 ......@..F......
+| 3600: b7 02 2f 8c a6 49 5a 1f ce 63 3a 66 31 c2 3b 78 ../..IZ..c:f1.;x
+| 3616: 84 00 80 8e 81 43 07 3a 43 ef e4 df 33 4b 18 33 .....C.:C...3K.3
+| 3632: 45 27 cc 2e e8 cf e8 be 1a 90 97 ed 99 9b b2 6f E'.............o
+| 3648: 65 ff 53 ad df f8 58 47 d9 5d 71 6a 38 e4 e8 17 e.S...XG.]qj8...
+| 3664: e1 1d 4c 03 cc c1 33 18 96 3e 9c 11 98 55 8e 62 ..L...3..>...U.b
+| 3680: 1a af a0 33 36 f7 0c 87 0a 0c f0 43 ff e4 71 19 ...36......C..q.
+| 3696: 5a 38 f8 9d 9a 53 d4 48 ff e3 40 89 e2 18 d5 3c Z8...S.H..@....<
+| 3712: fb 2c 67 2c b9 f3 e5 d7 5c 97 e9 8f fb 3e 3e a2 .,g,.........>>.
+| 3728: 22 63 47 fb d0 65 ed 87 b0 93 e4 28 e5 85 87 68 .cG..e.....(...h
+| 3744: fc 0b 64 4c 5b 3c 5f 9f 40 96 d7 34 5b cb d0 a9 ..dL[<_.@..4[...
+| 3760: 63 f5 f7 80 f4 67 49 1d 20 0d 84 f9 39 85 28 8b c....gI. ...9.(.
+| 3776: 78 52 fc 86 fb f8 33 cd d6 ef ef ca 32 51 98 2c xR....3.....2Q.,
+| 3792: 54 d4 2e b9 78 0c 2a 5e c0 e6 2c 58 83 60 85 ea T...x.*^..,X.`..
+| 3808: 0b 33 de 33 40 a4 05 80 0d 21 b5 0e 4f 87 a1 a2 .3.3@....!..O...
+| 3824: 3a 20 d6 ee 63 7a 31 93 5c 64 f4 f4 57 43 8a 65 : ..cz1..d..WC.e
+| 3840: 53 e0 6e 84 c0 ee f6 44 ce 46 ea 97 fc af ec 4b S.n....D.F.....K
+| 3856: ff af da 33 b8 69 e5 08 bd 36 17 aa be 1b 99 5f ...3.i...6....._
+| 3872: 80 c2 8c 27 56 1c f4 99 fa c3 1c 54 01 b7 3e 96 ...'V......T..>.
+| 3888: 67 b7 f0 31 f7 20 63 51 17 61 f1 b7 06 23 24 35 g..1. cQ.a...#$5
+| 3904: f3 84 c9 01 ec 59 ba 00 83 b8 6c f9 4b 94 01 53 .....Y....l.K..S
+| 3920: d4 06 ef b7 a9 08 3c 29 7d ab 8a 88 12 e2 3f a6 ......<)......?.
+| 3936: a1 27 be 2e 09 aa d4 15 bc 43 2a 10 ff 2a 2d 89 .'.......C*..*-.
+| 3952: fd a0 73 e7 91 14 a3 e2 2c 00 e8 c8 a7 bf 7c c3 ..s.....,.....|.
+| 3968: 4c a0 89 bb 70 da 99 1a 39 5f 81 77 af 17 8d af L...p...9_.w....
+| 3984: e8 b0 e0 27 fb f0 b2 39 45 4a 82 97 93 00 a5 54 ...'...9EJ.....T
+| 4000: 44 07 b7 1d ce 52 5f bd cd 07 6f ba 6f 8d 6d d7 D....R_...o.o.m.
+| 4016: 2b 4f f5 4b 7b 23 45 74 d9 d8 aa e0 15 14 f6 be +O.K.#Et........
+| 4032: 74 f2 b8 38 f9 ba 64 58 93 b2 b6 0c e7 62 10 81 t..8..dX.....b..
+| 4048: ad ce 6f 23 0e cd 1c 3c 1e 30 62 64 95 d6 48 55 ..o#...<.0bd..HU
+| 4064: fc 63 67 73 85 40 16 2b ab 0b 96 c4 90 8e ea 04 .cgs.@.+........
+| 4080: 64 13 bb 60 63 d8 6c d3 73 ed a9 10 03 bf 20 04 d..`c.l.s..... .
+| page 11 offset 40960
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 03 06 00 ae 7c 00 00 68 95 7f 98 0f 98 e0 e6 >....|..h.......
+| 1104: fd 92 02 0f 0f 29 aa bd bc 40 56 6c 5e fa 3f 54 .....)...@Vl^.?T
+| 1120: 10 24 70 48 b1 c5 fe e5 0b 21 21 65 1e a4 f1 2a .$pH.....!!e...*
+| 1136: fa 3e 9a a1 b8 67 92 ab cd 27 a2 0f f3 b1 77 9b .>...g...'....w.
+| 1152: 97 e6 c0 f2 c4 db a4 5c d8 f1 01 bd 3c f4 fd 0f ............<...
+| 1168: 00 ca 6d 75 11 fd 56 e2 12 96 e1 f7 18 99 f3 78 ..mu..V........x
+| 1184: 9b b7 ef 8c 50 1f dc c5 fa f5 92 fb 91 70 cc d3 ....P........p..
+| 1200: ca 0a c6 9b 42 d4 2f cc ce 98 48 a6 ab cd d1 d8 ....B./...H.....
+| 1216: 4c 8a 98 2f 2d dc 48 d9 84 52 8f 86 57 04 b8 14 L../-.H..R..W...
+| 1232: ec 33 d4 5e 69 da c5 45 8e 2c 4f d6 fc a3 ee f1 .3.^i..E.,O.....
+| 1248: 7c 47 c1 5c 8d 48 1b c2 be f1 ca b8 f4 91 d8 bd |G...H..........
+| 1264: d6 41 f6 40 ee 41 90 51 14 09 a8 c5 cf 38 16 21 .A.@.A.Q.....8.!
+| 1280: b5 84 48 6c 8e eb e7 b0 62 69 dd 04 c4 4a 75 f6 ..Hl....bi...Ju.
+| 1296: 6f 92 af 16 33 94 81 eb 26 00 9f dd d4 01 73 32 o...3...&.....s2
+| 1312: ec ee 9d 23 bf 82 8f e0 c8 eb 8f aa 4f 69 4b 68 ...#........OiKh
+| 1328: a8 4e 3d 6e d8 2c 99 49 fb 96 d1 77 f6 a0 c3 97 .N=n.,.I...w....
+| 1344: 7e c6 7d ff 90 fc 12 97 e7 71 7b 20 ea dd ba 47 ~........q. ...G
+| 1360: 3f bc bf 89 2e 26 82 91 71 97 6c 5e 2e ba 8d b9 ?....&..q.l^....
+| 1376: c6 ff 51 b3 17 7d e6 ca 99 75 53 73 99 9f 5a b8 ..Q......uSs..Z.
+| 1392: 11 db 5a fb b3 73 55 bd 61 0c 2c e5 03 b2 d5 1c ..Z..sU.a.,.....
+| 1408: ce ea ef b4 2e 2c dd d4 55 df cc 7b 13 c9 ba 87 .....,..U.......
+| 1424: 25 38 2d d7 fc 7b 47 c1 da 56 42 fe 50 8e 12 a8 %8-...G..VB.P...
+| 1440: fd 9d 90 e3 ae e1 f2 5d fa 1e c5 e2 d9 74 b9 55 .......].....t.U
+| 1456: d0 5b 90 1d 31 f0 fb 36 d6 e5 df 91 72 4b 69 41 .[..1..6....rKiA
+| 1472: 06 33 4e 77 cc 1c a7 d1 3e 49 7f 76 8d d3 73 88 .3Nw....>I.v..s.
+| 1488: 27 53 13 95 87 9a 99 cc b2 54 46 34 7f 96 98 1e 'S.......TF4....
+| 1504: fb 60 06 85 93 37 0a 90 30 4b 8a ca 7f e8 a6 6a .`...7..0K.....j
+| 1520: a1 94 da ac 1f 47 80 1a 81 8f dd 19 9d 70 88 73 .....G.......p.s
+| 1536: b7 4c 22 f7 fe 8b c1 05 5a ea e0 20 5d 01 55 c4 .L......Z.. ].U.
+| 1552: 7c 3d 99 f7 8a 1a 15 23 1a a6 5a 02 52 35 2f 14 |=.....#..Z.R5/.
+| 1568: ea 01 d4 2b 97 3f 7c e3 4f 7b 58 ea 83 2f 1f 03 ...+.?|.O.X../..
+| 1584: c3 64 4f e8 81 f2 ec 19 92 5f c7 b1 27 5a 74 12 .dO......_..'Zt.
+| 1600: fd f3 d1 48 0c eb fd 57 9d 28 1e 44 28 3d 69 aa ...H...W.(.D(=i.
+| 1616: 94 66 23 55 11 3b 01 52 76 0b 3b e0 fe 67 e0 fe .f#U.;.Rv.;..g..
+| 1632: f1 e5 18 2b 19 ec 22 a0 33 94 e2 33 3f 59 fc 04 ...+....3..3?Y..
+| 1648: 15 c3 ee a0 f8 18 7d 07 39 04 04 e5 df ee 0c 38 ........9......8
+| 1664: 31 94 76 b0 ec 42 89 fe 3a d9 d2 1a 4d ee b0 67 1.v..B..:...M..g
+| 1680: 10 f4 e6 d1 dd 96 9c d8 ec 10 f0 4b 8c 02 37 54 ...........K..7T
+| 1696: 5b b8 e6 d6 d2 d3 ad cd cc 84 02 bd 1f bf 36 de [.............6.
+| 1712: fe d3 8f 68 94 5d c7 19 18 d0 91 e5 be c2 e6 40 ...h.].........@
+| 1728: b6 21 ec 29 08 49 08 96 97 a1 14 3a 32 cb 0b 24 .!.).I.....:2..$
+| 1744: d4 8c 77 f9 f8 4b 78 8c cf de 90 27 b8 a1 5b dd ..w..Kx....'..[.
+| 1760: 84 c5 88 21 39 fe 1e 88 c0 1c 9b d7 46 44 4f a7 ...!9.......FDO.
+| 1776: 13 49 c0 49 d6 c4 c2 06 ab 24 9b 8d 80 83 32 32 .I.I.....$....22
+| 1792: b0 ff e5 47 db 08 c0 17 c5 98 67 12 fa 2f 86 39 ...G......g../.9
+| 1808: a5 f6 13 03 4d 25 af dc 2c 52 e2 5e f0 36 b3 a2 ....M%..,R.^.6..
+| 1824: 13 5b d4 47 14 5e 26 66 f5 a8 48 b3 1a 9e c5 03 .[.G.^&f..H.....
+| 1840: 39 66 f3 34 fc c2 ff a8 0f a5 66 a7 7a 6b ad dc 9f.4......f.zk..
+| 1856: 77 e2 c7 fb 10 c6 fe a6 2a 64 fc e3 84 8c 12 0e w.......*d......
+| 1872: 5d 96 80 c8 d2 0d d9 e4 f1 bd 96 51 a0 ad a2 cb ]..........Q....
+| 1888: 99 d9 13 4b de c3 f6 ab 20 d8 ad 61 23 fd be 39 ...K.... ..a#..9
+| 1904: 97 0b 90 22 49 08 e2 38 3e 43 e6 91 9a ef e5 d7 ....I..8>C......
+| 1920: 9e d3 ff 82 51 99 6d 12 f5 74 0d 84 6e f8 ed 63 ....Q.m..t..n..c
+| 1936: b8 ff 4d dd ea ae a3 0c 55 13 a1 03 4c 8b 3f 0e ..M.....U...L.?.
+| 1952: 54 b7 02 3e 01 5a 77 ad 6f fc 92 bd b3 6f 3e 89 T..>.Zw.o....o>.
+| 1968: 8e fe e1 2e 1c d4 56 c8 5f 4c 57 73 99 95 d6 be ......V._LWs....
+| 1984: f8 f5 17 22 5f 3f 13 5d 98 c9 b5 74 b2 17 7c c8 ...._?.]...t..|.
+| 2000: dd d0 a8 d1 fa da 22 5a e8 34 f9 83 93 1b 7f e7 .......Z.4......
+| 2016: ba 48 ab e4 cd 3d 54 ec a2 9b 4b ca cf 84 0a d3 .H...=T...K.....
+| 2032: 4d 8c bc 0d 73 1a 29 05 0c 60 0a 4a 6e 54 d3 0f M...s.)..`.JnT..
+| 2048: 84 00 df c0 f3 0b 73 2b 3b f0 60 68 91 ae cd 60 ......s+;.`h...`
+| 2064: 59 0b ee b7 dc 7c eb b1 cc 70 f3 bb 6a 27 3b bb Y....|...p..j';.
+| 2080: 20 41 3c 84 9d 3d 06 94 0c 53 eb 9c 31 e3 8a a0 A<..=...S..1...
+| 2096: 1e c1 65 ef a6 78 92 ae 2e f9 64 49 58 b7 c0 23 ..e..x....dIX..#
+| 2112: 2b 4c ab 93 2c 78 c2 86 32 09 d0 8e bf 34 b4 9e +L..,x..2....4..
+| 2128: 59 5c 6f 69 bb 85 5d a6 02 b2 01 85 89 23 40 7f Y.oi..]......#@.
+| 2144: 23 3f c7 67 da 35 cf 2e d0 36 1e 71 fa 78 da c5 #?.g.5...6.q.x..
+| 2160: 41 db 9a 14 b1 48 d4 02 36 2f ed 6a 85 4a f4 f6 A....H..6/.j.J..
+| 2176: f4 3f 46 81 2d fa 92 47 21 16 14 84 f8 c9 18 86 .?F.-..G!.......
+| 2192: 74 45 16 8d b3 cd 58 93 40 62 9b 24 6b af d3 44 tE....X.@b.$k..D
+| 2208: 67 f9 0a 7f e5 25 01 b9 76 3f 8e 4d 82 b8 04 ae g....%..v?.M....
+| 2224: ef ed 12 c3 9f c6 a9 54 03 8a 78 0d f4 7e bf 7d .......T..x..~..
+| 2240: c1 f5 be 24 33 54 77 e3 7f c4 c9 fd 5c 79 6d 54 ...$3Tw......ymT
+| 2256: 67 2f 83 a3 04 8b 16 09 71 ff 47 67 14 6a 84 71 g/......q.Gg.j.q
+| 2272: 39 54 18 0b 7d 7e ac ef 62 0f 4b dd 9c d0 0d 20 9T...~..b.K....
+| 2288: 9e 62 98 79 11 53 de 73 a9 9d 44 5e f5 5a 23 62 .b.y.S.s..D^.Z#b
+| 2304: 08 01 fb de 39 57 24 ac c6 b5 5f e2 6b 07 18 2e ....9W$..._.k...
+| 2320: 27 24 42 96 d8 31 68 d3 0e bb 65 9c 01 f8 93 ba '$B..1h...e.....
+| 2336: 4a 2a 60 3a b3 c2 9c 17 66 1d 34 4c 0f 90 38 5e J*`:....f.4L..8^
+| 2352: a4 9c 72 9c 16 d7 c4 98 33 ed c1 95 a2 d7 cc a1 ..r.....3.......
+| 2368: 3b 36 28 1c 44 1c 8f c9 f7 bc eb ed 5a d3 2d 69 ;6(.D.......Z.-i
+| 2384: 6f 86 9a 2f 15 91 aa 63 0d 19 f9 bb 07 6b 87 f5 o../...c.....k..
+| 2400: 0a 48 7e db b6 9a c3 97 01 d1 91 44 37 7c ce 5c .H~........D7|..
+| 2416: 63 43 c0 92 20 31 b4 5c 36 98 01 50 05 ec 1d ac cC.. 1..6..P....
+| 2432: 73 10 66 97 48 60 c2 2b 46 3e 2b fc 52 1d 42 87 s.f.H`.+F>+.R.B.
+| 2448: d3 af 2c 42 7f c4 a2 0b 2b d6 09 64 0a f9 9d f5 ..,B....+..d....
+| 2464: 54 b8 1d 96 23 1f 22 0e 56 de dc 0a f8 97 55 41 T...#...V.....UA
+| 2480: 56 ff 72 20 73 2b 50 fe 0d 79 c2 d3 61 73 22 da V.r s+P..y..as..
+| 2496: 68 8e 77 23 19 ca f9 7c a6 9c 91 27 ed eb f8 9c h.w#...|...'....
+| 2512: b6 bb 72 dc 3a 62 23 17 fb 04 98 bb ce 1a fb 1f ..r.:b#.........
+| 2528: 17 ab aa 46 46 5a 8b 98 c6 7e 0e 18 74 8a 62 9e ...FFZ...~..t.b.
+| 2544: 1f 7f f4 dd 8c 1d 68 8d 54 3d 0c 06 95 f9 9f 06 ......h.T=......
+| 2560: 3f 97 71 00 21 d5 e9 c0 44 7b 98 27 16 ba d2 fa ?.q.!...D..'....
+| 2576: c2 33 1d 4a 34 ec ae 4d a7 6c 68 77 9b f6 7b 2c .3.J4..M.lhw...,
+| 2592: 6e d3 f6 1b b6 35 6f 47 69 be 5f 96 66 13 c3 8e n....5oGi._.f...
+| 2608: 2f f1 4a 5e cb 26 00 73 33 a9 05 12 7b 6d 5b 96 /.J^.&.s3....m[.
+| 2624: b7 3d 7e bc 62 aa c7 fe d2 fb 11 d5 7c a3 bf 90 .=~.b.......|...
+| 2640: 09 fa ba 2b 2e 8d 65 c6 3f 21 41 fa 3d 71 f8 8d ...+..e.?!A.=q..
+| 2656: e5 77 34 b2 ea 4d 28 d1 48 fc 4c 1f 2e db 9c 58 .w4..M(.H.L....X
+| 2672: b1 04 54 ce 4b 68 a3 7b b6 28 16 19 22 d7 fe d3 ..T.Kh...(......
+| 2688: f9 88 dd ca f6 26 43 88 28 bb 0f 62 3b d5 d4 cf .....&C.(..b;...
+| 2704: af 90 27 ca 8e 40 62 f6 50 a8 2b 23 d4 3e 6d 32 ..'..@b.P.+#.>m2
+| 2720: e0 62 79 28 29 ab fe 77 21 ad 98 62 11 8a d2 90 .by()..w!..b....
+| 2736: 9a 83 73 c5 44 45 cb dd 71 7e 45 b7 79 d8 ab 3f ..s.DE..q~E.y..?
+| 2752: ea 53 89 0b 8c 18 b3 95 1b 45 d5 dd 45 5b 79 b0 .S.......E..E[y.
+| 2768: e8 c2 a9 58 77 cf c2 5b 43 a2 81 0e 43 9c c2 6d ...Xw..[C...C..m
+| 2784: 5b a3 7a ef ed e1 24 56 54 a4 e1 ef 07 e7 9b 0e [.z...$VT.......
+| 2800: 1f 32 78 3d a4 0f c2 52 ee 7d 4e 4d 80 4d ff 00 .2x=...R..NM.M..
+| 2816: 6c 8f da b7 ff aa fd a6 05 c1 31 e1 03 5c a4 e1 l.........1.....
+| 2832: 92 39 d9 be 7a 16 9a c2 4b c7 01 eb ef 54 f8 2a .9..z...K....T.*
+| 2848: 60 82 bb f6 4c 86 d5 8b 23 ce 88 52 a5 35 a7 ba `...L...#..R.5..
+| 2864: b6 31 e5 ec fe 30 f9 06 98 e7 bd eb 83 08 33 e5 .1...0........3.
+| 2880: c5 a2 12 68 ca cb 97 77 db 60 94 4a 43 fb c1 04 ...h...w.`.JC...
+| 2896: f1 8d 16 af 2e 8d bf 61 2a ff b5 4b 80 65 8a 07 .......a*..K.e..
+| 2912: 91 17 7f b7 ee c0 57 ce 40 82 c7 c8 57 89 62 61 ......W.@...W.ba
+| 2928: b8 63 fe eb c2 97 30 ed 71 84 23 b3 48 e9 d9 ba .c....0.q.#.H...
+| 2944: 71 c3 66 f5 6a 66 5a ee e6 bf 72 fe 80 a1 40 24 q.f.jfZ...r...@$
+| 2960: 75 0e 01 f9 1d 18 c3 fd 73 1c 21 92 5c 2b 07 a0 u.......s.!..+..
+| 2976: 83 80 5c 0f 20 fe e9 55 d6 f4 4c 96 d8 ab 7a 5c .... ..U..L...z.
+| 2992: d6 d1 1e 44 60 ee 0a 30 7e 92 cf af a3 41 20 d5 ...D`..0~....A .
+| 3008: 0b de fb 9c f4 81 76 5c d6 58 5d 86 1e 14 10 c5 ......v..X].....
+| 3024: 12 b5 f1 2d 73 09 0b ad 33 2c 49 5f 59 a7 08 80 ...-s...3,I_Y...
+| 3040: 30 bf 50 61 b4 0b b2 3c 53 f3 de 2f e0 87 59 58 0.Pa...MC....u.
+| 3200: 36 53 ad 19 cc d1 3c 57 45 64 fc e4 19 89 42 81 6S...........
+| 3424: 65 16 ad c6 c4 a3 75 78 94 b2 ce b5 9c 50 df 02 e.....ux.....P..
+| 3440: f3 c2 91 11 5a 81 de eb 31 24 16 50 16 d8 5f c5 ....Z...1$.P.._.
+| 3456: df 62 1b 24 37 bb cd 5d a8 a7 93 d0 6a 5e d8 55 .b.$7..]....j^.U
+| 3472: 74 cf 69 a2 4a 05 07 2e 61 09 0e fa 1e 12 ab 62 t.i.J...a......b
+| 3488: d9 ca ff ab 2b b0 3b 16 16 b0 95 15 27 26 89 46 ....+.;.....'&.F
+| 3504: d3 67 fb 0f 33 00 18 44 c3 a1 92 de 6e 6d b0 67 .g..3..D....nm.g
+| 3520: b0 65 97 fa b9 10 1d 39 15 10 95 f1 b3 cc a3 d4 .e.....9........
+| 3536: 28 06 9f b7 00 be a1 06 8f 61 34 66 92 fa 58 0b (........a4f..X.
+| 3552: 4f 91 6d 93 31 32 cb a1 97 a5 18 b2 f1 bc fc 70 O.m.12.........p
+| 3568: c0 86 62 24 4b 82 ce b3 71 30 53 ac 42 c7 32 2d ..b$K...q0S.B.2-
+| 3584: 3a 0e 3f 8a 91 89 0b 46 55 f3 5d 73 b1 74 a2 9e :.?....FU.]s.t..
+| 3600: 97 6e 85 b6 f0 3e 56 6d 31 50 96 87 3d 18 cf 5f .n...>Vm1P..=.._
+| 3616: 74 57 1a 65 b4 d2 4e 96 1c 6e 3f 5b a9 a0 47 2d tW.e..N..n?[..G-
+| 3632: 22 5b 16 ab 27 f4 86 36 f7 8e a1 f2 9c 69 7f 0c .[..'..6.....i..
+| 3648: 85 4d 3c 08 3b fa 96 ee 92 af f9 8d c2 ca a9 f1 .M<.;...........
+| 3664: 2b fa 90 4b a3 fb 35 c4 c6 05 c3 0f ad 5e bb f6 +..K..5......^..
+| 3680: 55 66 73 bd db 98 2f 70 7d 25 3f 05 3d 24 c6 0d Ufs.../p.%?.=$..
+| 3696: 8a e2 e1 3e 19 59 51 25 a9 e8 4a 0a 68 69 05 c9 ...>.YQ%..J.hi..
+| 3712: ce 1e 5f 96 c4 a1 98 2a 7b b9 e9 99 ce 84 af 0b .._....*........
+| 3728: 82 61 5b 97 b1 8c 2e ea 81 98 44 39 79 e0 d5 9c .a[.......D9y...
+| 3744: 6a b9 14 0f 36 98 ea c8 cd 6b 66 fa d1 23 cf cb j...6....kf..#..
+| 3760: c6 1b 25 6c 42 13 b2 67 f9 68 0a 62 ff 37 ab ca ..%lB..g.h.b.7..
+| 3776: 22 60 77 c1 30 e4 59 5f 17 b4 47 c3 ea c5 c4 2b .`w.0.Y_..G....+
+| 3792: 62 44 94 08 87 03 1a a5 10 ae b1 53 cd 2d 40 5a bD.........S.-@Z
+| 3808: 80 ef dd 56 6b 88 92 d7 3c d0 7a a0 2f 63 22 02 ...Vk...<.z./c..
+| 3824: 61 f1 ab 36 f9 16 f0 14 ba 67 7d 9c 7f 90 cc d9 a..6.....g......
+| 3840: b1 ac d3 1d 73 1e e8 bf 88 6a 6b 15 32 b3 b5 9c ....s....jk.2...
+| 3856: 4a ad bd 4f f8 f8 b8 b8 2e 48 0f e2 e9 d6 d9 72 J..O.....H.....r
+| 3872: 22 9a 28 8d 24 e2 f0 33 23 27 ff 37 5e 36 55 37 ..(.$..3#'.7^6U7
+| 3888: e1 92 78 19 a4 9d ff b9 22 e5 47 79 b8 de b4 9f ..x.......Gy....
+| 3904: 4e f0 65 1d 89 5e 55 86 bf 25 ff 6f 7e 27 f2 c1 N.e..^U..%.o~'..
+| 3920: 9d 26 69 ab 5b 1a 16 1d a1 b7 0a f0 60 06 12 4b .&i.[.......`..K
+| 3936: ce 6b 17 d3 e7 66 ef 6d 83 10 30 96 49 8b 8d 52 .k...f.m..0.I..R
+| 3952: 98 65 b1 48 a8 0d 96 ae 15 cd 00 5b f5 3e 4c f6 .e.H.......[.>L.
+| 3968: 16 b3 15 5b cf 3e ba 15 86 7e 9b 92 be cb 8a de ...[.>...~......
+| 3984: d0 de c8 0e ac cb 79 cc 8f ad f6 3a 40 33 9f 91 ......y....:@3..
+| 4000: 48 7c 3f d1 33 c1 d3 51 ba 44 47 0e 41 8d fa 2d H|?.3..Q.DG.A..-
+| 4016: 55 99 7f 4d 44 4a 85 dc 6b b1 9f 8a 4c 55 70 b7 U..MDJ..k...LUp.
+| 4032: 2d 14 4d 72 ea 76 c8 0c 9f 9c 99 0a c2 7e 95 94 -.Mr.v.......~..
+| 4048: 61 84 76 8c 20 1f a3 2d 5f 54 ab 5b 8c fc 04 0d a.v. ..-_T.[....
+| 4064: 25 33 9f d1 f3 f7 38 1d 64 4c c1 0d 38 0e 4d b8 %3....8.dL..8.M.
+| 4080: 61 16 f8 ea 3d 01 e9 f7 7b 6d 10 ed 08 07 86 f3 a...=....m......
+| page 12 offset 45056
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 04 06 00 ae 7c 00 00 72 d0 44 9f 95 5b ad 14 >....|..r.D..[..
+| 1104: 76 bf ee ef 64 b3 05 0c b8 3c fa 37 1b ab 5a f0 v...d....<.7..Z.
+| 1120: ae 4c 14 79 98 2a 95 49 a0 1e 3e ff 44 91 47 ad .L.y.*.I..>.D.G.
+| 1136: 40 a0 7b 5e 0c 5f 86 45 28 c7 d9 03 81 2b 26 13 @..^._.E(....+&.
+| 1152: 0c 38 01 db 73 e2 42 53 3c 8c d1 6c fd 51 a6 5a .8..s.BS<..l.Q.Z
+| 1168: fa 65 81 fc 71 89 ea 74 84 df da ea e0 d8 40 ce .e..q..t......@.
+| 1184: 56 a4 cb 65 0b 6b 79 7c 81 a9 55 79 8c 3e 02 dd V..e.ky|..Uy.>..
+| 1200: 17 7f 47 b6 84 c0 c2 a3 5e 79 66 83 e4 f2 73 6a ..G.....^yf...sj
+| 1216: 46 9f 20 24 f3 4e 2b 6e a9 2c 9b 51 39 96 42 82 F. $.N+n.,.Q9.B.
+| 1232: ec c0 c9 78 ec ec 90 e3 57 af fb 1f 51 41 a3 37 ...x....W...QA.7
+| 1248: b7 68 5d 84 5e 6a 9e 17 13 e1 87 7d 93 f5 92 8e .h].^j..........
+| 1264: 7a 8d 3b d4 40 35 df 0e 8f 80 13 f3 54 9c 57 a8 z.;.@5......T.W.
+| 1280: 86 88 69 32 7d a2 22 13 ab 14 db e6 8a 1c 84 ed ..i2............
+| 1296: 54 4e d3 0a ba 5f 9e 66 88 2a 64 d8 04 86 3c 5e TN..._.f.*d...<^
+| 1312: 41 b7 2d c2 c1 a0 73 61 d8 80 3b 9d 9d 1e 11 ab A.-...sa..;.....
+| 1328: ae 20 63 ac 31 80 2e 66 d5 a7 c8 8e 0a 55 78 53 . c.1..f.....UxS
+| 1344: 66 8d 5d 1e cb 04 13 d9 a8 d1 09 4b 31 3c e9 ba f.]........K1<..
+| 1360: 83 69 76 4c 12 e8 95 84 e1 fe c0 64 74 c5 74 8d .ivL.......dt.t.
+| 1376: 1f 75 28 75 1f 51 23 b7 df ef 45 66 61 1b 18 2e .u(u.Q#...Efa...
+| 1392: c8 56 69 8f fa 2a 08 41 21 2d 6a c7 79 46 8f 95 .Vi..*.A!-j.yF..
+| 1408: dc b1 b2 d7 39 b9 a6 41 af 06 3e 53 85 c2 db c3 ....9..A..>S....
+| 1424: 42 fb b7 4f e9 e0 11 c1 a6 9a 48 fb d6 c9 26 31 B..O......H...&1
+| 1440: 3b c4 7a e2 bd 53 d7 3e d7 56 60 8f 6a 80 60 19 ;.z..S.>.V`.j.`.
+| 1456: db fd 5a 7a 8c c7 43 c7 29 57 8b 6f 31 ea 13 af ..Zz..C.)W.o1...
+| 1472: de 2e 32 75 5f 63 b7 bb 45 07 9e da 69 54 a0 fd ..2u_c..E...iT..
+| 1488: 0e dc 0d f5 42 17 eb 64 60 0d d8 56 4b 61 6d 8c ....B..d`..VKam.
+| 1504: 82 09 f1 80 a2 25 5d 8b e5 67 76 13 9d 46 4a 6f .....%]..gv..FJo
+| 1520: 30 f6 eb e0 7b 0e 01 e1 a8 b2 38 1b 9b 21 48 ed 0.........8..!H.
+| 1536: c8 7f 7d 6b 0c 25 ce a8 0a 78 a8 48 45 2d b5 e7 ...k.%...x.HE-..
+| 1552: fd ca b2 a1 2b 2a b9 72 61 76 76 0c ae 9c b3 17 ....+*.ravv.....
+| 1568: fa 83 07 24 24 62 18 18 d6 12 2d ad 58 0b b3 5e ...$$b....-.X..^
+| 1584: 80 da 40 b5 d0 e7 aa 28 52 bc 7f 68 7a 1d 5a 1f ..@....(R..hz.Z.
+| 1600: 79 65 10 9e 4d fe be 32 c7 0f aa 7d a5 0a 43 0f ye..M..2......C.
+| 1616: 3d 17 0e 88 a3 7f 3f ff 04 bc 79 56 62 0e 9b a0 =.....?...yVb...
+| 1632: 51 1f 49 04 ff 40 7a c2 51 e8 36 44 85 63 df a4 Q.I..@z.Q.6D.c..
+| 1648: d5 63 a4 eb a3 71 44 b4 02 51 a1 2b 00 73 69 4e .c...qD..Q.+.siN
+| 1664: 07 76 42 84 bc 87 1a e6 15 13 f7 ac 7a e8 bf c0 .vB.........z...
+| 1680: a4 8a 64 fe 9c 17 a7 20 cb 67 cd e6 da f1 95 26 ..d.... .g.....&
+| 1696: b6 79 d4 93 e2 52 fd 6f 44 29 db 1e 34 02 46 a4 .y...R.oD)..4.F.
+| 1712: f1 c5 f0 b5 c3 19 1d 0e 14 d4 ba 08 1c 01 bf 39 ...............9
+| 1728: 54 02 e2 f5 d3 cf fb d1 d6 76 65 91 ba 7b c8 22 T........ve.....
+| 1744: 85 f8 fa c7 ae ae 21 85 b9 d2 09 5f f4 3b 27 c5 ......!...._.;'.
+| 1760: 13 39 39 7e 79 ae 07 37 26 72 07 22 01 40 2c 10 .99~y..7&r...@,.
+| 1776: 5b 2c 9b bf 30 92 2e f5 12 9f 19 f9 2d 69 2a c6 [,..0.......-i*.
+| 1792: 9a 26 1b de 18 b8 05 65 a8 b4 b3 3e 2c 04 5b bc .&.....e...>,.[.
+| 1808: 63 79 56 7a ba 24 ae 69 ee d6 d5 7c 3d 5f 2f 7b cyVz.$.i...|=_/.
+| 1824: e9 e5 55 f2 88 58 72 49 89 3e d5 91 be ae ea 9e ..U..XrI.>......
+| 1840: 58 20 45 2c da c7 b8 f9 db 97 68 59 c7 f4 d3 4b X E,......hY...K
+| 1856: 95 b6 c7 73 1c 9b 96 d2 1c 56 17 eb 18 a1 fa 17 ...s.....V......
+| 1872: 05 72 44 05 4f c3 2b 8c 89 d2 3c a2 25 d8 16 74 .rD.O.+...<.%..t
+| 1888: 48 b7 78 36 7a 86 88 ff cc 47 ac bd 73 28 1f 3f H.x6z....G..s(.?
+| 1904: 13 3d b9 d2 df 9a 93 43 a6 9f b9 fc 7c b2 d4 84 .=.....C....|...
+| 1920: c4 7e d0 14 60 01 63 fb 09 de a3 2f 1c ae 2e 6b .~..`.c..../...k
+| 1936: 9f 8d c8 f1 2d f0 c9 a5 1f 48 c1 7c 53 c5 63 8a ....-....H.|S.c.
+| 1952: 9b 0b fd f3 7f 3a 63 eb 2c 4f df 3a 57 8c 20 3e .....:c.,O.:W. >
+| 1968: 0b d1 00 0f ce e3 ab a8 77 31 63 4a aa 35 5f 3f ........w1cJ.5_?
+| 1984: 77 ba d3 38 7b a3 53 94 e6 9d 34 ec 5a 28 09 6e w..8..S...4.Z(.n
+| 2000: 5a 85 bc 72 18 bb 15 8a 20 01 f3 88 19 74 65 1b Z..r.... ....te.
+| 2016: 51 bc 8a 4d 32 a6 00 80 fc 06 f8 aa 1c ee 0e 84 Q..M2...........
+| 2032: b5 70 fe 09 02 78 d4 ae 3a bb 02 ed 5a 90 d2 a9 .p...x..:...Z...
+| 2048: 3e 58 8a 08 2d 4c 79 7c f2 94 89 ac 04 59 d8 17 >X..-Ly|.....Y..
+| 2064: 09 e4 c3 e0 78 6b 77 58 64 4f 2f 77 15 16 c2 41 ....xkwXdO/w...A
+| 2080: 96 61 8c 23 59 73 b9 56 c3 4e da 79 34 94 e5 31 .a.#Ys.V.N.y4..1
+| 2096: 9b a6 92 ca 23 64 e4 78 32 e2 9d 2e ad 18 11 b7 ....#d.x2.......
+| 2112: 12 0d 1b 40 44 4f 92 cf 78 80 86 fb af c9 30 20 ...@DO..x.....0
+| 2128: 52 9b 22 8f f4 ca 65 e5 f2 e7 a3 c3 e7 00 ee a1 R.....e.........
+| 2144: ca ab 3d 71 40 bd cf c3 2f 7b 59 e7 9d 18 6a 65 ..=q@.../.Y...je
+| 2160: a1 c9 84 cf 0f f5 36 d5 22 06 d4 6a b6 ad 38 03 ......6....j..8.
+| 2176: b4 ac 9e c4 7a b0 71 24 a9 01 f0 5c 5b e3 c9 bd ....z.q$....[...
+| 2192: d6 e7 ba 71 fd 44 22 14 af f7 18 ef 29 1d f2 0f ...q.D......)...
+| 2208: 5d e1 3a 71 3b 47 44 da 21 f6 73 8b 6a a1 ff 93 ].:q;GD.!.s.j...
+| 2224: d5 eb 5d d0 61 23 41 53 99 7f 23 0f c0 a3 18 3c ..].a#AS..#....<
+| 2240: bd 30 e0 bf 16 41 27 71 80 67 49 61 e9 64 71 e0 .0...A'q.gIa.dq.
+| 2256: 9d 42 e6 48 9b 0e 40 82 f9 e2 a5 b4 51 37 7d 6b .B.H..@.....Q7.k
+| 2272: 74 54 03 bb a2 93 ac 47 f8 a5 75 86 73 0f 12 47 tT.....G..u.s..G
+| 2288: 27 65 16 16 a2 ab 99 08 14 0b 7e 1b 2c 7e 9d 20 'e........~.,~.
+| 2304: 58 23 14 70 bd f5 7c 2b 74 ce d1 46 b3 29 03 8f X#.p..|+t..F.)..
+| 2320: 76 f3 20 ca 9e a3 fc 1a 17 f2 8e 78 97 4e 0b 5e v. ........x.N.^
+| 2336: 61 2b e1 3d f1 14 ae 9a 1f e8 a8 3c 99 02 a5 c0 a+.=.......<....
+| 2352: a6 ee bd 47 a4 3c 6d db 6c 20 dd c4 60 09 17 e7 ...G.h$^0....z.....
+| 2464: 89 df 3b c6 e1 09 1d 16 69 40 e9 d7 f7 41 d3 2b ..;.....i@...A.+
+| 2480: 52 6a 9a d9 65 e2 44 de 45 63 be 85 41 b8 d4 4a Rj..e.D.Ec..A..J
+| 2496: 49 b9 b8 bb 4d a6 6e 60 46 13 6f 7f b1 57 9c 5b I...M.n`F.o..W.[
+| 2512: 78 69 87 3d 42 e5 c2 0a 46 9c 38 9d e2 44 80 fe xi.=B...F.8..D..
+| 2528: c8 81 f4 fe bb ef 61 46 88 c7 6f 1a f8 00 0b 63 ......aF..o....c
+| 2544: d0 ac 8e 5e 88 8d 2d 56 15 79 d2 12 d9 94 ba 2b ...^..-V.y.....+
+| 2560: ae 71 63 be 62 08 75 b9 97 fc 1e 17 89 83 3b 30 .qc.b.u.......;0
+| 2576: 07 6e f0 db 44 17 c0 49 7f ed 0a 0a 43 13 6a 72 .n..D..I....C.jr
+| 2592: 78 9c 96 52 2c 02 ac da a0 90 b5 66 34 b7 a2 17 x..R,......f4...
+| 2608: e7 71 11 8d 8f 22 0e 40 90 9b 0f 99 f5 10 c0 64 .q.....@.......d
+| 2624: ac e3 24 0d 49 1a f4 2f 0b 13 fc 94 a7 18 b1 5f ..$.I../......._
+| 2640: a6 64 49 0b c2 35 99 b6 05 81 bd a8 f8 88 56 83 .dI..5........V.
+| 2656: 17 56 cc f8 91 db 5b 18 7c 42 46 3f 3d 9a 2d b6 .V....[.|BF?=.-.
+| 2672: 63 8c 62 bf 78 53 a0 23 53 40 c0 32 06 f1 c8 3a c.b.xS.#S@.2...:
+| 2688: f8 17 34 a7 29 1e ab 92 2d 2d 68 c5 83 e0 0a 2e ..4.)...--h.....
+| 2704: 7b f8 9c b7 32 86 c0 1e f5 29 44 a6 24 e1 d7 66 ....2....)D.$..f
+| 2720: 0d 48 2b 0e 49 f8 e4 52 4a 7d bd 1c c1 44 27 f0 .H+.I..RJ....D'.
+| 2736: c9 db 87 93 13 62 82 ef ad 2c ea 8f d1 3d a4 a6 .....b...,...=..
+| 2752: b8 80 87 e2 0e 27 27 b3 3d 56 66 39 de e8 21 5f .....''.=Vf9..!_
+| 2768: 95 25 d9 68 f1 57 50 0e 15 54 0b a6 44 27 e8 d9 .%.h.WP..T..D'..
+| 2784: f2 dc 5e 79 f0 ec 2b a3 39 77 8f 3d 53 70 8a d3 ..^y..+.9w.=Sp..
+| 2800: e5 aa 14 cb 7b dc 31 72 f6 90 5e 8b 3a 8c f3 77 ......1r..^.:..w
+| 2816: 4d 00 a3 1d 3a 63 47 c0 2a a2 32 98 6e 5c bc 21 M...:cG.*.2.n..!
+| 2832: f0 6a 34 6c 89 a5 bc 04 f6 3b 8c 96 b0 eb 0d 70 .j4l.....;.....p
+| 2848: 9f 18 d5 64 ec 2e df 19 7d 1d a4 61 48 e7 0b eb ...d.......aH...
+| 2864: f3 94 16 f5 7f 4c 9e 0c 78 aa 4b 61 14 13 eb e2 .....L..x.Ka....
+| 2880: 72 14 56 27 41 70 8f 7f cb e6 a1 c3 37 c4 78 32 r.V'Ap......7.x2
+| 2896: 85 ea e5 af 96 46 4b c3 93 af 8f 26 0c ea 08 b6 .....FK....&....
+| 2912: b4 a6 a4 78 6d 82 51 ab fb e5 a9 e9 89 c3 a1 be ...xm.Q.........
+| 2928: 3e b9 e3 8c 61 cf 42 1d de 25 45 9e f0 ff 8b 75 >...a.B..%E....u
+| 2944: 63 9b 3d d6 92 c3 ad ca c5 4c 79 9d 72 37 fd 3a c.=......Ly.r7.:
+| 2960: 21 f2 8d 34 37 b9 eb a0 86 d8 1a f2 9d aa 6a 53 !..47.........jS
+| 2976: f6 c9 29 d0 39 2c 66 24 c6 8e 68 9c 70 cc 9e cc ..).9,f$..h.p...
+| 2992: 25 a8 dd 5e d8 e6 87 1b dc 3a 26 20 e3 1c 3b ba %..^.....:& ..;.
+| 3008: f8 c4 80 83 79 49 f1 2a f0 e8 70 31 e7 b2 a5 e3 ....yI.*..p1....
+| 3024: 9f 5b 49 25 2c 33 b6 ea 38 ab a8 0a 9a a2 0e fd .[I%,3..8.......
+| 3040: 3a a8 9c 0f ab 93 45 a7 54 d2 18 2f 2e 94 34 cc :.....E.T../..4.
+| 3056: fa 14 b6 8e 01 8d af 80 94 e7 80 31 dc 2c b9 1e ...........1.,..
+| 3072: dd 35 91 29 28 a0 29 65 bc e3 a2 52 b0 e5 56 5a .5.)(.)e...R..VZ
+| 3088: 12 21 06 fd f3 04 77 31 6d f2 e0 66 0a a3 77 f3 .!....w1m..f..w.
+| 3104: 5a 17 37 59 65 d9 32 68 82 2c 72 05 16 e9 9a 89 Z.7Ye.2h.,r.....
+| 3120: 10 94 53 e9 be 63 2e 82 27 28 30 1d 2a bf ad 00 ..S..c..'(0.*...
+| 3136: 49 9a a7 e3 50 d0 61 b4 bd 73 3e 99 a3 a7 69 7f I...P.a..s>...i.
+| 3152: a8 4c 4d 12 7f c0 55 b7 de 0c 93 5e 27 cf 4a 53 .LM...U....^'.JS
+| 3168: 78 08 ee da 22 37 3f 94 2f dd a6 b2 28 84 0f 62 x....7?./...(..b
+| 3184: bc 7f be 3c af ad 84 82 70 b2 98 d5 9a d5 07 34 ...<....p......4
+| 3200: 41 6f 9c 0a 17 54 cf fc 43 1e 7c ca 48 6f 23 c5 Ao...T..C.|.Ho#.
+| 3216: 50 7b b6 ec e5 3a 27 0f 65 29 97 ad 37 b1 9f e6 P....:'.e)..7...
+| 3232: 6b d1 d4 41 ed 5e 0e 20 22 00 ca 41 58 d2 b9 73 k..A.^. ...AX..s
+| 3248: 08 2d 01 83 db d1 57 a2 e3 d2 34 c6 73 fd 2e b2 .-....W...4.s...
+| 3264: 9b f2 a4 a4 f1 1d 9f 7a cc d8 93 37 b3 95 2c 99 .......z...7..,.
+| 3280: f5 92 0c 91 d5 e2 2e b2 bb 49 76 19 c9 58 16 28 .........Iv..X.(
+| 3296: 1e 76 60 ba d9 a8 04 e9 91 5e 7f e6 b1 dc de 9f .v`......^......
+| 3312: 6f e6 52 f2 61 53 7b 09 f4 df c4 96 15 23 99 67 o.R.aS.......#.g
+| 3328: 6b b8 e8 04 05 62 0d 5f 05 d1 8a 6c 49 e8 2b 71 k....b._...lI.+q
+| 3344: 10 44 8e 93 13 bc 27 14 32 52 22 2d 11 cf cd 43 .D....'.2R.-...C
+| 3360: 77 a1 60 21 70 44 60 cb 64 9e b4 c6 23 aa f2 0d w.`!pD`.d...#...
+| 3376: c0 6d 50 0b d9 73 d0 eb 6d d5 03 fc 74 e1 fb 49 .mP..s..m...t..I
+| 3392: a1 18 4f bb a2 2f 09 54 28 80 8c 04 86 3d e1 fd ..O../.T(....=..
+| 3408: ff 55 c9 7a a0 35 ef 64 b8 87 1b 10 8c fc 3d 27 .U.z.5.d......='
+| 3424: e3 6c 30 3c 05 4d b3 37 b8 29 ba a2 46 9b 76 5d .l0<.M.7.)..F.v]
+| 3440: ff 1b 30 65 70 57 f2 89 c3 17 3f 21 5d 26 5f 58 ..0epW....?!]&_X
+| 3456: b1 50 6e 75 c3 dc be a9 0e 43 3e 34 4e 40 0e a1 .Pnu.....C>4N@..
+| 3472: f4 69 6d b1 56 a7 0f 09 7e 25 74 08 83 bb 9d 67 .im.V...~%t....g
+| 3488: a6 f6 68 87 e9 d9 ba 16 97 42 ca 66 29 e6 df cd ..h......B.f)...
+| 3504: e8 e4 ef ef c9 1f f7 d8 9c 8a a3 24 c9 43 60 4d ...........$.C`M
+| 3520: 9a 73 cb 73 9f b2 b1 fe 51 9d 55 9f 37 a0 d2 3c .s.s....Q.U.7..<
+| 3536: 7e be e4 35 1e 8e 81 f5 67 29 29 ac 95 0a 99 28 ~..5....g))....(
+| 3552: ec 4c f2 c6 03 6b 01 76 f5 87 77 58 51 51 40 d4 .L...k.v..wXQQ@.
+| 3568: 81 c7 d7 7b 40 09 8f f5 c8 a7 49 00 c9 ee 99 c9 ....@.....I.....
+| 3584: 6f 4a c5 6f e7 51 8e 4c 95 a3 de 6d 53 45 7b 97 oJ.o.Q.L...mSE..
+| 3600: 7b 7f 8b b4 db f7 52 97 08 2e 4f 36 41 24 79 bd ......R...O6A$y.
+| 3616: 54 bb b8 2c 32 6c 1f 54 e6 82 47 27 53 7f 57 ea T..,2l.T..G'S.W.
+| 3632: 4c 10 71 9b b2 0d 9a 80 fb d2 a6 ec 8d 6e 60 64 L.q..........n`d
+| 3648: 1a 73 43 13 b9 cb b1 bd da 84 82 8d 17 ae 75 4d .sC...........uM
+| 3664: 1a af 28 9d 01 6d c7 f7 25 8c b5 ef 1b 5e 33 86 ..(..m..%....^3.
+| 3680: e7 ce 59 c0 5b 3d e2 46 ab 85 3b b2 c0 9e 7a 75 ..Y.[=.F..;...zu
+| 3696: 26 15 cd 6e 6d c2 19 fc cb 3e 5c 5e 95 94 ec 29 &..nm....>.^...)
+| 3712: 94 8e d4 e6 0a 38 8c ef fc eb cb 3a 06 97 20 f3 .....8.....:.. .
+| 3728: 5f 53 b5 5f 40 33 9e 41 9c db a8 f3 7a d8 aa 0e _S._@3.A....z...
+| 3744: a3 37 00 87 ff 13 78 1a 98 c2 b2 aa bf 2d 10 24 .7....x......-.$
+| 3760: 8e e5 9f 9f 3c 4f e4 90 e0 6a 90 44 32 9f ca 6a ....9=J.4....
+| 3888: 9c 65 c7 29 02 bf a6 97 61 3c 6f 46 48 0a e5 a6 .e.)....a7~.
+| 3952: 43 f8 b7 ae 2e af d4 9d 67 8d fa c0 24 b2 1c 55 C.......g...$..U
+| 3968: ea aa 33 67 22 d4 f3 e7 87 a5 9d fe a3 04 55 ae ..3g..........U.
+| 3984: 56 87 2d 21 a9 02 c2 4d a3 88 a3 3f 48 18 83 a7 V.-!...M...?H...
+| 4000: 01 b9 6d 60 d4 0f 79 79 8a 4b 66 c3 49 c7 51 0b ..m`..yy.Kf.I.Q.
+| 4016: 15 73 df f2 53 eb 79 03 da 55 2f 5d 9f 8f 01 a7 .s..S.y..U/]....
+| 4032: c7 5d cf 61 f0 c2 78 52 56 b8 45 7d f2 d8 56 ca .].a..xRV.E...V.
+| 4048: 80 84 6e ee 2a 00 ba 00 74 46 0f 76 23 76 79 55 ..n.*...tF.v#vyU
+| 4064: 4f 97 57 f2 63 07 11 1f a3 46 07 14 3b 50 43 c0 O.W.c....F..;PC.
+| 4080: 72 b2 89 5a 44 15 dc c8 9b 2e f8 ad 69 80 3e d7 r..ZD.......i.>.
+| page 13 offset 49152
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 05 06 00 ae 7c 00 00 40 9e 86 c7 f4 d7 a0 78 >....|..@......x
+| 1104: b9 63 d2 14 9c 0c 6a 77 07 99 fe 03 10 f7 fd 07 .c....jw........
+| 1120: ea be 72 a1 24 46 49 15 05 16 1f 1c 80 72 1b 98 ..r.$FI......r..
+| 1136: e5 f9 d0 65 50 cb 29 09 d4 2b 17 e2 73 7e 45 4f ...eP.)..+..s~EO
+| 1152: 05 c8 b5 bb 1a 81 34 52 32 17 53 96 c8 0d 54 19 ......4R2.S...T.
+| 1168: bd d8 c3 af 35 79 a8 75 ae 2d 5d c4 44 eb b2 1f ....5y.u.-].D...
+| 1184: ab 9d f6 d8 42 7b 3b dd 10 f4 34 95 57 ff ec cc ....B.;...4.W...
+| 1200: 63 3f d3 93 e5 16 6d b5 3d e3 23 7b 32 88 b7 ce c?....m.=.#.2...
+| 1216: 7b 9a 8c 46 26 6f ed 2f a7 83 fb fd a7 b7 1b 48 ...F&o./.......H
+| 1232: 88 40 20 a5 9b de 7b d9 32 e5 72 1c 85 8a a2 63 .@ .....2.r....c
+| 1248: e2 8d 7b 25 a2 13 51 ec fd 0a ed 1b 76 8f 9d 62 ...%..Q.....v..b
+| 1264: 2e 9e cf 0f df 58 30 83 e5 90 40 df d2 9f c9 65 .....X0...@....e
+| 1280: 3f ae c6 4a 11 a3 16 5b 6f 24 74 95 5e 21 6a c8 ?..J...[o$t.^!j.
+| 1296: da 7a dc 82 c2 ab a0 93 c8 dd a8 f1 1d 78 5e 9b .z...........x^.
+| 1312: c8 17 c7 e0 4f 53 1d e1 5a 5f 5c bf 23 25 fb f3 ....OS..Z_..#%..
+| 1328: a0 d4 f5 f7 16 78 f8 00 2e 49 1f 7b ff 41 5c 11 .....x...I...A..
+| 1344: 83 9e c7 f4 f5 c7 85 d3 97 dd 67 5a 1e 47 d0 41 ..........gZ.G.A
+| 1360: ae cb 4c 47 4f 5f fc 9f bf 0b 20 04 94 08 11 8b ..LGO_.... .....
+| 1376: a8 98 f2 5e 86 19 3b f1 0f 9d 49 c8 02 14 68 24 ...^..;...I...h$
+| 1392: 20 71 28 49 3c 60 5a 92 ea d3 2c cd 8a 8a d7 cb q(I<`Z...,.....
+| 1408: fd 14 db 41 3c d0 24 89 46 6a c4 52 8d f0 c0 dd ...A<.$.Fj.R....
+| 1424: b4 a6 0f bd c2 5a fd d1 53 bb a9 82 88 64 4a 34 .....Z..S....dJ4
+| 1440: 0f 8f ed 49 49 81 03 29 c3 c3 01 00 6a 83 21 dd ...II..)....j.!.
+| 1456: bc 98 29 fb 2b 5e 78 95 4a 57 4f a7 d3 ec 44 a8 ..).+^x.JWO...D.
+| 1472: 97 6c 7f 39 11 6f aa a0 60 b1 71 43 a6 45 ea 9b .l.9.o..`.qC.E..
+| 1488: e1 6f 67 2b f9 e4 8a 55 60 5b 69 f3 54 bf 5c 78 .og+...U`[i.T..x
+| 1504: 32 d4 25 22 bf 9b 7a a6 a8 a3 70 53 7d e8 50 1c 2.%...z...pS..P.
+| 1520: cd 2a 4a 92 a7 f1 e4 84 39 8e 72 a4 cf 3a c8 b2 .*J.....9.r..:..
+| 1536: 3e f1 06 f2 83 80 0c 1c 10 91 7b 41 92 f5 df 0f >..........A....
+| 1552: 7a dc 04 78 3c b4 cd 96 b6 15 f6 7f 85 33 db 09 z..x<........3..
+| 1568: 92 de 83 ef fc 2c 75 43 49 0c 12 61 48 14 38 d3 .....,uCI..aH.8.
+| 1584: b4 fb 43 33 74 3a 0a 5b c5 03 0a d8 f2 2c 1d cf ..C3t:.[.....,..
+| 1600: e9 a0 7f be 25 24 90 77 75 2f 15 a7 ff 62 83 ef ....%$.wu/...b..
+| 1616: 01 04 b1 7c c8 5d 03 5a 28 1d a3 24 e9 7f 32 73 ...|.].Z(..$..2s
+| 1632: 19 59 8c 07 30 10 be 58 c2 48 f6 d1 c6 3c b3 09 .Y..0..X.H...<..
+| 1648: e0 bf 5c c3 47 81 c8 04 71 ab 55 cb a5 7c 7a a8 ....G...q.U..|z.
+| 1664: 45 28 03 75 e9 82 51 e8 bd 41 d4 1e cc b1 fe 43 E(.u..Q..A.....C
+| 1680: 4d 5c 66 25 6f fa da a6 fa ea d3 de 0a 2e 5a 3d M.f%o.........Z=
+| 1696: 68 65 10 b6 ee 3c 0b f6 13 bf 3e 6e 57 f3 30 43 he...<....>nW.0C
+| 1712: f6 f4 e0 34 e5 47 88 73 9d 9c 36 f0 90 98 0e 5a ...4.G.s..6....Z
+| 1728: 3b ab 0c 7f 8b ab ea 9c 8c 5e 34 26 d7 53 bb cb ;........^4&.S..
+| 1744: 18 58 a7 6f bf 78 43 7b 47 a6 3b 09 f7 9f 5f 81 .X.o.xC.G.;..._.
+| 1760: 87 c0 17 02 8f ad 78 32 8c dd 96 0e d8 b8 66 66 ......x2......ff
+| 1776: 23 91 e3 e3 37 5c 63 f4 16 c1 58 4f b7 63 de 7c #...7.c...XO.c.|
+| 1792: 36 c3 67 fc 32 a3 d8 84 20 fe e6 0f 2e 2d ee 11 6.g.2... ....-..
+| 1808: 3b 97 1a 05 47 ea a1 71 c4 11 08 b1 a9 52 b7 54 ;...G..q.....R.T
+| 1824: bf 4c 06 dd f5 a3 ec c2 ce eb c3 82 e0 5f 5c c1 .L..........._..
+| 1840: 51 9c e9 d7 d1 45 a6 ea 62 dd 3b 25 79 0a 5e ed Q....E..b.;%y.^.
+| 1856: 5a 9d 81 8e 7c a8 fd 60 31 88 80 f3 df de 60 23 Z...|..`1.....`#
+| 1872: 4e 07 7a 02 dd 89 7d 2c bd ce fa 45 ff c6 05 f4 N.z....,...E....
+| 1888: ff 2d 18 f5 13 37 c8 d8 be e9 6d 81 da 8f 03 e4 .-...7....m.....
+| 1904: 82 0a c3 3b 19 10 de 4a d8 12 37 37 ce 51 4d 41 ...;...J..77.QMA
+| 1920: 0a ad 6a 1f c2 80 49 84 15 7d d4 f0 53 5d d1 b1 ..j...I.....S]..
+| 1936: b3 c7 27 34 2f bd 05 af df 5c 5f 86 90 55 99 e5 ..'4/....._..U..
+| 1952: 4a 9f 86 34 30 b1 fe 0d 14 2c 1a 85 28 0e 09 5e J..40....,..(..^
+| 1968: d0 31 99 e7 8c ff 6e f9 e6 a5 cb fd 85 9b f7 31 .1....n........1
+| 1984: a0 07 f4 cc ca 5d c2 37 f9 a3 6e d2 5b 2e 04 32 .....].7..n.[..2
+| 2000: 19 03 7a ee fa 9c 5c 68 89 f7 94 b9 19 fe 05 d2 ..z....h........
+| 2016: 19 f8 3b fd cf dd 6f 23 3f c3 28 15 8a 8c 86 4b ..;...o#?.(....K
+| 2032: 8a ff ed ca b7 6a 69 4a fc 66 94 a0 ea b7 fa f0 .....jiJ.f......
+| 2048: b1 3b 67 85 2b 82 e4 7f 3b 8d da 02 9e 27 fb 69 .;g.+...;....'.i
+| 2064: 7b 20 c6 f6 fb c2 18 fa d5 6d 60 22 be 01 93 28 . .......m`....(
+| 2080: 08 71 9f b2 b0 e6 79 94 91 b6 b8 b0 ff a7 3f d8 .q....y.......?.
+| 2096: e3 eb b8 8f c7 02 5b f1 35 b7 15 db 01 cd c9 f6 ......[.5.......
+| 2112: d9 83 36 2f d0 8b 43 66 e2 3a 14 34 70 1e 68 e3 ..6/..Cf.:.4p.h.
+| 2128: e3 a7 fd 7f 51 cb ec 60 ca fb 13 fc 11 56 97 46 ....Q..`.....V.F
+| 2144: 23 53 0a aa 8d 15 de d4 cd 2b 1b de 3f d5 57 9c #S.......+..?.W.
+| 2160: e5 91 3b 15 98 3e 09 d9 4e d9 25 14 01 32 fc 23 ..;..>..N.%..2.#
+| 2176: 38 60 b2 8f 00 f3 21 8b 20 be 8f 6e 02 9a 58 3c 8`....!. ..n..X<
+| 2192: a7 a7 6f 3e 24 cc 1f 87 ab e6 12 0f bd 0a 8b 38 ..o>$..........8
+| 2208: 17 b2 ee 80 80 bb 50 df e0 cb 72 0a 98 07 40 bc ......P...r...@.
+| 2224: 8d 77 86 27 e8 07 57 4b 50 84 4c b4 73 b4 32 3d .w.'..WKP.L.s.2=
+| 2240: 89 61 e8 b8 dd bf 22 c8 06 07 e6 8f 6d 54 c7 e3 .a..........mT..
+| 2256: 12 f9 1f 61 cb e2 40 e1 14 34 9a 2b 16 a7 1f ec ...a..@..4.+....
+| 2272: 85 b8 76 8e 25 59 51 5a 19 82 d9 54 7f 3d 11 05 ..v.%YQZ...T.=..
+| 2288: a6 4c 43 28 9c 65 44 5e 57 fe 04 84 ae 7f 26 5b .LC(.eD^W.....&[
+| 2304: ed 26 e2 1c 07 1f fa f1 99 7b 69 f0 03 16 bf 7c .&........i....|
+| 2320: 13 16 75 80 d1 14 17 fa c9 f4 3b e5 9a 06 c0 d4 ..u.......;.....
+| 2336: c2 55 53 0a 78 32 86 3c 23 a4 f8 b6 5b d4 9a 51 .US.x2.<#...[..Q
+| 2352: 7c c3 1b 56 b1 e7 cd 83 02 75 8c 5e e3 6b b3 d3 |..V.....u.^.k..
+| 2368: 03 23 21 75 3f 78 a7 0f 66 87 2e 85 37 6b bc 0e .#!u?x..f...7k..
+| 2384: 2f 27 cd da 3c 1e 1a 35 2b bc 2d 97 ec 55 df 22 /'..<..5+.-..U..
+| 2400: fd 19 04 fa be 12 2a 1f 4b ed e3 0d 87 f0 61 db ......*.K.....a.
+| 2416: 06 1f 86 2f 9d 80 32 97 df 70 ff b4 78 df 95 7d .../..2..p..x...
+| 2432: a3 db a5 d0 db a0 b9 ed 4f a7 63 14 bf 8b 99 fd ........O.c.....
+| 2448: 6e 1b d0 02 07 93 e1 be 56 4e d5 c1 41 a6 f0 ea n.......VN..A...
+| 2464: 37 aa 21 7c 51 2f 5b c4 a0 ae ba e8 a7 1d c6 a5 7.!|Q/[.........
+| 2480: 1e 8b 3b 86 7b f2 ea 57 b7 2f 88 37 5e 7a 89 e6 ..;....W./.7^z..
+| 2496: 09 c0 e4 3b aa bf 78 41 7c 00 14 cc 37 f1 1a f6 ...;..xA|...7...
+| 2512: a5 79 49 f0 5a e0 1e 5d ba 33 ef fe 89 6e 20 01 .yI.Z..].3...n .
+| 2528: 96 70 7d 58 0a 98 e0 c4 3e 20 b2 46 83 b8 1f c9 .p.X....> .F....
+| 2544: fe 78 8a 41 a9 ca 3f 2c c1 d4 35 a3 39 85 4d a1 .x.A..?,..5.9.M.
+| 2560: 23 5e c7 b5 79 75 00 e7 d5 fb 30 99 00 c4 d0 31 #^..yu....0....1
+| 2576: 80 68 f2 80 1b 5e c8 30 f6 36 e1 a1 b5 87 92 35 .h...^.0.6.....5
+| 2592: 6b 9c ac 39 39 3f 54 e9 4d b4 8b bd 09 4c 6f 9a k..99?T.M....Lo.
+| 2608: 9a 6d 65 1a 7a 2f 98 0f 33 32 3a 4c bd d6 c3 d5 .me.z/..32:L....
+| 2624: 2b 3f 7f 0a d7 f7 f0 05 88 5e 36 30 4d a2 0a 65 +?.......^60M..e
+| 2640: f6 a9 5b 2d 5e 3f 0e 13 c9 45 1d c9 28 19 6d ba ..[-^?...E..(.m.
+| 2656: ff 9d af 10 17 b2 49 34 d8 a1 c8 ce d2 b7 99 3e ......I4.......>
+| 2672: 7c c6 f5 d6 74 84 05 84 2a bb 2d 25 27 67 04 f0 |...t...*.-%'g..
+| 2688: b3 6d 0a a9 43 f6 c4 51 71 1d 48 8d b3 a4 47 ed .m..C..Qq.H...G.
+| 2704: d6 14 c3 27 3e 6a e9 64 ef d7 af fb b0 eb ec 3c ...'>j.d.......<
+| 2720: bb 92 77 32 5e 4f 20 6d f7 a4 94 ce d9 9b c5 78 ..w2^O m.......x
+| 2736: 84 f0 c3 1a ca d8 e2 ce 76 0a 5e f8 73 9d 5a 82 ........v.^.s.Z.
+| 2752: 1e f5 0a 43 41 77 b9 d1 17 ef 47 0f 04 7b 5c b9 ...CAw....G.....
+| 2768: 3d 96 ec 7c b6 45 7d f9 fe 46 cb d2 50 a3 7f 99 =..|.E...F..P...
+| 2784: 16 ef 8d 2d d5 55 30 d8 27 18 bb f9 fa 76 80 55 ...-.U0.'....v.U
+| 2800: 13 1e f3 c2 dc 11 ef 8b 5d 67 d2 cd 70 74 b0 93 ........]g..pt..
+| 2816: f9 51 ec 35 24 cc 01 55 9f 92 a5 10 7f 66 07 e9 .Q.5$..U.....f..
+| 2832: f9 0a 32 06 db fd a6 ed 3e c6 b4 55 41 45 6c d3 ..2.....>..UAEl.
+| 2848: da a9 57 98 b1 79 3e 3a 6a e3 c4 37 3c 81 ba 16 ..W..y>:j..7<...
+| 2864: 3b 6a 3b 29 93 80 50 6d 94 05 dd 6b 37 10 f7 5c ;j;)..Pm...k7...
+| 2880: 5a 23 ef 13 1b 49 a5 fb 7b e8 49 a8 2a f4 e2 f4 Z#...I....I.*...
+| 2896: 0b a6 28 03 5b 3e ce c0 f6 b4 d3 c3 b5 ed 2f 87 ..(.[>......../.
+| 2912: a3 66 13 93 45 50 d5 3d 59 e4 42 fa f7 00 d8 b8 .f..EP.=Y.B.....
+| 2928: 7a 3a cc ce fc d2 8d a5 e9 1b 63 f8 21 6e 4f a3 z:........c.!nO.
+| 2944: 0e 17 92 56 d6 2e c9 a4 b8 07 2f 25 9e 3b ff a7 ...V....../%.;..
+| 2960: 9d 31 56 43 85 d6 ea 91 ab 29 8c 1e bd 29 f2 9c .1VC.....)...)..
+| 2976: 9c 48 81 a2 a9 da 80 c8 b6 8a 67 48 1d c0 02 4a .H........gH...J
+| 2992: fa a1 e3 69 15 83 c5 ca 9d 96 43 06 ad 97 c3 5c ...i......C.....
+| 3008: 09 e0 de b9 0d 4e f5 99 75 e1 c0 98 20 91 c3 5d .....N..u... ..]
+| 3024: 93 81 0f bf 2b 96 96 c0 9d 30 d3 84 c0 9e 60 56 ....+....0....`V
+| 3040: 08 0a 3d 48 be 6b 3d 32 c4 5b e8 87 02 88 f6 f3 ..=H.k=2.[......
+| 3056: 71 71 07 f8 66 42 8d df 4e aa 44 6f ec 3a b8 7e qq..fB..N.Do.:.~
+| 3072: 4d b3 83 74 b4 bf 34 d2 2c 95 3c 44 9b c1 cc 9a M..t..4.,.+......6..#.
+| 3120: 1b f5 ce 42 b0 0c 11 d4 69 a4 bf fa 4b 30 34 b4 ...B....i...K04.
+| 3136: 52 48 84 cc 31 08 03 a9 93 d9 e5 c8 44 cd cf fe RH..1.......D...
+| 3152: e4 2e c5 3a c2 b2 d9 bc 15 4d 7f 7a 81 52 9c 53 ...:.....M.z.R.S
+| 3168: 3e 1a 74 78 c8 38 4a 02 ce 6b 96 2d 9c 3b 74 41 >.tx.8J..k.-.;tA
+| 3184: 50 06 d9 6f fa c8 98 05 f5 70 c3 7f ca 0a 78 f4 P..o.....p....x.
+| 3200: 01 f1 a2 f5 46 8a 02 b8 c3 37 7e cc a0 87 b0 fc ....F....7~.....
+| 3216: 32 e5 86 6d 95 22 67 fd 10 56 c4 78 52 c5 12 e5 2..m..g..V.xR...
+| 3232: e9 f2 b2 fa f6 78 2e a3 82 a6 73 1b 9f 96 a7 e6 .....x....s.....
+| 3248: 81 49 e9 17 f1 0a e6 99 21 ce ec ff be aa 43 e6 .I......!.....C.
+| 3264: ea 6a ac 2b a4 b9 0b 48 6c 81 1a 26 bf 93 69 36 .j.+...Hl..&..i6
+| 3280: 53 1e 46 2a 43 af cc ef 96 4e 0b 32 38 93 10 d5 S.F*C....N.28...
+| 3296: d8 6f 88 e7 f9 92 f8 37 28 51 55 98 fa 1a 89 80 .o.....7(QU.....
+| 3312: 35 d5 d1 90 f1 91 8f 4a 5a 81 2f 79 a7 e4 80 3c 5......JZ./y...<
+| 3328: a2 5e e5 b3 f8 d3 56 ec cd 02 73 0e af 8d d8 81 .^....V...s.....
+| 3344: 26 7b 4d 96 f1 b3 75 7a de c3 b8 a6 b6 75 f2 5c &.M...uz.....u..
+| 3360: 97 08 a3 50 9b d8 cf 43 c0 90 f7 52 da 87 8d 12 ...P...C...R....
+| 3376: 1c d4 0a de 56 26 3d af d1 d5 03 ff d8 62 a1 c5 ....V&=......b..
+| 3392: f2 7c ea 1d 39 3f f0 e1 5f cb 3d db 1a 8a a1 b7 .|..9?.._.=.....
+| 3408: 10 01 f1 c6 17 53 bc 83 eb 2a c4 cf 3a 04 b1 8a .....S...*..:...
+| 3424: 6d 80 20 be 7b 72 6c c9 be 4e eb f4 cd c8 60 d2 m. ..rl..N....`.
+| 3440: 1c 46 b1 8a e5 9b 66 22 4f 05 bd c6 37 34 67 2d .F....f.O...74g-
+| 3456: b1 c5 bb 60 de 4b c4 3a 29 14 dc de 38 9c 0d 09 ...`.K.:)...8...
+| 3472: bd 78 2f f6 e4 34 18 9b 51 41 a7 57 f9 f2 ad 0d .x/..4..QA.W....
+| 3488: 82 70 5f b4 fa 84 19 5c 72 29 8e 5f b2 8b fa 2a .p_.....r)._...*
+| 3504: e1 d1 55 bf b8 45 c3 79 e0 04 62 10 1f 76 79 de ..U..E.y..b..vy.
+| 3520: 84 93 a8 df 92 8f 41 0d 38 14 70 b3 dd 9d c6 36 ......A.8.p....6
+| 3536: f6 12 72 ee 23 e6 ba ed 97 1f cd 36 55 ac 32 98 ..r.#......6U.2.
+| 3552: 78 12 55 23 d5 64 ad ed cf 32 d3 2d 7b 51 d7 7f x.U#.d...2.-.Q..
+| 3568: 3c 6f 0f fb c7 06 75 96 ef 64 ce c4 09 15 4f b8 ....|....c/....
+| 1104: f2 f2 37 ff aa 18 0f 69 94 cc 49 85 cd f7 bb 7b ..7....i..I.....
+| 1120: e5 c0 09 d1 a2 78 f4 c0 1b 23 e7 d5 ac 2d 85 27 .....x...#...-.'
+| 1136: c2 48 c2 80 ad 93 a0 10 44 98 5a 6e 9e f1 92 a9 .H......D.Zn....
+| 1152: 98 f9 0d 00 2a 3a 22 36 c5 21 63 fb 95 fb c7 7e ....*:.6.!c....~
+| 1168: 6c 07 7d d1 a5 f1 a9 8f f2 d2 e2 0f 3d 02 56 94 l...........=.V.
+| 1184: ea 44 2a 17 ee 99 82 71 9c 81 c7 9c 8f cd 2e 4d .D*....q.......M
+| 1200: 8d 0a 1e 71 18 3d 4d 9d a6 ae 35 36 48 08 24 e8 ...q.=M...56H.$.
+| 1216: 46 78 8e 66 f2 8a f1 3d c3 72 ad 65 18 5f ed 2d Fx.f...=.r.e._.-
+| 1232: 7e 92 18 9e 4c 23 7c f8 8d 83 20 43 50 63 db 75 ~...L#|... CPc.u
+| 1248: 12 7e 52 0e 71 13 e4 b6 31 c3 5f 88 b7 d0 76 80 .~R.q...1._...v.
+| 1264: d5 9f 7e dc 8c b4 be 11 da 2c e1 a9 28 5e c8 46 ..~......,..(^.F
+| 1280: 3c 0d cd 7a 2f b9 9f 53 9c 11 01 d1 09 31 5f 36 <..z/..S.....1_6
+| 1296: bb a4 f3 a0 ad ba b7 c4 ce d1 78 4e ad e8 cd f9 ..........xN....
+| 1312: 92 ed 51 05 69 ab 12 a3 89 4c 6d f5 7a c4 c5 54 ..Q.i....Lm.z..T
+| 1328: 1e 26 e7 f8 22 1c 42 cb 9e ac 7a 53 79 09 3c 04 .&....B...zSy.<.
+| 1344: 14 1d 49 15 c7 13 00 84 3c 7f 15 2d 5b 62 da d8 ..I.....<..-[b..
+| 1360: 8f 88 53 7a 78 f7 c4 7b be 67 25 cd 97 1f bf 19 ..Szx....g%.....
+| 1376: b4 8f 4a 10 63 89 2f cf 56 c1 63 79 92 cc b1 75 ..J.c./.V.cy...u
+| 1392: 45 ee 6a 9d c5 de 04 e0 60 49 c5 0e 09 a0 65 46 E.j.....`I....eF
+| 1408: 57 f3 6c 5f 0f 07 99 fa 2b 2c 2c 5b bd b3 9b 50 W.l_....+,,[...P
+| 1424: 38 43 94 4b 7b d2 b0 78 3b 4c e8 55 1d d3 6b 6a 8C.K...x;L.U..kj
+| 1440: f7 dc 27 ef b5 b1 3a 52 9f 5a e9 7d 87 bb 61 5b ..'...:R.Z....a[
+| 1456: 39 a3 eb 5e eb f1 80 78 85 d8 86 16 76 3c b3 b0 9..^...x....v<..
+| 1472: 44 72 d7 0e 91 95 5e 7d d5 93 0a 4d 60 46 ad a8 Dr....^....M`F..
+| 1488: b7 d5 30 e2 39 4c d8 0a d4 ea 5e 46 95 39 1a 1e ..0.9L....^F.9..
+| 1504: 9d 81 27 20 bc 01 1e f5 2d 4a 19 4a a5 2d 94 91 ..' ....-J.J.-..
+| 1520: c2 a3 31 65 aa 13 f4 92 ce b2 c1 61 25 13 7d 93 ..1e.......a%...
+| 1536: f0 c9 51 e5 ce 7c 0e 2d e4 f2 d4 b5 09 73 fc 96 ..Q..|.-.....s..
+| 1552: e0 a8 a7 85 b6 10 0f 95 a5 83 c5 4b ca 33 9f 98 ...........K.3..
+| 1568: 38 d9 50 29 38 08 cc b9 89 40 0e d7 1d 92 cc 4a 8.P)8....@.....J
+| 1584: 7f a2 53 dd 19 d3 13 63 04 29 04 18 c2 79 97 36 ..S....c.)...y.6
+| 1600: 85 e8 95 4a 2c 34 7c 39 78 a5 fe 8b bb 22 93 4c ...J,4|9x......L
+| 1616: 69 b6 86 ca 0c 61 39 b3 85 c1 df ee 28 b0 3d 73 i....a9.....(.=s
+| 1632: 2f 78 84 69 f4 55 ed 6c b8 98 61 0c f5 64 15 7e /x.i.U.l..a..d.~
+| 1648: 84 bd 4f de ae 6c 1b db c1 60 c9 0a b9 22 f0 7d ..O..l...`......
+| 1664: 03 23 0f e3 f5 77 3a 3b 4b 7f 33 d9 e6 7c ee 92 .#...w:;K.3..|..
+| 1680: 0c 95 f6 9d 98 53 e3 7b 92 3b 15 a2 de 84 e6 75 .....S...;.....u
+| 1696: 64 e1 44 b5 9d 16 77 10 78 65 e0 72 66 a9 13 db d.D...w.xe.rf...
+| 1712: 27 cf 9f 0d 33 5d ee 89 37 cf 2f b6 fc 28 b1 93 '...3]..7./..(..
+| 1728: c3 6d 0f 80 d8 5a 16 33 ea 06 d7 81 d3 45 59 94 .m...Z.3.....EY.
+| 1744: 07 73 bf 47 f6 fd 6e 78 13 5a ec 30 62 a4 c4 12 .s.G..nx.Z.0b...
+| 1760: 2a 56 8f 29 03 37 0c 98 80 8e e9 50 4f 3a 37 a6 *V.).7.....PO:7.
+| 1776: f6 29 3a 6f 17 54 45 8e df 98 62 1e 23 d0 ec 20 .):o.TE...b.#..
+| 1792: 4b c8 f6 cb ce ef f5 8b f2 fd a9 a8 51 5c 0f d0 K...........Q...
+| 1808: e4 4d 7c a1 a1 2a 88 f1 24 78 9e cb 7c 81 6b 0a .M|..*..$x..|.k.
+| 1824: 51 73 1e bf 48 21 fb b3 7a 5c 48 0f 53 04 00 5f Qs..H!..z.H.S.._
+| 1840: 7e 66 7a 2e c0 30 9f bf 2f e8 95 b5 fe ea 9c f8 ~fz..0../.......
+| 1856: 0e 6d 1f 54 81 da e9 bc 28 ea 42 de 5b e0 7f 93 .m.T....(.B.[...
+| 1872: 79 6d 6d 8e f3 3c ba 13 67 3a 08 31 03 43 da eb ymm..<..g:.1.C..
+| 1888: 34 40 04 3e a4 21 44 92 96 75 2c 9f 8f 03 89 98 4@.>.!D..u,.....
+| 1904: f0 27 dd 27 49 3d e3 9b 37 4e 66 ef 98 bd 1b ed .'.'I=..7Nf.....
+| 1920: 3f cc a4 10 85 a4 39 90 cc a3 80 3d fd e5 44 4f ?.....9....=..DO
+| 1936: 45 79 64 37 d2 70 ba 69 99 0f 4d 33 5a 68 bd 53 Eyd7.p.i..M3Zh.S
+| 1952: 92 24 0d 3f f4 e2 4b 72 35 cb 52 ea 3d d4 85 ee .$.?..Kr5.R.=...
+| 1968: e3 12 b3 87 3a 9d 70 b8 5c bb c7 c4 98 03 84 25 ....:.p........%
+| 1984: 5d 39 ef 24 bc ab b3 da 13 7b 2c bc 17 b1 76 4c ]9.$......,...vL
+| 2000: 5d 5a 1c 62 14 8d 5d 20 32 dc 16 64 79 7e 13 95 ]Z.b..] 2..dy~..
+| 2016: 27 f6 99 dd f2 32 c2 43 c6 77 b4 f4 11 88 6d 3f '....2.C.w....m?
+| 2032: 94 0e cb db c8 c3 9e 40 b1 7d d4 16 e6 95 f4 d9 .......@........
+| 2048: 3d 9b 5d df d5 a3 39 06 c1 eb a1 30 cb 85 77 d6 =.]...9....0..w.
+| 2064: 9b d9 12 7a 6a 82 9e 3a bf 5a ff 5c b8 6f 4a bb ...zj..:.Z...oJ.
+| 2080: 02 36 94 1d 5a 0c 95 da 85 d1 9c 22 5a 36 fd 28 .6..Z.......Z6.(
+| 2096: 51 cf 48 60 84 a1 ce ad a9 5f 4c 51 43 71 7f d5 Q.H`....._LQCq..
+| 2112: 1a e1 6f b0 01 a5 6b f1 57 91 84 78 b0 d5 06 7c ..o...k.W..x...|
+| 2128: f4 96 3d 9b e4 6d 04 b7 26 a0 5b 61 53 39 ba 49 ..=..m..&.[aS9.I
+| 2144: 2c ea d8 18 e5 aa b3 ef 3e 8e 5d 91 ba 93 15 2b ,.......>.]....+
+| 2160: 4d e6 5c e7 47 ee 7c 9e d5 ca f4 82 91 84 f4 33 M...G.|........3
+| 2176: 02 46 9d dc 34 8d f1 5b 1c 15 5d db 2f c9 d0 09 .F..4..[..]./...
+| 2192: fb a4 cf d9 0d 30 9f 16 3b 5e 80 ff 26 ac 19 b7 .....0..;^..&...
+| 2208: b2 56 1a bb 72 7f b9 2f e7 41 6a e3 fc e5 cc e0 .V..r../.Aj.....
+| 2224: 27 2c 78 86 1c 11 ee f4 51 2d 22 20 73 3b ed d6 ',x.....Q-. s;..
+| 2240: 42 c2 de 23 de c6 7d 43 8f 16 de 66 57 64 94 32 B..#...C...fWd.2
+| 2256: 13 da a6 91 b7 d5 8f 3a d6 c4 a7 e0 93 ff f8 9c .......:........
+| 2272: e3 70 a9 e9 e9 7a 50 37 3c 38 d3 fd 68 ff 17 5f .p...zP7<8..h.._
+| 2288: 96 b7 b4 77 c5 ce 1d 37 49 35 91 6c 2e 37 ef ac ...w...7I5.l.7..
+| 2304: 18 ee 9f 7a e5 28 88 a6 33 39 05 f7 c8 1f 1a 15 ...z.(..39......
+| 2320: f6 ad 55 5e 24 ea ce 21 c8 e2 1e 63 bd 7a 19 60 ..U^$..!...c.z.`
+| 2336: c0 aa e4 42 2f 0f 53 f4 2c 04 99 a4 9a 13 86 6f ...B/.S.,......o
+| 2352: 24 7b 42 ad c9 a9 c9 df 82 90 23 0a b6 e8 2a e4 $.B.......#...*.
+| 2368: 36 c5 04 1a e4 dd 87 06 ca 6e 04 7b be 37 b4 ef 6........n...7..
+| 2384: 05 1d 6a ab 36 c8 58 52 3d ad 26 21 45 58 f4 66 ..j.6.XR=.&!EX.f
+| 2400: 05 a2 95 89 9c 31 1c 3c 14 9b 59 90 29 28 f9 9d .....1.<..Y.)(..
+| 2416: f9 96 74 ab d7 30 91 81 17 ba b8 08 51 38 75 77 ..t..0......Q8uw
+| 2432: 06 ca 81 1d e3 9b 67 3e 0f d9 fe 98 69 e0 d8 f1 ......g>....i...
+| 2448: 78 dc 96 0e 88 50 9c b5 c1 1d 25 61 87 70 bf a5 x....P....%a.p..
+| 2464: 93 2f f9 c7 7b ab fd 2c 98 10 ef 0f ce a4 bd fa ./.....,........
+| 2480: 52 7f ff 29 53 5f 9c b5 92 2e 8c f5 36 a0 7c 88 R..)S_......6.|.
+| 2496: 84 18 80 59 66 d2 c6 58 55 c0 5d 07 9f 69 d2 72 ...Yf..XU.]..i.r
+| 2512: 88 0d 1d 8f 08 7c d5 b7 9c 15 4c 6c c6 1d f4 76 .....|....Ll...v
+| 2528: 0a 82 32 6c 72 4e 3e cc ff 8b 62 c5 37 4e 0c 0d ..2lrN>...b.7N..
+| 2544: 09 89 8a 95 1b 63 d3 85 c6 4a 41 7c 49 46 60 95 .....c...JA|IF`.
+| 2560: eb 37 60 82 84 55 ea fe 22 97 16 58 ad 33 06 ae .7`..U.....X.3..
+| 2576: d0 f5 5d 06 b3 2e b9 0a 6d d0 14 c8 d5 0b 8a cf ..].....m.......
+| 2592: 51 ff 64 db a8 81 e1 8b 39 1a ef 85 18 fd a2 48 Q.d.....9......H
+| 2608: 4f 47 b3 1e 5a 57 21 f0 6b 10 f0 ec 0a 4a 35 56 OG..ZW!.k....J5V
+| 2624: f5 79 c5 de 62 d1 4a c2 e5 bc 69 89 9d 9b b9 4b .y..b.J...i....K
+| 2640: ba 21 99 5a 58 c6 23 ab 67 45 13 4a 1d 3e da 68 .!.ZX.#.gE.J.>.h
+| 2656: cf a6 4b 20 58 b0 4e 2f 0d f2 42 83 9d 96 43 6e ..K X.N/..B...Cn
+| 2672: df 45 61 c5 bd ca 86 b3 6a ad 26 a2 8d c7 c4 03 .Ea.....j.&.....
+| 2688: 63 d8 b8 02 0a f6 96 f9 15 46 2c bd 04 68 aa 1b c........F,..h..
+| 2704: 00 46 7e a0 bb 47 fe 5f 2b 7b b4 59 54 14 e3 25 .F~..G._+..YT..%
+| 2720: cd 10 8b ff 05 6c 6d ab 9c 90 cb d4 d8 0d bd 58 .....lm........X
+| 2736: be bc d5 c0 67 bd 0f d3 9d 22 71 c4 65 e6 2f bc ....g.....q.e./.
+| 2752: 5e 3a 54 39 7a ec ab b1 46 80 25 5e 33 19 de 3b ^:T9z...F.%^3..;
+| 2768: 4a 84 28 04 80 f6 86 aa 32 75 8e 5b 51 66 b0 64 J.(.....2u.[Qf.d
+| 2784: 29 94 f6 56 6d 1c b1 2e 2f 4c 55 3b e5 82 01 75 )..Vm.../LU;...u
+| 2800: 3f 58 d3 a0 b9 0b 6b 25 24 94 9e a5 ce a4 1c db ?X....k%$.......
+| 2816: 51 f9 bb 53 71 19 0a 5a e3 2e 48 e1 06 24 7a b9 Q..Sq..Z..H..$z.
+| 2832: 88 fb dc 4c 2a 23 b9 b9 7e 26 a4 3f 7f c7 b5 f1 ...L*#..~&.?....
+| 2848: cd cb 82 17 34 89 70 b4 10 ad be b8 4b 0d aa 07 ....4.p.....K...
+| 2864: 61 6d b3 6f 56 ac a4 b2 e4 2f be 28 e6 24 3a ab am.oV..../.(.$:.
+| 2880: cc 1a 8a 7f 54 c7 a3 c8 49 50 91 76 f9 75 d8 3a ....T...IP.v.u.:
+| 2896: 76 1b ec 5b 51 c2 5f 6f c9 c7 60 24 0a 61 f4 ed v..[Q._o..`$.a..
+| 2912: d3 30 23 e7 a0 83 c7 5e f4 b8 1b 39 65 43 2a 8a .0#....^...9eC*.
+| 2928: 1d a8 64 4d c5 4a a6 ab e1 f4 66 90 f7 2b 1c d6 ..dM.J....f..+..
+| 2944: ba 76 96 43 2d a1 6b 26 ee f1 3b 8b 2f e4 78 7e .v.C-.k&..;./.x~
+| 2960: 9b bd fa 2e 80 ff ec 26 74 5b 56 11 92 88 51 8c .......&t[V...Q.
+| 2976: 6d 42 4f f5 3c 53 8b 42 3e b6 57 37 fe ad 66 59 mBO..W7..fY
+| 2992: 4a f4 0e a1 39 a2 32 c0 23 78 e0 e7 db f9 f9 44 J...9.2.#x.....D
+| 3008: 34 12 00 a0 d2 1f 45 25 4f 4a 72 74 9e b2 d5 e4 4.....E%OJrt....
+| 3024: 25 4e d5 0f ba 1b 87 7f 23 f2 7f dd 96 6c 1c 44 %N......#....l.D
+| 3040: 0d 11 9a 22 6a f8 83 bf 37 e6 c9 5d 2e d3 dc d3 ....j...7..]....
+| 3056: aa 03 03 7e bf a5 cc a1 d8 55 6f 05 1a 70 5e 89 ...~.....Uo..p^.
+| 3072: d5 8e a5 08 f4 fc 90 7c d2 8a 67 53 82 25 82 02 .......|..gS.%..
+| 3088: 98 e0 ad 57 bb d4 7e fc 18 8f 25 9d d7 11 57 ab ...W..~...%...W.
+| 3104: cf de 4b a5 1b 90 6b 38 a3 ef 93 ed 44 d7 9d f1 ..K...k8....D...
+| 3120: 54 b1 0b 9b 2d e9 e7 d3 a6 6c 78 fd 40 d9 ea 7f T...-....lx.@...
+| 3136: ec 10 60 2f ed 4c df f4 ef fb 4a cd fd 1a ea 94 ..`/.L....J.....
+| 3152: 7b ac 69 70 be d1 2c ca e3 88 a7 b4 7f 95 83 eb ..ip..,.........
+| 3168: 2e 82 0e 3e 60 27 b9 0c 62 56 3d b2 c4 7d 97 2c ...>`'..bV=....,
+| 3184: ac cd 0b 05 b3 41 ab 7c 2e eb 4e a7 3e 8f db 53 .....A.|..N.>..S
+| 3200: 88 59 f3 d6 f4 bf 5e 80 2e 5b f2 08 f8 dc 68 28 .Y....^..[....h(
+| 3216: a7 a3 e3 4e ef 8f 3f 4e a6 c0 4b 04 d9 59 3e 53 ...N..?N..K..Y>S
+| 3232: 07 78 2c b2 58 a6 78 a4 0a 6b 9e 6b 8d f2 3e 70 .x,.X.x..k.k..>p
+| 3248: 45 07 82 f9 f0 d4 0f f7 81 e9 ab 09 c6 7a 3a ff E............z:.
+| 3264: 98 6c bf 1f 43 c3 d5 ba c1 ad fe 9c a6 5e d5 f7 .l..C........^..
+| 3280: 93 ec 20 dd 33 ad 35 0b 74 47 80 1e 5b 8b c3 7c .. .3.5.tG..[..|
+| 3296: 5c 81 66 82 dd 18 70 19 b0 54 18 2f 90 c2 22 bf ..f...p..T./....
+| 3312: 75 e8 b6 8e b7 3e 7c 2d b4 e9 7c b4 08 4e e9 c3 u....>|-..|..N..
+| 3328: e1 80 88 63 f2 90 ee ae 3d 9e 55 15 62 7f ee df ...c....=.U.b...
+| 3344: 57 69 03 da 76 e9 f3 6b 90 9a a7 b9 bb 4b b7 2b Wi..v..k.....K.+
+| 3360: d0 a0 3b 70 b9 96 70 17 c8 0c cb ae 6e 3e e1 33 ..;p..p.....n>.3
+| 3376: 02 98 53 d6 af c6 d8 55 15 7a ea f1 8f 36 6b d4 ..S....U.z...6k.
+| 3392: f2 8c fd db a5 81 50 fe c8 a8 cb 7f e6 9a a9 9f ......P.........
+| 3408: 34 82 6d a5 11 6b e6 79 58 a8 54 ed 55 cd 19 46 4.m..k.yX.T.U..F
+| 3424: e9 7f 92 f8 0b 3e ab b5 8d d3 9f 33 5c e7 f6 1e .....>.....3....
+| 3440: 28 f7 5f 2f 38 36 25 ed 7f 36 93 19 f1 a7 9c e7 (._/86%..6......
+| 3456: ad 4e 11 33 17 93 82 cf b4 a7 93 36 97 d9 e0 3d .N.3.......6...=
+| 3472: 7e 54 b9 96 37 85 16 db e8 29 6f b0 b1 83 16 63 ~T..7....)o....c
+| 3488: 9b 19 30 85 c6 17 2c b7 bc f2 2f 87 07 56 97 b3 ..0...,.../..V..
+| 3504: c4 a6 47 d5 8b 7a 68 a4 d0 11 ce ff 6c 4c 28 93 ..G..zh.....lL(.
+| 3520: c3 37 ef 1e 7a 51 65 a9 6b 8a a0 a4 b0 b9 ef 17 .7..zQe.k.......
+| 3536: dc 44 99 34 7b 33 f4 b9 3f d3 20 36 54 5c 10 6d .D.4.3..?. 6T..m
+| 3552: 18 25 33 6e fc fa a0 16 c7 b6 78 f8 4b 0c 5e 7e .%3n......x.K.^~
+| 3568: c3 cb 95 54 90 88 57 20 d9 17 9b 82 dc e8 7f c6 ...T..W ........
+| 3584: bd d8 dc 13 ca 66 06 64 8e 46 2e 48 13 eb 4d 07 .....f.d.F.H..M.
+| 3600: 24 7f 8e 35 f3 bf fb 54 80 c7 6e 93 da ce 7f 2b $..5...T..n....+
+| 3616: 60 3e 53 82 33 38 fe 69 7b f6 fa 2f d8 40 bd c8 `>S.38.i.../.@..
+| 3632: 95 75 6b a2 e5 53 7f 5c f1 f3 23 07 8f 42 04 8f .uk..S....#..B..
+| 3648: 64 43 a2 25 c1 40 07 e9 be b6 3c d6 1b 86 7f 91 dC.%.@....<.....
+| 3664: f4 73 0f 6b ca 6b cb 8f 7c a8 5b 60 ee 20 a6 e6 .s.k.k..|.[`. ..
+| 3680: dc 96 6b 8f 8d 62 1e 42 e0 1b 85 49 85 34 b4 c9 ..k..b.B...I.4..
+| 3696: 85 06 ec c4 b7 b5 89 47 af fa db d1 5b 9f ac 6f .......G....[..o
+| 3712: 8a 27 53 48 4d ad a1 30 6b 3e 45 b1 b8 b9 50 17 .'SHM..0k>E...P.
+| 3728: 7b b7 29 a8 b3 d5 9a 42 a9 2a e4 01 79 34 c5 21 ..)....B.*..y4.!
+| 3744: a7 8b 21 69 ab c4 9b ec eb 0d 9f 34 b5 ff 46 2d ..!i.......4..F-
+| 3760: 68 55 9b 63 9a ac ac 80 4c 45 8d eb dd b2 26 4a hU.c....LE....&J
+| 3776: 91 8f ee f7 50 6f 84 81 c3 79 2e 6d 56 1c ee 01 ....Po...y.mV...
+| 3792: 20 2b e5 ca 3a 51 ba 40 b6 44 15 a4 4a 3d d0 33 +..:Q.@.D..J=.3
+| 3808: 7d 2d 3c ca e3 f8 e9 1d bc b2 1e 59 1e 57 10 2f .-<........Y.W./
+| 3824: 92 4b b7 50 41 98 6f 07 0b 38 ba 31 08 3e d4 34 .K.PA.o..8.1.>.4
+| 3840: 4f f4 99 32 2f e5 7f 8f 14 8e 48 11 88 ad 18 d6 O..2/.....H.....
+| 3856: db d0 e5 cc 17 4c b6 f7 45 f9 1e 9a d9 86 5d 56 .....L..E.....]V
+| 3872: fa 76 52 49 cd f1 76 ea 84 b1 55 03 54 e2 ff 91 .vRI..v...U.T...
+| 3888: 23 fb 22 b0 8a b8 da 6e 7e 54 25 03 f3 fb eb 9a #......n~T%.....
+| 3904: ce 64 cb 70 38 c9 aa 11 e8 36 45 16 8c 82 0e 18 .d.p8....6E.....
+| 3920: f3 cf 81 4c 7c ef 53 6a 5c 43 85 e3 01 c9 d5 97 ...L|.Sj.C......
+| 3936: 8b 03 78 90 35 c9 7c 3a 62 3d 66 d9 ff 6c 1f 3f ..x.5.|:b=f..l.?
+| 3952: 7f a1 85 ad ec 87 65 3b 48 3c 0b 0c 94 c0 05 85 ......e;H<......
+| 3968: f9 a4 4a 79 c1 dc 7b 9f 87 c0 4f c9 7b a7 ce 5c ..Jy......O.....
+| 3984: cd 11 68 d5 79 d2 e7 b5 8c 13 af d6 e9 81 ef 42 ..h.y..........B
+| 4000: 4c 11 2f c0 55 33 4c f4 44 c1 75 67 ae 43 95 68 L./.U3L.D.ug.C.h
+| 4016: da 90 26 d5 42 75 b6 ef 99 22 ce b8 2d 52 5f 43 ..&.Bu......-R_C
+| 4032: a4 f7 23 72 17 c6 66 36 84 e6 d3 a7 da a9 ec 82 ..#r..f6........
+| 4048: b2 fd 87 90 51 2e 78 71 3f 56 49 96 d2 da 6b 67 ....Q.xq?VI...kg
+| 4064: 2a f8 b1 eb ae 5d d0 e7 59 31 ed ed 24 b6 2c 32 *....]..Y1..$.,2
+| 4080: 7a b7 97 c5 e0 f1 a4 05 d3 8e fa 0f 10 ee 19 4d z..............M
+| page 15 offset 57344
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 07 06 00 ae 7c 00 00 07 2c f5 e5 48 a9 82 86 >....|...,..H...
+| 1104: 40 71 a9 80 b9 af 28 61 b5 17 5a cb c3 67 db aa @q....(a..Z..g..
+| 1120: fa 64 ec 63 b4 34 d5 37 ee 52 d8 d5 38 6a 25 d0 .d.c.4.7.R..8j%.
+| 1136: 1f 05 80 72 bd c3 b9 1a d1 ea f7 f0 73 0e 97 29 ...r........s..)
+| 1152: 41 19 09 d1 53 df c8 c5 02 ab a2 e8 76 b8 09 3d A...S.......v..=
+| 1168: 8b 07 21 05 5f 80 3d 88 67 fd fe ab e6 4b 7f 97 ..!._.=.g....K..
+| 1184: a6 17 42 02 f5 ad f3 74 6b bb 6e 2a fd af 88 3b ..B....tk.n*...;
+| 1200: d9 b2 3c 0d 33 a7 93 69 c0 97 c5 c4 c0 e9 29 d5 ..<.3..i......).
+| 1216: c3 78 96 13 55 f3 41 e6 87 eb 7a 2f b9 e2 28 f3 .x..U.A...z/..(.
+| 1232: e1 ed b8 c8 5d bd 80 80 a6 52 50 ff 0d db 2b f2 ....]....RP...+.
+| 1248: 7e 9e 91 32 fd 08 46 ba db 2b 41 00 70 6f cf 80 ~..2..F..+A.po..
+| 1264: 46 1b 49 cf ab 6e 1d 14 21 f2 3f 55 0a 4a ed 19 F.I..n..!.?U.J..
+| 1280: 11 9b 9e c0 f2 c4 55 86 2c 05 4e a2 6f 8c b2 9c ......U.,.N.o...
+| 1296: 11 fd 85 0c 5b d5 ee ef 9c f2 4b 1e 74 72 bd a4 ....[.....K.tr..
+| 1312: 29 8d 0d 92 67 97 b5 b5 03 b4 a7 68 15 50 c7 7e )...g......h.P.~
+| 1328: 91 22 a8 39 3e e2 18 bd 68 20 74 c1 e5 f2 8a e5 ...9>...h t.....
+| 1344: 1e 72 0c 2a e3 1a b2 60 57 ad 2b ee 1f 59 57 ce .r.*...`W.+..YW.
+| 1360: 6f b2 e0 15 96 73 f6 2e 5b 82 b7 ca 6b bf ed 78 o....s..[...k..x
+| 1376: e5 af 82 82 73 16 6a ce cb 09 b9 5f b3 2d c0 0c ....s.j...._.-..
+| 1392: 1d 46 5f 7e be ee 0c b3 54 e7 ed e7 cc cf f9 9d .F_~....T.......
+| 1408: 42 90 94 e2 e9 c2 76 2b 02 b9 a8 73 20 0a e3 6f B.....v+...s ..o
+| 1424: 23 a0 c0 59 f2 af 9d c4 78 90 ba 8e 0c ef b4 d6 #..Y....x.......
+| 1440: 37 03 5e f4 7f 54 a6 d7 87 bc 20 3f e1 7a 84 d9 7.^..T.... ?.z..
+| 1456: 1b 33 4a fc bd 1f c1 8b b3 db 8f 0c fa 49 7f d7 .3J..........I..
+| 1472: 9a d0 48 8e c6 3b 79 22 d6 0c fa 93 4d 43 f3 de ..H..;y.....MC..
+| 1488: bb 10 3e 81 d2 6b b4 9f 4c 91 05 d7 87 b5 35 98 ..>..k..L.....5.
+| 1504: eb 84 9d 2c 0e 4e 2b de 1b 23 0d f5 bd aa 4a 9c ...,.N+..#....J.
+| 1520: 6d 7e 48 23 18 f9 72 5b ef 9e da a9 ef 1b 29 08 m~H#..r[......).
+| 1536: 03 34 e2 86 97 ff c9 2d c6 04 34 65 84 20 5b 7c .4.....-..4e. [|
+| 1552: df e3 2c bc 73 04 22 70 f5 03 f2 8f fe fb 72 b5 ..,.s..p......r.
+| 1568: a1 93 91 a4 3e a5 20 ac 21 19 8a 60 60 48 63 a0 ....>. .!..``Hc.
+| 1584: 47 80 a8 ac 9f 68 a9 ab b7 0f 71 d5 44 1a fb 4a G....h....q.D..J
+| 1600: 99 06 2b fc 96 ad ac 5e 37 37 84 6e 4e de 66 ba ..+....^77.nN.f.
+| 1616: c6 10 fc e9 a0 26 cf 48 f6 f6 96 b7 69 35 30 06 .....&.H....i50.
+| 1632: f2 7a db 70 53 4d f9 5b 9b 5f 51 b8 f6 af fb 1c .z.pSM.[._Q.....
+| 1648: f5 2a d7 01 80 d2 0e b3 fe cc 99 ad 74 ad fa df .*..........t...
+| 1664: 26 86 c7 29 b2 b3 36 98 b8 b7 2c de 9c 78 41 99 &..)..6...,..xA.
+| 1680: ff 46 40 76 64 64 0c f5 46 d5 bd 72 a3 46 b0 b3 .F@vdd..F..r.F..
+| 1696: 75 45 03 d1 06 4b c9 ca a6 4f 90 f7 9b 60 4a 46 uE...K...O...`JF
+| 1712: ed af a1 d5 68 30 db a7 5e ca 76 bf 66 64 e7 fa ....h0..^.v.fd..
+| 1728: 50 5c 31 5f 86 94 3a 5c f4 98 3d d5 52 80 26 1e P.1_..:...=.R.&.
+| 1744: 55 07 14 d5 f5 2a 17 46 8b 6d 71 d2 da 4b e7 c8 U....*.F.mq..K..
+| 1760: 3d 8f 97 b7 97 51 c5 fb aa 4f 3f 3b 85 c1 aa e8 =....Q...O?;....
+| 1776: bf 3a d9 56 c0 d3 23 31 28 46 bd 45 2e 4b b5 e7 .:.V..#1(F.E.K..
+| 1792: f6 8e fa e2 28 65 6c 42 f2 68 8f 37 cb 4d e9 26 ....(elB.h.7.M.&
+| 1808: f7 63 58 8c 99 09 71 7c 14 3a d7 92 c4 cf 14 51 .cX...q|.:.....Q
+| 1824: af fe 6e 6b 50 e9 3a 70 0f ac 53 9d 57 01 4f 7a ..nkP.:p..S.W.Oz
+| 1840: cc b2 c5 b9 2a 3e 02 6a d4 15 6f 2e d3 20 99 ed ....*>.j..o.. ..
+| 1856: d7 1f 71 01 2f b4 e4 08 fe 8c 38 02 2c 14 e0 fd ..q./.....8.,...
+| 1872: ec 3e 61 a8 b7 fa de f0 81 56 6a e2 d1 3d 2f de .>a......Vj..=/.
+| 1888: f8 a3 75 5d 35 1b a4 a3 8e 6e 8c 9d b2 56 56 ba ..u]5....n...VV.
+| 1904: 89 ab 42 86 70 59 5e 70 51 27 fc 87 b4 5c e5 89 ..B.pY^pQ'......
+| 1920: 20 b5 bd 40 6a 68 cb 1a 70 49 b5 2f c4 02 34 66 ..@jh..pI./..4f
+| 1936: be cc 14 12 e0 f9 c7 4c 84 ff 37 a6 a5 ae 5c 36 .......L..7....6
+| 1952: 03 58 8e 44 17 e1 ca 30 3e 7f c9 54 94 f4 ff 86 .X.D...0>..T....
+| 1968: 57 8b 5e 2c aa 0b 28 30 ac 5a 1a 14 39 70 8a 84 W.^,..(0.Z..9p..
+| 1984: c2 4c 64 28 b1 87 6a 34 cf 50 b7 37 2e 96 ca ba .Ld(..j4.P.7....
+| 2000: c9 b1 37 d5 56 e7 39 b6 70 b1 16 2b 67 8a fb 0f ..7.V.9.p..+g...
+| 2016: b3 ec 53 b4 27 ba 3e 60 16 96 86 b0 02 ba c9 d7 ..S.'.>`........
+| 2032: e1 d9 17 0f d4 12 aa 5d 65 53 29 47 04 47 2f 6f .......]eS)G.G/o
+| 2048: 76 be c9 87 4b 41 27 63 28 f9 b0 48 a9 91 36 32 v...KA'c(..H..62
+| 2064: b7 e1 1f 84 52 c5 3f 81 98 6d de e0 31 27 eb 49 ....R.?..m..1'.I
+| 2080: 0c f6 0c 00 5c db 30 f4 67 4e 90 f8 32 10 87 0f ......0.gN..2...
+| 2096: 27 0c 19 71 b1 b8 e6 ea 40 e9 e0 fa 30 44 f0 d0 '..q....@...0D..
+| 2112: ae 89 05 c6 71 0d 18 36 f5 75 4d 6e b9 cf 60 2a ....q..6.uMn..`*
+| 2128: e9 3e 54 d3 86 34 3b 69 87 47 64 9f 0d 99 d5 d7 .>T..4;i.Gd.....
+| 2144: 42 bf c6 dd 24 51 32 5d e8 70 cf dc 67 55 58 bd B...$Q2].p..gUX.
+| 2160: a0 93 c4 f2 05 73 91 bc 46 d1 4a ac 03 9d b1 ab .....s..F.J.....
+| 2176: e9 6a de 28 8e d4 2a 75 e6 0b f5 ed a0 a6 45 e2 .j.(..*u......E.
+| 2192: ea 86 1e a9 9d ad d9 8c 82 72 26 9e 7b ca a5 13 .........r&.....
+| 2208: 3e ab 9f ed bf 81 9d 51 f0 f4 47 be 89 e1 0b a4 >......Q..G.....
+| 2224: ec 5f 1c 5d b2 64 d0 7f 31 59 2e 68 2c 54 d2 69 ._.].d..1Y.h,T.i
+| 2240: 91 34 56 e5 b9 83 0d 3a 00 9d e3 3d 78 6d 47 1d .4V....:...=xmG.
+| 2256: 09 7d 67 de d8 a2 92 e6 b1 36 4d 89 c0 dd ce 76 ..g......6M....v
+| 2272: df 73 aa 1d 88 38 c5 63 43 ac af 28 35 f8 48 5c .s...8.cC..(5.H.
+| 2288: 9c 4d 50 ab f4 f3 c8 3c 6a 82 99 68 f9 25 7e 86 .MP....>..tJU..O()
+| 2608: f8 00 70 ee 67 18 5e 7d 4d 1a fd b5 92 84 69 4e ..p.g.^.M.....iN
+| 2624: c4 de 4d 45 90 3e 70 22 d3 b6 b0 74 b3 b0 21 86 ..ME.>p....t..!.
+| 2640: 2d 10 d1 d3 2f d8 89 d5 b5 bd e0 92 66 a0 99 30 -.../.......f..0
+| 2656: 0f 6d de e8 db 9a 2d 6c 20 89 43 3c e0 61 32 67 .m....-l .C<.a2g
+| 2672: ee f6 be 79 20 b4 06 11 63 b3 89 0f df 28 56 df ...y ...c....(V.
+| 2688: 94 3c f2 31 b0 b8 5f 11 6c 6b 9b d3 43 cc f0 38 .<.1.._.lk..C..8
+| 2704: 6a 92 3d ee a6 92 95 9c 6c 02 94 31 7b ae 7a 0c j.=.....l..1..z.
+| 2720: 0b 49 0f 82 54 ae c4 b8 58 4d 57 75 d6 e9 20 5a .I..T...XMWu.. Z
+| 2736: bf 5a 2e ae 2d 18 4f 60 62 d9 1f 91 1d cd da f4 .Z..-.O`b.......
+| 2752: 00 e2 d8 fd f0 20 d3 70 2b 4d 6f a1 80 a2 25 16 ..... .p+Mo...%.
+| 2768: 7e 75 5e 7b 45 8d 72 62 11 ba 36 7e 4f 89 ba 4d ~u^.E.rb..6~O..M
+| 2784: e2 0c e3 f4 0d da ac 14 89 36 e5 c8 4f 67 a5 33 .........6..Og.3
+| 2800: ff c2 91 ac 81 25 39 21 c4 79 5c 97 6d 97 45 3a .....%9!.y..m.E:
+| 2816: 6e 00 60 1e c0 e4 ee f3 a6 98 16 43 ee 56 62 32 n.`........C.Vb2
+| 2832: 85 db 7a 83 af 26 a6 3f be 66 c6 5b ff 51 d7 f2 ..z..&.?.f.[.Q..
+| 2848: 8f 2e 13 c4 b2 67 72 ac c4 4d a3 3a 69 cb b5 bc .....gr..M.:i...
+| 2864: 01 74 09 53 16 3a fa 7d 0e 24 8a c8 93 14 4d ca .t.S.:...$....M.
+| 2880: 95 2f 30 dc d1 6c 42 d6 78 04 c8 91 4e 86 2a a0 ./0..lB.x...N.*.
+| 2896: 0f 71 da 74 20 b0 a9 a5 a5 7e 96 44 e1 86 d1 af .q.t ....~.D....
+| 2912: bc 1d 24 19 11 54 3a e1 a6 db 38 f8 64 59 29 0f ..$..T:...8.dY).
+| 2928: 3d 7b ce 0d c5 38 bd cd c2 85 13 f8 62 09 83 96 =....8......b...
+| 2944: 20 2c 3d 81 6b 9d 48 24 4e d6 eb 88 7e f4 6f f4 ,=.k.H$N...~.o.
+| 2960: fc 55 32 3d ab 74 bd f1 4f 75 66 f5 53 a5 a6 7f .U2=.t..Ouf.S...
+| 2976: f5 89 da df 35 a7 44 0b 84 8d 85 f3 08 9b 63 14 ....5.D.......c.
+| 2992: 8b ea 66 43 6f 07 a3 e5 33 eb fb 8b 11 40 10 7d ..fCo...3....@..
+| 3008: 11 cd 65 d7 38 4a 50 d7 02 73 ed a6 15 ac 82 77 ..e.8JP..s.....w
+| 3024: 0d 8c f3 7a ea a2 36 32 11 52 71 d3 f4 24 13 5a ...z..62.Rq..$.Z
+| 3040: 22 e6 75 14 28 7f b7 0c a8 71 16 20 3c 79 f5 ce ..u.(....q. ..L.....
+| 3552: 7f e9 e1 a6 3b 68 b0 1e a0 81 5a 54 f7 3c a2 7a ....;h....ZT.<.z
+| 3568: 24 ee 8e 43 a7 df 14 22 da b2 8c 80 6a 40 4c bf $..C........j@L.
+| 3584: f8 5a 4e d1 34 af 19 3f dc 4f 93 29 83 d1 af 7a .ZN.4..?.O.)...z
+| 3600: 33 fe 25 1a 1c d5 c1 e5 98 4e 30 4d 2b 2c 6e 55 3.%......N0M+,nU
+| 3616: 8d d3 0f d5 f5 a3 a1 44 10 ba d6 2d 05 71 5d 4d .......D...-.q]M
+| 3632: 15 e6 06 21 00 56 c1 45 21 63 f8 61 bf c5 75 79 ...!.V.E!c.a..uy
+| 3648: f5 5f 83 53 ba cd a0 e6 12 45 3b 8b 33 b6 4d 29 ._.S.....E;.3.M)
+| 3664: 41 c9 ad 09 a3 f1 a7 a6 6d 8d ec 16 68 b4 a3 fb A.......m...h...
+| 3680: 01 1a c3 ee 78 17 d9 de cb 2e 42 d4 a3 56 8f f4 ....x.....B..V..
+| 3696: 3c 75 b1 92 d0 b5 75 10 69 cc c0 50 a4 bb d0 4c r.
+| 3776: 8d e5 f5 f6 d4 49 8d b4 65 50 38 8b b3 3e 20 c1 .....I..eP8..> .
+| 3792: 07 cd ad 7d e3 d1 8e 5f 6e 76 7b fe 01 ba 08 74 ......._nv.....t
+| 3808: 16 a5 1b 5e 95 a2 ff 91 bb 9f 64 3f a4 e5 95 be ...^......d?....
+| 3824: d2 59 02 aa c5 06 66 9e fe 56 6e d1 1d 31 6f b3 .Y....f..Vn..1o.
+| 3840: da 6d b4 3a 17 86 e0 e6 c1 37 21 68 6c 33 d3 58 .m.:.....7!hl3.X
+| 3856: e8 67 fa 04 8d 59 ae e4 fb 1f 8c 48 17 7e bb 8c .g...Y.....H.~..
+| 3872: 17 61 b4 a7 e4 6b 87 c0 6a 8b 5f d1 76 16 5c f7 .a...k..j._.v...
+| 3888: 81 b4 2d 66 ad ba 46 6f 95 bf a8 19 e8 82 05 7f ..-f..Fo........
+| 3904: 43 47 8b 63 b4 14 c6 2a de 90 8c 6d 04 3d 90 dc CG.c...*...m.=..
+| 3920: c4 6b d0 4c 33 9f 6c a7 38 6b fd b8 53 de 17 5e .k.L3.l.8k..S..^
+| 3936: ef e4 17 19 25 32 eb 12 86 03 3c 61 2e b4 06 ca ....%2........|..~v3.]...
+| 1104: a8 31 d7 92 4a d2 68 29 8d e4 3c 76 6f d3 a0 f2 .1..J.h)..8...j..:.
+| 1152: 2a 01 f9 21 05 ec 07 3f 6f 7d ba 17 5d ba 3a 04 *..!...?o...].:.
+| 1168: a9 cc 88 35 4f 43 4c dc ab 1d 1d b0 24 1f a2 83 ...5OCL.....$...
+| 1184: 69 4a 89 1e a8 a3 de bc 17 15 be 3d 07 ae 42 02 iJ.........=..B.
+| 1200: f6 60 ff 36 08 cf 63 1f b5 be b1 1c 45 14 b0 56 .`.6..c.....E..V
+| 1216: 0c 2e b9 49 49 69 47 17 da 41 4e 91 0b 5a bd 76 ...IIiG..AN..Z.v
+| 1232: be 67 65 82 27 35 0a 23 a4 21 f4 ba 78 af 0a 7c .ge.'5.#.!..x..|
+| 1248: 0e f0 ca 90 c6 32 d9 dc f1 dc 25 33 da 76 c0 f5 .....2....%3.v..
+| 1264: c2 4d ed 55 d7 f8 1f 44 82 37 c3 d3 90 12 23 52 .M.U...D.7....#R
+| 1280: 8d 3c 3d f0 9e bf 7b 0e 49 8a 32 5d a1 64 53 26 .<=.....I.2].dS&
+| 1296: cb be bc 26 dd bf f8 a6 ad 57 e5 35 68 c1 6c b9 ...&.....W.5h.l.
+| 1312: 02 d7 0d 70 f4 d9 10 8f 75 35 8b 60 21 46 62 60 ...p....u5.`!Fb`
+| 1328: e4 e7 70 35 0f a9 70 0d 50 da 5c c2 17 9b c6 3b ..p5..p.P......;
+| 1344: 61 83 9f 3f 1d f4 28 dc c6 32 a6 12 ff 56 dd 0e a..?..(..2...V..
+| 1360: 57 08 0e 0d 5b f8 ea 32 33 20 a7 a1 a4 9b b3 77 W...[..23 .....w
+| 1376: 4f db 85 06 dd 0b 52 b0 45 ff a4 e5 23 5e ea c0 O.....R.E...#^..
+| 1392: d6 54 d6 84 cd c4 fc 2e 95 ec 78 13 cf 9a fa e3 .T........x.....
+| 1408: a1 5a b3 60 1a ab 1a 97 21 67 9c cd 44 6f ee a9 .Z.`....!g..Do..
+| 1424: bf 1f 07 52 d0 1a a4 ae 15 1e b5 01 0d ac 31 32 ...R..........12
+| 1440: 11 7f 67 b4 9c 20 78 28 8b 4a 79 32 44 c8 aa 1d ..g.. x(.Jy2D...
+| 1456: 05 4b 94 3e e2 f0 d4 f2 16 3c 8e b7 67 13 98 47 .K.>.....<..g..G
+| 1472: 2b 6a 1a 98 c9 82 7d a7 a7 7d ee 62 dd a8 29 58 +j.........b..)X
+| 1488: 98 5b 2e 5b 62 1b 1b 21 37 4d eb e7 85 ac a3 8d .[.[b..!7M......
+| 1504: fe 69 ca 05 34 83 84 34 47 8d 5b b0 8d 71 f1 22 .i..4..4G.[..q..
+| 1520: 07 b5 a9 be 42 88 58 27 84 3e 37 1c 0f c7 1f 77 ....B.X'.>7....w
+| 1536: 72 5e 2c fc 80 43 03 71 00 22 7f fe 5d fe ea a7 r^,..C.q....]...
+| 1552: 33 3a c6 ae db e7 1d ba 8b 61 8c b9 b4 b2 ab b4 3:.......a......
+| 1568: 2f ec 9d b1 9c bb 13 7b 6e 3a b9 aa 43 b2 14 6f /.......n:..C..o
+| 1584: f0 27 00 31 f6 5b 9c e9 96 40 3a 13 2f fc 6b ae .'.1.[...@:./.k.
+| 1600: 0a 55 bf b3 cd 83 23 25 f1 15 e2 2e bc 7c 6b 29 .U....#%.....|k)
+| 1616: 90 8f 85 ff 5b 5a 18 52 03 84 4d f9 f9 fa e1 a0 ....[Z.R..M.....
+| 1632: e8 32 29 9c 5b 9e ed 39 b3 17 f8 ef 7f 55 b4 3f .2).[..9.....U.?
+| 1648: c3 f3 66 f1 bc 15 1b 78 2c 9b ab cf e1 10 d0 46 ..f....x,......F
+| 1664: 3d 21 2b eb 4f 8f 1d eb 8a 5e 87 23 72 50 04 ea =!+.O....^.#rP..
+| 1680: 8f 53 1b 3a 3f cf d5 92 5a 06 c1 18 25 33 41 84 .S.:?...Z...%3A.
+| 1696: 77 56 bf a5 8a d1 ff 97 51 34 d3 24 88 12 dc 33 wV......Q4.$...3
+| 1712: 09 09 fc 68 b5 2a 4a cf 7c 73 d8 ff 93 29 40 1c ...h.*J.|s...)@.
+| 1728: 8e ea 7d e3 7f 25 57 f5 bf 2b 19 80 4d fa 23 35 .....%W..+..M.#5
+| 1744: 18 8b ad af 46 85 3b 51 34 49 dd cb 39 d8 50 50 ....F.;Q4I..9.PP
+| 1760: 7a a5 58 af 72 66 5d 21 c2 e2 03 1f ee bb d2 b4 z.X.rf]!........
+| 1776: 62 d2 f4 c0 fb 04 12 b2 35 0c 0f 0d b9 e2 a5 28 b.......5......(
+| 1792: 87 5b 76 c7 39 4d 18 8d 3f 61 ab a0 84 4a 11 22 .[v.9M..?a...J..
+| 1808: e1 a9 69 55 2b 03 41 34 73 83 0d 0b ed da a6 d8 ..iU+.A4s.......
+| 1824: f8 ff 9b d2 62 1b ca 1a 40 4f 0a 86 ad e7 92 af ....b...@O......
+| 1840: ce 69 19 8e 35 5d cd 50 4e 53 2d 90 46 90 ae 8a .i..5].PNS-.F...
+| 1856: 43 ac 8b 30 7f 3b b3 05 78 63 b3 b7 0b 3d 2a 13 C..0.;..xc...=*.
+| 1872: 55 83 ed a0 61 6b 12 30 5c 46 f3 1f 18 1f bd 89 U...ak.0.F......
+| 1888: af 86 9a 82 ed 89 35 0e 29 06 2c b8 97 c5 ef 46 ......5.).,....F
+| 1904: 90 ce 6c 83 f8 7d 08 75 76 b4 07 6b 48 15 bb bd ..l....uv..kH...
+| 1920: c2 fd 79 a8 7f 54 e4 d5 93 c2 17 09 3f bb 58 84 ..y..T......?.X.
+| 1936: dd 78 7a 81 c4 13 70 e5 23 73 d4 60 25 0f 91 bc .xz...p.#s.`%...
+| 1952: a9 8e 54 64 46 e1 8f 11 66 7c 1e 31 5b 9e 10 d9 ..TdF...f|.1[...
+| 1968: 7e 09 e8 bc 2f 73 d4 f6 27 0c a0 62 5d ce 65 40 ~.../s..'..b].e@
+| 1984: f7 24 b0 bf f0 26 c0 17 1a dd d3 5d 16 35 22 10 .$...&.....].5..
+| 2000: 4d c4 cf 5b 22 2f 12 b2 5b f2 87 04 34 4d 5c 9d M..[./..[...4M..
+| 2016: 50 48 71 c7 8e bb 7d ce 89 f3 e4 4a c1 f2 92 4f PHq........J...O
+| 2032: 90 4d 58 ac 27 60 a7 e9 31 41 ca b1 c0 38 ce 2d .MX.'`..1A...8.-
+| 2048: df 40 e9 cd db 2f f3 28 09 ef 14 79 99 ef 66 1b .@.../.(...y..f.
+| 2064: e6 c0 7f 4c cc 61 96 b6 f9 95 9d 1b 90 16 55 08 ...L.a........U.
+| 2080: 71 ad 92 88 98 01 7f b9 8e 9c a2 f4 d4 24 33 a0 q............$3.
+| 2096: 53 f2 01 df 47 3f 8d 15 a8 d1 70 a9 c2 70 f8 75 S...G?....p..p.u
+| 2112: b4 ed b6 7d 82 95 63 5e 86 c1 3a 7c de b1 46 fd ......c^..:|..F.
+| 2128: b8 30 42 36 83 35 e2 4a 78 c2 b5 b9 1e 57 f2 19 .0B6.5.Jx....W..
+| 2144: 91 6d ff 4f 87 97 55 98 a3 86 a2 54 1f 2f 0c 8e .m.O..U....T./..
+| 2160: 72 d6 a0 37 f2 bf 84 a3 a5 b3 87 12 a3 ef 0a 00 r..7............
+| 2176: 31 69 49 83 8c 6e 82 3a 84 62 a8 ce ee ce 91 61 1iI..n.:.b.....a
+| 2192: b7 26 c1 fd bf 77 15 81 23 e6 d5 6f bb c4 ab eb .&...w..#..o....
+| 2208: 8b a7 fc b6 4e cb c1 61 ab 59 a2 dc ca ca f3 42 ....N..a.Y.....B
+| 2224: 90 16 d8 d0 03 43 c1 e0 d9 25 50 b0 17 65 64 d0 .....C...%P..ed.
+| 2240: 11 be 52 a8 e3 bd dd 7f 39 1e 0b 85 ae 92 c0 1c ..R.....9.......
+| 2256: 0c 3b 06 2a bb be b6 c7 94 d6 83 6b b0 17 6d 24 .;.*.......k..m$
+| 2272: b1 b5 2d 22 5e 7f b9 db 47 65 e6 21 37 a2 2f d3 ..-.^...Ge.!7./.
+| 2288: 03 8a 91 c0 5a de 52 27 dc 4b 9a 92 f1 fc f0 93 ....Z.R'.K......
+| 2304: d1 de 9e 04 73 13 c5 ec 25 36 54 15 94 92 b9 de ....s...%6T.....
+| 2320: bd e2 39 b3 5c 88 8c e6 11 48 28 b8 0d 50 5a 6f ..9......H(..PZo
+| 2336: d9 8a a6 17 4f a0 82 ff 94 70 28 10 0c 41 80 c4 ....O....p(..A..
+| 2352: d9 42 a9 fe d2 f7 1c 70 45 74 fa 65 d2 cf 49 00 .B.....pEt.e..I.
+| 2368: b8 24 83 06 97 f5 1c 48 a7 dd 82 2f f0 77 f5 e6 .$.....H.../.w..
+| 2384: 5c 03 11 fa 65 46 57 90 c0 6f 1f 86 58 de 34 21 ....eFW..o..X.4!
+| 2400: 5f 76 d7 1e 1a 16 6a e1 ad 26 ae 6a 32 53 30 8b _v....j..&.j2S0.
+| 2416: db d9 05 93 22 87 58 e8 91 d8 26 80 85 f0 01 93 ......X...&.....
+| 2432: 77 0e 88 91 bc bc ce e9 5e 6e e8 b8 aa 4e ad fa w.......^n...N..
+| 2448: a8 a2 5a 17 b8 88 56 f5 71 8a 70 fe 83 4f 5c 8c ..Z...V.q.p..O..
+| 2464: 07 1a 45 cf a9 89 05 c6 81 79 90 a5 d2 53 a4 3e ..E......y...S.>
+| 2480: ac be 52 ae aa 9d 30 66 c5 b7 1f 7a c8 8e 6a 3b ..R...0f...z..j;
+| 2496: 82 54 6a 62 aa 6e 4a c4 02 11 5b 69 12 6f 84 23 .Tjb.nJ...[i.o.#
+| 2512: 17 f6 3d 81 1f 29 60 28 7c e2 95 b4 ae 39 e6 6b ..=..)`(|....9.k
+| 2528: 5e c5 df 82 66 82 57 d4 84 cd 2b 1e f2 a0 31 82 ^...f.W...+...1.
+| 2544: 8b 9f 0e 0c 72 76 6b 6c 5b cb 0c 5c 2a 77 22 df ....rvkl[...*w..
+| 2560: 1e 96 44 f9 4e 22 dd 22 ff fc 14 a2 cc 36 77 02 ..D.N........6w.
+| 2576: 81 8f 22 1e 46 ea 11 e1 85 41 8a ee 69 64 e6 27 ....F....A..id.'
+| 2592: 8b 46 0b 4a 47 35 f4 72 71 62 a1 0c 4d 55 be a0 .F.JG5.rqb..MU..
+| 2608: 1f ae ae 8b a6 2d de 54 04 24 05 98 06 43 04 57 .....-.T.$...C.W
+| 2624: 09 8e ff 81 ff 9c 9a 18 02 bf c3 66 8f 65 fb e3 ...........f.e..
+| 2640: 66 0c 20 bb 50 f5 0c a8 a8 e9 6f 53 65 b5 3a e4 f. .P.....oSe.:.
+| 2656: 48 d2 1c 86 e2 a6 35 c0 91 d4 72 b6 67 21 49 fb H.....5...r.g!I.
+| 2672: 0c f9 91 b8 64 46 c2 75 28 df ac c0 bc 4f 61 d9 ....dF.u(....Oa.
+| 2688: 92 06 6b 48 d8 29 ba 4f e6 40 a8 c8 35 8b 83 e6 ..kH.).O.@..5...
+| 2704: 79 ec a1 d3 c1 73 82 64 42 13 3c 7b 73 3e 7a 14 y....s.dB.<.s>z.
+| 2720: 2d db ac 00 76 00 81 ae fb c1 30 7b dc 57 39 f5 -...v.....0..W9.
+| 2736: 27 6b 1a d5 ed c2 4b 21 12 3e 4d e0 8e 58 69 9b 'k....K!.>M..Xi.
+| 2752: f5 cb 26 7a 62 e5 7b 3a fd 1a 8a e6 7d e6 f1 60 ..&zb..:.......`
+| 2768: cc 4f 30 39 76 b7 3d 49 3f b7 59 a3 d0 a6 c8 8e .O09v.=I?.Y.....
+| 2784: 3e a8 e1 a0 1b 7d 82 39 8b c6 a5 87 3e 2c da 16 >......9....>,..
+| 2800: f0 71 cc 5e 02 17 49 6d 48 24 8c 19 9e c4 d1 97 .q.^..ImH$......
+| 2816: a6 cc 28 28 c9 3e c2 e3 19 6a 05 f2 bd 4c ef 44 ..((.>...j...L.D
+| 2832: df 84 da 8c 3f 41 16 2f 87 b8 88 bd 6d 8b 6e dc ....?A./....m.n.
+| 2848: fa b0 44 08 ee ef 22 84 bf c0 5c a4 2f 2c 7e a2 ..D........./,~.
+| 2864: 50 8b 84 cd 60 08 d8 53 4b 2d 4f 1e 3b 14 b4 62 P...`..SK-O.;..b
+| 2880: 97 a1 66 49 2a 6f 3b 36 85 c2 42 58 98 5a db 3e ..fI*o;6..BX.Z.>
+| 2896: 64 fd ad 32 f2 e0 f9 5a 13 dd e1 68 6c 35 34 a5 d..2...Z...hl54.
+| 2912: 3c 9a b1 8a 51 78 49 5b c6 ef 57 7f 6e de fe 2d <...QxI[..W.n..-
+| 2928: 0a 2c 1b 74 3f 19 bf 8e 6d 2f 0b 22 91 36 95 5d .,.t?...m/...6.]
+| 2944: a3 65 b6 3b 3a e4 de 70 9e 29 f4 c6 0a 23 27 d6 .e.;:..p.)...#'.
+| 2960: d1 4a f6 2e 2b a0 ee 8d cd fc 42 7a c8 1a a6 36 .J..+.....Bz...6
+| 2976: 17 aa f4 03 b5 cc e2 54 7a c4 fb 27 e5 90 62 20 .......Tz..'..b
+| 2992: 03 77 4d fc 35 7c 59 87 01 49 86 ae 82 6b 8b a7 .wM.5|Y..I...k..
+| 3008: bc b0 b0 dd f2 ef f7 ef 0a 36 a6 25 f1 70 ba 89 .........6.%.p..
+| 3024: e8 00 f4 fc c0 98 73 f2 b0 9a a2 ed d5 1e 17 d1 ......s.........
+| 3040: 79 82 18 84 b0 f8 2a 5d f2 a1 03 d6 45 b0 01 26 y.....*]....E..&
+| 3056: 19 01 6d b3 0e 5f 55 6c 2b 21 72 33 84 a9 ab fb ..m.._Ul+!r3....
+| 3072: 64 4d bc f0 1d 16 ae aa 09 c1 29 60 e2 63 e1 d5 dM........)`.c..
+| 3088: 84 41 6e 5c 12 08 9a 04 dd 27 b8 fe 2f fb ca 83 .An......'../...
+| 3104: 2a 7b eb 05 3b 77 fd 42 31 42 84 98 89 24 3c cc *...;w.B1B...$<.
+| 3120: 47 f6 bc 13 37 d7 97 98 c4 61 24 50 0b 9e e5 53 G...7....a$P...S
+| 3136: 46 05 49 5e a5 51 d5 48 26 fa 31 eb 0e 76 14 16 F.I^.Q.H&.1..v..
+| 3152: e9 60 f6 05 d5 bb 47 85 e2 da f6 5a 0a c0 14 38 .`....G....Z...8
+| 3168: bb 70 4d be eb d8 6d 10 61 d6 9b c6 c4 f4 56 7f .pM...m.a.....V.
+| 3184: ff b8 fb 1f 92 a3 f5 74 78 7f c0 8d 9d f4 b1 a2 .......tx.......
+| 3200: f4 0c 33 da 98 9e a2 61 4c c7 41 9c ea 0f 33 54 ..3....aL.A...3T
+| 3216: 40 54 31 c3 04 fa d1 4b 67 80 e2 a7 6a 77 c6 ca @T1....Kg...jw..
+| 3232: 04 fc 71 ea fa 0f 92 8e d3 40 e8 0e 1c 48 a4 55 ..q......@...H.U
+| 3248: 7f 74 67 ea c9 29 67 73 b9 b9 73 b1 00 1a d4 0b .tg..)gs..s.....
+| 3264: 21 95 d6 1c b4 68 2b c5 e1 18 40 7e 8e 09 6f 28 !....h+...@~..o(
+| 3280: 88 2d 6f 24 d3 73 7b 89 7a a6 aa df ad ae 7b 14 .-o$.s..z.......
+| 3296: d9 f0 ff 20 ba fd bf a7 d7 04 6c 35 5c 76 4e f5 ... ......l5.vN.
+| 3312: d3 5b a9 2b 8f 3a 11 fa 35 26 eb 78 45 da cb 00 .[.+.:..5&.xE...
+| 3328: 78 97 b1 49 82 4e c1 4d b1 aa b7 80 75 fb 20 75 x..I.N.M....u. u
+| 3344: cb 3f ba 05 95 33 cd e9 b3 bd b2 84 c4 4f df af .?...3.......O..
+| 3360: 77 c2 44 24 57 01 f9 9d c1 ef b6 ce 01 6f a6 5d w.D$W........o.]
+| 3376: 3d 4b 12 e9 8f c2 a6 d5 1c 3b e4 05 83 48 aa 78 =K.......;...H.x
+| 3392: 4b 3a 1c 1b ad 8e bc 49 c5 ee 91 68 28 8d 74 74 K:.....I...h(.tt
+| 3408: a0 e1 20 ba 3d 62 97 0a 40 58 6b 1a c9 be 53 00 .. .=b..@Xk...S.
+| 3424: 5d 9f e7 8e b6 05 7a d2 d1 89 ac fd 7f 9b ec 19 ].....z.........
+| 3440: d0 95 35 e6 41 32 eb 68 85 eb 06 8c 53 f2 25 f3 ..5.A2.h....S.%.
+| 3456: 19 d9 1c e7 a8 c2 c3 1c cd 78 50 4d 73 2d 5c 15 .........xPMs-..
+| 3472: 7c 3e b5 f0 e8 64 f5 72 a1 4a 9d f3 87 1d 12 0b |>...d.r.J......
+| 3488: d6 50 21 18 ca 10 f9 29 32 53 14 54 08 ef 51 6d .P!....)2S.T..Qm
+| 3504: 6e 20 ae f1 3c b5 6b 8b 4c 4d 68 9f 73 99 2f d2 n ..<.k.LMh.s./.
+| 3520: f2 ea ba bd 72 e4 d5 de 71 c2 15 a2 57 f7 69 c0 ....r...q...W.i.
+| 3536: c4 6b cb c1 72 8e a8 fe f8 79 d2 6d 97 82 bf a1 .k..r....y.m....
+| 3552: 11 35 dc 30 36 e5 32 b5 81 f7 2b 58 06 c3 28 3a .5.06.2...+X..(:
+| 3568: 43 c0 bd 16 a4 b8 f7 37 2b 1f 5f 8a 2a 09 21 4e C......7+._.*.!N
+| 3584: d7 14 35 31 e6 36 8d 6f 2b 2a e2 63 1f 59 8d 62 ..51.6.o+*.c.Y.b
+| 3600: 16 cd 16 d5 5a 20 b0 4b 9c 44 4d bb 0e 8a 01 6d ....Z .K.DM....m
+| 3616: 6c 2e 09 48 6c 32 f5 96 45 0b df 3a a4 09 a4 1c l..Hl2..E..:....
+| 3632: 44 81 72 60 8a ed 10 29 c0 62 da ba 51 4f a0 7d D.r`...).b..QO..
+| 3648: e0 9b ed 31 6a 0e f8 b5 f4 69 b2 15 d4 01 ed c5 ...1j....i......
+| 3664: e2 09 df cc 97 13 70 57 48 1b bd 4a ad 0b ad 8a ......pWH..J....
+| 3680: 80 3d c1 c0 c7 f2 2d d9 a8 b7 3f b8 e5 aa 0f 5c .=....-...?.....
+| 3696: e6 95 2a c6 80 83 69 ca 0e dd f9 7e 04 48 7d d3 ..*...i....~.H..
+| 3712: d5 29 fd 9d 7f 59 d7 1d 9b cd c3 06 e7 51 13 bc .)...Y.......Q..
+| 3728: 60 d5 c3 d5 a9 0b 78 ab 01 3e 34 06 4f 8a 47 4a `.....x..>4.O.GJ
+| 3744: 0d a9 c1 b5 29 c4 26 c4 5d cb bd 80 f1 d4 eb b9 ....).&.].......
+| 3760: 6b 7d 2f c3 95 7c 2c e3 86 c9 5d 41 ee 76 89 9f k./..|,...]A.v..
+| 3776: 3a f3 e2 c8 6e f5 37 a7 68 01 06 26 47 9c 1b aa :...n.7.h..&G...
+| 3792: 5a dc 55 89 af 53 89 9f f2 30 ee 04 90 cc 30 de Z.U..S...0....0.
+| 3808: f4 2a c9 23 59 9d cf 65 7d 2c 30 7e ae 7d 08 43 .*.#Y..e.,0~...C
+| 3824: 1f a9 b8 14 3b e8 3d 1e 3e 4b 46 93 18 4b 08 ee ....;.=.>KF..K..
+| 3840: 53 f4 07 0d 4e 69 87 a4 61 9f b0 75 a7 fc 64 34 S...Ni..a..u..d4
+| 3856: 86 aa a2 82 21 40 d7 7a 03 30 d0 f4 47 d2 4a ff ....!@.z.0..G.J.
+| 3872: dd 27 02 69 99 d2 c9 61 d0 fa 46 dc 07 1d f7 0b .'.i...a..F.....
+| 3888: 39 0b a3 2d 7f 9f 1b ce ca 79 69 62 bc 50 1a 07 9..-.....yib.P..
+| 3904: 2c 1b 38 37 9f 93 65 dc 45 3a 1e 2b ff 3f d0 bb ,.87..e.E:.+.?..
+| 3920: 05 f2 9b 36 b5 79 9c ca 4f 7d 8a 2f 6e 62 1d 20 ...6.y..O../nb.
+| 3936: ab 6e 5f 75 19 67 e9 4a e1 c4 6a 2e 8a 06 b0 36 .n_u.g.J..j....6
+| 3952: 37 47 5f a1 27 93 d4 36 80 85 f9 29 94 db 83 13 7G_.'..6...)....
+| 3968: f5 16 1e 0e 6b 6c b1 c1 f2 66 0a 8e 63 ea ca 6b ....kl...f..c..k
+| 3984: f3 74 91 9e 73 62 d4 09 bd a9 64 54 e1 64 b0 e4 .t..sb....dT.d..
+| 4000: b6 47 e0 ff 92 09 88 39 e1 44 f8 50 20 b2 3c 6b .G.....9.D.P .....|..g.>@.E.y
+| 1104: ad 46 a6 a7 42 e7 7c 05 62 a4 28 61 03 fc 1c e4 .F..B.|.b.(a....
+| 1120: 48 2e f1 ef d9 09 23 04 f4 d7 c2 ad 73 c4 d8 69 H.....#.....s..i
+| 1136: cf 15 ef a5 1a ba db 63 7c d8 e9 4c 70 cf 08 d8 .......c|..Lp...
+| 1152: 62 d3 ec 60 a0 93 06 fe 50 87 b5 22 48 37 b8 46 b..`....P...H7.F
+| 1168: 30 26 ed 8d 2c f3 ed c1 51 62 e8 ce 13 45 b4 4a 0&..,...Qb...E.J
+| 1184: 9a 3c 76 c4 fd a6 e2 de 26 04 93 69 30 3c 26 4d .1..3. ..
+| 1248: 2f 8f 00 d5 47 ae 22 01 bf 83 40 da c4 74 43 56 /...G.....@..tCV
+| 1264: 32 35 6e c9 3a 82 44 0e 86 32 5a 8e 46 5c 16 23 25n.:.D..2Z.F..#
+| 1280: e5 dc 7e 38 26 fd ba d1 d3 d0 7e 4e 88 6e 2a 85 ..~8&.....~N.n*.
+| 1296: d1 25 70 b4 fc 55 2b 5a 5b 4e 01 1b 20 21 d2 2b .%p..U+Z[N.. !.+
+| 1312: c1 5b e9 3e f1 fe 3f 65 18 07 a6 10 3a 88 e5 9b .[.>..?e....:...
+| 1328: 4d 83 91 f2 1f b5 03 2a cb 57 21 e2 20 fc 35 99 M......*.W!. .5.
+| 1344: b1 49 4a 0c b9 04 35 b9 b0 43 52 14 e7 2d 03 30 .IJ...5..CR..-.0
+| 1360: 73 cc 40 39 c3 d6 58 1b 90 85 df 21 6b e4 03 87 s.@9..X....!k...
+| 1376: e1 de 4c 36 2c f3 c1 0b 75 92 a9 11 6e 9b de ac ..L6,...u...n...
+| 1392: cb 26 b9 8d 48 47 f3 63 44 30 b0 e6 84 31 ec aa .&..HG.cD0...1..
+| 1408: f9 64 3b b2 12 b4 13 46 be 97 6f 36 37 3a ea 4b .d;....F..o67:.K
+| 1424: ef 0d d6 04 44 21 e3 25 72 6c 70 d5 58 87 7d 16 ....D!.%rlp.X...
+| 1440: 37 39 d3 0a 7b fe e2 81 d1 50 6a 62 6c a8 86 ca 79.......Pjbl...
+| 1456: b9 f4 4e b5 04 c3 97 1b 4e 65 49 ee f4 cd 9c e4 ..N.....NeI.....
+| 1472: 89 7d 7e c8 29 9b 3e 88 82 b7 68 c4 9b ea 75 48 ..~.).>...h...uH
+| 1488: 1b 5b 93 0d 12 86 df 35 44 28 95 6c f2 c4 e5 3b .[.....5D(.l...;
+| 1504: 89 a7 bf 11 ce 79 76 99 bb 0d 01 2e 58 e3 e1 0d .....yv.....X...
+| 1520: 06 19 5e 28 bc 06 32 4e 76 bd e5 01 a0 20 5c 3f ..^(..2Nv.... .?
+| 1536: 15 ad e8 4e 64 5a 67 a4 77 3f 23 c2 be 0d 96 b5 ...NdZg.w?#.....
+| 1552: 28 e9 c3 60 ec 5d 09 73 e9 dd 40 a8 7d a0 ac 4f (..`.].s..@....O
+| 1568: ef 82 ac 4d 25 19 a8 1b 22 71 c2 fa 97 c3 27 da ...M%....q....'.
+| 1584: 44 14 f0 41 26 20 fd 57 4f 4e 9d f5 b3 d5 7c 72 D..A& .WON....|r
+| 1600: f4 e5 56 0c 8e e8 c0 39 1c 3c 0e bb ce 8f 08 cb ..V....9.<......
+| 1616: 7f dd 0c fc 11 17 4b 41 03 b6 43 17 25 92 84 8b ......KA..C.%...
+| 1632: f8 51 57 92 93 14 25 11 83 ce da bf 04 0d ed 32 .QW...%........2
+| 1648: 07 dc 6d b5 e1 c5 74 42 07 06 2a eb 2c a0 78 a7 ..m...tB..*.,.x.
+| 1664: de 21 66 0b ea 49 fc e9 26 87 63 5c 8f 66 59 95 .!f..I..&.c..fY.
+| 1680: c1 cd e9 00 79 05 0f 57 d0 d5 a9 1e 48 f6 7a 9d ....y..W....H.z.
+| 1696: 80 6d 5c 74 55 3d fd 67 0e ff 74 26 70 bf c3 9b .m.tU=.g..t&p...
+| 1712: 5f af 8b 43 69 e0 49 31 63 2b e4 9f 59 09 0e 5a _..Ci.I1c+..Y..Z
+| 1728: 18 84 b3 f4 19 17 18 16 5b fd ed 78 5f 68 ec 2c ........[..x_h.,
+| 1744: d7 66 05 6e 47 eb 9b a1 52 90 0f 34 99 4f a0 fd .f.nG...R..4.O..
+| 1760: 21 f7 4d da f6 ae e4 57 51 63 59 e1 ee b8 32 6a !.M....WQcY...2j
+| 1776: 03 ac c4 c4 69 73 10 32 d5 94 25 7e 6b d0 ec 62 ....is.2..%~k..b
+| 1792: 0d 17 f7 16 24 b5 df 11 7b 29 01 03 d8 ff 1a 2f ....$....)...../
+| 1808: 7f 51 ab 9e 41 5b aa 0c a5 5d e9 69 ce 3b 85 4e .Q..A[...].i.;.N
+| 1824: 7d ff 5a 37 b5 74 18 78 85 95 4d 44 8a d9 8c ea ..Z7.t.x..MD....
+| 1840: 2e 10 6e e6 cb a1 3d ef 57 38 f0 9b f0 8b 0b 68 ..n...=.W8.....h
+| 1856: f9 f8 9f ac 58 da f3 9c 2b 2a 90 c7 4d 00 e4 4c ....X...+*..M..L
+| 1872: 46 59 01 1c 0c 6b 08 6d 33 07 41 d0 5d 23 20 3b FY...k.m3.A.]# ;
+| 1888: 00 e0 6b 32 2e 76 3a 7e 09 3e c9 66 90 4f d5 9b ..k2.v:~.>.f.O..
+| 1904: 8a bd b1 6d f9 33 d9 5a b3 bb a1 2a 45 31 0b c6 ...m.3.Z...*E1..
+| 1920: ce 44 34 5d 88 61 89 d1 cc 7c 14 86 a3 d7 6b 6b .D4].a...|....kk
+| 1936: 22 d2 98 ab 62 7c 43 2e a8 92 12 de 43 d4 0a 9d ....b|C.....C...
+| 1952: 94 f0 41 2d 14 86 69 fe 98 71 1a a2 2b db 5b ec ..A-..i..q..+.[.
+| 1968: 23 00 e3 a3 03 1d 31 97 94 e4 85 1e 5f 53 44 66 #.....1....._SDf
+| 1984: 0a 21 df ec ca 6a a6 a3 f4 c8 00 40 8e 0f 19 3f .!...j.....@...?
+| 2000: 36 69 a3 7c de fc 73 16 d8 d3 f9 ff 03 ac 94 dd 6i.|..s.........
+| 2016: 38 d5 d9 20 2e d8 97 2a 22 9d bb a5 cc 04 07 8f 8.. ...*........
+| 2032: be 18 b4 a8 ae e5 b4 45 27 7f e2 7e 3f 91 67 98 .......E'..~?.g.
+| 2048: 86 3d 3c 05 3a 1e 71 bf 40 f8 a6 ca 48 7a ca c7 .=<.:.q.@...Hz..
+| 2064: b7 67 10 bd 99 79 53 32 70 b0 74 fc d9 93 60 c8 .g...yS2p.t...`.
+| 2080: 3e 39 5c fa 3c 97 34 70 57 a3 0f f8 ab 4e 3f a6 >9..<.4pW....N?.
+| 2096: a5 25 26 ea 0c 60 fe 32 f3 7a 68 d0 9f 50 a4 45 .%&..`.2.zh..P.E
+| 2112: 13 2e f8 41 3f e9 d1 9f 78 4a d0 a7 d3 57 3c af ...A?...xJ...W<.
+| 2128: a6 69 6f 2b 4e f0 86 b5 96 2d b2 de 06 5b 68 b2 .io+N....-...[h.
+| 2144: 9a b9 de e7 7d 54 0a ff b1 26 17 ea bc a7 37 ff .....T...&....7.
+| 2160: 46 7b f7 00 90 ec 71 92 cb 5a b7 c8 7f 45 60 ec F.....q..Z...E`.
+| 2176: 9e 30 ca 80 69 4c 07 4d c8 c9 53 c4 77 3c 93 15 .0..iL.M..S.w<..
+| 2192: 17 63 15 c0 3a 1d a2 02 82 6d 4b ed 50 4c 5d 93 .c..:....mK.PL].
+| 2208: 2d ef bf 1e 9a ff 04 26 1a f6 7b da c9 21 7b 50 -......&.....!.P
+| 2224: 4d 2f 53 c4 1e b4 dc 9f 5f 33 26 80 4a 8c ef 54 M/S....._3&.J..T
+| 2240: fb 58 95 55 3c ec c0 a7 c5 78 a0 91 08 b4 d6 ce .X.U<....x......
+| 2256: d8 25 27 2b 37 e9 63 72 94 c3 89 5a 58 85 f4 95 .%'+7.cr...ZX...
+| 2272: 09 fe db 6c 9c 71 54 af 1a 0c eb 2d e6 a9 db a0 ...l.qT....-....
+| 2288: 04 2c 29 70 12 b2 7e 66 ae 25 ce b4 b9 5c a2 12 .,)p..~f.%......
+| 2304: 1c 75 10 d5 54 f8 04 c5 8d be 38 29 64 f8 29 00 .u..T.....8)d.).
+| 2320: 07 35 e4 e7 6e bc 64 db 39 d8 98 ee 72 28 a8 8b .5..n.d.9...r(..
+| 2336: 0f 1b 87 26 6e d4 73 1b ef b6 d4 db 05 12 1b c7 ...&n.s.........
+| 2352: c6 1e 02 b1 ab bb e2 29 81 9a 9e b6 80 22 6e b4 .......)......n.
+| 2368: 3c 30 ad e7 8b a9 60 7e de 01 a3 74 0b 76 0b d6 <0....`~...t.v..
+| 2384: e8 a0 91 65 ce bb 6a d7 96 cc fa 96 d0 c0 39 d0 ...e..j.......9.
+| 2400: 54 80 1d 8d 79 17 11 86 c5 8f a7 7f 57 92 8d b2 T...y.......W...
+| 2416: 41 5b 86 61 94 23 99 77 b0 5d 5d f9 29 86 36 c8 A[.a.#.w.]].).6.
+| 2432: ea f8 2f b5 7d 42 66 fe c7 0d 19 17 e6 6f c5 79 ../..Bf......o.y
+| 2448: e0 22 24 70 eb 79 23 ec 45 77 d3 44 8f 74 15 bc ..$p.y#.Ew.D.t..
+| 2464: cf 46 cc ff 5b 05 1e 03 7d ea c5 82 14 11 86 4b .F..[..........K
+| 2480: cb 23 5b e0 1d 96 ca ea 62 d8 71 56 c4 1f d6 ed .#[.....b.qV....
+| 2496: 9e 8f bd b0 4a fe 53 87 c8 16 1a 31 cb 25 ba 18 ....J.S....1.%..
+| 2512: 66 c3 b2 a7 91 68 ff b9 2b bc c4 f5 50 36 79 e5 f....h..+...P6y.
+| 2528: 33 c3 d4 98 e1 fd f9 3a c7 a1 ef 79 29 c1 bf 7e 3......:...y)..~
+| 2544: db 7b 66 3b 95 37 02 c7 ee ca 7f 9f 50 8f 47 5d ..f;.7......P.G]
+| 2560: af 45 29 e3 f5 7e 07 93 73 a0 42 ef 05 a6 2b 74 .E)..~..s.B...+t
+| 2576: 92 ab 8a 9a 19 be 2f 21 cf 6a 90 02 a3 1f f4 5c ....../!.j......
+| 2592: 72 b3 31 00 85 9b 20 d8 f3 c5 00 a7 15 30 56 6c r.1... ......0Vl
+| 2608: 0f 7c 84 be 55 5b 8b aa df d6 bd 9e d9 55 54 93 .|..U[.......UT.
+| 2624: 44 7d 9a 9b b8 38 46 b7 1e 1c 75 17 bb 29 05 5f D....8F...u..)._
+| 2640: da 39 7e fe 9e 40 e3 a5 7c a2 ba 5d 7e 9d 14 57 .9~..@..|..]~..W
+| 2656: 19 10 2a d1 85 d3 06 0f d4 d8 ac f0 03 8a bd 61 ..*............a
+| 2672: 26 89 4e c6 92 0a 4b 0b a2 3e 1d 5e 88 8c ce 33 &.N...K..>.^...3
+| 2688: 47 e7 4e 69 0c e3 09 ef 3a 9f af 19 ae 83 68 21 G.Ni....:.....h!
+| 2704: 75 c3 54 7b 00 a5 f3 d2 32 41 69 ac fc 31 2e 0c u.T.....2Ai..1..
+| 2720: 91 dd 90 78 2c ab 3f 0c 37 a4 8c 69 a9 ae 41 8e ...x,.?.7..i..A.
+| 2736: 6b b5 b5 ee bf df bc 1c 61 bb c9 51 37 a5 d5 96 k.......a..Q7...
+| 2752: 0c 26 aa 97 67 72 73 cc c1 92 d3 46 cd 3e d8 ad .&..grs....F.>..
+| 2768: e6 8b 51 ee 41 ed 39 57 65 2e 5c 39 2b eb a7 72 ..Q.A.9We..9+..r
+| 2784: b6 4c a8 87 72 a4 16 b4 d9 90 db e9 25 11 53 4e .L..r.......%.SN
+| 2800: ef 24 1d b0 21 bc 97 52 38 53 49 c8 31 c1 c4 9f .$..!..R8SI.1...
+| 2816: 2b 13 0c 10 5b 4a 0c 6e 07 c0 ec d4 77 f0 f0 38 +...[J.n....w..8
+| 2832: a6 88 d4 28 40 30 76 f4 ab 2e 94 b5 6d 47 79 84 ...(@0v.....mGy.
+| 2848: f9 aa 28 32 66 c8 aa cf 17 18 3d 92 0e 66 4e fe ..(2f.....=..fN.
+| 2864: 5d 80 51 29 df 97 de a4 c6 57 23 67 84 f4 32 86 ].Q).....W#g..2.
+| 2880: 51 03 b6 67 29 54 74 87 da c0 41 e9 3a 3e 07 02 Q..g)Tt...A.:>..
+| 2896: d9 85 dc 55 e7 23 60 80 b0 01 48 cd 59 21 82 fe ...U.#`...H.Y!..
+| 2912: 14 65 1a 5d 9e 5e 2b 69 52 ee 64 01 4d 46 ac 94 .e.].^+iR.d.MF..
+| 2928: 60 04 d9 2c 41 e3 5b 35 e7 cc 75 06 7d ff 48 ae `..,A.[5..u...H.
+| 2944: 13 e5 4f 54 f6 78 86 c5 c4 99 58 02 41 87 a9 82 ..OT.x....X.A...
+| 2960: 34 95 75 b2 e5 5e 92 23 a1 7b 3c 7b 1d 94 dd 5f 4.u..^.#..<...._
+| 2976: f6 56 07 06 41 12 a0 56 7a 15 01 58 1f 9f 15 1a .V..A..Vz..X....
+| 2992: bd 2e c6 ea b8 29 ae 13 19 a6 40 b0 8d ec 3a cd .....)....@...:.
+| 3008: ca 6b b4 d5 96 95 fe 8d 34 23 aa ab df c3 23 fa .k......4#....#.
+| 3024: c4 02 eb 10 8c f2 e8 e0 5f d4 e9 4a ae f4 8d 60 ........_..J...`
+| 3040: a9 1f 65 40 93 26 bf 1c 49 9d b6 8f e3 f1 c7 0b ..e@.&..I.......
+| 3056: a7 bb d1 ae 56 60 5c 80 d8 e0 e4 f0 72 62 45 b7 ....V`......rbE.
+| 3072: 31 33 66 a7 17 a4 34 67 f6 55 b1 09 eb 75 8f f0 13f...4g.U...u..
+| 3088: cd c1 86 e3 f5 3a e7 d8 08 da 4c a7 b4 45 8b ce .....:....L..E..
+| 3104: 9c 8d 48 41 b4 3e 6b 2d fb be c3 e7 bf 80 d3 29 ..HA.>k-.......)
+| 3120: 9f 8c 5d 7e 48 76 dc 95 cc 30 bf 9f e1 e0 dc c1 ..]~Hv...0......
+| 3136: da 9c 73 18 3c ff 53 49 88 dc ef 90 20 5f 3f 75 ..s.<.SI.... _?u
+| 3152: 85 02 0c d4 c3 f4 c1 ed f7 82 05 c4 e9 80 97 65 ...............e
+| 3168: 09 2a ac 52 c5 77 6c f4 6b 35 30 c2 fd 38 48 ae .*.R.wl.k50..8H.
+| 3184: b6 f6 38 0f 87 1a 66 54 91 3a 5b a7 48 5c 9d 36 ..8...fT.:[.H..6
+| 3200: e5 7f 60 4d 68 19 ff 8d 2e 6a 8a 99 37 72 11 f9 ..`Mh....j..7r..
+| 3216: 5b 29 77 3e 76 cd 57 6b 07 d0 cf d6 b4 cd d0 1e [)w>v.Wk........
+| 3232: dd 6e 1c a1 bd 7f bd 9d 57 0d 14 25 9e 4a 36 8c .n......W..%.J6.
+| 3248: 9f 7b b4 f9 db 57 22 f1 0b 47 e8 2e 04 70 e2 d6 .....W...G...p..
+| 3264: 29 0e bb 52 33 80 6b 12 a5 20 97 3b 60 01 a2 8c )..R3.k.. .;`...
+| 3280: 74 68 0f b1 b0 44 63 04 fe 69 2f 98 ee d9 e9 39 th...Dc..i/....9
+| 3296: af 0d 7a 79 00 ca d4 3e 96 e1 27 f8 27 e6 a7 d5 ..zy...>..'.'...
+| 3312: 0c 7d 0c 13 de 31 bd 75 cf 41 04 1f 03 bb df 1d .....1.u.A......
+| 3328: c7 c0 3b a8 15 d8 15 4b b5 89 ff 4c 16 31 7a 62 ..;....K...L.1zb
+| 3344: bb f8 d0 f2 43 fe 03 68 b0 35 7a 33 ae 4e a9 0b ....C..h.5z3.N..
+| 3360: 6a c8 35 d3 2c bf 6c 35 7b 1d 4c 9d 62 c1 96 01 j.5.,.l5..L.b...
+| 3376: cf 7f 5f f0 20 ce 16 25 32 bc b2 bb 29 7a 6c f5 .._. ..%2...)zl.
+| 3392: 36 17 6e 1b 93 4f 0f f0 de eb 67 a8 be 6a ad 7a 6.n..O....g..j.z
+| 3408: e6 42 1f 63 d2 de 72 1b f6 01 08 e8 72 d6 85 81 .B.c..r.....r...
+| 3424: 3d ec 80 70 f3 84 5c 54 2a 2d 66 f8 e9 ba d7 7c =..p...T*-f....|
+| 3440: af df 2a 43 f4 6c 78 3e 5d e6 92 b4 9f 02 05 bb ..*C.lx>].......
+| 3456: 84 9e ed 44 71 74 21 c9 be 07 3b 98 b1 49 b7 81 ...Dqt!...;..I..
+| 3472: 6a 4a c4 08 28 1c 19 0f ae 36 c2 6c a2 55 af 09 jJ..(....6.l.U..
+| 3488: 47 da e4 a8 32 df 4f 68 83 b1 c8 89 a0 1a e1 72 G...2.Oh.......r
+| 3504: b2 dd ab e9 fd 2f c8 79 d1 7e 69 16 e7 72 85 09 ...../.y.~i..r..
+| 3520: 95 77 18 1f 2c d1 51 31 68 88 8f 0a fb a1 4f 3b .w..,.Q1h.....O;
+| 3536: 6d fb 24 cc 0a 77 34 cb 49 35 06 07 a6 cd 5e 27 m.$..w4.I5....^'
+| 3552: d6 87 cc ae e1 00 cc 69 22 0e 4f 5a 59 cc 8f 30 .......i..OZY..0
+| 3568: c3 65 8f 8d bc 1a 86 8f 02 9b 0a 2c 5b b5 3d fa .e.........,[.=.
+| 3584: c9 fd 1c 96 4c 59 e1 ac 43 17 e8 b1 18 57 c8 48 ....LY..C....W.H
+| 3600: c7 df e9 d1 d3 11 d9 4b 44 33 d9 da 9d 86 7a cb .......KD3....z.
+| 3616: de 17 ce 40 aa b8 2d b6 26 a9 68 e8 72 f3 cb e0 ...@..-.&.h.r...
+| 3632: ae ec b1 1e 76 0b 5c 49 93 f5 f1 04 56 fa ac 33 ....v..I....V..3
+| 3648: 65 de d4 36 6b 3a 3c e1 a7 7b b6 66 e1 69 e7 86 e..6k:<....f.i..
+| 3664: c0 42 a2 71 e5 f1 35 3b 38 1e 52 a2 bb 72 39 de .B.q..5;8.R..r9.
+| 3680: e2 78 23 3a 71 b3 0b 8d 94 e5 26 80 9d d3 67 76 .x#:q.....&...gv
+| 3696: 14 aa 98 b4 f8 42 78 6c a1 8f 7a bd 5a 5f 99 1f .....Bxl..z.Z_..
+| 3712: 14 5a d4 02 bf c3 60 a7 c7 34 8f 81 4b 4a f6 c2 .Z....`..4..KJ..
+| 3728: 21 0e 6e 26 55 79 10 67 13 dc da ac 80 37 ad 95 !.n&Uy.g.....7..
+| 3744: 11 4a 54 b5 f9 da f6 66 26 99 51 98 1e 05 c0 5b .JT....f&.Q....[
+| 3760: 2d 23 b8 a2 5b de c3 f4 4f 2b 3a 22 10 1c 25 cc -#..[...O+:...%.
+| 3776: 57 db 91 c4 6c df 33 a1 1f d6 a3 2e 56 de 54 d1 W...l.3.....V.T.
+| 3792: 02 ac 2d ff 96 d6 db ec 80 f7 79 ea 81 30 68 d0 ..-.......y..0h.
+| 3808: 90 b2 d1 cc 5e ac 50 df 5e 1b 0a 78 01 70 e8 21 ....^.P.^..x.p.!
+| 3824: 35 08 64 46 9a 55 91 aa 9e 41 df 4f 5b 2b 3e 1c 5.dF.U...A.O[+>.
+| 3840: bc f5 90 37 d7 35 ac 34 8e 70 94 28 46 eb c8 42 ...7.5.4.p.(F..B
+| 3856: 10 df 40 b6 c0 76 57 6d 79 d6 f7 b6 cf ca 88 bc ..@..vWmy.......
+| 3872: f9 f6 ce ad 69 d8 a6 a7 41 cb cb c6 bf 91 ef ff ....i...A.......
+| 3888: 72 6f d2 b0 1e bf db 33 4b cd 1b 81 2d 65 de ff ro.....3K...-e..
+| 3904: 5c 4b 45 f0 57 c3 5e 1f 77 6d 14 b7 ea e4 8c 88 .KE.W.^.wm......
+| 3920: d0 b1 63 86 fc 68 26 e3 b2 7a 5f ca ec 09 00 4b ..c..h&..z_....K
+| 3936: dc f0 d4 70 fd c1 10 36 a9 cc fc 0d fd 24 12 13 ...p...6.....$..
+| 3952: d9 bd f0 2f 87 99 00 d1 d4 7c c6 41 f3 59 2a db .../.....|.A.Y*.
+| 3968: e1 7c 44 99 65 e7 4b 2f 42 a6 02 ad eb 7b db 14 .|D.e.K/B.......
+| 3984: e4 c7 0d bf a7 f1 3d 69 01 cc c0 2e 82 06 fe 13 ......=i........
+| 4000: a3 f2 df 3f fe 65 d6 73 b3 d1 48 0c 00 5f 6c 4e ...?.e.s..H.._lN
+| 4016: 1e ff f6 d2 69 08 a0 7a ed 50 16 a5 b1 56 1c f5 ....i..z.P...V..
+| 4032: 14 b0 b8 3a 38 19 a6 e7 ef 28 3d b9 9f 5e 38 39 ...:8....(=..^89
+| 4048: bc 41 c2 b1 fa 0b be 8b e9 9f 2f a0 be 8a eb 7f .A......../.....
+| 4064: eb 55 5e fb 3a 36 82 02 fd 50 a6 b2 7d fb e7 5a .U^.:6...P.....Z
+| 4080: a4 b2 d9 d9 8b 93 7a 2e ed c3 0c 13 68 22 cf f9 ......z.....h...
+| page 18 offset 69632
+| 0: 0d 00 00 00 01 04 3f 00 04 3f 00 00 00 00 00 00 ......?..?......
+| 1072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................
+| 1088: 3e 0a 06 00 ae 7c 00 00 18 91 e3 df f3 2f 7b 53 >....|......./.S
+| 1104: 6d 25 6e 2a df e7 b0 18 33 2f 73 08 d7 a8 04 75 m%n*....3/s....u
+| 1120: 49 89 b0 84 41 57 fb 8f 24 85 4e 24 c6 f1 14 03 I...AW..$.N$....
+| 1136: 9e 8e ef 9d f0 5c 54 69 11 78 d5 0f d6 97 22 1e ......Ti.x......
+| 1152: b5 17 73 66 0d 95 db ce c4 12 cb b0 ae a8 53 70 ..sf..........Sp
+| 1168: c7 6b 02 f6 7d 56 49 eb 11 75 da b6 c2 ba a1 f2 .k...VI..u......
+| 1184: 19 8d c3 fc 6f 9d 3e e8 0e 1a 51 37 d7 ff b1 19 ....o.>...Q7....
+| 1200: 50 bd a1 74 26 2b 53 c6 1e 12 75 20 ed 43 51 0e P..t&+S...u .CQ.
+| 1216: 28 f7 c4 a3 b5 8c ec de 2c 58 29 8c 74 81 d7 2d (.......,X).t..-
+| 1232: a2 8d 0a d3 85 98 6b f2 3e 34 94 08 73 06 e7 06 ......k.>4..s...
+| 1248: 04 e3 81 81 2a d8 5c 61 1b e9 7c ff 92 a8 c9 50 ....*..a..|....P
+| 1264: 97 a0 8e f6 1f 4b 25 ae 8e fa 84 7a 6f a7 11 42 .....K%....zo..B
+| 1280: c2 97 7a 93 42 39 ab 41 9f c1 7c 86 4a 66 06 cd ..z.B9.A..|.Jf..
+| 1296: e3 20 2c 3e ba f5 3c 32 fd a7 4a 73 50 74 a4 50 . ,>..<2..JsPt.P
+| 1312: 89 28 57 71 bc 3d 31 77 89 ef cd cd ff b4 fb 2c .(Wq.=1w.......,
+| 1328: 5f a0 55 da b0 d9 18 d4 f7 a3 e4 f0 bf a8 86 b8 _.U.............
+| 1344: 64 97 49 26 1b 4a b7 e7 6f 88 a9 a8 ab 54 1c 48 d.I&.J..o....T.H
+| 1360: 0c 77 2c e3 7a 83 7d 05 c8 22 f7 b7 57 92 61 97 .w,.z.......W.a.
+| 1376: 69 52 51 f7 8d 4c 2a b5 5e d5 55 f4 fc ae 35 bc iRQ..L*.^.U...5.
+| 1392: fa 44 c5 19 ec 62 5e 98 12 bf a8 e1 53 32 76 4c .D...b^.....S2vL
+| 1408: fb 4e 80 40 85 39 71 69 bd 55 90 9b 4c 46 b1 06 .N.@.9qi.U..LF..
+| 1424: 84 14 80 f3 2b ba 43 15 7e 12 44 4b 38 2e 01 a8 ....+.C.~.DK8...
+| 1440: 2e 58 11 e1 dd 6b 24 9e 6a fb 21 14 f5 ae be 7a .X...k$.j.!....z
+| 1456: 9b 26 0d a8 2f 29 8c 5a 63 8a cf 58 36 e1 76 fb .&../).Zc..X6.v.
+| 1472: ca 95 7a 0c 74 0d d5 57 04 a4 65 5f 2a 0d 46 ee ..z.t..W..e_*.F.
+| 1488: 0c 2e a6 a1 dd 04 b8 1d b7 72 a0 d5 ad cc 8e d3 .........r......
+| 1504: bb 04 bc 39 4d 22 0f 4e 6c b1 4d b4 08 3b 7f a5 ...9M..Nl.M..;..
+| 1520: f1 7d 18 c5 bf 43 86 b3 c1 3b 85 6f 30 84 1a 7b .....C...;.o0...
+| 1536: 17 d0 91 d3 6d 99 cc ff ac 64 88 53 d3 ad 1e 5f ....m....d.S..._
+| 1552: ba 4c af 64 80 ae ca c7 27 56 7e 41 02 61 f1 d2 .L.d....'V~A.a..
+| 1568: e4 4b 99 7c e4 18 41 9c f7 b9 e8 5a 3f 6e a3 57 .K.|..A....Z?n.W
+| 1584: ca 18 c5 8a a8 39 c6 fe 02 d0 9d 26 37 42 07 3d .....9.....&7B.=
+| 1600: 38 4e fe 9a 3b 54 39 20 23 53 8a 84 2f 4a 06 06 8N..;T9 #S../J..
+| 1616: ed 56 dd d8 bf 56 ef ca a5 c0 a4 aa d5 88 41 42 .V...V........AB
+| 1632: 8a c0 37 65 f3 c8 4c 87 a5 f3 3d 99 78 2b d7 4e ..7e..L...=.x+.N
+| 1648: d7 6e 51 28 3f 5c 93 cb 56 08 91 39 8e 1d fb 26 .nQ(?...V..9...&
+| 1664: 5d 80 7c 44 59 c4 d4 b3 5e 0c c1 3f 85 f8 d6 d0 ].|DY...^..?....
+| 1680: 25 0f a8 c4 40 a5 f7 63 ec 2b fc 78 e6 b4 7c 72 %...@..c.+.x..|r
+| 1696: 87 f0 6d 2c 00 63 dc 29 4a e5 b5 6b 9e 73 33 b4 ..m,.c.)J..k.s3.
+| 1712: 19 03 1a 5c de 8f 98 fa ce 4d e3 1a 62 6b 5b f5 .........M..bk[.
+| 1728: 60 d6 4c 13 39 14 06 83 90 09 56 8b 71 3b b9 bc `.L.9.....V.q;..
+| 1744: e3 7e 5e ae f5 3e b7 aa bd 73 d6 f1 47 4a 84 60 .~^..>...s..GJ.`
+| 1760: 20 d7 93 ce f0 f2 1a 63 b7 f0 7e 3b 4e 36 1c dd ......c..~;N6..
+| 1776: cc ef 50 7a a9 90 f7 48 05 fb 78 e8 72 71 df 3a ..Pz...H..x.rq.:
+| 1792: 41 51 2c 4c 5d 0f cd 51 0e f3 5a a1 e6 81 15 b3 AQ,L]..Q..Z.....
+| 1808: bb 48 5e 13 cf 46 4c f1 26 47 4b 51 87 d7 39 a6 .H^..FL.&GKQ..9.
+| 1824: 38 c5 72 52 55 97 f6 81 bc 0f a1 95 72 b8 ec 6d 8.rRU.......r..m
+| 1840: dd 6d 92 03 b5 0f d6 fd 7e 29 c9 55 50 57 71 2c .m......~).UPWq,
+| 1856: 34 35 21 75 6a 4e e6 f0 6a 99 b7 51 b5 3e 0a 6c 45!ujN..j..Q.>.l
+| 1872: 1b c0 ba cb 92 90 15 b8 35 b9 6b 78 f2 c6 03 48 ........5.kx...H
+| 1888: 66 d6 2e 75 47 b8 eb d0 30 48 c9 4d 67 d1 c1 8a f..uG...0H.Mg...
+| 1904: b2 9c a9 c0 3d a1 77 e3 35 e4 85 01 e7 dc 74 bc ....=.w.5.....t.
+| 1920: 8d ff f6 f0 ad e1 35 63 75 6d ee 28 53 29 1c 9c ......5cum.(S)..
+| 1936: 67 dd ea 7d 1f af 87 c3 2e 8d a4 23 d2 6b db 49 g..........#.k.I
+| 1952: 1a 36 10 7b e1 6c 9a 1c a2 5f 17 fb 43 e5 da f5 .6...l..._..C...
+| 1968: 2c 60 86 42 1d 28 a1 5f cc 73 b2 5d 69 2b fa 18 ,`.B.(._.s.]i+..
+| 1984: 85 a2 de 30 9a c7 08 42 b9 e3 b1 a1 32 1d 70 31 ...0...B....2.p1
+| 2000: b4 7a cf f4 57 5d 5e 45 53 1d 79 35 7b 4f 9a 2f .z..W]^ES.y5.O./
+| 2016: 80 11 76 23 60 dc 86 e7 f0 74 2d 46 51 40 01 10 ..v#`....t-FQ@..
+| 2032: 13 69 90 a9 fb cb 66 8e 3f e0 a1 4e 99 eb 61 1b .i....f.?..N..a.
+| 2048: fe c7 5e b5 f5 0f a3 46 64 19 09 11 c0 83 c7 28 ..^....Fd......(
+| 2064: 41 20 81 d3 f5 9c 21 2b ed 06 1a 4a 89 4d 6a e5 A ....!+...J.Mj.
+| 2080: 2d 4f 95 d7 3b 95 8c 59 6f 3e 79 51 5f ef b8 2a -O..;..Yo>yQ_..*
+| 2096: 43 ef 07 e2 d1 d1 13 38 67 54 88 e2 6f 03 fe 05 C......8gT..o...
+| 2112: 10 0e e8 e9 4e 9a 75 92 ec 1f e7 56 61 3b 54 43 ....N.u....Va;TC
+| 2128: 08 af e9 d5 56 bc 87 a3 25 6f e2 b8 01 62 1a 30 ....V...%o...b.0
+| 2144: ba 26 8a b1 9a 7e 44 a2 f5 d4 75 2e a0 d0 b8 71 .&...~D...u....q
+| 2160: 61 61 92 ff 32 0b a8 94 a5 81 80 d0 3b b5 51 4a aa..2.......;.QJ
+| 2176: 01 e2 8e 0a 38 90 19 f7 b4 38 b0 9c 32 e1 6a f0 ....8....8..2.j.
+| 2192: f8 7b f0 58 0a d1 19 c0 20 d6 54 fe 28 ac 02 64 ...X.... .T.(..d
+| 2208: c4 33 55 01 d2 bd 01 51 87 01 0c 66 bb 6e 1b 94 .3U....Q...f.n..
+| 2224: 9c 24 50 40 5b 2f 64 f9 b5 b6 6b 15 fd f8 e7 05 .$P@[/d...k.....
+| 2240: 37 92 95 d3 b4 1e be b3 09 c0 74 f8 ca 03 10 89 7.........t.....
+| 2256: 2d 4d f5 56 0f 6e 20 72 a7 5e 1d 9f fd d5 43 af -M.V.n r.^....C.
+| 2272: 2e 7b f7 91 99 ed 47 ea c7 a4 76 82 ca 5f 94 20 ......G...v.._.
+| 2288: 52 01 b4 21 cb 50 d5 f2 d6 cf 1d 11 0f b2 07 ee R..!.P..........
+| 2304: f2 cf 2b 52 7b 1d e0 be 16 a1 cf 06 52 1b 33 f5 ..+R........R.3.
+| 2320: c2 8e ac f1 00 2b 82 cf b4 ae d5 f0 9b 4b 11 14 .....+.......K..
+| 2336: b5 c5 43 f4 08 9d 4a 59 ba a6 52 67 fe e1 bd 2d ..C...JY..Rg...-
+| 2352: c2 40 c6 3e d1 8a d1 f5 a0 b4 d0 b1 92 3f 9e 1d .@.>.........?..
+| 2368: 18 5e b4 78 30 45 57 29 30 e1 5a bb ee 7b 1e 99 .^.x0EW)0.Z.....
+| 2384: 0d 10 ea 14 7b 5e 36 32 8e e1 a7 e4 76 19 48 a8 .....^62....v.H.
+| 2400: c6 19 74 b9 4e 31 81 24 fe 07 e3 86 ec c4 1d 05 ..t.N1.$........
+| 2416: 1f 5a 52 14 0c 08 3f d1 93 fe b1 46 27 87 58 21 .ZR...?....F'.X!
+| 2432: 4b d5 ff bb 98 d8 f8 0c 96 66 02 9c 86 f9 0e 0b K........f......
+| 2448: f0 11 7a 99 39 52 38 84 22 04 58 07 f1 95 eb c7 ..z.9R8...X.....
+| 2464: 44 2e a5 fe d4 68 a9 98 77 14 4f 8a 44 4c 7d c4 D....h..w.O.DL..
+| 2480: 49 8a d7 89 83 8e e6 1e d0 af b7 41 3d 1a 85 14 I..........A=...
+| 2496: ec 3a e5 1b 2c c5 17 77 85 82 19 57 37 94 93 7e .:..,..w...W7..~
+| 2512: 52 16 a3 dd 0a fd 57 1a 57 32 11 4d 71 e3 4b 1b R.....W.W2.Mq.K.
+| 2528: c5 02 d7 89 74 85 b0 3d 8d 7b 53 a2 d6 60 99 d4 ....t..=..S..`..
+| 2544: ce f0 1c 3d a3 aa db db c4 80 38 7a cb 12 7e 66 ...=......8z..~f
+| 2560: 3f 69 af fa 57 49 35 05 94 33 df fe 91 8a 25 3d ?i..WI5..3....%=
+| 2576: 9b 32 71 72 d2 bc bc 23 61 69 9c 68 a7 58 c0 f1 .2qr...#ai.h.X..
+| 2592: 0e 20 a9 d3 d2 a9 11 d7 ee 52 46 70 b7 aa 6b f3 . .......RFp..k.
+| 2608: 4a 51 a7 a5 26 92 35 44 f9 cc 7b c7 ec db 5d b6 JQ..&.5D......].
+| 2624: 5c 88 d9 bd 14 df a0 14 35 09 2f c8 76 d4 4c 19 ........5./.v.L.
+| 2640: 12 29 b9 dd 9b 21 ed b8 ee 1f f9 38 05 9e 93 aa .)...!.....8....
+| 2656: ab 82 15 69 88 81 f6 4f 1b 72 bb 84 cb 9c 33 ec ...i...O.r....3.
+| 2672: 94 4d 44 42 8e 8f 12 91 1f 32 07 09 38 8b 44 be .MDB.....2..8.D.
+| 2688: 9e 31 49 9e 76 04 d8 b7 69 ad f1 59 81 5f d7 a0 .1I.v...i..Y._..
+| 2704: 2f 34 94 27 b4 c1 e9 f0 18 a7 43 7e 1e fd 27 5b /4.'......C~..'[
+| 2720: d8 e9 c3 5d be 8f 91 f2 4a cd 33 5f 6c 76 f6 f1 ...]....J.3_lv..
+| 2736: 17 ae 80 87 e7 ec 22 ef 73 8e a7 3a 30 dd 27 3d ........s..:0.'=
+| 2752: 6d 95 59 eb f3 7f 97 b7 b9 8d ff 86 ed dd 5d f4 m.Y...........].
+| 2768: 39 3c 6a 13 3d 7a 93 3d 37 ed 8c d6 98 0f 0b 7a 9.....p..$o.....
+| 3040: e1 6a a9 0a d8 f6 89 09 51 98 1f 89 1b f1 34 87 .j......Q.....4.
+| 3056: a5 b3 22 d0 65 53 bd ae 57 7a 8a 8f a8 a6 10 9e ....eS..Wz......
+| 3072: 72 7c 6e 37 8f 67 db d8 89 54 77 87 6d 63 6e 31 r|n7.g...Tw.mcn1
+| 3088: ef ae 41 51 22 cc 24 08 89 f6 dd 2c f9 cb a4 f8 ..AQ..$....,....
+| 3104: ea f9 42 33 01 fd cf b9 d6 73 aa b4 9d 45 31 eb ..B3.....s...E1.
+| 3120: 42 ca df 3a d2 3c c9 41 28 fd e4 a2 2f cf bf ca B..:.<.A(.../...
+| 3136: 63 94 a2 74 ee 6b 4c 62 bb 74 5f cc 39 68 b5 e9 c..t.kLb.t_.9h..
+| 3152: 68 47 90 45 85 f0 20 4e 3a fe 4a 4f ab f2 fe c7 hG.E.. N:.JO....
+| 3168: f5 23 56 6e 09 9e c6 3d 36 30 82 62 6f 5f 78 f6 .#Vn...=60.bo_x.
+| 3184: f6 07 58 e8 fd 98 09 e5 a5 5b 65 27 43 e6 9e 3d ..X......[e'C..=
+| 3200: 98 d5 db 1d 09 35 48 b0 cd 5e 53 a1 d6 b2 4f 85 .....5H..^S...O.
+| 3216: e5 4d 80 18 8f 78 6e a0 0e 35 08 7d 1d 5d 3e ab .M...xn..5...]>.
+| 3232: c3 5c dc ec c9 e0 22 1a 17 a3 80 40 3d e7 66 df ...........@=.f.
+| 3248: b2 38 f4 59 6d 20 e8 83 93 53 8c ac 52 26 ec 60 .8.Ym ...S..R&.`
+| 3264: f8 50 85 1c 97 9c ae a3 9f bd af 75 be 73 23 b5 .P.........u.s#.
+| 3280: 7f fa 1f 7f 28 16 c7 7c 5f 0a 5b 32 1a c8 45 cf ....(..|_.[2..E.
+| 3296: df 2e 8e d1 d9 59 76 d5 6c 8d b5 12 8a c5 77 32 .....Yv.l.....w2
+| 3312: d4 87 02 80 09 b6 43 34 76 09 f9 b4 74 66 ce ee ......C4v...tf..
+| 3328: 26 77 62 11 b0 23 92 5c 72 38 41 e9 70 4f b5 83 &wb..#..r8A.pO..
+| 3344: e4 35 7c b2 2a 38 49 12 48 18 1c 95 5c b1 18 1a .5|.*8I.H.......
+| 3360: 51 cd 4b 7b 22 94 0e c7 da c1 30 97 d1 be 42 07 Q.K.......0...B.
+| 3376: 94 01 a5 fd 2f 0d 2c 53 33 c0 91 c6 bc af 2c f2 ..../.,S3.....,.
+| 3392: f2 07 6e 4a d2 22 3e 3c 18 3c ca 24 bf 42 78 7a ..nJ..><.<.$.Bxz
+| 3408: 69 0e a9 12 e3 20 fa 8b ad 75 27 0c c3 82 84 8d i.... ...u'.....
+| 3424: 46 af 3e 1e 89 27 4d 7e f7 21 96 b4 6c 17 7f 19 F.>..'M~.!..l...
+| 3440: 8a 78 d7 bb 40 67 35 45 2d d4 97 6a 4c e9 4a 58 .x..@g5E-..jL.JX
+| 3456: 22 a3 bb 31 d5 4f 26 40 cc fe c8 cd 1d a4 0d 67 ...1.O&@.......g
+| 3472: 14 13 05 4d 0e 15 40 ea 7d 62 c6 80 08 b9 f6 b2 ...M..@..b......
+| 3488: 44 58 66 d5 ca b6 f4 20 b0 4a b8 37 64 3d b0 a7 DXf.... .J.7d=..
+| 3504: a7 87 70 26 b2 ea f9 cf 98 03 6e 63 5a fe c4 cd ..p&......ncZ...
+| 3520: 80 cb ca f4 a6 02 11 39 4f 6c bf bf a4 8e 99 32 .......9Ol.....2
+| 3536: e3 47 51 3e 85 f6 84 6b 3d 9a fe 2f 96 18 49 2a .GQ>...k=../..I*
+| 3552: dc a4 56 77 d1 3f 94 61 2b 58 e7 74 ee c9 16 7b ..Vw.?.a+X.t....
+| 3568: 6f 76 47 da b2 fb 89 75 80 78 05 69 c8 3e f0 97 ovG....u.x.i.>..
+| 3584: 1b 40 f1 48 43 7f cd 0b b1 c6 cf 59 73 4f 3f 33 .@.HC......YsO?3
+| 3600: 2e 32 d2 b6 69 fc 6b f2 20 0f 12 bf f0 98 2e e2 .2..i.k. .......
+| 3616: 4f ed 80 27 00 e2 b1 c2 ca cd 6b de e1 b4 af 9e O..'......k.....
+| 3632: df 4f d2 da 6d 9f b4 5d 99 4a c4 59 d4 e1 98 05 .O..m..].J.Y....
+| 3648: 68 00 a5 72 3f 0e 35 29 59 81 8a f9 f2 c0 5a de h..r?.5)Y.....Z.
+| 3664: 25 35 d5 60 03 f7 0f 20 3a bb a6 45 fc cc 2d e9 %5.`... :..E..-.
+| 3680: fe 37 0b 6c f2 96 19 dc 39 62 6e f7 9c 17 37 8c .7.l....9bn...7.
+| 3696: 8a dd 62 a2 a3 e6 b8 a0 cd 61 f5 27 3b 29 e2 f4 ..b......a.';)..
+| 3712: 0a 06 21 c3 b9 8e 70 34 59 ca d9 a1 92 db a9 74 ..!...p4Y......t
+| 3728: d1 7c a1 ef 64 c2 75 51 02 b3 6a 57 6d 12 f6 eb .|..d.uQ..jWm...
+| 3744: 3b 41 ce a5 ca 69 62 3e c3 55 eb 1c 80 01 79 05 ;A...ib>.U....y.
+| 3760: a4 51 7c 45 00 76 41 5e 57 1a 88 aa 15 c8 42 82 .Q|E.vA^W.....B.
+| 3776: d5 83 74 97 93 b4 28 df 4d 82 7d 6f ef 6a d4 e4 ..t...(.M..o.j..
+| 3792: 03 e7 20 4a e8 84 54 0c 6e 5f 8e b0 d1 0d 67 aa .. J..T.n_....g.
+| 3808: f9 20 21 ea c0 4e 5c e3 f8 65 d7 67 0a 7a e0 0b . !..N...e.g.z..
+| 3824: d8 1e 53 95 bf 24 39 12 d4 30 8c 2c b4 13 2e bd ..S..$9..0.,....
+| 3840: f8 81 d5 15 35 d7 3f f2 23 a4 2c 1b cd 29 e8 88 ....5.?.#.,..)..
+| 3856: a8 f1 cc 3f 9b 72 d0 8e c0 cb 80 ca c9 68 1a ca ...?.r.......h..
+| 3872: 38 09 59 e5 a6 33 95 57 55 c9 dd c4 8a 8d 36 e5 8.Y..3.WU.....6.
+| 3888: 0c 40 95 77 63 4b 82 53 98 d0 bd cd 57 b6 f7 2b .@.wcK.S....W..+
+| 3904: fe 1c 25 d4 95 3d 4c 63 b7 fb 94 37 3f 6d 96 28 ..%..=Lc...7?m.(
+| 3920: 1d 13 76 d2 ab 9a 7e 8f f5 a2 e6 15 0b 1c 10 14 ..v...~.........
+| 3936: c3 b5 c0 1c 52 af 2a 32 35 05 4a 0c f1 cb ed 5e ....R.*25.J....^
+| 3952: 42 6c 31 8b dc 78 4b 68 5a b7 0f e3 6c d6 da e6 Bl1..xKhZ...l...
+| 3968: 59 f3 34 43 47 1c 2b f6 f4 eb 6e 12 4d 60 f4 d9 Y.4CG.+...n.M`..
+| 3984: 39 2f 84 a5 8f f0 03 e7 ce b6 10 d0 a9 f9 69 76 9/............iv
+| 4000: 94 29 2e 60 db fc e7 5f e6 c5 5b b9 c5 a7 1f 95 .).`..._..[.....
+| 4016: 0d 66 aa 55 7b f5 ec 67 c6 f7 26 52 c4 02 60 31 .f.U...g..&R..`1
+| 4032: 7d 5e de ba 06 2f 09 1d a1 db 61 83 c8 13 be 98 .^.../....a.....
+| 4048: 14 9d c9 15 1e 33 04 de a5 53 ed 42 ab 45 b1 f3 .....3...S.B.E..
+| 4064: 09 a7 47 54 14 bc a0 88 80 58 94 0a 78 f2 31 3d ..GT.....X..x.1=
+| 4080: bc 0d 85 bf da a0 7e d2 be e4 1c cc b4 45 a8 bd ......~......E..
+| page 19 offset 73728
+| 0: 0d 0f e6 00 03 0c 8a 00 0c 8a 0f ec 0c 94 00 00 ................
+| 3200: 00 00 00 00 00 00 00 00 00 00 08 01 03 00 16 2e ................
+| 3216: b1 7d 24 24 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 01 01 34 00 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 3d ......0000000..=
+| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
+| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 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 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............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 07 65 ebug...........e
+| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 d3 02 01 02 nable...........
+| 3456: 02 01 02 02 02 02 02 01 02 02 01 02 02 01 02 02 ................
+| 3472: 01 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 67 63 63 01 02 54 01 02 03 01 02 03 ....gcc..T......
+| 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 6e 31 13 02 03 01 02 03 01 02 ...json1........
+| 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 13 06 01 02 02 03 06 01 02 02 03 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 02 02 03 06 ..im............
+| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
+| 3792: 02 01 f3 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 08 ................
+| 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 06 01 01 02 01 ................
+| 3904: 06 01 01 02 01 06 01 01 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 ad 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 01 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 0e fc 0e 11 10 0f 0e 10 0f .D...G..........
+| 4064: 44 0f 10 40 15 0f 00 00 00 06 14 24 12 0a 03 00 D..@.......$....
+| 4080: 2a 00 00 00 00 01 02 08 00 02 01 01 01 02 01 07 *...............
+| page 20 offset 77824
+| 0: 0d 00 00 00 01 00 22 00 00 22 00 00 00 00 00 00 ................
+| 32: 00 00 9f 56 88 80 80 80 80 01 04 00 bf 30 00 00 ...V.........0..
+| 48: 0e 9c 02 30 30 01 0c 74 81 44 06 81 0b 01 0a 81 ...00..t.D......
+| 64: 03 58 58 04 01 10 82 66 10 0f 0b 81 14 24 01 0c .XX....f.....$..
+| 80: 81 14 47 4a 20 6e 01 0e 71 81 41 05 82 0f 03 01 ..GJ n..q.A.....
+| 96: 0c 53 54 4c 2c 70 7d 01 12 81 43 06 1e 37 42 37 .STL,p....C..7B7
+| 112: 77 3e 01 14 81 22 07 81 30 81 5d 03 05 0d 01 08 w>......0.].....
+| 128: 82 01 81 21 01 0e 81 45 54 51 81 0a 61 02 01 30 ...!...ETQ..a..0
+| 144: 01 04 82 6e 02 01 36 08 04 83 7e 02 01 38 02 04 ...n..6...~..8..
+| 160: 83 4f 02 01 62 06 04 81 11 03 01 36 08 04 81 5b .O..b......6...[
+| 176: 03 01 64 02 04 84 5d 02 01 63 05 04 81 02 02 01 ..d...]..c......
+| 192: 64 07 04 81 67 02 01 65 0a 04 83 0c 03 02 70 77 d...g..e......pw
+| 208: 04 04 83 70 02 02 66 79 08 04 82 25 02 01 68 0a ...p..fy...%..h.
+| 224: 04 81 34 02 01 6b 03 02 4d 03 04 84 32 02 01 70 ..4..k..M...2..p
+| 240: 01 04 81 15 02 01 73 07 04 83 4d 02 02 37 02 01 ......s...M..7..
+| 256: 74 02 02 40 03 01 68 07 04 83 45 02 02 76 69 09 t..@..h...E..vi.
+| 272: 04 82 66 03 01 6c 09 04 82 34 02 01 79 01 04 84 ..f..l...4..y...
+| 288: 13 02 02 c2 ba 0a 04 81 68 03 01 bc 0a 04 83 0d ........h.......
+| 304: 02 04 ca 80 69 6c 09 04 81 5a 02 02 d3 84 05 04 ....il...Z......
+| 320: 83 0a 01 01 31 01 16 18 1a 30 81 4c 31 12 54 81 ....1....0.L1.T.
+| 336: 00 1d 01 0e 02 25 82 4b 1d 3f 76 01 0c 43 79 4b .....%.K.?v..CyK
+| 352: 5b 0b 76 01 0e 35 1a 81 08 82 77 10 01 0c 81 24 [.v..5....w....$
+| 368: 18 07 74 6f 01 08 29 81 08 69 01 10 81 0e 0d 4a ..to..)..i.....J
+| 384: 81 01 07 58 01 08 6b 51 76 7a 01 0c 20 81 18 6c ...X..kQvz.. ..l
+| 400: 2c 18 01 08 83 7c 7b 0e 02 01 32 08 02 48 03 04 ,....|....2..H..
+| 416: f3 a1 97 a5 03 04 83 71 02 01 33 02 04 81 2f 03 .......q..3.../.
+| 432: 01 66 09 04 83 15 02 03 61 ca b1 08 04 81 48 02 .f......a.....H.
+| 448: 01 63 01 02 1c 02 03 65 c2 aa 06 02 5a 02 01 68 .c.....e....Z..h
+| 464: 03 04 81 6e 02 01 69 0a 04 82 5a 03 01 69 08 04 ...n..i...Z..i..
+| 480: 81 65 02 01 6a 02 02 64 06 04 84 12 02 01 6c 01 .e..j..d......l.
+| 496: 02 1f 02 01 6e 03 04 83 24 02 03 6f c2 b3 07 04 ....n...$..o....
+| 512: 84 52 02 03 72 c9 9b 04 04 82 6e 02 01 73 07 04 .R..r.....n..s..
+| 528: 82 10 02 01 77 0a 02 31 02 01 79 07 04 81 7f 02 ....w..1..y.....
+| 544: 02 7a 62 09 04 83 49 02 02 c2 b9 02 04 83 01 03 .zb...I.........
+| 560: 02 bd 75 09 04 83 45 02 02 c6 aa 02 04 83 08 02 ..u...E.........
+| 576: 03 d7 92 6a 08 02 04 01 01 32 01 0c 81 7d 72 81 ...j.....2....r.
+| 592: 4e 36 01 0e 1a 81 10 81 10 11 2e 01 08 78 49 82 N6...........xI.
+| 608: 3b 01 0e 73 81 64 05 1b 81 69 01 1a 18 06 7e 2c ;..s.d...i....~,
+| 624: 21 12 20 5a 28 69 06 1e 06 01 0c 81 48 05 31 81 !. Z(i......H.1.
+| 640: 24 01 14 25 81 42 3e 81 16 81 37 13 13 01 0c 21 $..%.B>...7....!
+| 656: 0d 0f 3e 82 03 01 08 6b 60 81 27 01 10 2d 81 41 ..>....k`.'..-.A
+| 672: 06 69 81 08 30 02 01 32 03 04 81 01 02 01 33 08 .i..0..2......3.
+| 688: 02 3c 02 01 35 0a 04 84 64 02 01 38 05 04 83 41 .<..5...d..8...A
+| 704: 02 02 61 69 09 04 82 49 02 03 66 c8 ab 09 04 82 ..ai...I..f.....
+| 720: 68 02 01 68 04 04 83 27 02 01 6c 04 04 84 18 03 h..h...'..l.....
+| 736: 02 72 6e 06 04 82 30 02 01 6e 04 04 84 55 03 01 .rn...0..n...U..
+| 752: 6d 05 04 83 30 03 03 76 c2 bd 09 02 57 02 01 71 m...0..v....W..q
+| 768: 02 04 84 22 03 04 84 11 03 05 72 f0 92 bc bc 0a ..........r.....
+| 784: 04 82 40 02 01 72 04 04 83 5b 02 01 73 05 02 6f ..@..r...[..s..o
+| 800: 03 04 83 6f 02 01 75 04 02 55 02 01 78 03 04 82 ...o..u..U..x...
+| 816: 56 02 01 7a 06 04 85 01 03 02 25 02 02 c2 b2 07 V..z......%.....
+| 832: 04 83 7a 03 03 b3 ce bc 03 04 84 2b 03 03 bc c2 ..z........+....
+| 848: b2 09 04 83 53 02 04 ce a2 38 6e 07 04 82 23 03 ....S....8n...#.
+| 864: 01 bc 08 04 83 7f 02 03 d2 b7 69 0a 04 84 19 02 ..........i.....
+| 880: 02 d6 84 09 04 81 0e 01 01 33 01 06 2a 83 69 01 .........3..*.i.
+| 896: 18 0f 0e 25 42 81 71 81 21 17 07 03 0d 01 1a 15 ...%B.q.!.......
+| 912: 13 42 03 81 40 45 21 60 4d 1a 04 0e 01 0a 83 18 .B..@E!`M.......
+| 928: 81 11 0a 01 08 64 83 24 24 01 16 62 1d 0c 06 62 .....d.$$..b...b
+| 944: 50 2c 73 17 15 4d 01 0e 1b 82 15 4d 31 3a 4f 01 P,s..M.....M1:O.
+| 960: 0e 22 63 51 81 7f 81 22 01 0e 21 81 0a 3e 42 82 ..cQ......!..>B.
+| 976: 08 01 12 05 82 0a 33 19 10 81 37 63 02 01 32 05 ......3...7c..2.
+| 992: 04 82 3c 02 01 36 02 04 84 0f 02 01 38 06 04 84 ..<..6......8...
+| 1008: 1f 02 01 39 06 04 82 06 02 01 61 08 04 81 00 03 ...9......a.....
+| 1024: 03 33 6f 62 01 02 69 02 01 65 02 04 84 05 07 04 .3ob..i..e......
+| 1040: 84 0e 02 01 67 09 04 82 44 02 01 6a 07 02 55 02 ....g...D..j..U.
+| 1056: 01 6b 02 04 84 04 07 04 84 44 02 01 6c 06 04 84 .k.......D..l...
+| 1072: 0d 02 01 6e 06 04 84 10 03 01 77 03 02 46 02 01 ...n......w..F..
+| 1088: 74 08 04 83 33 03 01 77 03 04 81 5b 02 01 75 0a t...3..w...[..u.
+| 1104: 04 81 75 02 01 78 01 04 83 48 03 02 c2 b2 02 04 ..u..x...H......
+| 1120: 81 77 02 04 c2 b3 c2 b3 09 02 1b 02 06 f2 98 9e .w..............
+| 1136: a2 61 6c 08 04 83 31 01 01 34 01 0e 81 1c 82 11 .al...1..4......
+| 1152: 4e 81 06 01 10 4a 12 64 39 18 81 24 72 01 04 81 N....J.d9..$r...
+| 1168: 0b 01 10 81 08 81 50 48 2a 79 15 01 14 13 72 07 ......PH*y....r.
+| 1184: 2f 42 81 21 50 81 02 01 10 6d 46 3e 81 0c 81 17 /B.!P....mF>....
+| 1200: 23 01 08 0a 5f 83 38 01 0a 57 81 3e 82 0f 01 10 #..._.8..W.>....
+| 1216: 81 07 81 7e 0c 81 14 1d 01 08 1f 82 42 4e 02 01 ...~........BN..
+| 1232: 30 01 04 81 36 04 04 81 39 03 02 c2 bd 02 04 81 0...6...9.......
+| 1248: 1e 02 01 31 05 04 84 31 02 01 35 0a 04 81 2b 02 ...1...1..5...+.
+| 1264: 06 37 c2 b9 eb a0 86 04 04 83 0d 02 02 61 6f 04 .7...........ao.
+| 1280: 04 83 39 02 01 63 07 04 83 3c 03 01 67 0a 04 84 ..9..c...<..g...
+| 1296: 6a 02 01 65 07 06 68 82 7d 02 03 66 c2 be 07 04 j..e..h....f....
+| 1312: 81 3d 02 01 67 08 02 58 01 04 83 16 02 01 6c 03 .=..g..X......l.
+| 1328: 04 81 73 02 01 6d 08 04 81 42 02 01 6e 04 04 83 ..s..m...B..n...
+| 1344: 75 02 03 6f 65 32 06 04 84 4f 02 01 70 05 04 81 u..oe2...O..p...
+| 1360: 56 03 01 77 09 04 81 47 02 02 72 32 05 02 0b 02 V..w...G..r2....
+| 1376: 01 73 01 02 47 04 04 84 09 02 01 74 07 04 85 05 .s..G......t....
+| 1392: 02 01 75 01 02 5b 02 04 76 e5 b9 83 07 04 82 03 ..u..[..v.......
+| 1408: 02 01 78 01 04 81 11 02 02 c6 bf 02 04 81 3b 02 ..x...........;.
+| 1424: 02 ce bc 06 04 84 3a 02 03 e1 83 93 03 04 81 2b ......:........+
+| 1440: 01 01 35 01 0e 81 7b 61 23 71 55 0c 01 08 82 30 ..5....a#qU....0
+| 1456: 2a 7b 01 0c 81 45 81 20 72 38 01 0c 29 82 25 55 *....E. r8..).%U
+| 1472: 4c 21 01 0c 81 53 38 25 3a 63 01 08 83 55 81 0f L!...S8%:c...U..
+| 1488: 01 0e 81 32 5b 81 1b 31 6f 01 16 1e 6d 17 0e 17 ...2[..1o...m...
+| 1504: 1f 6b 0b 3e 3d 3a 01 12 32 81 4a 81 04 55 47 20 .k.>=:..2.J..UG
+| 1520: 09 01 10 82 4b 81 0a 17 3e 05 2a 02 01 31 08 04 ....K...>.*..1..
+| 1536: 84 04 02 02 36 68 06 02 18 02 01 61 02 04 84 3d ....6h.....a...=
+| 1552: 08 04 81 38 03 01 34 01 02 71 02 03 63 75 6d 0a ...8..4..q..cum.
+| 1568: 04 81 3a 02 01 64 09 02 52 01 04 82 48 02 01 68 ..:..d..R...H..h
+| 1584: 08 02 30 02 04 83 4e 02 01 6e 01 02 42 02 05 6f ..0...N..n..B..o
+| 1600: 63 6c dc ab 08 02 11 03 04 67 69 c2 be 03 04 82 cl.......gi.....
+| 1616: 29 02 01 71 07 04 82 12 02 01 79 06 04 84 1b 02 )..q......y.....
+| 1632: 02 7a 33 09 04 83 4c 02 02 c2 b2 05 04 84 17 03 .z3...L.........
+| 1648: 01 b9 09 02 35 04 02 6b 78 0a 04 81 31 03 01 bc ....5..kx...1...
+| 1664: 0a 02 41 02 08 cb 8a f0 9c bb a1 67 68 02 04 81 ..A........gh...
+| 1680: 75 01 01 36 01 10 55 77 30 36 21 31 69 60 01 0e u..6..Uw06!1i`..
+| 1696: 3b 0b 3e 4e 1c 2c 1b 01 16 44 32 54 07 2f 0e 81 ;.>N.,...D2T./..
+| 1712: 11 81 03 14 01 04 81 63 01 0e 81 16 82 5c 15 20 .......c.......
+| 1728: 19 01 12 0d 1f 43 6e 39 06 18 81 54 01 0c 81 40 .....Cn9...T...@
+| 1744: 2c 81 0f 4d 01 10 16 82 5e 0e 08 0d 78 51 01 12 ,..M....^...xQ..
+| 1760: 1d 81 73 81 22 29 17 66 1a 01 0a 81 3f 81 3f 19 ..s..).f....?.?.
+| 1776: 02 01 30 0a 04 83 47 03 01 6d 05 04 82 3e 02 01 ..0...G..m...>..
+| 1792: 32 07 04 81 5e 03 04 82 19 02 04 34 71 6c 38 01 2...^......4ql8.
+| 1808: 04 83 6b 02 02 37 67 08 04 84 53 02 01 64 04 02 ..k..7g...S..d..
+| 1824: 7b 03 01 71 02 04 81 71 02 01 65 01 04 83 66 05 ...q...q..e...f.
+| 1840: 04 84 5c 02 01 69 09 04 81 3a 02 01 6a 03 04 83 .....i...:..j...
+| 1856: 35 02 01 6b 06 04 83 6d 01 04 83 5f 02 04 84 0f 5..k...m..._....
+| 1872: 02 01 73 03 04 83 2d 02 01 74 06 04 84 0e 02 04 ..s...-..t......
+| 1888: 82 02 02 01 75 05 04 83 73 03 01 37 03 04 84 32 ....u...s..7...2
+| 1904: 02 01 76 03 04 83 0f 02 01 77 08 04 82 33 03 01 ..v......w...3..
+| 1920: 6f 01 02 0b 02 01 78 02 02 36 02 02 c2 b3 03 04 o.....x..6......
+| 1936: 81 07 02 04 84 29 02 02 ca a9 05 04 83 19 02 03 .....)..........
+| 1952: ce bc 79 08 04 84 4b 02 02 d0 b8 05 04 81 06 02 ..y...K.........
+| 1968: 06 f1 b5 87 92 35 6b 05 04 82 34 01 01 37 01 14 .....5k...4..7..
+| 1984: 81 3d 4b 17 08 16 81 03 81 20 01 0e 42 81 27 32 .=K...... ..B.'2
+| 2000: 20 0c 7a 01 0a 4c 83 12 40 19 01 16 06 21 6f 81 .z..L..@....!o.
+| 2016: 02 70 36 0d 49 2e 2d 01 14 81 12 19 19 60 06 4c .p6.I.-......`.L
+| 2032: 44 17 4f 01 12 03 81 12 04 81 23 81 4b 0a 01 12 D.O.......#.K...
+| 2048: 0b 48 50 22 10 7f 81 38 56 01 0e 27 38 81 21 82 .HP....8V..'8.!.
+| 2064: 08 2a 01 08 81 6b 41 24 01 0c 81 7c 73 81 3e 05 .*...kA$...|s.>.
+| 2080: 02 02 34 67 05 04 83 5d 02 01 37 05 04 81 2f 02 ..4g...]..7.../.
+| 2096: 02 73 02 01 38 01 02 21 02 01 39 09 02 4a 02 01 .s..8..!..9..J..
+| 2112: 62 0a 02 70 03 02 71 7a 01 04 83 26 02 01 64 0a b..p..qz...&..d.
+| 2128: 04 84 04 02 01 65 0a 02 78 02 01 68 02 04 82 26 .....e..x..h...&
+| 2144: 02 02 69 35 06 04 82 02 02 01 6b 02 04 82 0a 03 ..i5......k.....
+| 2160: 02 c2 bc 05 04 82 08 02 01 6d 08 02 54 02 01 6e .........m..T..n
+| 2176: 06 04 82 32 02 03 6f 74 61 02 04 81 2a 02 05 71 ...2..ota...*..q
+| 2192: f2 96 8c 90 01 04 83 5a 02 01 72 09 04 83 31 02 .......Z..r...1.
+| 2208: 01 74 03 02 71 04 04 83 62 02 02 79 65 04 04 83 .t..q...b..ye...
+| 2224: 26 02 02 c2 aa 05 04 82 19 03 01 b3 02 02 10 02 &...............
+| 2240: 04 83 48 03 01 bd 01 04 84 10 02 02 cf ad 06 04 ..H.............
+| 2256: 82 04 02 04 f0 97 97 98 08 04 83 1f 02 04 f3 a5 ................
+| 2272: b3 87 08 04 81 64 01 01 38 01 0a 16 82 49 81 30 .....d..8....I.0
+| 2288: 01 0e 81 19 27 34 53 82 19 01 12 20 1f 5c 5f 81 ....'4S.... .._.
+| 2304: 50 81 17 04 01 10 0e 81 2e 2d 51 67 81 16 01 0c P........-Qg....
+| 2320: 81 62 09 81 79 10 01 08 63 04 81 1c 01 0a 81 2e .b..y...c.......
+| 2336: 5d 81 0f 01 0a 0b 81 40 81 63 01 10 27 81 17 81 ]......@.c..'...
+| 2352: 2b 48 6c 4c 01 10 81 23 4d 64 0a 7f 81 01 02 01 +HlL...#Md......
+| 2368: 31 03 02 6b 02 01 36 06 04 83 79 02 01 37 08 04 1..k..6...y..7..
+| 2384: 84 47 02 04 39 c2 bc 61 09 04 84 61 02 05 64 c2 .G..9..a...a..d.
+| 2400: b9 da 9c 01 04 81 73 02 01 66 01 04 81 58 08 04 ......s..f...X..
+| 2416: 82 39 02 02 67 74 0a 04 81 5f 02 01 68 09 04 83 .9..gt..._..h...
+| 2432: 2a 02 01 69 0a 04 83 6a 03 01 78 02 04 83 11 02 *..i...j..x.....
+| 2448: 01 6a 05 04 83 26 02 06 0d 82 58 03 01 70 07 04 .j...&....X..p..
+| 2464: 83 2b 02 01 6b 07 08 83 58 81 12 02 01 6e 0a 02 .+..k...X....n..
+| 2480: 71 02 01 77 0a 04 83 04 02 03 c2 ba 31 06 04 84 q..w........1...
+| 2496: 4e 03 01 bd 07 04 83 18 02 02 d3 b5 05 02 68 01 N.............h.
+| 2512: 01 39 01 0a 53 81 03 81 24 01 0e 13 82 3d 81 1e .9..S...$....=..
+| 2528: 37 2d 01 0c 6a 15 09 13 82 58 01 08 83 0f 81 3f 7-..j....X.....?
+| 2544: 01 10 4f 81 60 81 29 64 15 0c 01 0e 4b 0d 62 0d ..O.`.)d....K.b.
+| 2560: 81 00 5e 01 0a 37 81 1b 59 56 01 0e 81 0c 6b 6d ..^..7..YV....km
+| 2576: 81 67 1d 01 10 38 2f 63 38 0c 37 20 6b 01 10 7e .g...8/c8.7 k..~
+| 2592: 10 18 81 4a 81 64 23 02 01 32 02 04 83 2c 02 01 ...J.d#..2...,..
+| 2608: 39 04 04 81 10 01 04 82 35 02 04 62 6e c7 9c 0a 9.......5..bn...
+| 2624: 04 84 2b 02 02 65 63 06 04 83 0a 03 01 6a 02 04 ..+..ec......j..
+| 2640: 84 4d 02 01 66 01 04 83 4d 02 04 81 0a 02 03 68 .M..f...M......h
+| 2656: ce bc 0a 04 83 41 02 01 6c 06 02 54 02 01 6d 08 .....A..l..T..m.
+| 2672: 04 81 14 02 02 6f 6c 0a 04 84 0a 02 01 70 02 04 .....ol......p..
+| 2688: 82 2b 05 04 81 49 02 05 71 69 c2 bd 75 0a 02 46 .+...I..qi..u..F
+| 2704: 02 02 72 38 0a 04 82 26 02 01 74 04 04 81 0b 04 ..r8...&..t.....
+| 2720: 04 84 6e 02 01 77 03 04 81 6a 01 04 82 6b 03 01 ..n..w...j...k..
+| 2736: 65 09 04 82 58 02 01 78 06 02 6e 02 02 c2 b3 08 e...X..x..n.....
+| 2752: 06 76 81 10 03 01 b9 04 02 47 03 01 bc 0a 04 83 .v.......G......
+| 2768: 03 02 02 ce bc 02 06 83 3f 19 02 03 d9 be 7a 03 ........?.....z.
+| 2784: 04 82 5d 01 01 61 01 1e 17 50 16 12 12 2d 32 81 ..]..a...P...-2.
+| 2800: 1e 56 81 06 04 06 1b 01 16 43 5c 52 64 19 15 27 .V.......C.Rd..'
+| 2816: 1d 29 0e 52 01 1c 1d 03 81 1c 13 6b 3d 64 14 32 .).R.......k=d.2
+| 2832: 16 29 09 0a 01 22 32 13 07 81 08 03 22 05 17 20 .)....2........
+| 2848: 07 0e 7a 15 71 22 22 01 1c 30 05 06 0b 22 40 11 ..z.q....0....@.
+| 2864: 49 1c 0c 15 81 1f 27 01 0c 4a 14 1c 7a 36 66 01 I.....'..J..z6f.
+| 2880: 1c 10 19 81 0a 81 1c 81 02 10 54 33 09 0c 07 01 ..........T3....
+| 2896: 1e 38 2e 33 3a 22 1e 2e 35 3a 0f 07 77 15 0b 2f .8.3:...5:..w../
+| 2912: 01 2a 08 5a 35 13 0b 07 05 04 17 42 32 14 04 09 .*.Z5......B2...
+| 2928: 1d 0b 09 06 42 72 1c 01 1e 22 0a 15 2b 03 04 6c ....Br......+..l
+| 2944: 05 81 3d 14 19 58 21 4a 02 01 32 08 04 83 64 03 ..=..X!J..2...d.
+| 2960: 01 67 07 04 82 5c 02 02 34 66 03 04 83 6d 03 01 .g......4f...m..
+| 2976: 73 08 04 81 18 02 05 37 6a 77 c2 b9 0a 04 83 1d s......7jw......
+| 2992: 02 02 38 7a 0a 04 82 3a 02 01 39 05 02 5c 03 02 ..8z...:..9.....
+| 3008: c2 b3 06 02 70 02 01 61 01 04 83 03 02 01 66 02 ....p..a......f.
+| 3024: 04 81 5b 02 04 82 37 02 01 68 04 04 82 78 01 02 ..[...7..h...x..
+| 3040: 67 02 01 69 04 04 84 0e 06 04 82 41 02 01 6a 01 g..i.......A..j.
+| 3056: 04 82 4c 02 02 4e 03 04 81 73 03 01 6c 02 04 81 ..L..N...s..l...
+| 3072: 5f 02 01 6b 08 04 81 26 02 05 6d c2 b3 6f 76 06 _..k...&..m..ov.
+| 3088: 04 82 7c 02 01 6e 08 02 1c 02 01 6f 02 04 83 24 ..|..n.....o...$
+| 3104: 07 04 83 77 02 01 70 04 04 82 7e 02 01 71 0a 04 ...w..p...~..q..
+| 3120: 81 19 02 06 72 f1 b6 bc b3 68 01 04 83 0e 02 01 ....r....h......
+| 3136: 73 03 04 82 17 01 08 81 70 81 65 03 04 39 c2 ba s.......p.e..9..
+| 3152: 69 06 04 81 65 03 01 76 02 04 81 26 02 01 74 01 i...e..v...&..t.
+| 3168: 02 4c 02 01 75 01 04 84 67 02 02 77 69 0a 02 09 .L..u...g..wi...
+| 3184: 02 04 78 d2 b9 73 04 04 83 42 02 03 7a c2 b3 08 ..x..s...B..z...
+| 3200: 02 43 02 02 c2 aa 01 04 82 61 06 04 84 10 02 02 .C.......a......
+| 3216: c6 88 07 02 1f 02 04 c8 b8 dd bf 05 04 81 72 02 ..............r.
+| 3232: 02 c9 ad 07 04 84 2f 02 02 ce bc 07 02 05 02 02 ....../.........
+| 3248: cf 85 0a 04 84 36 02 02 d9 a3 02 04 81 72 02 04 .....6.......r..
+| 3264: f1 a9 82 9b 0a 04 82 72 01 01 62 01 1c 81 17 06 .......r..b.....
+| 3280: 4a 46 28 2a 0a 4a 10 36 05 52 20 01 1c 1f 15 5f JF(*.J.6.R ...._
+| 3296: 17 12 2b 46 03 81 2b 0f 1b 1f 4f 01 26 6d 68 10 ..+F..+...O.&mh.
+| 3312: 04 08 06 20 04 10 05 20 05 07 6d 2e 09 14 05 24 ... ... ..m....$
+| 3328: 01 18 21 2b 11 12 81 0f 3e 22 11 28 51 28 01 18 ..!+....>..(Q(..
+| 3344: 12 11 4e 36 81 5a 23 3b 1a 16 26 2a 01 20 34 79 ..N6.Z#;..&*. 4y
+| 3360: 1e 32 14 05 27 17 0c 4a 49 46 09 03 0d 2f 01 0e .2..'..JIF.../..
+| 3376: 15 35 6f 3c 24 5e 2e 01 14 15 40 49 25 2c 0a 1d .5o<$^....@I%,..
+| 3392: 67 70 2e 01 1c 06 03 0b 0e 76 81 0e 15 81 25 0b gp.......v....%.
+| 3408: 39 2d 1a 01 14 27 1e 81 01 27 81 54 76 14 3e 02 9-...'...'.Tv.>.
+| 3424: 02 31 62 08 04 83 1d 02 01 33 0a 04 83 35 02 01 .1b......3...5..
+| 3440: 37 02 04 82 6b 02 01 39 0a 02 29 02 01 61 03 04 7...k..9..)..a..
+| 3456: 82 72 02 01 64 01 04 81 05 02 04 84 1f 02 01 65 .r..d..........e
+| 3472: 01 04 81 69 02 01 66 04 04 82 50 05 04 82 10 02 ...i..f...P.....
+| 3488: 01 69 01 02 0d 02 01 6b 0a 04 81 0a 02 01 6c 02 .i.....k......l.
+| 3504: 04 81 79 04 04 84 6e 03 01 31 0a 04 84 66 02 01 ..y...n..1...f..
+| 3520: 6f 0a 04 83 48 02 01 73 01 02 3d 03 02 10 02 01 o...H..s..=.....
+| 3536: 74 02 04 82 0e 02 01 75 06 04 84 74 03 01 32 01 t......u...t..2.
+| 3552: 04 82 0d 02 01 76 06 04 83 3a 02 01 78 08 04 82 .....v...:..x...
+| 3568: 73 03 01 6c 09 04 84 1c 03 01 78 02 04 82 08 03 s..l......x.....
+| 3584: 02 7a 69 0a 04 83 73 02 01 79 03 04 82 42 02 01 .zi...s..y...B..
+| 3600: 7a 08 04 83 03 02 06 c2 b9 e3 b1 a1 32 0a 04 81 z...........2...
+| 3616: 46 03 01 bc 04 04 83 36 03 01 be 04 04 84 3f 02 F......6......?.
+| 3632: 02 c6 80 0a 04 84 00 02 03 d4 a3 76 07 04 84 33 ...........v...3
+| 3648: 02 04 da ba 71 6f 08 04 84 11 02 02 dd a8 08 02 ....qo..........
+| 3664: 51 02 06 eb 9e ac 7a 73 79 06 02 32 01 01 63 01 Q.....zsy..2..c.
+| 3680: 18 04 39 12 3a 05 34 56 46 59 81 0b 43 01 22 2a ..9.:.4VFY..C..*
+| 3696: 1d 1f 53 2b 60 22 12 0d 13 1c 2e 35 05 03 0f 54 ..S+`......5...T
+| 3712: 01 14 81 1e 81 1f 17 03 24 2a 81 0b 01 24 34 20 ........$*...$4
+| 3728: 06 21 0a 30 05 08 03 62 0c 26 10 6c 3b 0d 44 3a .!.0...b.&.l;.D:
+| 3744: 01 1a 15 0b 77 04 45 3f 34 37 3f 08 13 36 53 01 ....w.E?47?..6S.
+| 3760: 1c 02 38 33 49 1e 2e 81 19 43 33 3e 24 15 08 01 ..83I....C3>$...
+| 3776: 1a 09 81 55 40 43 09 21 27 4c 04 5b 07 07 07 07 ...U@C.!'L.[....
+| 3792: 07 07 07 07 07 08 08 07 0a 07 0a 06 07 08 07 07 ................
+| 3808: 08 07 0a 08 56 06 0a 07 07 09 06 08 07 07 07 0a ....V...........
+| 3824: 06 07 09 09 07 06 07 08 08 08 08 08 5e 07 06 07 ............^...
+| 3840: 07 08 09 07 07 08 07 07 08 0b 0b 07 0a 06 07 0a ................
+| 3856: 08 09 09 0a 07 09 08 65 07 07 07 07 07 08 0b 07 .......e........
+| 3872: 06 0b 07 07 06 07 07 07 07 08 09 0c 57 0b 08 07 ............W...
+| 3888: 07 0c 08 07 07 08 09 0a 07 07 07 09 07 07 07 0a ................
+| 3904: 07 06 0a 07 08 08 09 5b 07 07 0b 06 09 0a 0a 06 .......[........
+| 3920: 0a 0a 07 07 08 08 06 08 06 0e 5f 07 07 0b 0a 08 .........._.....
+| 3936: 06 07 0b 07 07 0f 07 0b 07 07 07 07 06 06 0c 08 ................
+| 3952: 09 08 0c 65 08 0a 06 06 06 08 07 06 07 08 07 08 ...e............
+| 3968: 06 07 09 0b 07 0a 08 08 0a 07 08 0a 0a 58 06 07 .............X..
+| 3984: 07 0a 0b 0b 08 07 07 07 0c 07 09 06 07 09 07 07 ................
+| 4000: 58 07 0b 0a 08 07 0b 09 06 07 08 0b 0a 08 0b 0b X...............
+| 4016: 07 06 09 06 07 09 09 81 25 07 07 08 07 0b 08 06 ........%.......
+| 4032: 07 07 0b 0a 0b 0e 07 07 0b 06 0b 07 07 0c 0d 0a ................
+| 4048: 07 06 07 07 0a 08 0c 07 0a 08 07 08 08 0a 81 17 ................
+| 4064: 08 07 07 06 07 0b 07 0b 06 07 0b 07 07 09 07 07 ................
+| 4080: 07 07 07 07 07 08 07 07 0c 07 07 08 09 0a 07 0b ................
+| page 21 offset 81920
+| 0: 0d 00 00 00 01 00 21 00 00 21 00 00 00 00 00 00 ......!..!......
+| 32: 00 9f 57 88 80 80 80 80 02 04 00 bf 32 00 08 0e ..W.........2...
+| 48: 8c 3a 14 04 29 08 18 17 4a 44 3a 19 4e 5f 56 16 .:..)...JD:.N_V.
+| 64: 08 30 25 01 1c 0e 13 32 1b 0b 41 03 2f 81 34 3c .0%....2..A./.4<
+| 80: 14 09 21 01 14 81 01 06 10 30 1f 28 0f 51 5f 04 ..!......0.(.Q_.
+| 96: 30 63 33 74 05 02 69 02 02 34 76 0a 04 83 63 02 0c3t..i..4v...c.
+| 112: 04 36 e7 8e a1 03 04 84 03 02 04 61 77 c2 b9 05 .6.........aw...
+| 128: 04 82 56 02 01 63 03 04 82 02 04 04 82 0a 02 02 ..V..c..........
+| 144: 64 30 09 02 40 02 01 67 02 06 61 83 38 02 04 82 d0..@..g..a.8...
+| 160: 70 03 04 84 62 03 01 73 02 04 84 5f 02 01 68 01 p...b..s..._..h.
+| 176: 04 81 76 03 01 32 07 04 84 3f 02 01 69 09 02 7e ..v..2...?..i..~
+| 192: 02 01 6a 01 04 81 57 02 01 6b 01 04 82 33 02 01 ..j...W..k...3..
+| 208: 6d 05 02 7b 02 01 6e 06 04 82 51 02 01 6f 06 02 m.....n...Q..o..
+| 224: 0e 03 01 65 01 04 81 3c 02 02 70 63 06 02 1e 02 ...e...<..pc....
+| 240: 01 71 02 04 84 3b 08 02 1a 02 01 72 09 06 36 81 .q...;.....r..6.
+| 256: 38 02 01 75 02 04 83 3b 03 02 54 02 01 77 04 04 8..u...;..T..w..
+| 272: 83 5c 06 04 83 21 02 01 78 07 04 81 21 02 01 79 .....!..x...!..y
+| 288: 06 02 3a 02 02 7a 31 02 04 84 2a 02 02 c2 b2 02 ..:..z1...*.....
+| 304: 04 81 01 03 01 b3 07 04 82 5e 03 02 bd 7a 06 04 .........^...z..
+| 320: 82 08 02 02 c6 9e 0a 04 83 4d 02 02 ce bc 05 04 .........M......
+| 336: 84 70 02 02 d3 86 06 04 82 33 02 02 d4 a7 01 02 .p.......3......
+| 352: 7c 02 02 d8 b8 06 04 82 53 02 02 df a4 04 02 7c |.......S......|
+| 368: 02 03 e0 b7 ae 04 04 84 5e 02 03 e6 91 9a 03 04 ........^.......
+| 384: 81 18 02 04 f0 90 ac 8e 04 04 82 39 01 01 64 01 ...........9..d.
+| 400: 16 23 2f 1a 6d 81 47 65 09 1b 42 25 01 10 0d 82 .#/.m.Ge..B%....
+| 416: 18 81 3c 50 06 34 01 10 60 31 5a 14 18 16 5f 18 ....J.Z.!.
+| 464: 18 0a 0a 67 3d 81 37 40 68 0e 30 17 18 01 12 08 ...g=.7@h.0.....
+| 480: 6a 54 81 0c 49 14 4f 21 01 16 26 82 0d 3c 0c 60 jT..I.O!..&..<.`
+| 496: 19 27 51 05 07 01 16 24 20 07 1a 81 1c 1f 24 43 .'Q....$ .....$C
+| 512: 81 5b 01 16 42 21 05 81 07 0d 36 5b 21 81 15 02 .[..B!....6[!...
+| 528: 01 30 01 04 84 4d 02 01 32 04 04 84 38 02 01 34 .0...M..2...8..4
+| 544: 06 04 83 1e 02 04 84 3c 01 04 81 2c 02 01 62 08 .......<...,..b.
+| 560: 04 82 51 03 01 61 05 04 84 3e 02 01 63 06 04 84 ..Q..a...>..c...
+| 576: 24 03 04 83 40 02 01 64 01 08 81 18 83 2e 02 01 $...@..d........
+| 592: 65 03 04 82 46 02 01 66 09 04 84 33 02 01 67 03 e...F..f...3..g.
+| 608: 04 81 55 02 07 68 c2 b9 62 71 61 30 02 02 48 02 ..U..h..bqa0..H.
+| 624: 01 69 04 04 82 4b 03 01 78 03 04 81 3c 02 02 6a .i...K..x...<..j
+| 640: 34 05 02 47 02 01 6b 01 04 82 29 03 01 38 0a 02 4..G..k...)..8..
+| 656: 49 02 01 6c 02 04 84 1a 01 04 84 58 07 04 82 2c I..l.......X...,
+| 672: 02 01 6d 06 04 83 0b 02 04 84 0c 03 02 c2 bc 08 ..m.............
+| 688: 04 83 17 02 01 6e 02 04 83 70 02 01 6f 04 04 81 .....n...p..o...
+| 704: 56 03 01 61 03 02 5b 03 04 65 79 64 37 06 04 81 V..a..[..eyd7...
+| 720: 38 03 03 ee a9 bf 08 02 45 02 01 71 04 04 81 75 8.......E..q...u
+| 736: 03 01 74 09 04 83 66 02 01 72 06 02 4f 02 01 73 ..t...f..r..O..s
+| 752: 01 04 81 26 07 02 2d 02 01 74 02 02 14 02 02 3c ...&..-..t.....<
+| 768: 04 04 84 5d 02 02 77 64 02 02 31 02 01 78 02 04 ...]..wd..1..x..
+| 784: 84 59 03 04 84 65 02 01 79 02 02 58 04 04 81 49 .Y...e..y..X...I
+| 800: 01 04 83 17 03 02 7f 02 02 c2 b3 04 02 05 03 01 ................
+| 816: b9 01 04 84 09 03 01 be 0a 04 82 59 02 02 ce bc ...........Y....
+| 832: 06 04 81 02 02 02 d7 9d 06 04 83 31 02 04 df 84 ...........1....
+| 848: da 8c 08 04 82 67 02 04 e1 b5 b6 6b 0a 04 81 7b .....g.....k....
+| 864: 02 03 e3 a1 92 03 04 83 66 02 04 f0 9b 93 a9 07 ........f.......
+| 880: 04 85 0b 04 02 a8 81 06 04 82 3e 01 01 65 01 24 ..........>..e.$
+| 896: 43 34 18 15 08 09 51 19 5b 17 28 26 11 06 23 38 C4....Q.[.(&..#8
+| 912: 2b 2b 01 1e 1c 32 20 17 0f 2c 03 0c 1b 0c 6f 25 ++...2 ..,....o%
+| 928: 73 16 40 01 1e 07 12 81 5a 44 19 06 03 24 5c 0e s.@.....ZD...$..
+| 944: 16 18 39 0d 01 26 0d 09 06 41 42 09 24 1d 25 0c ..9..&...AB.$.%.
+| 960: 06 1d 63 14 26 18 7d 0a 1d 01 14 25 56 29 0a 81 ..c.&......%V)..
+| 976: 1a 1b 37 5d 3d 01 16 1c 81 26 25 7f 41 52 46 08 ..7]=....&%.ARF.
+| 992: 1b 16 01 12 81 0f 6b 7b 0f 2d 03 7f 07 01 18 19 ......k..-......
+| 1008: 28 81 01 50 36 41 16 81 22 17 03 01 1c 16 1a 81 (..P6A..........
+| 1024: 1f 10 17 41 4c 1c 0b 66 49 10 06 01 18 54 82 38 ...AL..fI....T.8
+| 1040: 13 2a 0b 14 4c 15 0f 36 0b 02 01 30 07 04 82 28 .*..L..6...0...(
+| 1056: 02 01 31 09 04 81 2b 01 04 83 38 02 01 33 03 04 ..1...+...8..3..
+| 1072: 81 76 02 01 61 08 04 84 6b 03 05 7a ea 86 b3 6a .v..a...k..z...j
+| 1088: 06 04 82 52 02 01 62 0a 04 83 19 02 01 63 02 04 ...R..b......c..
+| 1104: 82 4d 03 02 c2 be 04 04 82 29 02 01 64 05 04 81 .M.......)..d...
+| 1120: 7a 03 04 81 72 02 02 66 61 04 02 41 03 01 77 06 z...r..fa..A..w.
+| 1136: 02 3e 02 04 82 10 02 01 67 05 04 84 48 02 01 69 .>......g...H..i
+| 1152: 01 04 83 12 02 02 6c 62 07 04 81 1d 02 01 6d 01 ......lb......m.
+| 1168: 04 83 6e 02 01 6f 05 02 09 02 04 81 16 02 01 70 ..n..o.........p
+| 1184: 05 06 07 82 72 03 01 38 07 04 84 46 02 01 73 02 ....r..8...F..s.
+| 1200: 04 84 2d 05 04 81 58 03 04 81 4a 03 02 c2 bd 0a ..-...X...J.....
+| 1216: 04 83 2d 02 01 74 02 04 84 55 05 04 85 02 02 01 ..-..t...U......
+| 1232: 75 02 04 82 62 02 01 76 01 04 84 31 02 01 77 09 u...b..v...1..w.
+| 1248: 04 82 15 02 01 78 01 02 45 05 04 82 14 03 04 83 .....x..E.......
+| 1264: 01 02 01 79 06 04 81 0c 02 02 7a 78 09 04 81 6d ...y......zx...m
+| 1280: 02 04 c2 bc 61 72 04 04 83 20 04 01 6f 01 02 70 ....ar... ..o..p
+| 1296: 02 02 c9 9e 01 04 82 02 02 02 ca 83 05 04 82 3f ...............?
+| 1312: 03 01 9b 05 02 52 03 01 aa 07 04 83 65 02 02 cd .....R......e...
+| 1328: bb 01 04 83 07 02 02 ce b2 06 02 5b 02 03 cf a7 ...........[....
+| 1344: 78 03 04 81 3b 02 03 ef a9 89 08 04 82 20 02 04 x...;........ ..
+| 1360: f5 87 b0 93 02 04 84 18 01 01 66 01 1c 2b 3d 5b ..........f..+=[
+| 1376: 23 45 2d 41 17 0e 81 1d 0f 15 1f 01 16 05 81 20 #E-A...........
+| 1392: 0d 27 81 0f 3e 28 2b 13 01 14 62 2c 44 26 17 04 .'..>(+...b,D&..
+| 1408: 23 50 6d 5b 01 1c 30 5b 81 27 07 29 38 15 4d 11 #Pm[..0[.'.)8.M.
+| 1424: 2e 20 17 20 01 1a 19 65 4f 14 2e 55 0e 12 39 13 . . ...eO..U..9.
+| 1440: 1d 70 12 01 20 1a 0d 2f 05 81 19 2b 42 05 37 4c .p.. ../...+B.7L
+| 1456: 21 22 04 25 2b 01 14 45 3e 05 10 81 47 6c 81 11 !..%+..E>...Gl..
+| 1472: 11 01 1e 78 04 12 18 0a 05 10 14 6b 05 0a 04 82 ...x.......k....
+| 1488: 05 15 01 1e 05 23 4b 18 24 31 20 27 12 2e 81 0e .....#K.$1 '....
+| 1504: 31 18 18 01 10 55 7e 29 2a 06 19 65 38 02 01 30 1....U~)*..e8..0
+| 1520: 09 02 14 02 01 31 02 04 84 00 02 01 36 06 04 84 .....1......6...
+| 1536: 7a 02 01 61 07 04 83 71 02 01 62 05 04 83 10 03 z..a...q..b.....
+| 1552: 02 34 02 02 63 6f 07 04 83 27 02 01 64 07 04 81 .4..co...'..d...
+| 1568: 0c 03 04 81 55 03 01 6f 03 02 7e 02 01 69 02 04 ....U..o..~..i..
+| 1584: 81 08 03 02 05 03 04 82 70 02 01 6a 05 02 41 03 ........p..j..A.
+| 1600: 02 6f 30 04 02 5e 02 01 6b 02 04 82 13 02 01 6c .o0..^..k......l
+| 1616: 02 04 83 2d 08 04 81 20 02 01 6e 09 04 82 69 02 ...-... ..n...i.
+| 1632: 02 6f 38 02 04 83 73 02 01 71 0a 04 81 4f 02 01 .o8...s..q...O..
+| 1648: 74 09 04 83 2c 02 01 75 03 04 83 79 03 03 68 c2 t...,..u...y..h.
+| 1664: b3 03 04 81 09 02 02 77 64 06 04 81 79 02 01 78 .......wd...y..x
+| 1680: 03 04 83 41 03 02 19 02 01 79 02 04 82 1a 07 02 ...A.....y......
+| 1696: 72 03 01 6a 06 04 83 1a 02 01 7a 05 04 84 6d 01 r..j......z...m.
+| 1712: 04 81 24 02 03 c2 aa 75 0a 04 84 72 03 01 b3 04 ..$....u...r....
+| 1728: 04 82 02 03 04 82 2c 03 01 ba 07 04 26 51 03 02 ......,.....&Q..
+| 1744: bd 65 07 04 81 1a 03 01 be 09 02 44 02 02 ca 97 .e.........D....
+| 1760: 02 04 84 30 02 03 d5 a7 6f 04 02 36 03 02 bd 72 ...0....o..6...r
+| 1776: 07 04 81 03 02 05 f3 b2 a7 91 68 09 04 82 22 01 ..........h.....
+| 1792: 01 67 01 16 81 41 81 1f 4c 0f 0d 0d 6f 3d 04 01 .g...A..L...o=..
+| 1808: 18 12 08 5e 05 16 4f 42 61 22 45 3c 27 01 20 08 ...^..OBa.E<'. .
+| 1824: 13 27 14 17 1f 08 3e 0d 41 81 1c 3e 06 1c 1e 01 .'....>.A..>....
+| 1840: 16 0c 11 6b 26 54 05 14 03 81 6b 12 01 1a 36 41 ...k&T....k...6A
+| 1856: 11 0b 0c 36 7c 08 0e 0c 52 4f 50 01 0c 81 0e 22 ...6|...ROP.....
+| 1872: 3d 72 1f 01 22 07 0e 22 3c 4d 1c 09 03 2d 22 1e =r.........?.....u..
+| 2656: be 6b 05 04 83 0c 02 04 c3 b8 66 70 01 04 82 2f .k........fp.../
+| 2672: 02 02 ce bc 08 04 81 04 02 03 cf a7 6b 06 04 82 ............k...
+| 2688: 4d 02 03 d9 84 72 03 02 13 02 02 da 90 06 04 84 M....r..........
+| 2704: 73 02 04 f0 ad 93 a0 06 02 09 01 01 69 01 20 37 s...........i. 7
+| 2720: 4d 55 11 49 26 3c 17 0d 4a 26 03 05 0c 20 43 01 MU.I&<..J&... C.
+| 2736: 10 59 08 37 5a 56 72 81 05 01 1a 16 33 32 0a 03 .Y.7ZVr.....32..
+| 2752: 18 81 17 5f 59 27 37 08 01 24 0a 70 1f 07 40 3b ..._Y'7..$.p..@;
+| 2768: 15 20 09 15 30 0f 17 06 36 81 08 17 01 1c 32 0a . ..0...6.....2.
+| 2784: 05 1a 5f 1c 32 78 03 15 17 81 2b 1e 01 1a 04 03 .._.2x....+.....
+| 2800: 2b 07 0c 38 43 6c 0f 81 77 0e 0e 01 1a 1c 3d 81 +..8Cl..w.....=.
+| 2816: 0d 0d 17 1d 4c 63 44 2e 11 2b 01 18 2b 2d 49 72 ....LcD..+..+-Ir
+| 2832: 1d 22 17 31 19 27 32 4c 01 1c 0b 67 27 20 81 1c ...1.'2L...g' ..
+| 2848: 47 31 29 0d 0b 12 4c 07 01 18 35 81 0b 08 0e 5f G1)...L...5...._
+| 2864: 11 18 37 81 09 09 02 01 30 09 02 19 02 02 31 63 ..7.....0.....1c
+| 2880: 09 02 7f 02 01 32 04 02 2c 05 04 83 6e 02 01 35 .....2..,...n..5
+| 2896: 09 04 83 7a 03 01 79 05 02 0f 02 02 36 73 05 04 ...z..y.....6s..
+| 2912: 83 3d 02 03 38 6a 70 07 04 84 39 02 01 61 07 04 .=..8jp...9..a..
+| 2928: 83 44 02 01 62 0a 04 84 37 02 01 64 01 04 85 00 .D..b...7..d....
+| 2944: 07 04 82 36 03 02 cf a7 01 04 82 5f 02 01 66 06 ...6......._..f.
+| 2960: 04 82 35 03 03 71 70 6e 04 04 82 14 02 02 67 7a ..5..qpn......gz
+| 2976: 02 04 82 00 02 01 68 01 02 14 02 01 69 05 02 48 ......h.....i..H
+| 2992: 02 01 6a 01 04 83 7a 07 02 12 01 02 33 02 01 6d ..j...z.....3..m
+| 3008: 04 04 83 76 03 01 68 08 04 82 63 02 01 6f 03 06 ...v..h...c..o..
+| 3024: 2c 81 52 06 04 81 4f 02 01 70 06 04 83 00 03 02 ,.R...O..p......
+| 3040: c2 be 06 04 83 37 02 01 72 09 04 82 78 03 03 71 .....7..r...x..q
+| 3056: 61 6c 0a 02 3e 03 02 c2 be 05 04 84 67 02 01 73 al..>.......g..s
+| 3072: 09 04 81 0d 02 01 74 04 02 58 02 01 75 08 04 81 ......t..X..u...
+| 3088: 17 02 01 76 04 04 83 4b 06 04 84 70 02 01 7a 02 ...v...K...p..z.
+| 3104: 04 83 7e 02 02 c2 aa 03 02 61 03 01 b2 08 04 84 ..~......a......
+| 3120: 13 03 04 b9 c2 b2 6a 01 02 19 03 02 bc 63 05 04 ......j......c..
+| 3136: 84 12 02 02 c7 86 09 04 84 11 02 02 ce bc 02 02 ................
+| 3152: 17 02 03 cf ab 6e 07 02 29 02 06 d5 b1 30 d1 bb .....n..)....0..
+| 3168: 6e 01 02 4e 02 03 eb 8b a7 08 04 81 6b 03 02 b5 n..N........k...
+| 3184: bc 07 04 83 08 01 01 6a 01 14 81 07 79 0f 79 32 .......j....y.y2
+| 3200: 33 13 81 16 01 16 2c 0a 81 1b 24 2f 05 81 19 19 3.....,...$/....
+| 3216: 2d 01 16 81 4c 03 14 4f 81 08 2d 05 2f 21 01 18 -...L..O..-./!..
+| 3232: 27 1f 0e 81 16 0c 82 4b 04 12 06 0e 01 1e 26 05 '......K......&.
+| 3248: 22 14 55 05 09 81 16 21 05 19 37 74 32 01 1e 37 ..U....!..7t2..7
+| 3264: 07 1e 03 10 81 2c 38 07 1a 2a 2b 81 0d 08 01 1e .....,8..*+.....
+| 3280: 2b 19 31 3c 4c 03 1a 14 04 1c 06 76 04 48 62 01 +.1-......p$D..b
+| 3760: 12 3b 50 15 34 03 16 01 0c 32 08 08 0a 0a 0b 07 .;P.4....2......
+| 3776: 10 07 07 07 06 07 07 06 07 06 07 07 0a 08 0a 0b ................
+| 3792: 07 06 08 08 07 08 08 08 08 07 08 07 09 09 0a 81 ................
+| 3808: 03 07 07 0f 07 07 0b 09 07 07 07 0c 07 07 07 07 ................
+| 3824: 06 0f 0b 08 07 07 06 0a 08 07 07 06 0a 0d 07 0b ................
+| 3840: 11 07 07 07 08 08 0a 0a 09 0a 08 81 1e 07 0b 07 ................
+| 3856: 07 0b 07 07 08 0b 07 0a 07 07 08 07 0a 08 07 0f ................
+| 3872: 08 0b 07 07 07 0e 07 08 0a 06 08 08 06 07 08 07 ................
+| 3888: 09 09 0a 81 15 06 07 07 07 0a 08 0b 06 0e 06 07 ................
+| 3904: 07 0b 07 08 07 07 07 09 08 0a 0a 07 0b 09 0b 07 ................
+| 3920: 08 06 08 08 08 0b 81 0d 08 08 07 07 07 0b 0b 0b ................
+| 3936: 08 07 07 07 0f 0b 06 07 07 07 08 0c 07 07 08 08 ................
+| 3952: 0e 09 0b 07 06 08 06 07 07 08 09 07 0a 0a 81 1f ................
+| 3968: 07 09 08 06 0b 0a 0d 07 0a 07 08 0a 09 07 08 07 ................
+| 3984: 07 09 06 0d 09 07 0a 08 08 0b 0b 06 08 0a 08 09 ................
+| 4000: 08 08 09 81 1c 06 07 0a 07 06 08 09 07 07 0b 08 ................
+| 4016: 07 09 08 06 06 0d 07 07 0c 07 08 07 08 08 07 06 ................
+| 4032: 07 0b 07 07 07 09 08 08 07 08 0b 09 08 81 16 09 ................
+| 4048: 07 07 07 07 08 07 09 07 07 07 07 07 07 07 0a 07 ................
+| 4064: 07 07 07 09 07 09 08 07 07 07 07 07 07 07 09 09 ................
+| 4080: 0a 07 06 07 0b 09 07 09 07 08 09 09 0c 0b 07 07 ................
+| page 22 offset 86016
+| 0: 0d 00 00 00 01 00 24 00 00 24 00 00 00 00 00 00 ......$..$......
+| 32: 00 00 00 00 9f 54 88 80 80 80 80 03 04 00 bf 2c .....T.........,
+| 48: 00 0a 0e 8b 61 42 11 82 12 4d 05 12 81 47 48 81 ....aB...M...GH.
+| 64: 1c 3a 41 17 25 01 2a 42 21 1d 1f 07 44 65 2c 0f .:A.%.*B!...De,.
+| 80: 18 20 18 08 03 19 04 10 19 0b 17 26 01 1a 14 1f . .........&....
+| 96: 11 1f 2b 10 82 08 26 2b 76 0c 27 01 22 4c 23 06 ..+...&+v.'..L#.
+| 112: 81 10 2e 2e 03 37 4b 13 14 14 1b 15 24 0d 01 18 .....7K.....$...
+| 128: 3a 0e 4b 15 7b 2a 4a 13 24 81 10 0a 01 18 11 16 :.K..*J.$.......
+| 144: 28 1f 57 54 15 16 6b 50 2f 04 04 30 6b 30 34 05 (.WT..kP/..0k04.
+| 160: 04 83 1c 02 01 31 04 02 39 02 02 22 01 04 82 48 .....1..9......H
+| 176: 02 01 32 09 04 81 25 02 01 34 01 04 81 1a 02 01 ..2...%..4......
+| 192: 35 01 02 09 03 01 30 09 04 83 29 02 01 37 05 04 5.....0...)..7..
+| 208: 82 70 02 01 38 06 04 83 2f 02 01 39 03 04 83 29 .p..8.../..9...)
+| 224: 02 01 61 09 02 67 02 01 62 02 04 82 57 02 01 63 ..a..g..b...W..c
+| 240: 01 04 82 24 02 02 64 33 09 04 84 06 02 01 65 09 ...$..d3......e.
+| 256: 04 84 46 02 01 66 03 04 84 15 01 04 84 69 04 04 ..F..f.......i..
+| 272: 84 36 02 01 67 06 04 84 7e 02 08 83 35 81 2c 02 .6..g...~...5.,.
+| 288: 01 68 03 04 82 3a 05 08 81 2e 81 20 02 01 69 02 .h...:..... ..i.
+| 304: 04 81 69 02 01 6a 06 02 46 01 08 82 1e 82 5b 02 ..i..j..F.....[.
+| 320: 04 84 20 02 01 6b 09 04 81 2e 02 01 6c 08 04 84 .. ..k......l...
+| 336: 56 03 01 62 0a 04 83 3f 02 02 6d 6a 01 04 82 15 V..b...?..mj....
+| 352: 02 04 6f 69 72 33 01 04 82 25 02 01 72 01 02 44 ..oir3...%..r..D
+| 368: 03 01 35 06 04 81 3b 02 02 74 74 04 04 81 79 02 ..5...;..tt...y.
+| 384: 01 78 01 04 81 5b 02 02 7a 02 01 79 04 02 19 02 .x...[..z..y....
+| 400: 03 7a 71 6b 03 04 83 37 02 02 c2 b3 01 02 31 04 .zqk...7......1.
+| 416: 04 82 04 03 07 ba 6e f5 9a 8b 98 76 02 02 5b 02 ......n....v..[.
+| 432: 02 cb 8f 06 04 84 28 02 02 ce bc 01 04 81 66 06 ......(.......f.
+| 448: 04 81 1b 02 04 83 47 04 06 ce bc ce bf df bc 09 ......G.........
+| 464: 04 82 4f 02 02 dd 9c 03 04 81 62 02 04 f2 86 b3 ..O.......b.....
+| 480: bb 01 04 82 08 01 01 6c 01 12 81 34 81 00 0d 2a .......l...4...*
+| 496: 81 48 13 01 1a 0e 14 4f 81 17 14 12 10 75 68 36 .H.....O.....uh6
+| 512: 0b 1d 01 16 12 22 23 51 1d 7c 25 08 20 4f 7a 01 ......#Q.|%. Oz.
+| 528: 12 08 0b 81 7c 71 81 12 0b 0b 01 0e 4e 50 55 82 ....|q......NPU.
+| 544: 1e 2e 23 01 1c 0f 10 24 07 33 06 81 0c 73 42 1d ..#....$.3...sB.
+| 560: 81 04 16 01 16 5e 62 6a 06 32 81 03 2f 0f 08 4e .....^bj.2../..N
+| 576: 01 06 81 2c 22 01 12 53 81 1e 6e 40 31 0b 1c 41 ...,...S..n@1..A
+| 592: 01 18 79 14 11 17 13 81 0f 81 15 19 35 40 02 01 ..y.........5@..
+| 608: 30 01 04 81 0d 03 04 83 6b 02 01 33 07 04 84 66 0.......k..3...f
+| 624: 03 04 83 08 02 01 35 08 04 83 43 01 04 83 50 02 ......5...C...P.
+| 640: 01 36 09 02 3b 02 01 37 07 04 84 38 02 01 61 0a .6..;..7...8..a.
+| 656: 04 83 17 03 04 e1 8d 93 69 01 04 81 0e 02 01 62 ........i......b
+| 672: 03 04 84 16 04 04 83 0e 02 01 63 05 04 81 79 05 ..........c...y.
+| 688: 04 84 5d 02 01 64 07 04 81 4a 03 02 6d 6e 08 02 ..]..d...J..mn..
+| 704: 09 02 01 65 06 04 84 3e 03 02 76 7a 02 02 76 02 ...e...>..vz..v.
+| 720: 01 66 0a 02 47 03 01 79 09 04 81 21 02 02 67 6f .f..G..y...!..go
+| 736: 05 02 38 02 02 68 77 03 04 82 27 02 01 69 02 02 ..8..hw...'..i..
+| 752: 6f 04 02 6f 02 01 6b 07 04 82 61 02 01 6c 06 08 o..o..k...a..l..
+| 768: 82 2e 81 5a 02 01 6d 01 04 84 25 03 04 83 31 02 ...Z..m...%...1.
+| 784: 06 2f 82 2e 03 01 68 08 04 83 73 02 01 6e 09 04 ./....h...s..n..
+| 800: 84 5a 02 01 6f 05 04 82 39 02 01 70 04 04 82 19 .Z..o...9..p....
+| 816: 05 02 0f 02 01 71 07 04 83 39 03 02 63 71 06 04 .....q...9..cq..
+| 832: 81 5e 03 01 67 07 04 83 73 03 01 70 08 04 84 6a .^..g...s..p...j
+| 848: 02 01 73 03 04 83 40 02 01 74 07 04 84 7c 03 06 ..s...@..t...|..
+| 864: 35 69 7a 70 c2 bd 01 04 83 1a 02 01 75 01 08 82 5izp........u...
+| 880: 2e 81 13 05 04 82 69 03 01 70 03 04 84 50 02 01 ......i..p...P..
+| 896: 76 01 04 82 52 09 04 82 64 02 02 77 73 03 04 81 v...R...d..ws...
+| 912: 27 02 01 78 08 02 1f 01 04 83 64 02 01 79 04 08 '..x......d..y..
+| 928: 81 49 81 44 05 04 84 01 02 03 c2 aa 76 02 04 82 .I.D........v...
+| 944: 67 03 01 b9 02 02 4f 06 02 31 03 01 bd 05 04 82 g.....O..1......
+| 960: 3d 02 02 ce bc 01 02 2c 01 01 6d 01 12 0c 47 83 =......,..m...G.
+| 976: 0a 07 52 16 41 05 01 18 50 05 74 25 21 81 16 16 ..R.A...P.t%!...
+| 992: 05 24 16 6c 01 22 81 05 18 06 12 2a 59 09 1f 09 .$.l.......*Y...
+| 1008: 3d 27 39 17 3a 1f 04 01 14 72 81 1a 24 81 38 20 ='9.:....r..$.8
+| 1024: 27 19 2b 01 18 81 2b 24 63 0b 11 5d 2d 0c 41 1a '.+...+$c..]-.A.
+| 1040: 30 01 1e 15 04 3c 3a 15 0e 28 18 06 56 81 37 20 0....<:..(..V.7
+| 1056: 0d 6b 01 1e 63 3f 42 73 0a 26 0c 6f 0f 15 13 0b .k..c?Bs.&.o....
+| 1072: 04 25 33 01 16 24 52 16 3a 21 1b 63 26 31 20 34 .%3..$R.:!.c&1 4
+| 1088: 01 0e 1a 60 13 19 3d 82 1f 01 1e 5b 07 26 07 20 ...`..=....[.&.
+| 1104: 03 5a 69 6c 27 0b 22 24 20 0f 02 01 31 01 04 82 .Zil'..$ ...1...
+| 1120: 6f 02 01 32 03 04 82 41 01 04 81 43 02 01 33 09 o..2...A...C..3.
+| 1136: 04 81 23 03 05 7a 68 c2 bd 73 06 04 81 3a 02 01 ..#..zh..s...:..
+| 1152: 35 07 04 83 6c 02 01 38 01 04 83 1c 02 02 62 6f 5...l..8......bo
+| 1168: 06 04 83 16 02 01 63 07 02 5b 03 06 6e 31 cf af ......c..[..n1..
+| 1184: 61 71 0a 04 83 33 03 02 c2 be 03 04 83 2b 02 01 aq...3.......+..
+| 1200: 64 09 04 81 19 01 04 83 09 03 01 62 0a 04 82 56 d..........b...V
+| 1216: 03 01 6a 03 04 84 4e 02 01 65 05 04 82 3a 02 04 ..j...N..e...:..
+| 1232: 82 53 02 01 66 09 04 82 7a 02 01 67 02 04 82 69 .S..f...z..g...i
+| 1248: 08 04 81 35 02 01 68 09 04 83 2f 02 01 69 01 04 ...5..h.../..i..
+| 1264: 81 62 02 01 6a 0a 04 81 59 02 01 6b 09 04 81 5f .b..j...Y..k..._
+| 1280: 02 01 6c 08 04 84 0d 02 01 6d 05 04 84 32 02 01 ..l......m...2..
+| 1296: 6e 01 04 83 05 02 01 6f 07 04 82 6f 02 01 70 04 n......o...o..p.
+| 1312: 04 83 60 03 04 82 0d 03 03 c2 b9 70 02 04 81 43 ..`........p...C
+| 1328: 02 01 71 07 04 81 13 03 04 82 35 02 01 72 03 04 ..q.......5..r..
+| 1344: 84 51 02 02 73 65 04 04 84 14 02 01 74 01 04 83 .Q..se......t...
+| 1360: 5f 02 01 75 03 02 0b 03 02 c2 be 08 04 82 3a 02 _..u..........:.
+| 1376: 01 76 06 04 84 43 02 01 77 01 04 82 18 01 04 81 .v...C..w.......
+| 1392: 32 02 01 78 08 04 81 47 02 01 7a 01 04 82 44 02 2..x...G..z...D.
+| 1408: 02 c2 b3 05 04 83 12 03 04 83 14 04 01 37 04 04 .............7..
+| 1424: 83 6c 03 03 ba dd af 05 04 82 41 02 02 c3 9f 07 .l........A.....
+| 1440: 04 82 34 02 03 c6 80 78 0a 04 83 14 02 02 ca 95 ..4....x........
+| 1456: 07 04 83 0c 02 03 ce b0 67 03 02 6e 03 01 bc 05 ........g..n....
+| 1472: 02 17 04 02 6c 02 03 e7 a4 94 05 04 82 51 01 01 ....l........Q..
+| 1488: 6e 01 18 56 26 2f 54 29 5a 25 11 28 24 81 0f 01 n..V&/T)Z%.($...
+| 1504: 1c 06 39 06 13 59 09 07 81 39 16 0c 39 27 4a 01 ..9..Y...9..9'J.
+| 1520: 14 2a 03 53 23 81 0d 7d 5b 06 03 01 18 1e 03 81 .*.S#...[.......
+| 1536: 02 34 37 29 15 34 81 30 36 01 1a 81 25 19 07 21 .47).4.06...%..!
+| 1552: 07 33 12 82 02 45 04 05 01 12 82 0f 42 55 1d 08 .3...E......BU..
+| 1568: 1a 44 3d 01 16 18 17 36 54 6e 1b 49 1f 30 09 1c .D=....6Tn.I.0..
+| 1584: 01 16 68 81 00 08 48 3a 13 50 3c 28 27 01 1c 28 ..h...H:.P<('..(
+| 1600: 03 06 12 5b 06 30 38 04 65 54 1a 0b 4d 01 20 03 ...[.08.eT..M. .
+| 1616: 09 3d 27 04 11 59 11 1a 0b 73 53 81 03 04 26 02 .='..Y...sS...&.
+| 1632: 01 32 02 04 83 3e 02 01 36 01 02 73 09 04 81 14 .2...>..6..s....
+| 1648: 02 01 37 0a 04 83 30 02 01 62 08 04 84 4d 02 02 ..7...0..b...M..
+| 1664: 63 7a 0a 04 84 08 02 01 64 07 04 83 61 03 02 7a cz......d...a..z
+| 1680: 67 09 02 58 02 02 65 69 09 02 4e 02 05 67 eb 9b g..X..ei..N..g..
+| 1696: a1 72 09 04 81 06 02 01 68 01 04 82 13 02 01 69 .r......h......i
+| 1712: 08 04 84 39 01 04 82 45 02 01 6a 0a 04 83 72 02 ...9...E..j...r.
+| 1728: 02 6b 70 07 04 81 25 02 01 6c 0a 02 5a 02 01 6d .kp...%..l..Z..m
+| 1744: 03 08 82 58 81 11 01 04 84 2c 02 01 6e 07 02 74 ...X.....,..n..t
+| 1760: 02 01 6f 05 04 82 7d 02 01 71 0a 02 7c 02 02 72 ..o......q..|..r
+| 1776: 75 05 04 83 09 02 01 74 03 04 83 1d 02 01 75 07 u......t......u.
+| 1792: 04 84 21 02 01 76 07 04 84 49 02 01 77 03 02 09 ..!..v...I..w...
+| 1808: 02 04 81 01 02 01 78 06 04 81 0f 02 01 7a 04 04 ......x......z..
+| 1824: 81 3e 02 04 c2 aa 64 6f 05 04 83 11 03 02 bc 64 .>....do.......d
+| 1840: 09 04 81 7b 02 05 c6 80 39 63 64 01 04 83 62 03 ........9cd...b.
+| 1856: 01 92 09 04 82 42 02 02 ce bc 09 02 4d 02 02 cf .....B......M...
+| 1872: 97 06 04 83 42 02 02 d1 8b 02 02 2d 02 05 dd b1 ....B......-....
+| 1888: ca b2 70 01 02 1b 02 03 e6 b5 96 09 04 81 50 02 ..p...........P.
+| 1904: 04 e8 b8 aa 6e 08 04 82 1a 02 05 f0 90 b2 b2 6c ....n..........l
+| 1920: 01 02 59 02 04 f1 8f 99 80 0a 04 83 25 01 01 6f ..Y.........%..o
+| 1936: 01 26 05 6b 0f 30 12 1f 16 5d 19 08 20 08 33 33 .&.k.0...].. .33
+| 1952: 1e 12 31 31 06 01 16 04 63 33 67 24 2b 81 0a 5d ..11....c3g$+..]
+| 1968: 2c 0b 01 14 18 0f 36 82 49 0c 1c 08 27 4b 01 1a ,.....6.I...'K..
+| 1984: 4b 24 3a 13 64 07 14 0b 43 08 68 2e 3c 01 26 1a K$:.d...C.h.<.&.
+| 2000: 0b 06 58 10 3d 1b 0a 2f 3e 27 36 1b 1b 21 05 25 ..X.=../>'6..!.%
+| 2016: 0d 41 01 12 81 16 4b 2e 7c 7d 32 1f 1e 01 1a 2e .A....K.|.2.....
+| 2032: 20 62 72 11 22 05 20 0a 2c 24 60 5e 01 2a 0e 5e br... .,$`^.*.^
+| 2048: 13 22 2d 1c 0c 1f 0c 10 0c 47 05 4e 03 15 06 33 ..-......G.N...3
+| 2064: 1d 06 29 01 10 81 08 81 0b 81 48 53 11 01 20 14 ..).......HS.. .
+| 2080: 25 81 17 10 08 08 47 2a 56 2b 2f 20 05 26 22 02 %.....G*V+/ .&..
+| 2096: 01 30 0a 02 5e 03 02 39 76 08 04 82 5c 02 01 31 .0..^..9v......1
+| 2112: 04 02 54 02 01 33 01 04 81 2d 02 02 36 37 09 02 ..T..3...-..67..
+| 2128: 45 03 01 61 04 04 84 16 02 01 37 0a 04 84 5e 02 E..a......7...^.
+| 2144: 03 39 c2 b3 01 04 83 2c 02 01 61 08 04 82 4b 02 .9.....,..a...K.
+| 2160: 01 62 08 04 83 08 03 02 65 30 07 04 84 0d 02 01 .b......e0......
+| 2176: 64 02 04 82 5e 02 04 81 07 02 05 65 70 6b 7a 35 d...^......epkz5
+| 2192: 02 02 4e 03 03 db 8a 69 01 04 83 0b 02 01 66 05 ..N....i......f.
+| 2208: 04 84 34 03 01 68 04 04 84 51 02 01 67 05 02 53 ..4..h...Q..g..S
+| 2224: 02 04 82 78 02 01 68 09 04 83 6f 02 01 69 03 04 ...x..h...o..i..
+| 2240: 81 42 02 01 6a 01 04 84 55 03 04 84 10 02 04 81 .B..j...U.......
+| 2256: 56 03 02 72 74 06 04 83 20 02 02 6c 7a 01 04 83 V..rt... ..lz...
+| 2272: 38 02 01 6e 01 02 15 02 01 6f 01 04 81 7c 01 02 8..n.....o...|..
+| 2288: 27 02 01 73 01 02 36 04 02 2e 03 03 65 ce bc 08 '..s..6.....e...
+| 2304: 04 82 43 02 01 74 09 04 82 7f 02 01 75 07 04 82 ..C..t......u...
+| 2320: 13 03 01 66 07 04 83 21 03 02 6a 69 07 04 83 7e ...f...!..ji...~
+| 2336: 03 01 6b 01 04 84 26 02 01 76 0a 04 82 7f 03 05 ..k...&..v......
+| 2352: 67 da b2 65 75 0a 04 84 13 03 06 c2 be c9 87 6b g..eu..........k
+| 2368: 61 07 04 81 5b 02 02 77 64 01 02 3c 02 01 7a 06 a...[..wd..<..z.
+| 2384: 04 81 21 01 04 81 29 02 04 84 4b 03 02 79 30 09 ..!...)...K..y0.
+| 2400: 04 83 7d 03 02 ce bc 02 04 81 6a 02 02 c2 aa 05 ..........j.....
+| 2416: 02 50 03 01 b2 02 04 81 12 05 02 3e 04 01 63 07 .P.........>..c.
+| 2432: 04 84 04 03 03 b3 62 61 01 04 84 3e 03 02 ba 6f ......ba...>...o
+| 2448: 02 04 84 51 02 02 c4 91 04 04 84 36 02 05 ce b9 ...Q.......6....
+| 2464: 65 c9 97 07 04 83 76 02 04 ef 82 ac 6d 09 02 5d e.....v.....m..]
+| 2480: 02 05 f0 92 bd b3 6f 03 04 81 25 03 04 99 ba 8f ......o...%.....
+| 2496: 64 02 04 81 1f 02 05 f3 8a bd b1 6d 09 04 81 28 d..........m...(
+| 2512: 01 01 70 01 18 46 7c 1f 14 0a 1b 2e 1c 2d 14 6b ..p..F|......-.k
+| 2528: 07 01 18 19 81 05 2e 28 40 11 2b 22 0b 07 18 01 .......(@.+.....
+| 2544: 14 40 13 81 36 12 2d 7f 1f 1b 1a 01 12 82 76 1e .@..6.-.......v.
+| 2560: 1d 12 81 03 07 12 01 10 5a 81 38 19 36 52 26 18 ........Z.8.6R&.
+| 2576: 01 12 64 5d 40 25 05 57 33 31 11 01 1e 36 36 25 ..d]@%.W31...66%
+| 2592: 1b 28 07 22 42 13 0f 07 1c 5a 73 51 01 24 07 2d .(..B....ZsQ.$.-
+| 2608: 06 03 81 00 22 03 1d 19 18 26 2c 16 23 4f 76 08 .........&,.#Ov.
+| 2624: 01 1c 11 1b 54 78 23 1a 81 13 75 04 0c 14 12 0c ....Tx#...u.....
+| 2640: 01 12 24 0d 81 4d 11 7f 22 35 2e 02 01 30 02 04 ..$..M...5...0..
+| 2656: 83 5e 02 01 31 0a 04 81 47 03 05 e7 b2 a5 c3 9f .^..1...G.......
+| 2672: 04 04 83 16 02 01 35 08 02 35 02 02 36 79 09 04 ......5..5..6y..
+| 2688: 82 24 02 01 37 01 04 81 30 03 02 6d 65 04 04 82 .$..7...0..me...
+| 2704: 0e 02 02 38 63 06 02 41 03 02 c9 aa 06 04 84 5b ...8c..A.......[
+| 2720: 02 01 61 03 04 83 0b 03 04 84 4c 03 04 83 5f 03 ..a.......L..._.
+| 2736: 01 6c 07 04 83 7f 02 01 63 04 04 84 7b 02 01 64 .l......c......d
+| 2752: 04 04 83 5d 02 01 65 06 04 83 4c 03 01 74 08 04 ...]..e...L..t..
+| 2768: 82 0b 02 01 68 03 02 06 03 04 71 e7 8e bb 08 04 ....h.....q.....
+| 2784: 81 43 03 01 74 07 04 82 30 02 03 69 ce bc 07 04 .C..t...0..i....
+| 2800: 81 3c 02 03 6a 62 6c 09 02 4b 02 01 6c 09 04 81 .<..jbl..K..l...
+| 2816: 60 02 01 6d 05 04 82 6f 04 04 81 62 03 04 6c 74 `..m...o...b..lt
+| 2832: c2 b9 07 04 85 08 03 02 c2 be 08 04 83 2b 02 02 .............+..
+| 2848: 6e 73 08 04 81 1f 03 01 75 04 04 83 72 02 01 6f ns......u...r..o
+| 2864: 06 08 81 14 83 2f 03 02 ce bc 0a 04 83 67 03 03 ...../.......g..
+| 2880: cf 80 66 07 02 28 02 01 70 01 04 82 2a 03 01 7a ..f..(..p...*..z
+| 2896: 08 04 81 0d 02 01 71 07 04 81 37 02 01 73 05 02 ......q...7..s..
+| 2912: 59 03 01 6d 07 02 7a 02 01 74 05 04 82 62 02 02 Y..m..z..t...b..
+| 2928: 75 6a 03 04 81 37 02 02 77 68 08 04 84 14 02 01 uj...7..wh......
+| 2944: 78 01 04 83 6f 02 01 79 01 04 82 66 06 04 81 36 x...o..y...f...6
+| 2960: 02 01 7a 0a 04 81 15 03 05 6f f0 99 8a a6 08 04 ..z......o......
+| 2976: 82 06 02 02 c2 b2 04 04 83 38 03 03 b3 dd 9d 05 .........8......
+| 2992: 04 83 6f 03 01 b9 06 04 83 66 03 01 ba 01 04 81 ..o......f......
+| 3008: 0c 07 04 83 10 04 01 69 06 04 81 39 03 01 bd 04 .......i...9....
+| 3024: 04 82 00 06 02 16 02 02 da 99 02 04 84 49 02 07 .............I..
+| 3040: dd 9b 6e e6 89 a0 75 01 04 81 6e 02 09 f0 92 ab ..n...u...n.....
+| 3056: ab ec 8c 8d ca 81 01 04 81 46 01 01 71 01 1a 1a .........F..q...
+| 3072: 08 41 65 0b 22 18 69 2f 81 0e 13 05 01 18 08 2d .Ae...i/.......-
+| 3088: 07 04 81 70 23 18 20 1a 0c 74 01 16 1f 11 05 6b ...p#. ..t.....k
+| 3104: 2f 18 47 13 16 30 4c 01 22 12 05 2d 39 05 07 61 /.G..0L....-9..a
+| 3120: 0b 06 0a 56 3f 56 2e 10 0d 50 01 16 1f 1f 3c 2b ...V?V...P....<+
+| 3136: 32 0c 43 4b 81 18 5a 01 18 16 0d 0e 32 40 42 1c 2.CK..Z.....2@B.
+| 3152: 4a 24 12 17 13 01 20 03 6e 0e 1c 0f 04 0b 3b 05 J$.... .n.....;.
+| 3168: 52 4e 0e 23 26 50 20 01 12 59 09 72 4f 47 44 15 RN.#&P ..Y.rOGD.
+| 3184: 41 28 01 16 5e 36 24 0e 19 81 15 07 81 26 16 01 A(..^6$......&..
+| 3200: 18 81 0e 0f 5e 81 01 04 04 1a 1a 44 50 02 02 31 ....^......DP..1
+| 3216: 68 09 04 83 76 02 01 32 07 04 81 70 02 02 33 7a h...v..2...p..3z
+| 3232: 05 04 84 4a 02 01 34 08 04 81 02 03 01 69 08 04 ...J..4......i..
+| 3248: 81 0b 03 01 76 02 04 81 62 02 01 37 04 04 81 78 ....v...b..7...x
+| 3264: 05 04 82 51 01 02 15 02 03 38 75 77 06 04 82 1b ...Q.....8uw....
+| 3280: 02 01 39 04 02 20 03 04 84 03 03 01 74 03 04 81 ..9.. ......t...
+| 3296: 60 02 01 61 04 02 24 01 04 83 63 02 01 62 09 02 `..a..$...c..b..
+| 3312: 15 02 01 63 05 06 51 84 0e 03 03 c2 be 62 04 04 ...c..Q......b..
+| 3328: 82 3d 02 02 64 70 03 04 83 36 02 01 66 06 04 82 .=..dp...6..f...
+| 3344: 66 02 02 6a 38 02 04 84 0a 02 02 6d 61 05 04 81 f..j8......ma...
+| 3360: 30 03 01 6e 08 04 83 71 02 01 6e 01 02 60 02 01 0..n...q..n..`..
+| 3376: 70 02 04 82 43 02 01 71 05 06 82 48 49 02 01 73 p...C..q...HI..s
+| 3392: 06 04 81 1f 02 01 74 09 04 81 70 02 01 75 05 04 ......t...p..u..
+| 3408: 83 44 02 01 76 05 04 84 08 04 04 82 1d 02 01 77 .D..v..........w
+| 3424: 09 02 69 02 02 78 69 08 04 82 79 02 01 7a 05 04 ..i..xi...y..z..
+| 3440: 84 22 03 09 66 cf 9f 71 67 36 e2 b1 a5 02 04 81 ....f..qg6......
+| 3456: 21 02 03 c2 aa 6a 01 04 81 12 03 01 b3 03 02 35 !....j.........5
+| 3472: 02 04 84 1f 04 04 84 19 03 04 b9 d4 87 68 02 04 .............h..
+| 3488: 81 42 03 01 ba 06 04 84 44 04 02 64 67 03 04 84 .B......D..dg...
+| 3504: 4b 03 01 bc 04 04 81 42 03 01 be 01 02 48 02 02 K......B.....H..
+| 3520: ce bc 0a 04 81 2e 02 02 cf a7 02 04 83 6e 02 04 .............n..
+| 3536: e7 a4 ba 67 07 04 83 59 01 01 72 01 20 41 1d 3a ...g...Y..r. A.:
+| 3552: 0b 05 04 12 1f 3c 03 2f 81 05 81 2e 13 01 14 0c .....<./........
+| 3568: 81 3f 17 81 07 63 08 81 07 01 12 81 06 71 17 0b .?...c.......q..
+| 3584: 46 81 5a 13 01 18 02 81 06 0f 49 42 2d 39 2e 2c F.Z.......IB-9.,
+| 3600: 45 27 01 16 06 19 27 1d 3f 53 81 3a 45 0d 20 01 E'....'.?S.:E. .
+| 3616: 14 1b 07 2a 76 37 36 09 82 4d 04 01 14 0c 30 2d ...*v76..M....0-
+| 3632: 2d 51 38 31 49 49 74 01 16 29 17 0a 2f 72 1d 4a -Q81IIt..)../r.J
+| 3648: 81 27 11 18 01 14 63 81 1c 5f 04 4d 38 19 18 0e .'....c.._.M8...
+| 3664: 01 1c 56 2f 25 5f 07 05 03 28 24 5d 2b 4d 42 13 ..V/%_...($]+MB.
+| 3680: 02 02 30 71 01 04 84 03 02 01 33 08 04 83 16 01 ..0q......3.....
+| 3696: 04 83 3d 02 01 35 03 02 58 02 01 37 04 04 83 0c ..=..5..X..7....
+| 3712: 03 01 64 04 04 84 46 02 02 38 61 0a 04 83 66 03 ..d...F..8a...f.
+| 3728: 02 73 69 09 04 82 5f 02 01 39 09 04 84 17 02 02 .si..._..9......
+| 3744: 61 6a 03 04 83 12 02 01 62 07 04 82 72 03 01 65 aj......b...r..e
+| 3760: 09 04 83 14 04 01 68 07 04 82 24 6a 09 0d 07 07 ......h...$j....
+| 3776: 06 07 07 07 07 06 07 07 08 07 0f 0d 0d 07 10 07 ................
+| 3792: 07 07 08 0a 06 07 08 0a 06 09 0b 0c 08 10 0c 08 ................
+| 3808: 0a 79 0b 0b 0b 06 07 07 0a 0b 0b 07 07 07 07 06 .y..............
+| 3824: 07 07 08 09 07 09 10 07 07 07 0a 07 08 07 07 07 ................
+| 3840: 07 0c 0d 07 0b 08 0a 0d 09 09 07 07 81 12 07 0b ................
+| 3856: 07 0b 07 07 08 06 0c 08 0b 07 07 0b 07 0b 07 07 ................
+| 3872: 07 07 07 07 07 07 0b 09 0b 07 08 07 06 08 07 0b ................
+| 3888: 07 07 0c 07 09 08 09 08 08 09 09 81 11 07 0a 07 ................
+| 3904: 07 08 07 07 07 0b 07 0b 07 08 06 0d 06 07 06 08 ................
+| 3920: 07 07 07 0a 07 07 0a 08 0b 07 07 08 07 0a 09 0a ................
+| 3936: 0a 0a 81 22 06 08 06 07 07 07 07 09 07 07 08 0b ................
+| 3952: 0a 09 07 07 0a 07 07 0f 08 08 06 0a 09 09 07 07 ................
+| 3968: 07 08 07 07 0b 0c 07 0f 08 08 07 0a 07 09 08 08 ................
+| 3984: 0b 09 0b 0a 0b 81 0b 07 07 0b 06 08 07 08 07 08 ................
+| 4000: 0f 07 07 07 07 07 06 0a 07 09 08 07 0b 0a 08 08 ................
+| 4016: 07 09 08 08 07 07 07 06 06 07 08 08 07 0b 07 0b ................
+| 4032: 08 09 07 0b 07 0a 08 0d 0f 81 13 08 07 08 07 07 ................
+| 4048: 07 0e 09 0a 07 0a 06 08 09 08 07 08 08 07 06 07 ................
+| 4064: 08 07 07 07 0b 06 08 07 0f 09 0e 0a 07 08 07 06 ................
+| 4080: 08 08 0a 81 08 08 0b 06 07 07 08 08 07 08 07 07 ................
+| page 23 offset 90112
+| 0: 0d 00 00 00 01 00 22 00 00 22 00 00 00 00 00 00 ................
+| 32: 00 00 9f 56 88 80 80 80 80 04 04 00 bf 30 00 00 ...V.........0..
+| 48: 0e 8c 03 30 72 64 04 04 81 24 02 01 66 06 04 81 ...0rd...$..f...
+| 64: 05 02 04 81 0f 03 01 70 0a 04 82 45 02 01 67 01 .......p...E..g.
+| 80: 04 84 1a 02 04 81 03 07 04 82 13 02 01 68 05 04 .............h..
+| 96: 83 1d 02 01 6a 02 04 83 03 02 06 82 26 39 03 01 ....j.......&9..
+| 112: 67 01 04 81 0a 02 02 6c 70 09 02 48 03 03 c9 be g......lp..H....
+| 128: 6e 05 04 83 58 02 01 6e 07 04 83 10 03 02 30 6d n...X..n......0m
+| 144: 07 04 84 20 02 03 6f d2 b1 09 04 84 43 02 01 70 ... ..o.....C..p
+| 160: 07 02 24 01 02 7d 02 01 71 07 04 83 2f 03 04 81 ..$.....q.../...
+| 176: 18 03 01 62 08 04 82 39 02 02 72 75 0a 04 81 24 ...b...9..ru...$
+| 192: 02 01 75 02 04 81 4e 05 04 83 3d 02 01 76 03 02 ..u...N...=..v..
+| 208: 64 03 02 6b 6c 08 04 82 2f 02 01 78 05 04 84 66 d..kl.../..x...f
+| 224: 02 02 79 36 02 02 39 02 02 c2 b2 04 04 84 7c 04 ..y6..9.......|.
+| 240: 02 dd ab 09 04 83 71 03 02 b3 31 09 04 82 33 03 ......q...1...3.
+| 256: 01 bc 04 02 6e 03 01 bd 07 04 85 09 04 01 75 07 ....n.........u.
+| 272: 02 0e 02 02 ce bc 07 02 6b 02 02 d1 9e 0a 04 84 ........k.......
+| 288: 51 02 03 d5 b1 36 09 02 1e 02 04 e4 8d ac 38 01 Q....6........8.
+| 304: 02 61 02 04 f0 96 85 81 09 04 83 5e 03 03 9a 87 .a.........^....
+| 320: 8d 05 04 83 51 01 01 73 01 30 0f 1c 12 09 29 0d ....Q..s.0....).
+| 336: 07 2e 81 01 11 2a 22 1d 04 2e 0f 08 04 23 29 0b .....*.......#).
+| 352: 3b 15 01 16 2f 2f 81 20 81 07 13 56 26 3b 25 01 ;...//. ...V&;%.
+| 368: 28 49 03 0a 61 04 08 2e 03 22 10 38 34 0c 09 29 (I..a......84..)
+| 384: 0c 0c 34 28 0b 01 1e 0f 3c 5b 13 0a 34 11 5a 73 ..4(....<[..4.Zs
+| 400: 1e 22 03 1a 54 03 01 22 08 06 3c 41 06 2c 2b 16 ....T......^btG7
+| 1328: 20 3d 07 20 0e 01 1e 10 69 42 48 08 04 08 56 08 =. ....iBH...V.
+| 1344: 66 21 10 07 1a 34 01 18 1f 28 31 41 81 06 36 19 f!...4...(1A..6.
+| 1360: 53 0d 0f 0c 01 1c 16 0a 0e 04 52 17 22 48 7b 43 S.........R..H.C
+| 1376: 3e 04 47 44 01 1e 25 4b 0b 30 2c 0a 0c 6b 71 15 >.GD..%K.0,..kq.
+| 1392: 03 4c 19 0f 16 01 22 2b 13 28 1d 24 4c 0f 46 0f .L.....+.(.$L.F.
+| 1408: 2f 0b 1c 03 0e 4a 4a 33 01 10 19 29 81 24 0a 82 /....JJ3...).$..
+| 1424: 0c 46 02 01 30 05 04 82 5d 02 01 32 07 04 83 1f .F..0...]..2....
+| 1440: 02 02 33 6c 06 04 84 6f 02 01 35 08 02 33 02 06 ..3l...o..5..3..
+| 1456: 37 6e 66 ef 98 bd 06 04 81 35 02 02 61 76 03 06 7nf......5..av..
+| 1472: 82 12 73 02 01 63 02 02 57 02 04 83 09 03 01 69 ..s..c..W......i
+| 1488: 05 02 66 02 01 64 06 04 81 01 02 01 65 06 02 3b ..f..d......e..;
+| 1504: 03 01 71 01 04 83 6c 02 01 66 01 04 84 7c 01 04 ..q...l..f...|..
+| 1520: 83 5c 03 03 69 c2 b2 08 04 84 74 03 03 73 c2 bd ....i.....t..s..
+| 1536: 03 04 84 0a 02 01 67 06 08 82 1d 82 56 04 04 81 ......g.....V...
+| 1552: 33 02 01 68 09 02 51 02 01 69 0a 02 08 02 01 6a 3..h..Q..i.....j
+| 1568: 06 02 6c 03 01 6e 0a 04 81 2c 02 01 6c 08 04 83 ..l..n...,..l...
+| 1584: 15 02 01 6d 04 04 84 24 03 01 33 01 04 81 3a 03 ...m...$..3...:.
+| 1600: 03 6e c2 b9 07 04 81 6b 02 01 6f 06 04 83 28 02 .n.....k..o...(.
+| 1616: 03 70 77 71 0a 04 81 2a 02 01 71 0a 04 84 34 02 .pwq...*..q...4.
+| 1632: 01 73 05 04 81 7f 03 02 6a 73 01 04 83 08 02 01 .s......js......
+| 1648: 74 02 04 81 60 01 04 83 5e 06 04 82 37 02 01 76 t...`...^...7..v
+| 1664: 08 04 81 2d 02 01 77 01 04 82 12 01 02 46 02 03 ...-..w......F..
+| 1680: 78 73 66 04 02 37 03 02 7a 62 02 04 83 1a 02 01 xsf..7..zb......
+| 1696: 79 04 02 1a 03 04 84 2a 02 04 84 22 02 01 7a 05 y......*......z.
+| 1712: 04 83 4d 02 02 c2 b2 09 04 83 04 03 01 b9 04 04 ..M.............
+| 1728: 82 3e 03 02 bd 6c 07 04 84 06 03 02 be 73 0a 04 .>...l.......s..
+| 1744: 83 5b 02 06 c9 82 71 c6 9a 61 05 02 7a 03 04 89 .[....q..a..z...
+| 1760: e3 a1 be 04 04 83 05 02 04 ca aa 33 67 04 04 84 ...........3g...
+| 1776: 61 02 03 d6 83 6b 08 04 81 77 02 02 da b0 0a 02 a....k...w......
+| 1792: 32 03 01 b6 0a 02 13 02 03 e3 9a bb 04 04 84 42 2..............B
+| 1808: 02 04 f0 b6 8e b7 06 04 83 5a 01 01 76 01 1a 7f .........Z..v...
+| 1824: 38 16 7c 3b 26 23 08 05 47 1c 19 20 01 1c 28 45 8.|;..G.. ..(E
+| 1840: 20 0a 81 0a 45 15 44 05 03 1d 26 44 01 10 0c 3e ...E.D...&D...>
+| 1856: 26 3c 6d 82 43 04 01 1c 04 15 3a 56 62 39 16 03 &..xqg2..
+| 2192: 84 72 03 02 76 76 01 04 82 1f 02 03 79 75 6f 04 .r..vv......yuo.
+| 2208: 04 84 77 03 04 f6 84 93 a8 05 04 83 6c 02 01 7a ..w.........l..z
+| 2224: 02 02 7c 02 04 83 21 05 04 83 07 02 02 c2 aa 01 ..|...!.........
+| 2240: 04 81 2f 03 01 bc 0a 04 81 65 02 02 c3 be 01 04 ../......e......
+| 2256: 82 04 02 02 df 94 07 04 82 5f 02 04 ea 80 84 6e ........._.....n
+| 2272: 04 04 84 73 03 03 84 b1 75 06 04 84 56 02 03 ef ...s....u...V...
+| 2288: 89 9e 07 04 83 7b 02 04 f0 92 ab 9a 0a 04 84 60 ...............`
+| 2304: 01 01 77 01 18 49 1d 46 47 07 65 21 05 81 13 1a ..w..I.FG.e!....
+| 2320: 06 01 16 81 7e 5a 26 1b 12 05 0f 44 03 57 01 16 ....~Z&....D.W..
+| 2336: 14 4d 31 81 0d 2c 2a 07 03 81 2c 01 14 23 0a 2a .M1..,*...,..#.*
+| 2352: 66 18 65 76 21 5a 5f 01 14 14 81 4c 11 10 24 81 f.ev!Z_....L..$.
+| 2368: 49 48 28 01 16 7b 0a 4c 08 10 22 81 2d 03 69 38 IH(....L....-.i8
+| 2384: 01 0e 3c 6e 1f 81 6a 2a 16 01 1a 3b 81 25 0d 28 ....d......i
+| 2592: 06 04 83 60 03 01 35 0a 04 82 3d 02 01 6b 09 04 ...`..5...=..k..
+| 2608: 83 34 03 01 70 05 04 81 6e 02 01 6c 09 04 83 28 .4..p...n..l...(
+| 2624: 02 01 6d 04 04 82 6f 04 04 83 09 01 04 84 48 02 ..m...o.......H.
+| 2640: 04 6e 79 68 31 03 04 83 4d 02 01 6f 03 02 2d 03 .nyh1...M..o..-.
+| 2656: 01 6e 09 02 61 02 01 70 04 04 82 67 02 03 71 63 .n..a..p...g..qc
+| 2672: 79 09 04 81 0b 03 02 c2 bc 0a 02 30 02 01 72 08 y..........0..r.
+| 2688: 02 5e 02 01 73 08 04 81 07 02 01 75 05 02 6c 05 .^..s......u..l.
+| 2704: 04 84 56 02 01 76 08 04 81 01 02 01 78 05 04 84 ..V..v......x...
+| 2720: 61 02 04 84 6c 02 01 7a 0a 04 83 2e 02 02 c2 ba a...l..z........
+| 2736: 04 04 81 39 03 01 bc 01 04 83 23 02 02 c9 a8 03 ...9......#.....
+| 2752: 04 83 38 02 04 ce bc 62 68 02 04 82 25 02 02 d4 ..8....bh...%...
+| 2768: 85 08 04 82 2d 02 02 db 91 09 04 84 29 01 01 78 ....-.......)..x
+| 2784: 01 0a 27 82 4d 5c 23 01 1c 11 62 38 15 17 67 05 ..'.M.#...b8..g.
+| 2800: 3e 05 33 1b 29 1c 26 01 16 0d 81 33 0c 0c 09 61 >.3.).&....3...a
+| 2816: 4e 1a 54 47 01 18 22 43 09 60 11 2a 08 1b 81 30 N.TG...C.`.*...0
+| 2832: 27 44 01 24 2d 06 1c 19 2a 5e 22 24 04 2a 5c 0b 'D.$-...*^.$.*..
+| 2848: 42 0d 0f 37 06 2d 01 1a 4c 28 2d 47 14 46 18 45 B..7.-..L(-G.F.E
+| 2864: 0e 2c 04 81 1a 01 14 1d 33 75 70 62 32 75 26 2d .,......3upb2u&-
+| 2880: 08 01 18 41 0b 0a 0c 1f 17 27 61 81 37 3b 21 01 ...A.....'a.7;!.
+| 2896: 1e 39 12 0e 1b 17 17 08 4c 04 81 18 0a 81 12 1a .9......L.......
+| 2912: 01 22 0d 11 30 32 1f 5d 31 08 1e 2e 23 3b 03 49 ....02.]1...#;.I
+| 2928: 05 6d 03 02 01 30 01 04 81 47 04 02 22 03 02 65 .m...0...G.....e
+| 2944: 77 0a 04 82 16 02 01 32 04 08 81 55 81 2e 01 06 w......2...U....
+| 2960: 57 3a 73 02 01 36 0a 02 4f 03 01 7a 04 04 81 27 W:s..6..O..z...'
+| 2976: 02 01 61 05 04 82 21 02 01 62 01 02 7e 02 01 63 ..a...!..b..~..c
+| 2992: 05 04 81 0c 03 02 c2 b3 08 04 81 24 02 01 65 05 ...........$..e.
+| 3008: 04 84 5e 01 04 81 04 01 04 82 3e 01 04 83 46 02 ..^.......>...F.
+| 3024: 01 67 02 04 84 09 02 01 68 01 04 83 04 02 01 69 .g......h......i
+| 3040: 04 04 82 31 04 04 82 5a 02 01 6a 01 04 81 21 02 ...1...Z..j...!.
+| 3056: 01 6b 08 04 83 5e 03 02 68 7a 0a 04 84 67 03 04 .k...^..hz...g..
+| 3072: 77 78 64 6f 04 04 81 4c 02 01 6d 04 04 83 03 03 wxdo...L..m.....
+| 3088: 01 37 01 04 83 75 03 01 67 07 04 82 04 02 01 6e .7...u..g......n
+| 3104: 06 02 2c 04 04 83 52 02 01 6f 05 04 81 14 02 03 ..,...R..o......
+| 3120: 70 6d 73 08 04 83 68 02 01 71 06 04 84 7c 02 01 pms...h..q...|..
+| 3136: 72 02 04 84 20 03 04 83 33 01 04 82 13 02 04 82 r... ...3.......
+| 3152: 17 03 01 69 04 04 81 1c 03 01 76 04 04 84 71 02 ...i......v...q.
+| 3168: 01 73 04 04 82 53 02 01 75 01 04 81 3b 05 04 82 .s...S..u...;...
+| 3184: 2a 02 01 77 03 04 82 4f 02 01 79 02 02 60 02 01 *..w...O..y..`..
+| 3200: 7a 08 04 81 34 02 04 c2 aa 6b 61 04 04 82 7b 02 z...4....ka.....
+| 3216: 02 c6 b4 0a 04 81 02 02 02 ca 83 03 02 5a 02 02 .............Z..
+| 3232: d4 ae 04 04 81 45 02 02 d7 bb 0a 04 83 78 02 02 .....E.......x..
+| 3248: dc 96 06 04 82 1f 02 02 df 95 05 04 82 11 02 03 ................
+| 3264: ea b7 a6 07 04 83 6e 02 04 f0 93 a0 b9 06 04 82 ......n.........
+| 3280: 6c 02 05 f5 af 82 82 73 07 02 41 01 01 79 01 1e l......s..A..y..
+| 3296: 07 21 30 08 81 04 17 25 0a 0c 81 17 27 81 25 01 .!0....%....'.%.
+| 3312: 1a 03 5d 21 81 16 07 3f 27 16 3f 14 08 18 01 12 ..]!...?'.?.....
+| 3328: 68 4f 0e 25 34 3a 3d 81 16 01 12 09 81 0a 3c 72 hO.%4:=...............n..t...
+| 3648: 17 02 03 c5 a7 33 0a 04 84 55 02 02 c7 9d 04 04 .....3...U......
+| 3664: 81 60 02 08 ca 81 30 68 f0 90 90 b2 09 04 84 2e .`....0h........
+| 3680: 03 01 b5 02 04 82 33 02 03 d1 9e 6c 02 04 81 1a ......3....l....
+| 3696: 02 02 d4 93 04 04 81 05 02 02 d8 ab 03 04 82 49 ...............I
+| 3712: 03 02 b8 73 01 04 84 1d 02 03 e2 af 9d 07 02 4d ...s...........M
+| 3728: 02 03 ec 8f ad 03 04 84 47 01 01 7a 01 22 1d 42 ........G..z...B
+| 3744: 10 5f 1b 08 63 1e 07 0a 30 07 0b 26 31 61 07 01 ._..c...0..&1a..
+| 3760: 1c 0a 37 29 0a 68 40 38 0a 4a 04 08 0b 07 0f 07 ..7).h@8.J......
+| 3776: 0c 07 07 09 07 08 09 09 0b 07 08 0b 06 08 07 07 ................
+| 3792: 08 08 08 06 07 06 07 08 08 09 0a 09 81 31 06 07 .............1..
+| 3808: 0d 06 06 07 0a 07 08 0e 08 07 07 0b 06 07 09 07 ................
+| 3824: 0b 07 07 07 0c 07 07 07 07 08 09 08 07 0a 81 14 ................
+| 3840: 07 07 06 0b 08 06 07 09 07 07 0f 0e 06 0b 0b 0a ................
+| 3856: 0c 07 06 06 09 06 08 0b 09 07 08 0f 0b 07 0c 08 ................
+| 3872: 06 07 07 09 08 09 07 09 0a 81 20 07 07 08 06 0c .......... .....
+| 3888: 09 0a 06 07 06 07 0b 09 09 0d 06 06 06 07 07 07 ................
+| 3904: 07 09 07 09 07 07 08 0f 07 0a 08 08 0e 07 08 07 ................
+| 3920: 08 08 0b 0a 0a 09 07 06 09 0a 81 10 07 06 09 0a ................
+| 3936: 07 08 07 07 08 07 0d 0a 07 07 0a 07 08 07 13 0a ................
+| 3952: 08 08 08 08 07 09 0a 08 09 0a 0e 08 07 08 08 0a ................
+| 3968: 09 09 0a 81 08 07 08 08 0b 08 07 07 08 0b 07 0b ................
+| 3984: 0b 0a 07 07 07 07 07 07 07 07 07 07 0f 0a 06 06 ................
+| 4000: 07 09 07 06 07 0a 07 0b 07 08 07 08 0a 08 08 81 ................
+| 4016: 16 0a 08 0e 06 07 07 06 07 08 13 07 07 0b 07 07 ................
+| 4032: 08 0a 07 07 07 0a 07 09 07 13 07 07 07 0b 07 06 ................
+| 4048: 07 0a 08 07 08 08 08 08 09 0a 0a 81 06 07 0e 07 ................
+| 4064: 0b 06 0b 0b 0b 07 08 07 0f 07 06 08 07 09 0b 0a ................
+| 4080: 06 0e 07 08 09 07 09 08 0e 07 09 08 08 08 08 09 ................
+| page 24 offset 94208
+| 0: 0d 00 00 00 01 00 28 00 00 28 00 00 00 00 00 00 ......(..(......
+| 32: 00 00 00 00 00 00 00 00 9f 50 88 80 80 80 80 05 .........P......
+| 48: 04 00 bf 24 00 09 0e 5b 14 06 1c 0d 12 03 18 37 ...$...[.......7
+| 64: 1f 05 55 32 10 15 5a 81 07 4b 04 01 16 07 0e 5f ..U2..Z..K....._
+| 80: 0b 46 0b 22 81 41 24 23 01 28 2a 07 11 09 15 0b .F...A$#.(*.....
+| 96: 0f 0c 09 0a 1e 05 1f 5e 07 19 1c 1e 33 3e 01 18 .......^....3>..
+| 112: 26 0c 1b 43 08 38 11 05 81 1b 5f 20 01 1e 06 1c &..C.8...._ ....
+| 128: 36 27 33 20 53 4f 06 03 1a 2f 2c 40 6d 01 18 72 6'3 SO.../,@m..r
+| 144: 81 0d 20 3a 23 05 34 19 23 2b 36 01 12 2c 4d 0c .. :#.4.#+6..,M.
+| 160: 59 82 04 46 40 0f 01 1a 28 15 32 33 2e 52 0f 49 Y..F@...(.23.R.I
+| 176: 04 09 81 33 26 03 30 7a 34 01 04 82 05 02 01 36 ...3&.0z4......6
+| 192: 06 04 81 5a 02 04 37 ce bc 74 09 04 81 17 02 01 ...Z..7..t......
+| 208: 38 01 04 83 79 03 03 dd 9a 73 02 04 84 12 02 01 8...y....s......
+| 224: 61 04 04 82 1c 02 01 62 01 04 83 4e 07 04 82 5b a......b...N...[
+| 240: 02 01 63 0a 02 4e 02 01 64 04 04 84 7d 02 01 65 ..c..N..d......e
+| 256: 01 04 84 2a 02 01 67 01 04 81 75 02 04 68 d0 bf ...*..g...u..h..
+| 272: 70 09 04 81 4a 02 01 69 01 04 84 34 05 04 82 48 p...J..i...4...H
+| 288: 02 01 6a 02 02 1d 04 04 81 54 02 01 6b 03 04 81 ..j......T..k...
+| 304: 0d 02 01 6c 09 04 83 54 02 01 6e 06 02 0b 01 04 ...l...T..n.....
+| 320: 84 1c 02 01 6f 0a 02 26 03 01 6a 08 04 82 26 03 ....o..&..j...&.
+| 336: 05 73 75 c2 bd 61 03 02 38 02 02 70 37 06 04 81 .su..a..8..p7...
+| 352: 7e 02 01 71 01 04 83 67 03 01 65 06 04 84 08 02 ~..q...g..e.....
+| 368: 01 72 0a 04 82 1e 02 01 74 01 04 82 6c 02 02 5d .r......t...l..]
+| 384: 04 04 84 17 03 04 82 77 02 01 75 04 08 82 22 82 .......w..u.....
+| 400: 0b 02 02 76 6c 03 04 83 25 02 01 77 03 04 81 24 ...vl...%..w...$
+| 416: 03 04 82 42 02 01 78 06 04 82 4a 03 02 c2 b2 02 ...B..x...J.....
+| 432: 04 83 21 02 01 79 09 04 83 43 02 01 7a 04 02 51 ..!..y...C..z..Q
+| 448: 02 02 c2 aa 02 02 51 03 01 b3 09 04 81 2a 03 01 ......Q......*..
+| 464: b9 06 04 82 73 03 02 bd 73 04 02 4e 04 05 76 c2 ....s...s..N..v.
+| 480: be 67 65 08 02 1d 04 03 78 de bc 02 04 83 6d 04 .ge.....x.....m.
+| 496: 01 7a 09 04 84 1d 02 04 ca a2 36 32 07 04 83 2e .z........62....
+| 512: 02 02 d8 aa 04 04 84 31 02 02 df 8a 02 02 73 01 .......1......s.
+| 528: 02 c2 aa 01 08 81 7f 82 01 01 06 56 83 70 02 06 ...........V.p..
+| 544: 74 82 6d 01 06 81 5d 45 01 04 82 7b 01 0c 81 46 t.m...]E.......F
+| 560: 13 6a 82 12 01 0c 82 24 63 15 35 74 01 12 81 14 .j.....$c.5t....
+| 576: 81 24 1f 3d 7c 15 1c 01 0a 82 39 1a 81 6f 03 02 .$.=|.....9..o..
+| 592: 30 65 07 04 83 3a 03 01 63 03 04 81 7d 03 01 65 0e...:..c......e
+| 608: 09 02 03 03 01 66 01 02 6c 04 02 66 7a 03 04 82 .....f..l..fz...
+| 624: 1c 03 01 6b 0a 04 82 46 03 01 7a 08 04 84 2d 03 ...k...F..z...-.
+| 640: 03 c2 bd 73 0a 04 81 10 05 02 c2 bc 03 02 03 04 ...s............
+| 656: 01 be 02 04 84 35 03 04 f0 9f ad ae 08 04 83 41 .....5.........A
+| 672: 02 01 b2 01 0a 3e 77 21 82 5f 01 08 81 74 82 68 .....>w!._...t.h
+| 688: 01 0e 39 81 0c 81 4b 1c 4e 01 0e 83 46 06 3b 1d ..9...K.N...F.;.
+| 704: 0e 38 01 0e 81 50 15 81 53 35 57 01 08 82 7d 26 .8...P..S5W....&
+| 720: 1c 01 04 2f 0e 01 08 66 5d 83 24 01 0e 43 81 10 .../...f].$..C..
+| 736: 24 82 77 04 01 0a 82 0a 81 61 1f 03 01 35 08 04 $.w......a...5..
+| 752: 81 11 03 01 61 09 04 82 0b 03 01 64 07 04 81 7e ....a......d...~
+| 768: 03 01 66 05 04 82 29 03 01 67 03 04 84 17 03 04 ..f...)..g......
+| 784: 69 34 d8 a1 05 04 82 42 03 01 73 04 04 84 3d 03 i4.....B..s...=.
+| 800: 01 76 06 04 81 70 04 03 76 c2 ba 07 04 81 34 03 .v...p..v.....4.
+| 816: 01 78 06 04 83 48 03 03 c2 b3 36 07 02 7f 03 02 .x...H....6.....
+| 832: d4 85 04 04 81 2d 03 02 d9 bc 05 04 83 20 03 04 .....-....... ..
+| 848: ee b5 9c 70 03 04 83 57 03 05 f6 80 80 bb 70 05 ...p...W......p.
+| 864: 04 81 6a 02 01 b3 01 06 82 41 12 01 08 67 0d 82 ..j......A...g..
+| 880: 69 01 0e 81 51 22 5c 7d 81 00 01 10 68 05 2f 81 i...Q.......h./.
+| 896: 4e 81 78 03 01 0a 74 81 58 81 72 01 0c 4e 72 07 N.x...t.X.r..Nr.
+| 912: 79 81 7d 01 10 44 3b 58 66 82 08 0c 2f 01 06 0c y....D;Xf.../...
+| 928: 65 36 01 04 81 02 01 08 5d 43 82 10 03 01 61 06 e6......]C....a.
+| 944: 04 83 3c 03 01 63 07 04 82 32 03 01 68 03 04 82 ..<..c...2..h...
+| 960: 76 03 03 6a 77 6d 0a 04 84 35 03 01 70 01 04 84 v..jwm...5..p...
+| 976: 70 03 01 74 01 06 84 05 0a 06 02 47 04 04 6a 75 p..t.......G..ju
+| 992: ce bc 07 04 82 4d 03 02 75 65 07 04 81 05 03 01 .....M..ue......
+| 1008: 77 01 04 81 59 04 03 6f db 85 08 02 3d 03 04 c2 w...Y..o....=...
+| 1024: be c2 b9 01 04 81 04 03 07 c4 a7 67 d5 bb 7a 68 ...........g..zh
+| 1040: 06 04 84 05 03 02 c7 a5 02 04 81 10 02 01 b9 01 ................
+| 1056: 0c 1e 81 43 0b 81 56 01 08 82 70 81 27 01 06 34 ...C..V...p.'..4
+| 1072: 83 38 01 0c 81 0f 1d 04 81 74 01 06 82 58 65 01 .8.......t...Xe.
+| 1088: 10 27 55 7a 4b 81 00 2c 29 01 0e 04 1f 24 09 83 .'UzK..,)....$..
+| 1104: 44 04 01 08 65 2f 41 2b 01 0c 34 0c 81 17 83 0f D...e/A+..4.....
+| 1120: 01 04 82 69 03 02 61 73 02 02 4d 03 01 65 01 04 ...i..as..M..e..
+| 1136: 81 2e 03 02 69 61 04 04 83 06 04 03 69 69 67 08 ....ia......iig.
+| 1152: 02 1b 03 03 6b c2 ba 06 04 82 49 03 01 6d 04 04 ....k.....I..m..
+| 1168: 84 67 03 01 6f 02 04 82 4b 03 01 70 06 04 84 34 .g..o...K..p...4
+| 1184: 03 04 72 61 76 76 04 02 67 03 03 73 c2 be 07 04 ..ravv..g..s....
+| 1200: 82 17 03 01 76 03 04 81 56 03 01 78 02 04 84 24 ....v...V..x...$
+| 1216: 03 03 79 69 38 05 04 84 68 03 05 c2 aa 63 c2 b2 ..yi8...h....c..
+| 1232: 08 02 69 04 01 b9 06 04 82 75 04 01 ba 01 04 81 ..i......u......
+| 1248: 51 04 01 bc 0a 04 81 0f 03 02 c5 a7 0a 04 84 71 Q..............q
+| 1264: 03 05 c9 99 ee 84 af 03 04 84 10 04 06 9f db a5 ................
+| 1280: 30 71 68 07 04 82 46 03 05 ca 8b 64 78 66 0a 04 0qh...F....dxf..
+| 1296: 84 01 03 02 dd 9b 0a 04 82 4e 03 02 de bd 08 04 .........N......
+| 1312: 82 03 03 07 eb b1 bd f2 84 82 8d 04 04 84 23 02 ..............#.
+| 1328: 01 ba 01 0c 2d 81 55 09 82 17 01 04 07 64 01 0e ....-.U......d..
+| 1344: 33 81 73 0e 36 81 63 01 0e 2f 60 82 09 5b 5f 2c 3.s.6.c../`..[_,
+| 1360: 01 08 82 6d 81 69 01 0c 81 2d 3c 35 81 0b 01 10 ...m.i...-<5....
+| 1376: 4f 81 08 03 82 4f 29 27 01 0c 0f 03 55 82 6d 10 O....O)'....U.m.
+| 1392: 01 08 0d 82 16 1e 01 06 2c 82 56 03 01 33 05 04 ........,.V..3..
+| 1408: 82 25 03 01 36 07 04 82 73 03 01 63 0a 02 48 03 .%..6...s..c..H.
+| 1424: 02 66 6f 07 04 84 60 03 01 67 03 04 84 27 03 01 .fo...`..g...'..
+| 1440: 6c 0a 02 63 03 01 6d 07 04 82 75 03 01 6f 08 04 l..c..m...u..o..
+| 1456: 82 4d 04 04 61 74 d4 a5 02 04 83 3c 03 02 d9 a8 .M..at.....<....
+| 1472: 04 04 83 4e 03 03 db 93 61 02 04 81 52 03 03 e1 ...N....a...R...
+| 1488: bf a7 08 04 83 42 02 01 bc 01 06 81 6c 2f 01 06 .....B......l/..
+| 1504: 81 31 32 01 06 30 81 02 01 0c 81 02 81 73 04 67 .12..0.......s.g
+| 1520: 01 06 81 6c 20 01 0e 57 6d 04 81 1f 81 24 01 04 ...l ..Wm....$..
+| 1536: 83 54 01 0c 70 49 81 59 81 11 01 0e 56 81 44 0d .T..pI.Y....V.D.
+| 1552: 3d 81 23 01 0a 83 15 81 6b 06 03 02 39 6d 0a 02 =.#.....k...9m..
+| 1568: 59 03 03 62 c2 aa 03 04 82 2f 03 01 63 02 04 84 Y..b...../..c...
+| 1584: 45 04 05 79 76 7a c2 ba 04 04 81 19 03 01 66 07 E..yvz........f.
+| 1600: 04 81 74 03 01 69 08 04 83 59 03 02 6f 37 09 04 ..t..i...Y..o7..
+| 1616: 84 38 03 01 72 04 04 81 3f 03 01 73 07 02 69 03 .8..r...?..s..i.
+| 1632: 03 79 76 62 04 02 76 03 02 c2 b2 06 04 84 48 04 .yvb..v.......H.
+| 1648: 03 b3 34 79 02 04 81 3d 04 01 bc 08 04 82 19 03 ..4y...=........
+| 1664: 04 ce bc ce bc 01 04 84 4a 03 04 e7 a8 a1 79 01 ........J.....y.
+| 1680: 02 03 02 01 bd 01 06 58 82 1d 01 0a 82 7b 81 02 .......X........
+| 1696: 57 01 04 0a 6b 01 08 81 5f 70 13 01 12 0e 38 65 W...k..._p....8e
+| 1712: 11 34 52 4c 5c 75 01 06 82 56 3e 01 02 23 01 0a .4RL.u...V>..#..
+| 1728: 81 29 08 83 2f 01 0c 81 43 81 48 2f 03 01 08 83 .)../...C.H/....
+| 1744: 5a 76 3a 03 01 30 04 04 81 71 03 01 32 01 04 82 Zv:..0...q..2...
+| 1760: 1d 03 01 36 02 04 84 34 03 01 61 09 04 82 41 03 ...6...4..a...A.
+| 1776: 01 68 07 02 38 03 01 6a 08 04 84 15 03 01 6c 08 .h..8..j......l.
+| 1792: 04 82 66 03 01 6d 08 04 82 69 03 01 6f 01 04 82 ..f..m...i..o...
+| 1808: 40 02 04 84 2d 03 02 78 03 01 73 04 08 81 29 82 @...-..x..s...).
+| 1824: 08 03 03 75 75 6b 06 04 84 21 03 01 78 05 04 83 ...uuk...!..x...
+| 1840: 61 04 04 c2 be c2 bc 06 04 82 5c 03 01 79 01 04 a............y..
+| 1856: 83 46 03 02 c2 b3 06 02 40 02 01 be 01 08 81 0f .F......@.......
+| 1872: 81 71 01 0e 81 25 60 81 39 1d 70 01 06 1b 83 53 .q...%`.9.p....S
+| 1888: 01 06 83 37 52 01 10 6b 65 18 2a 81 4d 47 33 01 ...7R..ke.*.MG3.
+| 1904: 06 82 79 07 01 02 46 01 08 03 13 81 64 01 0c 5a ..y...F.....d..Z
+| 1920: 65 76 82 33 04 01 08 82 61 82 19 03 02 35 64 01 ev.3....a....5d.
+| 1936: 04 84 17 03 01 37 06 04 82 10 03 01 62 08 02 5b .....7......b..[
+| 1952: 03 01 66 07 04 83 04 03 01 67 06 02 36 03 01 6a ..f......g..6..j
+| 1968: 01 04 83 3e 08 04 83 59 03 01 71 01 04 82 47 03 ...>...Y..q...G.
+| 1984: 01 72 08 06 81 73 32 03 01 75 09 04 82 35 03 02 .r...s2..u...5..
+| 2000: 77 76 07 04 83 68 03 01 78 05 02 72 03 02 c2 b3 wv...h..x..r....
+| 2016: 0a 04 81 7e 04 01 bd 05 04 84 35 03 02 cb 8a 03 ...~......5.....
+| 2032: 04 84 46 03 02 ce bc 02 04 82 72 01 05 c3 9f ca ..F.......r.....
+| 2048: 83 74 03 04 81 58 02 01 a6 08 04 84 26 02 04 82 .t...X......&...
+| 2064: 1d 02 01 be 06 04 81 4f 03 04 83 1d 01 02 c4 a7 .......O........
+| 2080: 01 02 0e 05 04 81 7c 04 04 84 09 02 01 b3 01 04 ......|.........
+| 2096: 81 43 09 04 82 70 03 02 67 72 07 04 83 06 02 01 .C...p..gr......
+| 2112: b8 06 04 83 09 03 04 78 6d 77 75 07 04 82 69 01 .......xmwu...i.
+| 2128: 02 c5 80 06 04 83 40 02 01 82 06 04 82 6a 03 04 ......@......j..
+| 2144: 82 1a 02 01 89 07 08 81 39 81 6c 02 01 8b 06 04 ........9.l.....
+| 2160: 81 1a 03 01 6a 02 02 26 02 01 93 04 04 83 49 03 ....j..&......I.
+| 2176: 02 6e 70 03 02 0f 01 02 c6 83 01 04 82 5b 06 04 .np..........[..
+| 2192: 83 6a 02 01 85 02 04 82 0d 03 01 31 09 02 41 03 .j.........1..A.
+| 2208: 01 6b 0a 04 84 0d 02 01 88 04 06 82 16 7f 02 01 .k..............
+| 2224: 95 06 04 81 50 02 04 84 18 01 04 84 3f 03 01 78 ....P.......?..x
+| 2240: 06 04 84 11 02 01 99 05 04 83 38 01 04 81 4a 02 ..........8...J.
+| 2256: 01 9a 04 04 81 16 02 02 9b 62 03 02 10 02 01 a3 .........b......
+| 2272: 04 04 82 0d 01 04 84 64 02 01 a5 05 06 81 3d 61 .......d......=a
+| 2288: 03 02 79 69 05 04 82 23 02 01 a8 09 04 83 44 02 ..yi...#......D.
+| 2304: 01 ab 03 04 81 13 02 02 ad 75 06 04 82 07 02 01 .........u......
+| 2320: b4 05 04 82 74 03 04 75 61 65 6c 05 04 82 68 02 ....t..uael...h.
+| 2336: 01 b6 03 04 81 6b 02 01 ba 05 04 83 72 02 01 bd .....k......r...
+| 2352: 06 04 84 15 02 02 be 74 02 04 84 57 03 01 79 07 .......t...W..y.
+| 2368: 04 82 5d 02 02 bf 67 09 04 81 42 03 01 72 03 04 ..]...g...B..r..
+| 2384: 82 7a 03 01 77 0a 02 3c 01 02 c7 80 02 04 84 1d .z..w..<........
+| 2400: 03 01 31 04 04 83 1d 02 03 81 c9 ab 06 04 83 4d ..1............M
+| 2416: 02 01 82 09 04 83 25 02 03 86 d3 97 05 02 34 02 ......%.......4.
+| 2432: 02 89 78 02 04 83 19 02 01 8c 03 02 56 02 04 81 ..x.........V...
+| 2448: 3b 02 04 82 16 02 01 9c 03 04 82 55 04 04 81 08 ;..........U....
+| 2464: 02 01 9d 07 04 81 1c 03 01 68 04 04 83 11 02 01 .........h......
+| 2480: 9f 05 04 81 0e 02 01 a1 01 04 84 79 08 04 82 27 ...........y...'
+| 2496: 02 01 a3 04 04 81 5c 06 02 33 02 02 a5 76 0a 04 .........3...v..
+| 2512: 82 07 02 08 ad 7a c8 bf e0 a4 8a 64 04 04 81 03 .....z.....d....
+| 2528: 02 01 af 05 04 84 25 02 01 b3 03 02 5c 02 01 bb ......%.........
+| 2544: 06 02 06 03 01 68 03 04 81 2c 03 01 71 04 04 81 .....h...,..q...
+| 2560: 69 02 01 bd 03 06 81 7a 6f 02 04 84 2f 01 03 c8 i......zo.../...
+| 2576: 9d 36 02 04 83 43 02 02 a1 70 01 04 82 4a 02 01 .6...C...p...J..
+| 2592: a5 02 04 83 45 02 01 ad 01 04 81 10 02 01 b1 02 ....E...........
+| 2608: 04 84 4c 07 04 84 03 02 01 bc 08 04 81 3b 03 01 ..L..........;..
+| 2624: 31 03 04 83 45 02 01 bf 07 04 81 17 01 02 c9 80 1...E...........
+| 2640: 01 02 3a 01 04 83 62 02 01 82 02 04 81 55 04 04 ..:...b......U..
+| 2656: 84 6d 02 02 50 02 01 8f 02 04 84 16 06 04 83 57 .m..P..........W
+| 2672: 02 01 91 04 04 83 4f 02 01 93 0a 04 81 1d 03 01 ......O.........
+| 2688: 69 05 04 83 37 03 01 79 08 04 82 21 02 01 96 04 i...7..y...!....
+| 2704: 04 82 13 04 02 6c 02 04 83 29 02 01 97 04 02 2d .....l...).....-
+| 2720: 02 03 99 6d 74 05 04 81 73 02 01 9f 09 04 84 63 ...mt...s......c
+| 2736: 02 01 a0 05 02 6a 02 02 76 02 01 a2 02 02 2e 02 .....j..v.......
+| 2752: 01 a3 01 04 82 16 02 01 a5 04 04 81 31 06 04 83 ............1...
+| 2768: 0f 02 01 a8 03 04 83 47 02 01 a9 06 06 82 0d 49 .......G.......I
+| 2784: 02 01 af 0a 04 83 1c 02 02 b2 34 04 04 81 3c 02 ..........4...<.
+| 2800: 04 b5 74 c2 b2 03 04 81 28 02 01 ba 09 04 83 62 ..t.....(......b
+| 2816: 02 01 bb 07 04 84 73 02 01 bc 06 04 81 2a 02 01 ......s......*..
+| 2832: bd 04 04 81 68 02 01 be 09 04 83 67 03 01 73 08 ....h......g..s.
+| 2848: 04 83 5f 01 02 ca 80 07 04 84 0b 03 01 77 02 04 .._..........w..
+| 2864: 82 59 02 01 81 06 04 82 1c 02 01 83 08 04 83 1b .Y..............
+| 2880: 01 04 81 71 02 01 86 07 04 81 79 02 01 88 08 02 ...q......y.....
+| 2896: 62 01 04 81 0a 02 01 89 04 04 81 62 02 01 8a 03 b..........b....
+| 2912: 04 83 11 01 04 83 50 02 01 8c 06 04 84 2e 02 01 ......P.........
+| 2928: 8e 03 04 82 3e 04 04 82 33 03 01 68 07 04 82 3b ....>...3..h...;
+| 2944: 02 01 8f 04 04 82 63 03 01 73 08 02 7e 02 01 90 ......c..s..~...
+| 2960: 08 02 20 02 01 91 01 04 83 52 02 01 94 06 04 83 .. ......R......
+| 2976: 36 02 02 95 7a 0a 02 51 02 04 99 75 73 73 03 02 6...z..Q...uss..
+| 2992: 36 02 01 9c 06 04 81 27 02 01 a5 07 04 81 7b 03 6......'........
+| 3008: 07 e0 a4 aa d5 b8 61 62 0a 02 77 02 02 a6 6f 07 ......ab..w...o.
+| 3024: 04 81 07 03 03 ec b2 be 02 04 82 39 02 02 a7 33 ...........9...3
+| 3040: 08 02 61 02 01 a9 03 04 84 07 02 01 b6 0a 04 84 ..a.............
+| 3056: 02 02 01 b7 05 04 81 4a 03 03 6a 69 6a 05 04 81 .......J..jij...
+| 3072: 48 02 01 b8 09 04 83 0a 03 04 c4 91 d8 bd 03 02 H...............
+| 3088: 1c 02 01 b9 09 02 4c 02 04 ba c9 b1 37 07 04 81 ......L.....7...
+| 3104: 4e 02 02 bb 70 01 04 84 4c 02 01 bc 01 04 83 0c N...p...L.......
+| 3120: 02 02 be 72 05 02 04 01 02 cb 80 0a 04 84 52 02 ...r..........R.
+| 3136: 01 88 07 04 83 1d 02 01 8a 08 02 7c 02 01 a1 09 ...........|....
+| 3152: 04 81 1b 03 01 30 06 04 81 52 03 01 6a 01 04 82 .....0...R..j...
+| 3168: 34 02 01 a2 01 04 83 30 02 03 a3 71 64 04 02 7e 4......0...qd..~
+| 3184: 02 01 a4 0a 04 83 34 02 01 ae 06 04 84 7f 03 01 ......4.........
+| 3200: 6e 06 04 83 68 01 02 cd b1 02 04 82 55 03 01 6a n...h.......U..j
+| 3216: 01 04 83 5d 02 01 b7 08 04 81 58 03 01 75 07 04 ...]......X..u..
+| 3232: 84 09 02 01 b8 01 04 82 0e 06 02 22 03 04 82 4f ...............O
+| 3248: 03 02 dd af 05 04 84 3f 02 01 bc 01 04 84 3b 02 .......?......;.
+| 3264: 01 bd 09 04 81 61 01 04 83 3c 02 03 bf 64 67 02 .....a...<...dg.
+| 3280: 04 82 0c 01 05 ce 81 66 da 94 01 02 10 03 01 6b .......f.......k
+| 3296: 0a 04 82 7e 02 01 8d 08 04 83 02 02 07 ad 69 f0 ...~..........i.
+| 3312: 98 a6 a7 61 09 04 84 41 03 01 72 03 04 82 62 02 ...a...A..r...b.
+| 3328: 01 ae 06 04 83 5d 02 04 81 44 03 01 37 06 04 81 .....]...D..7...
+| 3344: 08 02 05 af 64 cf 8d 32 01 02 11 02 01 b1 05 04 ....d..2........
+| 3360: 84 52 03 01 61 08 04 81 68 03 01 68 08 04 83 5a .R..a...h..h...Z
+| 3376: 02 01 b2 05 04 84 43 01 02 7e 03 04 83 23 02 04 ......C..~...#..
+| 3392: b3 71 30 73 03 04 83 76 02 01 b5 02 04 82 04 02 .q0s...v........
+| 3408: 01 b6 0a 04 84 6e 02 01 b7 03 04 81 36 02 01 b8 .....n......6...
+| 3424: 01 04 84 60 02 02 3a 03 04 84 76 01 02 50 03 02 ...`..:...v..P..
+| 3440: 32 6a 09 04 81 0c 03 01 68 03 02 11 02 01 b9 04 2j......h.......
+| 3456: 04 84 0f 02 04 bb d2 b5 62 08 04 81 10 02 01 bc ........b.......
+| 3472: 01 0e 4d 81 25 3f 1b 81 54 01 0c 55 81 38 06 82 ..M.%?..T..U.8..
+| 3488: 1b 01 08 21 82 66 37 01 08 65 09 83 3c 02 0a 82 ...!.f7..e..<...
+| 3504: 21 08 81 52 01 08 83 4e 81 29 01 0e 47 15 81 21 !..R...N.)..G..!
+| 3520: 81 0f 65 01 10 12 20 2d 38 81 00 81 73 01 10 0e ..e... -8...s...
+| 3536: 33 6c 2d 3e 81 4e 07 03 01 67 03 04 83 52 03 01 3l->.N...g...R..
+| 3552: 6b 08 04 83 72 03 02 6c 32 02 04 81 51 03 03 6d k...r..l2...Q..m
+| 3568: 67 79 09 04 82 67 03 01 70 04 04 81 44 03 02 71 gy...g..p...D..q
+| 3584: 6a 0a 04 81 6d 03 01 79 01 04 81 5e 03 02 c2 bd j...m..y...^....
+| 3600: 07 04 81 3a 04 01 be 08 02 18 03 02 ce bc 07 02 ...:............
+| 3616: 34 02 01 bd 03 02 28 03 01 67 04 04 82 09 03 02 4.....(..g......
+| 3632: 6e 6c 01 02 22 03 01 78 02 04 83 5f 02 01 bf 02 nl.....x..._....
+| 3648: 02 16 03 01 7a 06 04 82 05 01 02 cf 80 03 02 69 ....z..........i
+| 3664: 03 01 6e 05 04 83 40 02 02 81 6c 06 04 84 5d 03 ..n...@...l...].
+| 3680: 02 ca ab 04 04 81 5d 02 01 84 03 04 81 2e 03 04 ......].........
+| 3696: 82 6e 02 01 85 06 04 82 40 02 01 88 04 02 62 02 .n......@.....b.
+| 3712: 03 8a 75 6a 03 04 83 50 02 01 8b 05 04 82 60 81 ..uj...P......`.
+| 3728: 01 08 07 0a 07 09 07 0b 06 07 07 07 0a 0b 0a 07 ................
+| 3744: 07 0a 06 07 0a 08 07 07 07 12 09 08 0b 07 08 07 ................
+| 3760: 06 07 07 07 07 0a 09 07 0a 08 07 3f 08 07 06 06 ...........?....
+| 3776: 08 07 07 09 07 07 0a 4b 07 07 07 07 07 0a 07 07 .......K........
+| 3792: 09 07 08 08 08 0a 0b 49 07 07 07 09 07 0b 0a 08 .......I........
+| 3808: 07 08 0a 0d 08 48 07 07 08 08 09 07 07 07 09 09 .....H..........
+| 3824: 07 07 09 0a 07 07 07 08 0b 0c 0b 08 08 0d 4c 07 ..............L.
+| 3840: 07 06 08 07 06 07 07 0a 08 09 09 44 07 09 07 0b ...........D....
+| 3856: 07 07 08 07 06 08 08 09 07 0a 09 41 07 07 07 07 ...........A....
+| 3872: 06 07 07 07 0e 09 09 07 0a 07 07 42 08 07 06 07 ...........B....
+| 3888: 06 0b 07 08 07 08 06 08 07 08 08 0b 0b 0b 0f 0b ................
+| 3904: 08 07 0a 08 0b 09 07 06 07 07 0c 07 06 07 08 0f ................
+| 3920: 07 0b 07 07 0b 08 08 07 07 08 07 0a 07 07 07 08 ................
+| 3936: 07 08 07 06 08 07 09 07 08 08 0e 0b 07 07 07 0b ................
+| 3952: 0a 08 0e 07 06 06 07 07 0c 09 08 07 07 0b 07 07 ................
+| 3968: 07 0b 0e 0b 07 07 07 07 0e 06 09 07 09 06 07 0b ................
+| 3984: 07 08 07 08 0a 07 07 07 07 07 07 08 07 07 0b 07 ................
+| 4000: 0a 07 0b 07 0b 07 07 06 06 07 07 07 09 07 07 0c ................
+| 4016: 08 09 07 07 07 07 09 07 09 06 0a 08 07 07 08 07 ................
+| 4032: 06 07 07 07 07 08 07 07 07 08 07 07 07 0e 08 07 ................
+| 4048: 0b 09 0a 07 07 0d 07 0b 07 0a 07 07 07 0e 0a 07 ................
+| 4064: 07 07 11 08 06 07 0a 4a 07 07 08 09 07 08 07 08 .......J........
+| 4080: 06 07 06 07 07 07 06 07 07 07 08 08 0b 07 06 09 ................
+| page 25 offset 98304
+| 0: 0d 00 00 00 01 00 29 00 00 29 00 00 00 00 00 00 ......)..)......
+| 32: 00 00 00 00 00 00 00 00 00 9f 4f 88 80 80 80 80 ..........O.....
+| 48: 06 04 00 bf 22 00 00 0e 17 04 30 cf 8c 70 03 02 ..........0..p..
+| 64: 0e 02 01 8d 05 04 82 5c 03 01 63 07 04 84 19 02 ..........c.....
+| 80: 01 8e 09 02 66 02 01 93 06 04 83 30 02 01 99 06 ....f......0....
+| 96: 04 84 75 04 04 84 07 03 02 c6 a3 05 04 84 01 02 ..u.............
+| 112: 01 9b 08 02 42 02 01 9d 07 02 30 03 02 0b 02 01 ....B.....0.....
+| 128: 9f 06 04 81 06 03 02 da a9 07 02 66 02 01 a5 09 ...........f....
+| 144: 02 0c 02 01 ab 02 04 81 39 02 01 ad 01 02 6d 03 ........9.....m.
+| 160: 04 82 62 02 01 b2 0a 04 83 36 02 03 b3 d6 88 07 ..b......6......
+| 176: 04 84 78 02 01 b8 05 04 84 02 05 04 81 5d 01 02 ..x..........]..
+| 192: d0 b1 0a 02 5f 03 01 7a 03 02 76 02 02 b5 35 08 ...._..z..v...5.
+| 208: 04 83 63 03 01 75 07 04 84 35 02 04 b8 71 61 61 ..c..u...5...qaa
+| 224: 0a 04 81 6b 02 01 bb 08 04 84 4a 02 01 bd 0a 06 ...k......J.....
+| 240: 6f 83 6d 01 02 d1 80 06 04 83 65 02 01 84 07 04 o.m.......e.....
+| 256: 82 1b 02 01 85 09 04 82 3f 02 02 86 6f 08 04 82 ........?...o...
+| 272: 5f 02 01 88 03 04 81 29 02 01 89 02 04 83 14 08 _......)........
+| 288: 04 84 6f 03 01 63 02 04 84 1c 02 01 8a 0a 06 82 ..o..c..........
+| 304: 14 2d 03 02 6c 69 04 04 83 57 02 01 8e 07 04 84 .-..li...W......
+| 320: 48 02 06 90 e1 91 8f 6a 7a 05 04 83 46 02 03 91 H......jz...F...
+| 336: 64 37 03 04 82 01 02 01 93 0a 04 82 1f 02 01 98 d7..............
+| 352: 05 04 84 30 02 03 9b 63 66 05 04 81 55 02 05 9f ...0...cf...U...
+| 368: 78 6a d1 87 09 04 81 4d 02 02 a3 78 06 02 07 02 xj.....M...x....
+| 384: 04 a5 e1 a9 8f 06 02 10 02 02 af 76 09 04 83 13 ...........v....
+| 400: 03 02 7a 33 07 04 84 1f 02 01 b1 05 04 84 0e 02 ..z3............
+| 416: 02 b7 71 0a 04 82 7b 02 02 bf 62 0a 04 83 6f 01 ..q.......b...o.
+| 432: 04 d2 8b 67 73 06 04 83 2b 02 04 97 e3 86 b2 07 ...gs...+.......
+| 448: 04 84 12 02 01 9f 02 04 81 05 03 02 24 02 01 a7 ............$...
+| 464: 04 04 84 1f 02 01 a9 04 04 81 47 06 06 23 82 23 ..........G..#.#
+| 480: 02 02 b1 78 06 02 43 02 01 b9 02 04 82 44 02 01 ...x..C......D..
+| 496: bd 02 04 83 3d 08 04 81 76 02 01 bf 0a 04 85 04 ....=...v.......
+| 512: 01 02 d3 8e 06 04 85 02 02 02 8f 68 03 02 75 02 ...........h..u.
+| 528: 01 91 08 02 28 02 01 93 05 02 16 02 01 9d 06 04 ....(...........
+| 544: 82 5e 02 02 9f 33 06 04 83 78 02 03 a7 6c 78 06 .^...3...x...lx.
+| 560: 04 83 33 03 09 da a9 ec 82 b2 e1 87 90 71 06 04 ..3..........q..
+| 576: 84 7b 02 01 ab 06 04 83 27 02 01 ad 03 02 72 02 ........'.....r.
+| 592: 01 af 03 04 82 0c 02 01 b5 0a 04 81 7d 02 01 bb ................
+| 608: 0a 02 58 03 01 6a 03 04 81 70 01 02 d4 81 04 04 ..X..j...p......
+| 624: 84 0d 02 01 85 06 04 81 3d 02 02 8b 35 07 04 83 ........=...5...
+| 640: 50 02 02 8d 77 03 02 79 02 01 95 0a 04 84 5c 02 P...w..y........
+| 656: 03 97 6a 6c 0a 04 83 7a 02 01 99 09 04 82 26 02 ..jl...z......&.
+| 672: 02 9b 71 05 04 82 01 02 02 9d 67 04 04 84 5f 02 ..q.......g..._.
+| 688: 01 a7 04 04 82 4a 01 02 d5 a3 0a 04 81 00 03 01 .....J..........
+| 704: 39 06 04 81 51 02 01 a5 06 02 5e 03 01 67 02 04 9...Q.....^..g..
+| 720: 81 0d 02 01 a9 08 04 84 1e 01 02 75 02 01 aa 04 ...........u....
+| 736: 04 81 0a 02 01 ab 03 04 83 21 02 01 ac 06 02 08 .........!......
+| 752: 02 01 ad 0a 02 57 02 02 b3 74 0a 04 84 40 02 03 .....W...t...@..
+| 768: b4 61 6e 08 04 83 1a 03 02 6d 76 02 04 81 0a 02 .an......mv.....
+| 784: 01 ba 06 04 83 51 02 01 bb 03 04 82 61 03 01 67 .....Q......a..g
+| 800: 08 04 83 28 02 01 bc 01 02 62 01 02 d6 80 01 04 ...(.....b......
+| 816: 84 53 02 02 82 7a 08 02 7f 02 01 83 06 02 50 02 .S...z........P.
+| 832: 04 81 32 02 01 86 09 04 82 52 02 01 87 09 04 83 ..2......R......
+| 848: 7b 02 01 8c 03 04 83 19 01 03 d7 89 74 0a 04 82 ............t...
+| 864: 37 02 01 92 07 04 81 23 02 01 93 0a 04 81 12 02 7......#........
+| 880: 01 9a 07 02 58 02 01 9e 03 04 81 19 02 01 a0 0a ....X...........
+| 896: 04 82 5e 03 01 6c 01 02 0a 03 04 78 c2 b9 63 05 ..^..l.....x..c.
+| 912: 02 02 02 01 a8 0a 02 07 02 01 ab 01 04 81 01 02 ................
+| 928: 03 af c3 b0 05 04 82 4e 02 04 b7 69 c2 be 04 04 .......N...i....
+| 944: 84 44 02 05 bd e4 98 a5 6c 03 04 83 51 01 03 d8 .D......l...Q...
+| 960: 9c 38 08 04 84 73 02 02 9d 73 0a 04 83 0b 02 01 .8...s...s......
+| 976: aa 02 04 84 56 02 02 ab 7a 03 04 82 7f 02 01 ac ....V...z.......
+| 992: 09 04 82 40 02 02 ad 61 03 04 81 14 03 03 c6 8c ...@...a........
+| 1008: 71 09 04 82 56 02 02 b7 69 0a 04 82 5c 02 03 b8 q...V...i.......
+| 1024: 66 66 05 04 81 11 03 01 7a 05 04 82 7a 02 01 be ff......z...z...
+| 1040: 05 04 81 2a 02 02 bf 76 0a 02 76 01 02 d9 81 01 ...*...v..v.....
+| 1056: 04 83 76 02 01 83 02 02 3c 03 01 36 05 04 81 54 ..v.....<..6...T
+| 1072: 02 01 85 09 04 82 73 02 01 86 06 04 84 53 02 03 ......s......S..
+| 1088: a7 6a 61 01 04 82 0f 02 01 a8 04 02 38 02 01 b1 .ja.........8...
+| 1104: 01 04 83 21 03 03 dc 94 6a 02 02 2b 02 01 b2 07 ...!....j..+....
+| 1120: 02 1a 02 01 b6 04 04 82 17 02 01 ba 04 04 83 7b ................
+| 1136: 03 01 71 03 04 82 77 02 01 bd 09 04 84 4f 01 04 ..q...w......O..
+| 1152: 82 49 01 07 da 80 e8 b6 8a 67 68 05 04 83 04 02 .I.......gh.....
+| 1168: 03 85 d1 9c 06 04 81 59 02 01 8f 05 04 81 2c 02 .......Y......,.
+| 1184: 01 93 01 04 83 3d 02 04 9a ed 90 8b 01 04 83 44 .....=.........D
+| 1200: 02 02 9c 73 09 04 83 21 02 01 a0 0a 04 85 03 02 ...s...!........
+| 1216: 01 a6 05 02 7e 03 04 81 19 02 02 a9 77 05 04 82 ....~.......w...
+| 1232: 69 02 01 ac 03 02 4f 04 04 82 76 03 03 67 c2 bc i.....O...v..g..
+| 1248: 07 04 83 38 02 01 b7 03 04 82 5b 02 01 bf 09 02 ...8......[.....
+| 1264: 6a 01 02 db 83 08 04 84 55 02 02 93 70 02 04 81 j.......U...p...
+| 1280: 47 02 01 a5 05 04 82 12 02 01 a6 01 02 52 01 02 G............R..
+| 1296: dc 8e 01 02 6a 02 02 96 6b 06 04 84 29 02 01 9a ....j...k...)...
+| 1312: 05 04 84 05 03 04 82 3e 02 01 9f 09 04 81 64 02 .......>......d.
+| 1328: 03 a4 76 77 0a 04 84 0f 02 01 a6 06 04 83 52 02 ..vw..........R.
+| 1344: 01 aa 01 04 83 70 02 01 ae 01 04 83 33 01 02 dd .....p......3...
+| 1360: 8c 03 04 82 1f 02 02 90 78 09 04 82 4b 02 01 96 ........x...K...
+| 1376: 05 04 81 10 03 01 6c 06 04 83 24 02 02 9c 6a 04 ......l...$...j.
+| 1392: 04 82 1b 02 05 a0 79 c9 a8 75 01 02 34 02 01 a8 ......y..u..4...
+| 1408: 05 02 2c 02 01 b2 06 04 84 3f 02 02 ba 67 03 02 ..,......?...g..
+| 1424: 2f 02 05 bf e0 a6 ad 77 08 02 2f 01 02 de 83 05 /......w../.....
+| 1440: 02 65 02 01 84 06 04 81 00 02 01 85 01 04 82 60 .e.............`
+| 1456: 01 04 81 57 02 01 8f 03 04 83 3b 02 01 90 03 02 ...W......;.....
+| 1472: 7b 02 01 91 07 04 83 5d 02 03 9c 78 61 07 04 81 .......]...xa...
+| 1488: 00 02 01 9e 08 04 82 00 02 02 9f 6f 04 04 83 51 ...........o...Q
+| 1504: 02 01 a3 04 04 81 2f 02 02 a5 73 0a 04 84 7a 02 ....../...s...z.
+| 1520: 02 b1 66 08 04 81 5a 02 02 b7 78 02 02 78 02 01 ..f...Z...x..x..
+| 1536: b9 05 04 83 08 02 01 ba 0a 04 84 76 02 01 bb 07 ...........v....
+| 1552: 02 5c 02 01 bc 08 02 13 02 01 bf 08 02 2a 01 03 .............*..
+| 1568: df 82 66 08 04 82 2c 02 01 87 01 04 83 0a 02 01 ..f...,.........
+| 1584: 8d 05 04 84 0c 02 05 91 72 6b 69 61 03 02 45 02 ........rkia..E.
+| 1600: 03 97 de a4 09 04 82 6b 02 02 98 62 06 04 81 18 .......k...b....
+| 1616: 02 01 a0 0a 04 82 4a 02 01 bf 05 02 39 01 06 e0 ......J.....9...
+| 1632: a7 9d 31 76 63 05 04 83 00 02 02 af aa 02 04 81 ..1vc...........
+| 1648: 2b 02 03 b7 ae 65 01 04 84 36 02 02 bb 98 0a 04 +....e...6......
+| 1664: 82 23 01 04 e1 80 88 63 06 04 83 5c 03 01 a2 04 .#.....c........
+| 1680: 02 5c 02 02 85 9b 05 04 81 3e 02 04 8b b3 db 8f .........>......
+| 1696: 07 02 56 02 04 91 b8 64 66 08 04 82 49 02 02 95 ..V....df...I...
+| 1712: 9d 08 04 81 4e 03 01 a2 03 04 81 77 02 02 9a a0 ....N......w....
+| 1728: 01 04 82 39 02 03 9d 90 69 03 02 41 02 03 a6 9a ...9....i..A....
+| 1744: 68 04 02 4c 02 05 a7 9c c7 ad 6e 06 04 83 7b 02 h..L......n.....
+| 1760: 03 a8 b2 38 04 02 5f 02 02 af 88 07 02 19 02 03 ...8.._.........
+| 1776: bd 96 71 03 04 81 11 01 03 e2 83 80 05 02 5f 02 ..q..........._.
+| 1792: 02 b1 a6 01 04 83 34 01 04 84 06 02 02 b3 9d 01 ......4.........
+| 1808: 04 83 0f 02 03 ba 9a 64 01 04 84 4f 01 03 e3 81 .......d...O....
+| 1824: 81 0a 02 21 02 02 84 8c 03 04 81 10 02 02 90 a1 ...!............
+| 1840: 02 04 81 1b 02 02 9c a3 02 04 82 2e 02 02 a5 89 ................
+| 1856: 04 04 82 23 02 02 a6 98 07 04 83 00 02 09 ab a8 ...#............
+| 1872: 77 31 63 6a c2 aa 35 04 04 81 38 03 01 aa 01 04 w1cj..5...8.....
+| 1888: 82 1e 02 02 ac a4 02 02 37 02 05 b9 8e 70 34 79 ........7....p4y
+| 1904: 0a 04 84 30 02 02 bd bf 01 04 83 19 01 05 e4 80 ...0............
+| 1920: 83 79 69 04 04 83 15 03 01 bb 01 02 63 02 03 8a .yi.........c...
+| 1936: 8d 36 0a 04 84 57 02 05 8c 88 d0 b1 63 09 04 84 .6...W......c...
+| 1952: 49 02 02 90 8e 02 04 84 60 02 02 a1 98 03 04 84 I.......`.......
+| 1968: 0f 02 02 b1 a2 08 04 83 30 01 04 e5 85 87 68 02 ........0.....h.
+| 1984: 04 84 19 02 03 8a a8 39 0a 02 6e 02 03 8d be 38 .......9..n....8
+| 2000: 09 04 81 78 02 04 8f 85 68 30 05 04 84 5a 03 01 ...x....h0...Z..
+| 2016: a7 09 04 82 09 02 03 92 8e 7a 04 02 28 02 02 95 .........z..(...
+| 2032: 89 01 02 38 03 01 be 07 04 84 4d 02 08 9e 9e f4 ...8......M.....
+| 2048: 95 95 98 68 71 07 04 84 13 02 02 9f 9f 04 04 84 ...hq...........
+| 2064: 35 02 02 a0 a2 02 02 24 03 05 b4 f0 90 b1 92 0a 5......$........
+| 2080: 04 82 15 02 03 a3 a1 64 07 04 84 22 02 02 a6 bb .......d........
+| 2096: 04 04 84 52 02 05 a8 af 75 c2 bd 01 04 81 25 02 ...R....u.....%.
+| 2112: 02 aa b3 06 04 81 66 02 03 ae be 7a 0a 02 4d 02 ......f....z..M.
+| 2128: 08 af 96 66 6b f3 93 af 8f 04 04 83 02 02 03 bd ...fk...........
+| 2144: aa 6a 07 02 62 01 04 e6 80 83 69 08 04 84 19 02 .j..b.....i.....
+| 2160: 02 81 bc 0a 04 81 25 02 04 86 aa 32 75 06 04 82 ......%....2u...
+| 2176: 65 02 05 96 b7 69 35 30 07 02 78 02 03 9d 98 73 e....i50..x....s
+| 2192: 06 02 7f 02 02 a3 97 02 04 81 7f 02 05 a5 80 e7 ................
+| 2208: a0 b6 01 04 81 37 03 01 87 08 04 82 61 02 02 b3 .....7......a...
+| 2224: b2 03 04 83 1e 02 02 b8 a0 0a 04 84 2e 02 02 bc ................
+| 2240: af 0a 04 83 71 02 02 bf 91 09 04 84 42 01 03 e7 ....q.......B...
+| 2256: 81 b4 07 04 84 5e 02 02 86 8e 01 04 84 2c 02 02 .....^.......,..
+| 2272: 8b a9 09 04 82 02 02 03 8d 9d 30 05 04 84 1a 02 ..........0.....
+| 2288: 02 8e b6 08 04 83 60 02 02 91 99 0a 04 82 05 02 ......`.........
+| 2304: 02 92 af 08 04 81 1c 02 02 94 b9 05 04 81 45 02 ..............E.
+| 2320: 02 9c 8f 06 02 14 02 02 9e a2 07 04 83 78 02 02 .............x..
+| 2336: a0 83 06 04 83 08 02 02 a1 a8 01 02 78 02 02 ae ............x...
+| 2352: ae 04 04 81 0e 02 02 b5 8c 06 04 84 6c 02 02 bf ............l...
+| 2368: 80 09 04 83 1e 01 04 e8 83 93 73 0a 04 83 57 02 ..........s...W.
+| 2384: 02 88 a8 0a 04 84 50 02 02 89 a0 09 04 83 70 02 ......P.......p.
+| 2400: 02 8a ad 05 04 83 18 02 02 95 84 04 02 3b 03 01 .............;..
+| 2416: b5 06 04 81 26 02 08 a0 91 65 ce bb 6a d7 96 09 ....&....e..j...
+| 2432: 04 82 05 02 02 a7 bf 02 04 84 47 02 02 b5 bb 05 ..........G.....
+| 2448: 02 0a 02 04 bf 88 6a 6b 03 04 84 2a 01 04 e9 80 ......jk...*....
+| 2464: 97 65 09 04 83 26 02 02 9a 89 04 04 83 29 02 02 .e...&.......)..
+| 2480: a4 b8 05 04 82 7f 02 05 ba 83 69 76 6c 04 02 3a ..........ivl..:
+| 2496: 03 01 87 03 02 3c 02 02 be b6 06 04 84 25 01 06 .....<.......%..
+| 2512: ea 81 98 64 39 79 03 04 84 12 02 02 88 bc 09 04 ...d9y..........
+| 2528: 84 40 02 03 8c b5 39 01 04 83 11 02 02 91 ab 05 .@....9.........
+| 2544: 04 83 01 02 03 9d 97 63 05 04 83 07 02 02 9e a3 .......c........
+| 2560: 04 04 82 04 02 02 ae a3 03 04 81 20 02 02 b2 a1 ........... ....
+| 2576: 04 02 66 02 04 b4 9d 65 6b 02 02 29 02 03 ba bd ..f....ek..)....
+| 2592: 72 08 04 83 75 02 03 bc a7 37 09 04 81 55 01 03 r...u....7...U..
+| 2608: eb 84 9d 07 02 60 02 06 8f aa 6f 69 6b 68 03 02 .....`....oikh..
+| 2624: 29 02 02 92 90 0a 04 81 30 02 04 99 ba 6e 65 02 ).......0....ne.
+| 2640: 04 82 1e 02 02 b8 8f 05 04 81 52 02 02 bd 80 08 ..........R.....
+| 2656: 04 84 23 02 02 be bc 08 02 2e 02 02 bf bc 01 04 ..#.............
+| 2672: 82 6b 01 04 ec 85 b8 76 05 04 81 76 02 03 99 ad .k.....v...v....
+| 2688: 74 07 02 7e 02 02 a3 80 06 04 81 37 02 04 ac a9 t..~.......7....
+| 2704: 79 75 01 02 6f 02 02 b9 89 06 02 66 01 03 ed 8a yu..o......f....
+| 2720: 8a 05 02 3f 02 02 96 b6 05 02 63 01 04 ee 8d 91 ...?......c.....
+| 2736: 7a 02 04 82 2a 02 02 92 af 03 04 84 06 02 03 98 z...*...........
+| 2752: be 78 01 04 81 50 02 03 99 82 71 06 02 13 02 04 .x...P....q.....
+| 2768: 9c 8d 68 61 09 04 83 1b 02 02 a4 bd 06 04 82 24 ..ha...........$
+| 2784: 02 02 ad a9 06 04 81 5d 02 02 b4 b9 09 04 81 75 .......].......u
+| 2800: 02 02 bb 8d 05 04 84 39 01 03 ef af 90 03 04 82 .......9........
+| 2816: 3d 03 02 a3 61 03 04 83 02 02 02 b4 ae 0a 04 82 =...a...........
+| 2832: 0e 02 02 b5 b1 06 02 47 02 02 b7 a9 02 04 84 42 .......G.......B
+| 2848: 01 05 f0 90 8e bf 34 03 04 81 40 03 04 ad b0 33 ......4...@....3
+| 2864: 38 05 04 84 19 03 02 ae 89 07 04 81 68 03 03 af 8...........h...
+| 2880: b7 61 0a 04 82 2f 02 03 91 81 a7 02 04 81 04 03 .a.../..........
+| 2896: 02 89 ac 08 04 83 62 03 02 97 a6 08 04 82 64 03 ......b.......d.
+| 2912: 02 af bc 07 04 83 14 03 02 b1 b3 05 04 81 34 03 ..............4.
+| 2928: 02 b7 ad 07 04 82 35 03 03 bb 9f 64 07 04 84 4c ......5....d...L
+| 2944: 02 03 92 8d a5 05 04 82 7b 03 03 98 ab 62 09 04 .............b..
+| 2960: 81 2f 03 02 b7 99 05 04 82 43 02 04 93 85 98 6b ./.......C.....k
+| 2976: 0a 02 1e 03 02 a9 90 01 04 84 62 03 05 b6 b0 74 ..........b....t
+| 2992: c2 b3 07 04 82 55 02 03 95 8e a5 06 04 83 2a 03 .....U........*.
+| 3008: 02 96 95 09 04 83 0c 03 02 97 8b 06 04 84 60 03 ..............`.
+| 3024: 02 b5 bd 07 04 82 56 03 02 b7 9c 06 04 82 2d 02 ......V.......-.
+| 3040: 04 96 a0 80 6e 01 04 83 7f 03 02 a5 ad 03 04 83 ....n...........
+| 3056: 3c 03 02 ad ac 07 02 72 02 04 97 87 b5 35 07 02 <......r.....5..
+| 3072: 5f 04 01 bc 07 02 53 03 02 8f 90 02 02 70 02 06 _.....S......p..
+| 3088: 98 8f 88 73 7a 78 06 02 35 04 01 ba 02 02 23 03 ...szx..5.....#.
+| 3104: 06 a2 92 ca 8a 36 6d 07 04 82 06 02 04 99 8b 93 .....6m.........
+| 3120: 7a 09 04 84 6b 03 03 8c 82 72 07 04 81 7a 03 02 z...k....r...z..
+| 3136: 94 ba 04 04 82 3c 03 02 a1 92 0a 04 84 31 03 02 .....<.......1..
+| 3152: a8 b7 08 04 84 16 03 02 b1 ac 03 04 84 28 02 05 .............(..
+| 3168: 9a 99 8d d7 b5 01 04 84 65 03 03 9d 86 7a 09 04 ........e....z..
+| 3184: 84 07 03 03 ac 80 37 09 04 84 24 02 03 9b 87 93 ......7...$.....
+| 3200: 04 04 82 60 03 02 91 8b 05 04 84 6c 03 02 a0 b9 ...`.......l....
+| 3216: 05 04 82 13 03 03 a5 81 70 06 04 83 6e 03 02 b6 ........p...n...
+| 3232: 9a 03 04 82 00 02 03 9c 8a a3 04 04 83 7e 03 02 .............~..
+| 3248: 96 b7 01 04 83 5b 03 02 a8 88 02 04 83 7a 03 03 .....[.......z..
+| 3264: a9 98 77 02 04 81 38 03 02 b1 b2 04 02 46 03 03 ..w...8......F..
+| 3280: b6 bb 72 03 04 82 1a 03 02 be a9 04 04 83 73 02 ..r...........s.
+| 3296: 04 9d 8a 9a 6a 01 02 32 03 02 96 9c 03 02 6f 03 ....j..2......o.
+| 3312: 02 a6 b2 04 04 83 35 03 02 b4 a6 05 02 43 03 02 ......5......C..
+| 3328: bc 98 05 02 4a 02 03 9e 8f 98 0a 04 81 08 03 03 ....J...........
+| 3344: 90 8c 6d 07 04 84 64 03 03 b4 9f 6e 03 04 84 35 ..m...d....n...5
+| 3360: 02 04 9f a1 a9 69 07 04 84 43 02 03 a7 85 b6 06 .....i...C......
+| 3376: 02 60 02 03 ad ba b7 06 02 2b 02 03 bc b6 b6 01 .`.......+......
+| 3392: 04 81 31 01 04 f1 92 a9 98 06 02 0c 03 03 b1 9d ..1.............
+| 3408: 69 08 04 84 65 02 06 9e 91 a5 ea b0 98 07 04 82 i...e...........
+| 3424: 43 02 03 a1 b7 be 02 04 81 13 02 03 b4 af 9e 0a C...............
+| 3440: 04 84 1d 02 05 b5 92 84 69 6e 07 04 82 52 01 05 ........in...R..
+| 3456: f2 90 9a 83 73 03 04 82 45 02 03 91 ac 81 07 04 ....s...E.......
+| 3472: 82 7a 03 02 be 94 02 04 81 46 02 03 94 89 ac 04 .z.......F......
+| 3488: 04 81 4a 02 04 95 b4 ae 39 08 04 82 2a 02 05 a0 ..J.....9...*...
+| 3504: 90 b5 66 34 04 04 82 46 02 05 a6 91 b7 d5 bf 06 ..f4...F........
+| 3520: 04 81 7b 02 03 ab a0 93 05 02 2b 02 04 b2 8c 80 ..........+.....
+| 3536: 6a 07 04 84 1a 03 02 9c a9 0a 04 81 36 03 02 aa j...........6...
+| 3552: bf 04 04 84 34 01 05 f3 82 84 8d 66 0a 04 83 75 ....4......f...u
+| 3568: 02 03 88 a7 b4 06 04 83 38 02 03 ab bf a6 02 04 ........8.......
+| 3584: 81 65 02 05 b0 ae a8 73 70 0a 02 10 02 04 b8 a6 .e.....sp.......
+| 3600: b6 75 05 04 83 4e 02 03 bd b2 84 08 04 83 50 01 .u...N........P.
+| 3616: 04 f4 82 91 84 06 04 81 6a 02 03 8c b4 be 06 02 ........j.......
+| 3632: 24 02 03 9b b2 83 01 04 84 4b 02 03 a0 87 b0 05 $........K......
+| 3648: 04 83 2f 03 03 ae ba 61 05 04 82 1b 04 08 07 07 ../....a........
+| 3664: 06 07 0b 08 06 09 07 07 06 07 0a 07 09 0b 07 06 ................
+| 3680: 08 07 0a 07 08 08 07 07 08 07 0b 07 08 08 07 0c ................
+| 3696: 09 07 07 09 0b 07 09 08 08 07 08 08 0a 0a 0a 07 ................
+| 3712: 0c 07 07 0b 07 08 07 06 06 07 08 09 0f 07 06 07 ................
+| 3728: 07 06 07 08 07 08 07 07 09 07 08 08 07 08 07 06 ................
+| 3744: 07 0a 07 07 06 06 08 09 08 07 07 07 06 08 07 0a ................
+| 3760: 07 07 07 09 07 07 06 07 07 06 09 06 07 09 0a 0b ................
+| 3776: 09 08 07 08 07 08 09 08 09 07 07 07 08 06 07 07 ................
+| 3792: 07 09 06 07 08 06 07 07 07 0b 0d 09 07 07 0a 08 ................
+| 3808: 07 0a 08 0a 09 07 06 08 08 07 06 07 08 0b 07 09 ................
+| 3824: 07 07 07 08 08 07 07 08 0a 06 07 07 0a 07 07 0b ................
+| 3840: 07 06 07 09 07 08 07 08 08 07 07 07 06 06 06 09 ................
+| 3856: 07 07 0a 09 08 07 06 0c 08 09 08 0a 06 08 09 0a ................
+| 3872: 08 07 08 08 08 0b 08 07 09 08 0c 08 09 08 08 08 ................
+| 3888: 08 08 08 0f 07 07 0b 08 0b 06 09 0b 08 08 08 0a ................
+| 3904: 08 09 0a 07 08 07 07 0e 08 07 0b 09 08 0b 08 08 ................
+| 3920: 0e 08 0a 08 0a 0a 08 08 0b 07 08 08 08 08 09 08 ................
+| 3936: 08 09 08 08 08 08 07 08 08 07 08 08 08 0a 08 08 ................
+| 3952: 08 07 07 0e 08 07 0a 0a 08 08 0a 06 08 0c 08 09 ................
+| 3968: 08 09 08 08 07 09 09 09 08 0b 08 0a 08 08 07 08 ................
+| 3984: 0a 08 08 09 07 08 07 0a 08 09 08 0a 08 08 08 08 ................
+| 4000: 09 08 08 07 08 0b 0a 08 09 09 08 08 08 08 08 09 ................
+| 4016: 09 09 08 09 08 0b 09 08 08 08 08 0a 08 07 09 06 ................
+| 4032: 07 0b 06 0c 0a 09 08 08 08 08 0b 09 09 09 08 08 ................
+| 4048: 09 08 09 08 08 09 07 09 08 09 07 08 07 07 09 09 ................
+| 4064: 09 0a 08 08 09 09 09 0c 09 09 0b 0b 09 08 09 0a ................
+| 4080: 0b 0b 08 0a 08 08 0b 09 09 0a 0a 09 0a 08 09 09 ................
+| page 26 offset 102400
+| 0: 0d 00 00 00 01 0e a7 00 0e a7 00 00 00 00 00 00 ................
+| 3744: 00 00 00 00 00 00 00 82 51 88 80 80 80 80 07 04 ........Q.......
+| 3760: 00 85 26 00 00 01 2d 05 30 f4 a3 b5 8c 0a 02 1b ..&...-.0.......
+| 3776: 02 03 b4 91 a9 02 04 82 1b 02 04 b7 b5 89 67 06 ..............g.
+| 3792: 04 84 2f 01 04 f5 86 a9 bd 01 04 81 13 02 06 91 ../.............
+| 3808: be ae ca 9e 78 04 04 81 1d 02 05 99 9b b2 6f 65 ....x.........oe
+| 3824: 02 04 84 07 02 03 9e 99 8b 02 02 15 02 03 a1 ab ................
+| 3840: b6 02 04 83 0f 02 03 a3 96 8c 02 04 82 20 02 03 ............. ..
+| 3856: ac a3 8d 08 02 55 02 03 b0 80 82 02 04 81 18 02 .....U..........
+| 3872: 03 b1 9c bb 08 02 67 02 03 b5 be 81 07 04 83 79 ......g........y
+| 3888: 02 04 bf 81 9d 71 07 04 81 7c 01 04 f6 83 ab 80 .....q...|......
+| 3904: 01 04 81 2a 02 04 89 8c a8 61 01 04 82 30 02 03 ...*.....a...0..
+| 3920: 8e ae 81 07 04 84 05 02 04 8f bd b0 6a 09 04 82 ............j...
+| 3936: 1e 02 04 92 95 9c 6c 07 04 82 64 03 02 b4 9f 09 ......l...d.....
+| 3952: 04 83 65 02 04 9a a9 9f 34 06 04 83 70 02 03 a4 ..e.....4...p...
+| 3968: ad af 01 02 02 02 03 b4 9a 90 07 04 83 5e 01 04 .............^..
+| 3984: f7 87 a5 9d 04 04 84 62 02 03 89 83 8e 0a 04 82 .......b........
+| 4000: 2e 02 03 98 bd 8e 01 04 84 06 02 03 99 a7 8e 02 ................
+| 4016: 04 83 7d 02 03 a0 a1 bb 01 04 81 4e 02 04 a8 86 ...........N....
+| 4032: b8 64 0a 02 34 02 03 b2 9a 9e 05 04 83 16 02 04 .d..4...........
+| 4048: b4 a7 93 36 06 04 83 7d 03 02 ba 9c 02 04 83 07 ...6............
+| 4064: 04 09 09 0a 0a 0c 0b 08 09 09 08 09 08 09 0a 0a ................
+| 4080: 0a 09 0a 0a 08 0a 08 09 0a 09 09 09 09 09 09 0a ................
+| end x.db
+}]} {}
+
+do_catchsql_test 74.1 {
+ SELECT rowid, quote(matchinfo(t1,'p�xyb...
+| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
+| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
+| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
+| 2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
+| 2480: 00 3c 00 00 00 16 04 33 74 68 65 03 06 01 01 04 .<.....3the.....
+| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
+| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
+| 2528: 01 05 01 03 74 61 62 03 02 03 04 0a 19 8c 80 80 ....tab.........
+| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 77 68 03 02 .....8.....2wh..
+| 2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80 ...3fts.........
+| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
+| 2592: 03 02 01 68 03 06 01 01 04 04 07 1b 8c 80 80 80 ...h............
+| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
+| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
+| 2640: 82 d0 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
+| 2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80 ....is..........
+| 2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
+| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
+| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
+| 2720: 01 02 05 01 01 6f 03 06 01 01 06 04 09 18 8c 80 .....o..........
+| 2736: 81 80 80 06 03 00 36 00 00 00 13 04 02 31 66 03 ......6......1f.
+| 2752: 02 02 01 01 69 03 06 01 01 03 05 06 1c 8c 80 80 ....i...........
+| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
+| 2784: 06 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
+| 2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........0.......
+| 2816: 06 30 74 61 62 6c 65 03 02 03 07 1c 8c 80 80 80 .0table.........
+| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
+| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
+| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f fc 01 03 02 .......,........
+| 2880: 30 6e 03 06 01 00 f2 07 1b 8c 80 80 80 80 01 03 0n..............
+| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
+| 2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 18 ea 00 ....is..........
+| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
+| 2944: 80 80 80 80 12 03 00 12 10 00 00 05 02 1c 88 80 ................
+| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
+| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
+| 2992: 15 88 80 80 80 80 10 03 00 2f ff ff f0 11 02 01 ........./......
+| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
+| 3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
+| 3040: 02 06 01 01 05 01 03 74 68 65 02 08 05 0a 1b 88 .......the......
+| 3056: 80 80 80 80 0d 03 00 3c 00 00 00 16 01 01 02 04 .......<........
+| 3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08 3are.....bet....
+| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 03 32 .........<.....2
+| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
+| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
+| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
+| 3152: 01 05 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .............6..
+| 3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
+| 3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 00 00 ............<...
+| 3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
+| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
+| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
+| 3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00 ..............4.
+| 3264: 01 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
+| 3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00 ............8...
+| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
+| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
+| 3328: 16 06 30 74 68 65 72 65 e7 02 02 00 02 31 31 02 ..0there.....11.
+| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
+| 3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07 .......0the.....
+| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
+| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
+| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 00 .............<..
+| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
+| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
+| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
+| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
+| 3488: 34 01 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2
+| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
+| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
+| 3536: 00 16 05 34 74 61 62 6c 01 06 01 01 05 02 03 65 ...4tabl.......e
+| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
+| 3568: 00 00 00 16 05 34 65 61 63 68 01 02 02 01 04 70 .....4each.....p
+| 3584: 72 65 73 01 02 05 04 09 1a 84 80 80 80 80 0f 03 res.............
+| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
+| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
+| 3632: 03 00 3c 00 00 00 16 04 33 70 72 65 01 02 05 01 ..<.....3pre....
+| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
+| 3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 02 ....:.....3for..
+| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
+| 3696: 80 80 0c 03 00 3c 00 00 00 16 03 32 74 68 01 06 .....<.....2th..
+| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84 .....3eac.......
+| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
+| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
+| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01 ......8.....2in.
+| 3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80 ......pr........
+| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
+| 3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
+| 3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04 .....<.....1t...
+| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
+| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
+| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
+| 3888: 80 80 06 03 00 36 00 00 00 13 02 31 65 01 02 03 .....6.....1e...
+| 3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80 ..f.............
+| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
+| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
+| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 74 61 62 ............0tab
+| 3968: 6c 65 01 06 01 01 05 04 15 84 7f 80 80 80 03 03 le..............
+| 3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74 .0......0present
+| 4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00 .............<..
+| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
+| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
+| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 03 66 .....0each.....f
+| 4064: 6f 72 01 02 02 04 09 06 01 03 00 12 03 0b 0f 00 or..............
+| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
+| page 3 offset 8192
+| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
+| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
+| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
+| 48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 03 .V.M.A.8./.&....
+| 64: 0f 0a 0f 00 9e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
+| 80: 0e c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
+| 3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e .....4t ......4.
+| 3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
+| 3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10 3n.......2w.....
+| 3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
+| 3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 08 ....2.......1t..
+| 3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
+| 3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
+| 3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
+| 3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
+| 3808: 10 01 02 34 72 22 07 04 01 0e 01 02 34 20 08 04 ...4r.......4 ..
+| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
+| 3840: 1c 18 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
+| 3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01 2i.......2ar....
+| 3872: 10 01 02 31 74 14 08 04 01 0f 01 02 31 6e 12 0a ...1t.......1n..
+| 3888: d4 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
+| 3904: 0e 0b 04 01 16 01 02 30 74 68 65 72 0c 08 04 01 .......0ther....
+| 3920: 10 01 02 30 74 0a 08 04 01 10 01 02 30 6e 08 08 ...0t.......0n..
+| 3936: 04 01 10 01 02 30 62 06 08 04 01 10 01 02 30 61 .....0b.......0a
+| 3952: 04 06 04 01 0c 01 02 02 07 04 09 10 01 34 74 22 .............4t.
+| 3968: 06 04 09 0e 01 34 20 08 04 09 12 01 33 74 65 1e .....4 .....3te.
+| 3984: 07 04 09 10 01 33 70 1c 07 04 09 10 01 33 66 1a .....3p......3f.
+| 4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 74 .....2th......2t
+| 4016: 16 07 04 09 10 01 32 69 14 07 04 09 10 01 32 66 ......2i......2f
+| 4032: 12 07 04 09 10 01 31 74 10 07 04 09 10 01 31 69 ......1t......1i
+| 4048: 0e 06 04 09 0e 01 31 0c 08 04 09 12 01 30 74 65 ......1......0te
+| 4064: 0a 07 04 09 10 01 30 74 08 07 04 09 10 01 30 70 ......0t......0p
+| 4080: 06 08 04 09 1e 61 30 66 74 04 05 04 09 0c 01 02 .....a0ft.......
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 03 03 00 10 ................
+| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
+| page 5 offset 16384
+| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
+| 4080: 67 73 7a 18 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version.
+| page 6 offset 20480
+| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 03 03 02 01 da 03 02 02 01 02 00 00 00 00 ................
+| end crash-53216796d7c3d8.db
+}]} {}
+
+do_catchsql_test 77.1 {
+ UPDATE t1 SET B =quote(zeroblob(200)) WHERE b MATCH 'threa*thrad*tlrad*the�d';
+} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
diff --git a/ext/fts5/test/fts5corrupt4.test b/ext/fts5/test/fts5corrupt4.test
index dc9ca661d..b31f4d96e 100644
--- a/ext/fts5/test/fts5corrupt4.test
+++ b/ext/fts5/test/fts5corrupt4.test
@@ -29,6 +29,8 @@ do_execsql_test 1.0 {
INSERT INTO ttt SELECT a||a, b||b FROM ttt;
}
+expr srand(1)
+
proc mutate {blob i} {
set o [expr {$i % [string length $blob]}]
set a [string range $blob 0 $o-1]
diff --git a/ext/fts5/test/fts5delete.test b/ext/fts5/test/fts5delete.test
index 467e2e570..1214fec4f 100644
--- a/ext/fts5/test/fts5delete.test
+++ b/ext/fts5/test/fts5delete.test
@@ -91,6 +91,27 @@ do_catchsql_test 2.4 {
SELECT rowid FROM test_idx WHERE test_idx MATCH 'two' ORDER BY rank;
} {1 {database disk image is malformed}}
-
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE VIRTUAL TABLE tx USING fts5(a, b, c, d, content=);
+ INSERT INTO tx(rowid, a, c) VALUES(1, 'abc def', 'a b c');
+ INSERT INTO tx(rowid, a, c) VALUES(5, 'a b c', 'a b d def');
+}
+do_execsql_test 3.1 {
+ INSERT INTO tx(tx, rowid, a, b, c, d)
+ VALUES('delete', 5, 'a b c', NULL, 'a b d def', NULL);
+}
+do_execsql_test 3.2 {
+ INSERT INTO tx(tx) VALUES('integrity-check');
+}
+do_execsql_test 3.3 {
+ INSERT INTO tx(tx, rowid, a, b, c, d)
+ VALUES('delete', 1, 'abc def', NULL, 'a b c', NULL);
+}
+do_execsql_test 3.4 {
+ INSERT INTO tx(tx) VALUES('integrity-check');
+}
finish_test
+
diff --git a/ext/fts5/test/fts5doclist.test b/ext/fts5/test/fts5doclist.test
index d8308fd0f..08b773f6f 100644
--- a/ext/fts5/test/fts5doclist.test
+++ b/ext/fts5/test/fts5doclist.test
@@ -42,5 +42,26 @@ do_execsql_test 1.2 {
INSERT INTO ccc(ccc) VALUES('integrity-check');
}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 2.1 {
+ CREATE VIRTUAL TABLE tx USING fts5(x);
+}
+
+set doc [string repeat "abc " 5000]
+do_execsql_test 2.2 {
+ BEGIN;
+ INSERT INTO tx(rowid, x) VALUES(-9000000000000000000, $doc);
+ INSERT INTO tx(rowid, x) VALUES(9000000000000000000, $doc);
+ COMMIT;
+}
+
+do_execsql_test 2.3 {
+ SELECT rowid FROM tx('abc');
+} {
+ -9000000000000000000
+ 9000000000000000000
+}
finish_test
diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test
index 7118427a2..6862acf17 100644
--- a/ext/fts5/test/fts5plan.test
+++ b/ext/fts5/test/fts5plan.test
@@ -30,23 +30,23 @@ do_eqp_test 1.1 {
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
+ |--SCAN t1
+ `--SCAN f1 VIRTUAL TABLE INDEX 0:M1
}
do_eqp_test 1.2 {
SELECT * FROM t1, f1 WHERE f1 > t1.x
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
- `--SCAN TABLE t1
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:
+ `--SCAN t1
}
do_eqp_test 1.3 {
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:M1
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -54,12 +54,12 @@ do_eqp_test 1.4 {
SELECT * FROM f1 ORDER BY rank
} {
QUERY PLAN
- |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
+ |--SCAN f1 VIRTUAL TABLE INDEX 0:
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 1.5 {
SELECT * FROM f1 WHERE rank MATCH ?
-} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
+} {SCAN f1 VIRTUAL TABLE INDEX 0:r}
finish_test
diff --git a/ext/fts5/test/fts5prefix2.test b/ext/fts5/test/fts5prefix2.test
new file mode 100644
index 000000000..bf16e81a7
--- /dev/null
+++ b/ext/fts5/test/fts5prefix2.test
@@ -0,0 +1,57 @@
+# 2020 Dec 3
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file contains tests focused on prefix indexes.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5prefix2
+
+# If SQLITE_ENABLE_FTS5 is defined, omit this file.
+ifcapable !fts5 {
+ finish_test
+ return
+}
+
+foreach p {3 2 1} {
+ reset_db
+ do_execsql_test 1.$p.0 "
+ CREATE VIRTUAL TABLE t1 USING fts5(xyz, prefix=$p);
+ "
+ do_execsql_test 1.$p.1 {
+ INSERT INTO t1 VALUES
+ ('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 f.');
+ }
+
+ do_execsql_test 1.$p.2 {
+ SELECT highlight(t1, 0, '[', ']') FROM t1('f*');
+ } {
+ {May you [find] [forgiveness] [for] yourself and [forgive] others.}
+ {May you share [freely], never taking more than you give [f].}
+ }
+}
+
+do_execsql_test 2.0 {
+ CREATE VIRTUAL TABLE t2 USING fts5(one, prefix=3);
+ INSERT INTO t2 VALUES('top');
+ INSERT INTO t2 VALUES('to');
+ INSERT INTO t2 VALUES('tommy');
+}
+
+do_execsql_test 2.1 {
+ SELECT * FROM t2('to*');
+} {top to tommy}
+
+
+
+finish_test
diff --git a/ext/fts5/test/fts5trigram.test b/ext/fts5/test/fts5trigram.test
index 26eb7ba8d..fb66efed6 100644
--- a/ext/fts5/test/fts5trigram.test
+++ b/ext/fts5/test/fts5trigram.test
@@ -192,10 +192,9 @@ do_eqp_test 6.2 {
} {VIRTUAL TABLE INDEX 0:G0}
do_eqp_test 6.3 {
SELECT * FROM ci1 WHERE x LIKE ?
-} {{SCAN TABLE ci1 VIRTUAL TABLE INDEX 0:}}
+} {{SCAN ci1 VIRTUAL TABLE INDEX 0:}}
do_eqp_test 6.4 {
SELECT * FROM ci1 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}
finish_test
-
diff --git a/ext/misc/appendvfs.c b/ext/misc/appendvfs.c
index 14260efb5..eb9ed01f6 100644
--- a/ext/misc/appendvfs.c
+++ b/ext/misc/appendvfs.c
@@ -14,24 +14,23 @@
** appended onto the end of some other file, such as an executable.
**
** A special record must appear at the end of the file that identifies the
-** file as an appended database and provides an offset to page 1. For
-** best performance page 1 should be located at a disk page boundary, though
-** that is not required.
+** file as an appended database and provides the offset to the first page
+** of the exposed content. (Or, it is the length of the content prefix.)
+** For best performance page 1 should be located at a disk page boundary,
+** though that is not required.
**
** When opening a database using this VFS, the connection might treat
-** the file as an ordinary SQLite database, or it might treat is as a
-** database appended onto some other file. Here are the rules:
+** the file as an ordinary SQLite database, or it might treat it as a
+** database appended onto some other file. The decision is made by
+** applying the following rules in order:
**
-** (1) When opening a new empty file, that file is treated as an ordinary
-** database.
+** (1) An empty file is an ordinary database.
**
-** (2) When opening a file that begins with the standard SQLite prefix
-** string "SQLite format 3", that file is treated as an ordinary
-** database.
+** (2) If the file ends with the appendvfs trailer string
+** "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
**
-** (3) When opening a file that ends with the appendvfs trailer string
-** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
-** database.
+** (3) If the file begins with the standard SQLite prefix string
+** "SQLite format 3", that file is an ordinary database.
**
** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
** set, then a new database is appended to the already existing file.
@@ -39,13 +38,13 @@
** (5) Otherwise, SQLITE_CANTOPEN is returned.
**
** To avoid unnecessary complications with the PENDING_BYTE, the size of
-** the file containing the database is limited to 1GB. This VFS will refuse
-** to read or write past the 1GB mark. This restriction might be lifted in
-** future versions. For now, if you need a large database, then keep the
-** database in a separate file.
+** the file containing the database is limited to 1GiB. (1073741824 bytes)
+** This VFS will not read or write past the 1GiB mark. This restriction
+** might be lifted in future versions. For now, if you need a larger
+** database, then keep it in a separate file.
**
-** If the file being opened is not an appended database, then this shim is
-** a pass-through into the default underlying VFS.
+** If the file being opened is a plain database (not an appended one), then
+** this shim is a pass-through into the default underlying VFS. (rule 3)
**/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
@@ -58,17 +57,27 @@ SQLITE_EXTENSION_INIT1
** 123456789 123456789 12345
**
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
-** the offset to page 1.
+** the offset to page 1, and also the length of the prefix content.
*/
#define APND_MARK_PREFIX "Start-Of-SQLite3-"
#define APND_MARK_PREFIX_SZ 17
-#define APND_MARK_SIZE 25
+#define APND_MARK_FOS_SZ 8
+#define APND_MARK_SIZE (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
/*
** Maximum size of the combined prefix + database + append-mark. This
** must be less than 0x40000000 to avoid locking issues on Windows.
*/
-#define APND_MAX_SIZE (65536*15259)
+#define APND_MAX_SIZE (0x40000000)
+
+/*
+** Try to align the database to an even multiple of APND_ROUNDUP bytes.
+*/
+#ifndef APND_ROUNDUP
+#define APND_ROUNDUP 4096
+#endif
+#define APND_ALIGN_MASK ((sqlite3_int64)(APND_ROUNDUP-1))
+#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
/*
** Forward declaration of objects used by this utility
@@ -82,11 +91,45 @@ typedef struct ApndFile ApndFile;
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
-/* An open file */
+/* An open appendvfs file
+**
+** An instance of this structure describes the appended database file.
+** A separate sqlite3_file object is always appended. The appended
+** sqlite3_file object (which can be accessed using ORIGFILE()) describes
+** the entire file, including the prefix, the database, and the
+** append-mark.
+**
+** The structure of an AppendVFS database is like this:
+**
+** +-------------+---------+----------+-------------+
+** | prefix-file | padding | database | append-mark |
+** +-------------+---------+----------+-------------+
+** ^ ^
+** | |
+** iPgOne iMark
+**
+**
+** "prefix file" - file onto which the database has been appended.
+** "padding" - zero or more bytes inserted so that "database"
+** starts on an APND_ROUNDUP boundary
+** "database" - The SQLite database file
+** "append-mark" - The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
+** the offset from the start of prefix-file to the start
+** of "database".
+**
+** The size of the database is iMark - iPgOne.
+**
+** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
+** of iPgOne stored as a big-ending 64-bit integer.
+**
+** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
+** Or, iMark is -1 to indicate that it has not yet been written.
+*/
struct ApndFile {
- sqlite3_file base; /* IO methods */
- sqlite3_int64 iPgOne; /* File offset to page 1 */
- sqlite3_int64 iMark; /* Start of the append-mark */
+ sqlite3_file base; /* Subclass. MUST BE FIRST! */
+ sqlite3_int64 iPgOne; /* Offset to the start of the database */
+ sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */
+ /* Always followed by another sqlite3_file that describes the whole file */
};
/*
@@ -178,8 +221,6 @@ static const sqlite3_io_methods apnd_io_methods = {
apndUnfetch /* xUnfetch */
};
-
-
/*
** Close an apnd-file.
*/
@@ -197,22 +238,37 @@ static int apndRead(
int iAmt,
sqlite_int64 iOfst
){
- ApndFile *p = (ApndFile *)pFile;
+ ApndFile *paf = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
- return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
+ return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}
/*
-** Add the append-mark onto the end of the file.
+** Add the append-mark onto what should become the end of the file.
+* If and only if this succeeds, internal ApndFile.iMark is updated.
+* Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
*/
-static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
- int i;
+static int apndWriteMark(
+ ApndFile *paf,
+ sqlite3_file *pFile,
+ sqlite_int64 iWriteEnd
+){
+ sqlite_int64 iPgOne = paf->iPgOne;
unsigned char a[APND_MARK_SIZE];
+ int i = APND_MARK_FOS_SZ;
+ int rc;
+ assert(pFile == ORIGFILE(paf));
memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
- for(i=0; i<8; i++){
- a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
+ while( --i >= 0 ){
+ a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
+ iPgOne >>= 8;
+ }
+ iWriteEnd += paf->iPgOne;
+ if( SQLITE_OK==(rc = pFile->pMethods->xWrite
+ (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
+ paf->iMark = iWriteEnd;
}
- return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
+ return rc;
}
/*
@@ -224,38 +280,28 @@ static int apndWrite(
int iAmt,
sqlite_int64 iOfst
){
- int rc;
- ApndFile *p = (ApndFile *)pFile;
+ ApndFile *paf = (ApndFile *)pFile;
+ sqlite_int64 iWriteEnd = iOfst + iAmt;
+ if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
pFile = ORIGFILE(pFile);
- if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
- rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
- if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
- sqlite3_int64 sz = 0;
- rc = pFile->pMethods->xFileSize(pFile, &sz);
- if( rc==SQLITE_OK ){
- p->iMark = sz - APND_MARK_SIZE;
- if( iOfst + iAmt + p->iPgOne > p->iMark ){
- p->iMark = p->iPgOne + iOfst + iAmt;
- rc = apndWriteMark(p, pFile);
- }
- }
+ /* If append-mark is absent or will be overwritten, write it. */
+ if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
+ int rc = apndWriteMark(paf, pFile, iWriteEnd);
+ if( SQLITE_OK!=rc ) return rc;
}
- return rc;
+ return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
}
/*
** Truncate an apnd-file.
*/
static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
- int rc;
- ApndFile *p = (ApndFile *)pFile;
+ ApndFile *paf = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
- rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
- if( rc==SQLITE_OK ){
- p->iMark = p->iPgOne+size;
- rc = apndWriteMark(p, pFile);
- }
- return rc;
+ /* The append mark goes out first so truncate failure does not lose it. */
+ if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
+ /* Truncate underlying file just past append mark */
+ return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
}
/*
@@ -268,16 +314,12 @@ static int apndSync(sqlite3_file *pFile, int flags){
/*
** Return the current file-size of an apnd-file.
+** If the append mark is not yet there, the file-size is 0.
*/
static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- ApndFile *p = (ApndFile *)pFile;
- int rc;
- pFile = ORIGFILE(p);
- rc = pFile->pMethods->xFileSize(pFile, pSize);
- if( rc==SQLITE_OK && p->iPgOne ){
- *pSize -= p->iPgOne + APND_MARK_SIZE;
- }
- return rc;
+ ApndFile *paf = (ApndFile *)pFile;
+ *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
+ return SQLITE_OK;
}
/*
@@ -308,12 +350,13 @@ static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
** File control method. For custom operations on an apnd-file.
*/
static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
- ApndFile *p = (ApndFile *)pFile;
+ ApndFile *paf = (ApndFile *)pFile;
int rc;
pFile = ORIGFILE(pFile);
+ if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
- *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
+ *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
}
return rc;
}
@@ -372,6 +415,9 @@ static int apndFetch(
void **pp
){
ApndFile *p = (ApndFile *)pFile;
+ if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
+ return SQLITE_IOERR; /* Cannot read what is not yet there. */
+ }
pFile = ORIGFILE(pFile);
return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
}
@@ -383,95 +429,155 @@ static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
}
-/*
-** Check to see if the file is an ordinary SQLite database file.
-*/
-static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
- int rc;
- char zHdr[16];
- static const char aSqliteHdr[] = "SQLite format 3";
- if( sz<512 ) return 0;
- rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
- if( rc ) return 0;
- return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
-}
-
/*
** Try to read the append-mark off the end of a file. Return the
-** start of the appended database if the append-mark is present. If
-** there is no append-mark, return -1;
+** start of the appended database if the append-mark is present.
+** If there is no valid append-mark, return -1;
+**
+** An append-mark is only valid if the NNNNNNNN start-of-database offset
+** indicates that the appended database contains at least one page. The
+** start-of-database value must be a multiple of 512.
*/
static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
int rc, i;
sqlite3_int64 iMark;
+ int msbs = 8 * (APND_MARK_FOS_SZ-1);
unsigned char a[APND_MARK_SIZE];
- if( sz<=APND_MARK_SIZE ) return -1;
+ if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
if( rc ) return -1;
if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
- iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
- for(i=1; i<8; i++){
- iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
+ iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
+ for(i=1; i<8; i++){
+ msbs -= 8;
+ iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]< (sz - APND_MARK_SIZE - 512) ) return -1;
+ if( iMark & 0x1ff ) return -1;
return iMark;
}
+static const char apvfsSqliteHdr[] = "SQLite format 3";
+/*
+** Check to see if the file is an appendvfs SQLite database file.
+** Return true iff it is such. Parameter sz is the file's size.
+*/
+static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
+ int rc;
+ char zHdr[16];
+ sqlite3_int64 iMark = apndReadMark(sz, pFile);
+ if( iMark>=0 ){
+ /* If file has the correct end-marker, the expected odd size, and the
+ ** SQLite DB type marker where the end-marker puts it, then it
+ ** is an appendvfs database.
+ */
+ rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
+ if( SQLITE_OK==rc
+ && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
+ && (sz & 0x1ff) == APND_MARK_SIZE
+ && sz>=512+APND_MARK_SIZE
+ ){
+ return 1; /* It's an appendvfs database */
+ }
+ }
+ return 0;
+}
+
+/*
+** Check to see if the file is an ordinary SQLite database file.
+** Return true iff so. Parameter sz is the file's size.
+*/
+static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
+ char zHdr[16];
+ if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
+ || (sz & 0x1ff) != 0
+ || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
+ || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
+ ){
+ return 0;
+ }else{
+ return 1;
+ }
+}
+
/*
** Open an apnd file handle.
*/
static int apndOpen(
- sqlite3_vfs *pVfs,
+ sqlite3_vfs *pApndVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
- ApndFile *p;
- sqlite3_file *pSubFile;
- sqlite3_vfs *pSubVfs;
+ ApndFile *pApndFile = (ApndFile*)pFile;
+ sqlite3_file *pBaseFile = ORIGFILE(pFile);
+ sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
int rc;
- sqlite3_int64 sz;
- pSubVfs = ORIGVFS(pVfs);
+ sqlite3_int64 sz = 0;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
+ /* The appendvfs is not to be used for transient or temporary databases.
+ ** Just use the base VFS open to initialize the given file object and
+ ** open the underlying file. (Appendvfs is then unused for this file.)
+ */
+ return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
}
- p = (ApndFile*)pFile;
- memset(p, 0, sizeof(*p));
- pSubFile = ORIGFILE(pFile);
+ memset(pApndFile, 0, sizeof(ApndFile));
pFile->pMethods = &apnd_io_methods;
- rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
- if( rc ) goto apnd_open_done;
- rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
+ pApndFile->iMark = -1; /* Append mark not yet written */
+
+ rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
+ if( rc==SQLITE_OK ){
+ rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
+ if( rc ){
+ pBaseFile->pMethods->xClose(pBaseFile);
+ }
+ }
if( rc ){
- pSubFile->pMethods->xClose(pSubFile);
- goto apnd_open_done;
+ pFile->pMethods = 0;
+ return rc;
}
- if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
- memmove(pFile, pSubFile, pSubVfs->szOsFile);
+ if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
+ /* The file being opened appears to be just an ordinary DB. Copy
+ ** the base dispatch-table so this instance mimics the base VFS.
+ */
+ memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
return SQLITE_OK;
}
- p->iMark = 0;
- p->iPgOne = apndReadMark(sz, pFile);
- if( p->iPgOne>0 ){
+ pApndFile->iPgOne = apndReadMark(sz, pFile);
+ if( pApndFile->iPgOne>=0 ){
+ pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
return SQLITE_OK;
}
if( (flags & SQLITE_OPEN_CREATE)==0 ){
- pSubFile->pMethods->xClose(pSubFile);
+ pBaseFile->pMethods->xClose(pBaseFile);
rc = SQLITE_CANTOPEN;
+ pFile->pMethods = 0;
+ }else{
+ /* Round newly added appendvfs location to #define'd page boundary.
+ ** Note that nothing has yet been written to the underlying file.
+ ** The append mark will be written along with first content write.
+ ** Until then, paf->iMark value indicates it is not yet written.
+ */
+ pApndFile->iPgOne = APND_START_ROUNDUP(sz);
}
- p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
-apnd_open_done:
- if( rc ) pFile->pMethods = 0;
return rc;
}
/*
-** All other VFS methods are pass-thrus.
+** Delete an apnd file.
+** For an appendvfs, this could mean delete the appendvfs portion,
+** leaving the appendee as it was before it gained an appendvfs.
+** For now, this code deletes the underlying file too.
*/
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}
+
+/*
+** All other VFS methods are pass-thrus.
+*/
static int apndAccess(
sqlite3_vfs *pVfs,
const char *zPath,
@@ -551,6 +657,7 @@ int sqlite3_appendvfs_init(
(void)pzErrMsg;
(void)db;
pOrig = sqlite3_vfs_find(0);
+ if( pOrig==0 ) return SQLITE_ERROR;
apnd_vfs.iVersion = pOrig->iVersion;
apnd_vfs.pAppData = pOrig;
apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
diff --git a/ext/misc/cksumvfs.c b/ext/misc/cksumvfs.c
index a0888c002..8c340889f 100644
--- a/ext/misc/cksumvfs.c
+++ b/ext/misc/cksumvfs.c
@@ -356,6 +356,41 @@ static void cksmVerifyFunc(
sqlite3_result_int(context, memcmp(data+nByte-8,cksum,8)==0);
}
+#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
+/*
+** SQL function: initialize_cksumvfs(SCHEMANAME)
+**
+** This SQL functions (whose name is actually determined at compile-time
+** by the value of the SQLITE_CKSUMVFS_INIT_FUNCNAME macro) invokes:
+**
+** sqlite3_file_control(db, SCHEMANAME, SQLITE_FCNTL_RESERVE_BYTE, &n);
+**
+** In order to set the reserve bytes value to 8, so that cksumvfs will
+** operation. This feature is provided (if and only if the
+** SQLITE_CKSUMVFS_INIT_FUNCNAME compile-time option is set to a string
+** which is the name of the SQL function) so as to provide the ability
+** to invoke the file-control in programming languages that lack
+** direct access to the sqlite3_file_control() interface (ex: Java).
+**
+** This interface is undocumented, apart from this comment. Usage
+** example:
+**
+** 1. Compile with -DSQLITE_CKSUMVFS_INIT_FUNCNAME="ckvfs_init"
+** 2. Run: "SELECT cksum_init('main'); VACUUM;"
+*/
+static void cksmInitFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int nByte = 8;
+ const char *zSchemaName = (const char*)sqlite3_value_text(argv[0]);
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ sqlite3_file_control(db, zSchemaName, SQLITE_FCNTL_RESERVE_BYTES, &nByte);
+ /* Return NULL */
+}
+#endif /* SQLITE_CKSUMBFS_INIT_FUNCNAME */
+
/*
** Close a cksm-file.
*/
@@ -544,6 +579,18 @@ static int cksmFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( op==SQLITE_FCNTL_CKPT_START || op==SQLITE_FCNTL_CKPT_DONE ){
p->inCkpt = op==SQLITE_FCNTL_CKPT_START;
if( p->pPartner ) p->pPartner->inCkpt = p->inCkpt;
+ }else if( op==SQLITE_FCNTL_CKSM_FILE ){
+ /* This VFS needs to obtain a pointer to the corresponding database
+ ** file handle from within xOpen() calls to open wal files. To do this,
+ ** it uses the sqlite3_database_file_object() API to obtain a pointer
+ ** to the file-handle used by SQLite to access the db file. This is
+ ** fine if cksmvfs happens to be the top-level VFS, but not if there
+ ** are one or more wrapper VFS. To handle this case, this file-control
+ ** is used to extract the cksmvfs file-handle from any wrapper file
+ ** handle. */
+ sqlite3_file **ppFile = (sqlite3_file**)pArg;
+ *ppFile = (sqlite3_file*)p;
+ return SQLITE_OK;
}
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
@@ -653,6 +700,8 @@ static int cksmOpen(
if( rc ) goto cksm_open_done;
if( flags & SQLITE_OPEN_WAL ){
sqlite3_file *pDb = sqlite3_database_file_object(zName);
+ rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
+ assert( rc==SQLITE_OK );
p->pPartner = (CksmFile*)pDb;
assert( p->pPartner->pPartner==0 );
p->pPartner->pPartner = p;
@@ -715,7 +764,17 @@ static int cksmGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int cksmCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
- return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
+ sqlite3_vfs *pOrig = ORIGVFS(pVfs);
+ int rc;
+ assert( pOrig->iVersion>=2 );
+ if( pOrig->xCurrentTimeInt64 ){
+ rc = pOrig->xCurrentTimeInt64(pOrig, p);
+ }else{
+ double r;
+ rc = pOrig->xCurrentTime(pOrig, &r);
+ *p = (sqlite3_int64)(r*86400000.0);
+ }
+ return rc;
}
static int cksmSetSystemCall(
sqlite3_vfs *pVfs,
@@ -746,6 +805,11 @@ static int cksmRegisterFunc(
rc = sqlite3_create_function(db, "verify_checksum", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, cksmVerifyFunc, 0, 0);
+#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
+ (void)sqlite3_create_function(db, SQLITE_CKSUMVFS_INIT_FUNCNAME, 1,
+ SQLITE_UTF8|SQLITE_DIRECTONLY,
+ 0, cksmInitFunc, 0, 0);
+#endif
return rc;
}
@@ -759,6 +823,7 @@ static int cksmRegisterVfs(void){
sqlite3_vfs *pOrig;
if( sqlite3_vfs_find("cksmvfs")!=0 ) return SQLITE_OK;
pOrig = sqlite3_vfs_find(0);
+ if( pOrig==0 ) return SQLITE_ERROR;
cksm_vfs.iVersion = pOrig->iVersion;
cksm_vfs.pAppData = pOrig;
cksm_vfs.szOsFile = pOrig->szOsFile + sizeof(CksmFile);
@@ -806,9 +871,6 @@ int sqlite3_cksumvfs_init(
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* not used */
rc = cksmRegisterFunc(db, 0, 0);
- if( rc==SQLITE_OK ){
-
- }
if( rc==SQLITE_OK ){
rc = cksmRegisterVfs();
}
diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c
index a8d68ac72..37c6c2f52 100644
--- a/ext/misc/decimal.c
+++ b/ext/misc/decimal.c
@@ -459,10 +459,11 @@ static void decimalSubFunc(
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
- if( pB==0 ) return;
- pB->sign = !pB->sign;
- decimal_add(pA, pB);
- decimal_result(context, pA);
+ if( pB ){
+ pB->sign = !pB->sign;
+ decimal_add(pA, pB);
+ decimal_result(context, pA);
+ }
decimal_free(pA);
decimal_free(pB);
}
diff --git a/ext/misc/ieee754.c b/ext/misc/ieee754.c
index 121eb43d6..6cdd79a4d 100644
--- a/ext/misc/ieee754.c
+++ b/ext/misc/ieee754.c
@@ -167,6 +167,14 @@ static void ieee754func(
int isNeg = 0;
m = sqlite3_value_int64(argv[0]);
e = sqlite3_value_int64(argv[1]);
+
+ /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */
+ if( e>10000 ){
+ e = 10000;
+ }else if( e<-10000 ){
+ e = -10000;
+ }
+
if( m<0 ){
isNeg = 1;
m = -m;
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 77641064d..077d02d91 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -299,7 +299,7 @@ static void jsonAppendSeparator(JsonString *p){
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
+ if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
p->zBuf[p->nUsed++] = '"';
for(i=0; inUsed>1 ){
jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
}
+ pStr->pCtx = ctx;
jsonAppendValue(pStr, argv[0]);
}
}
@@ -1959,11 +1959,7 @@ static void jsonGroupInverse(
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
- for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
- if( i>=pStr->nUsed ){
- pStr->nUsed = 1;
- return;
- }
+ for(i=1; inUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
inStr = !inStr;
}else if( c=='\\' ){
@@ -1973,8 +1969,13 @@ static void jsonGroupInverse(
if( c=='}' || c==']' ) nNest--;
}
}
- pStr->nUsed -= i;
- memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ if( inUsed ){
+ pStr->nUsed -= i;
+ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ z[pStr->nUsed] = 0;
+ }else{
+ pStr->nUsed = 1;
+ }
}
#else
# define jsonGroupInverse 0
@@ -2002,8 +2003,8 @@ static void jsonObjectStep(
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
}
+ pStr->pCtx = ctx;
z = (const char*)sqlite3_value_text(argv[0]);
n = (u32)sqlite3_value_bytes(argv[0]);
jsonAppendString(pStr, z, n);
diff --git a/ext/misc/memvfs.c b/ext/misc/memvfs.c
index 27a61c35e..83fc9468e 100644
--- a/ext/misc/memvfs.c
+++ b/ext/misc/memvfs.c
@@ -559,6 +559,7 @@ int sqlite3_memvfs_init(
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
mem_vfs.pAppData = sqlite3_vfs_find(0);
+ if( mem_vfs.pAppData==0 ) return SQLITE_ERROR;
mem_vfs.szOsFile = sizeof(MemFile);
rc = sqlite3_vfs_register(&mem_vfs, 1);
#ifdef MEMVFS_TEST
diff --git a/ext/misc/regexp.c b/ext/misc/regexp.c
index 03bbeb97d..99fb453ce 100644
--- a/ext/misc/regexp.c
+++ b/ext/misc/regexp.c
@@ -248,7 +248,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
break;
}
case RE_OP_ANY: {
- re_add_state(pNext, x+1);
+ if( c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
@@ -256,7 +256,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
break;
}
case RE_OP_NOTWORD: {
- if( !re_word_char(c) ) re_add_state(pNext, x+1);
+ if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_DIGIT: {
@@ -264,7 +264,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
break;
}
case RE_OP_NOTDIGIT: {
- if( !re_digit_char(c) ) re_add_state(pNext, x+1);
+ if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_SPACE: {
@@ -272,7 +272,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
break;
}
case RE_OP_NOTSPACE: {
- if( !re_space_char(c) ) re_add_state(pNext, x+1);
+ if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_BOUNDARY: {
@@ -297,8 +297,11 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
rc = 1;
goto re_match_end;
}
- case RE_OP_CC_INC:
case RE_OP_CC_EXC: {
+ if( c==0 ) break;
+ /* fall-through */
+ }
+ case RE_OP_CC_INC: {
int j = 1;
int n = pRe->aArg[x];
int hit = 0;
@@ -319,7 +322,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
}
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
if( hit ) re_add_state(pNext, x+n);
- break;
+ break;
}
}
}
@@ -480,7 +483,7 @@ static const char *re_subcompile_string(ReCompiled *p){
iStart = p->nState;
switch( c ){
case '|':
- case '$':
+ case '$':
case ')': {
p->sIn.i--;
return 0;
@@ -496,7 +499,7 @@ static const char *re_subcompile_string(ReCompiled *p){
if( rePeek(p)=='*' ){
re_append(p, RE_OP_ANYSTAR, 0);
p->sIn.i++;
- }else{
+ }else{
re_append(p, RE_OP_ANY, 0);
}
break;
@@ -673,8 +676,8 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
** regex engine over the string. Do not worry able trying to match
** unicode characters beyond plane 0 - those are very rare and this is
** just an optimization. */
- if( pRe->aOp[0]==RE_OP_ANYSTAR ){
- for(j=0, i=1; jzInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
+ if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
+ for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
pRe->zInit[j++] = (unsigned char)x;
@@ -705,8 +708,8 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
** is implemented as regexp(B,A).
*/
static void re_sql_func(
- sqlite3_context *context,
- int argc,
+ sqlite3_context *context,
+ int argc,
sqlite3_value **argv
){
ReCompiled *pRe; /* Compiled regular expression */
@@ -715,11 +718,12 @@ static void re_sql_func(
const char *zErr; /* Compile error message */
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
+ (void)argc; /* Unused */
pRe = sqlite3_get_auxdata(context, 0);
if( pRe==0 ){
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
- zErr = re_compile(&pRe, zPattern, 0);
+ zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
if( zErr ){
re_free(pRe);
sqlite3_result_error(context, zErr, -1);
@@ -754,7 +758,14 @@ int sqlite3_regexp_init(
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
+ (void)pzErrMsg; /* Unused */
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
0, re_sql_func, 0, 0);
+ if( rc==SQLITE_OK ){
+ /* The regexpi(PATTERN,STRING) function is a case-insensitive version
+ ** of regexp(PATTERN,STRING). */
+ rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
+ (void*)db, re_sql_func, 0, 0);
+ }
return rc;
}
diff --git a/ext/misc/series.c b/ext/misc/series.c
index 092383e57..a4e92ace8 100644
--- a/ext/misc/series.c
+++ b/ext/misc/series.c
@@ -247,7 +247,8 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** 4: step=VALUE
**
** Also, if bit 8 is set, that means that the series should be output
-** in descending order rather than in ascending order.
+** in descending order rather than in ascending order. If bit 16 is
+** set, then output must appear in ascending order.
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
@@ -273,7 +274,12 @@ static int seriesFilter(
}
if( idxNum & 4 ){
pCur->iStep = sqlite3_value_int64(argv[i++]);
- if( pCur->iStep<1 ) pCur->iStep = 1;
+ if( pCur->iStep==0 ){
+ pCur->iStep = 1;
+ }else if( pCur->iStep<0 ){
+ pCur->iStep = -pCur->iStep;
+ if( (idxNum & 16)==0 ) idxNum |= 8;
+ }
}else{
pCur->iStep = 1;
}
@@ -367,7 +373,11 @@ static int seriesBestIndex(
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy==1 ){
- if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
+ if( pIdxInfo->aOrderBy[0].desc ){
+ idxNum |= 8;
+ }else{
+ idxNum |= 16;
+ }
pIdxInfo->orderByConsumed = 1;
}
}else{
diff --git a/ext/misc/shathree.c b/ext/misc/shathree.c
index 56a5584f3..ef25cb56c 100644
--- a/ext/misc/shathree.c
+++ b/ext/misc/shathree.c
@@ -31,7 +31,10 @@ SQLITE_EXTENSION_INIT1
#include
#include
#include
+
+#ifndef SQLITE_AMALGAMATION
typedef sqlite3_uint64 u64;
+#endif /* SQLITE_AMALGAMATION */
/******************************************************************************
** The Hash Engine
diff --git a/ext/misc/vfslog.c b/ext/misc/vfslog.c
index 24a46a921..cb5bc5513 100644
--- a/ext/misc/vfslog.c
+++ b/ext/misc/vfslog.c
@@ -754,6 +754,7 @@ static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
*/
int sqlite3_register_vfslog(const char *zArg){
vlog_vfs.pVfs = sqlite3_vfs_find(0);
+ if( vlog_vfs.pVfs==0 ) return SQLITE_ERROR;
vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
return sqlite3_vfs_register(&vlog_vfs.base, 1);
}
diff --git a/ext/misc/vfsstat.c b/ext/misc/vfsstat.c
index 186ed788f..83a7a3df7 100644
--- a/ext/misc/vfsstat.c
+++ b/ext/misc/vfsstat.c
@@ -806,6 +806,7 @@ int sqlite3_vfsstat_init(
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
vstat_vfs.pVfs = sqlite3_vfs_find(0);
+ if( vstat_vfs.pVfs==0 ) return SQLITE_ERROR;
vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
if( rc==SQLITE_OK ){
diff --git a/ext/misc/wholenumber.c b/ext/misc/wholenumber.c
index 5643f9cf7..03d6e6902 100644
--- a/ext/misc/wholenumber.c
+++ b/ext/misc/wholenumber.c
@@ -220,7 +220,7 @@ static int wholenumberBestIndex(
pIdxInfo->orderByConsumed = 1;
}
if( (idxNum & 12)==0 ){
- pIdxInfo->estimatedCost = (double)100000000;
+ pIdxInfo->estimatedCost = 1e99;
}else if( (idxNum & 3)==0 ){
pIdxInfo->estimatedCost = (double)5;
}else{
diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c
index f9fbcfc0b..b727f9f2b 100644
--- a/ext/misc/zipfile.c
+++ b/ext/misc/zipfile.c
@@ -36,10 +36,24 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_AMALGAMATION
+#ifndef UINT32_TYPE
+# ifdef HAVE_UINT32_T
+# define UINT32_TYPE uint32_t
+# else
+# define UINT32_TYPE unsigned int
+# endif
+#endif
+#ifndef UINT16_TYPE
+# ifdef HAVE_UINT16_T
+# define UINT16_TYPE uint16_t
+# else
+# define UINT16_TYPE unsigned short int
+# endif
+#endif
typedef sqlite3_int64 i64;
typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned long u32;
+typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
+typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
@@ -706,34 +720,24 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/
static u32 zipfileMtime(ZipfileCDS *pCDS){
- int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
- int M = ((pCDS->mDate >> 5) & 0x0F);
- int D = (pCDS->mDate & 0x1F);
- int B = -13;
-
- int sec = (pCDS->mTime & 0x1F)*2;
- int min = (pCDS->mTime >> 5) & 0x3F;
- int hr = (pCDS->mTime >> 11) & 0x1F;
- i64 JD;
-
- /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
-
- /* Calculate the JD in seconds for noon on the day in question */
- if( M<3 ){
- Y = Y-1;
- M = M+12;
+ int Y,M,D,X1,X2,A,B,sec,min,hr;
+ i64 JDsec;
+ Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
+ M = ((pCDS->mDate >> 5) & 0x0F);
+ D = (pCDS->mDate & 0x1F);
+ sec = (pCDS->mTime & 0x1F)*2;
+ min = (pCDS->mTime >> 5) & 0x3F;
+ hr = (pCDS->mTime >> 11) & 0x1F;
+ if( M<=2 ){
+ Y--;
+ M += 12;
}
- JD = (i64)(24*60*60) * (
- (int)(365.25 * (Y + 4716))
- + (int)(30.6001 * (M + 1))
- + D + B - 1524
- );
-
- /* Correct the JD for the time within the day */
- JD += (hr-12) * 3600 + min * 60 + sec;
-
- /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
- return (u32)(JD - (i64)(24405875) * 24*60*6);
+ X1 = 36525*(Y+4716)/100;
+ X2 = 306001*(M+1)/10000;
+ A = Y/100;
+ B = 2 - A + (A/4);
+ JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
+ return (u32)(JDsec - (i64)24405875*(i64)8640);
}
/*
@@ -1482,6 +1486,7 @@ static int zipfileBegin(sqlite3_vtab *pVtab){
static u32 zipfileTime(void){
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
u32 ret;
+ if( pVfs==0 ) return 0;
if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
i64 ms;
pVfs->xCurrentTimeInt64(pVfs, &ms);
@@ -2170,6 +2175,10 @@ static int zipfileRegister(sqlite3 *db){
zipfileStep, zipfileFinal
);
}
+ assert( sizeof(i64)==8 );
+ assert( sizeof(u32)==4 );
+ assert( sizeof(u16)==2 );
+ assert( sizeof(u8)==1 );
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/ext/rbu/rbu.c b/ext/rbu/rbu.c
index 02822c4a4..7a24db214 100644
--- a/ext/rbu/rbu.c
+++ b/ext/rbu/rbu.c
@@ -56,7 +56,7 @@ void usage(const char *zArgv0){
void report_default_vfs(){
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
- fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName);
+ fprintf(stdout, "default vfs is \"%s\"\n", pVfs ? pVfs->zName : "NULL");
}
void report_rbu_vfs(sqlite3rbu *pRbu){
@@ -183,6 +183,13 @@ int main(int argc, char **argv){
break;
}
+ if( nStatStep>0 ){
+ sqlite3_int64 nUsed;
+ sqlite3_int64 nHighwater;
+ sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0);
+ fprintf(stdout, "memory used=%lld highwater=%lld\n", nUsed, nHighwater);
+ }
+
sqlite3_free(zErrmsg);
return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;
}
diff --git a/ext/rbu/rbu1.test b/ext/rbu/rbu1.test
index 7ec075b7e..9237dbcea 100644
--- a/ext/rbu/rbu1.test
+++ b/ext/rbu/rbu1.test
@@ -132,6 +132,11 @@ foreach {tn3 create_vfs destroy_vfs} {
} {
sqlite3rbu_destroy_vfs myrbu
}
+ 3 {
+ sqlite3_register_cksumvfs
+ } {
+ sqlite3_unregister_cksumvfs
+ }
} {
eval $create_vfs
diff --git a/ext/rbu/rbudiff.test b/ext/rbu/rbudiff.test
index 965ce297e..5c2bf9bee 100644
--- a/ext/rbu/rbudiff.test
+++ b/ext/rbu/rbudiff.test
@@ -268,6 +268,14 @@ tablE t1 USING FTs5(c);
DELETE FROM t1 WHERE rowid = 1;
INSERT INTO t1 VALUES('a b c');
}
+ 4 {
+ creAte virTUal tablE t1 USING FTs5(c);
+ INSERT INTO t1 VALUES('a b c');
+ INSERT INTO t1 VALUES('a b c');
+ } {
+ DELETE FROM t1 WHERE rowid = 1;
+ INSERT INTO t1 VALUES('a b c');
+ }
} {
forcedelete test.db test.db2
diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c
index 12a0a4660..1a13b6c4a 100644
--- a/ext/rbu/sqlite3rbu.c
+++ b/ext/rbu/sqlite3rbu.c
@@ -1620,7 +1620,9 @@ char *rbuVacuumIndexStart(
zSep = "";
for(iCol=0; iColnCol; iCol++){
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
- if( zQuoted[0]=='N' ){
+ if( zQuoted==0 ){
+ p->rc = SQLITE_NOMEM;
+ }else if( zQuoted[0]=='N' ){
bFailed = 1;
break;
}
@@ -4828,22 +4830,24 @@ static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
#endif
assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
- /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
- ** taking this lock also prevents any checkpoints from occurring.
- ** todo: really, it's not clear why this might occur, as
- ** wal_autocheckpoint ought to be turned off. */
+ if( pRbu && (
+ pRbu->eStage==RBU_STAGE_OAL
+ || pRbu->eStage==RBU_STAGE_MOVE
+ || pRbu->eStage==RBU_STAGE_DONE
+ )){
+ /* Prevent SQLite from taking a shm-lock on the target file when it
+ ** is supplying heap memory to the upper layer in place of *-shm
+ ** segments. */
if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
}else{
int bCapture = 0;
if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
bCapture = 1;
}
-
if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
if( bCapture && rc==SQLITE_OK ){
- pRbu->mLock |= (1 << ofst);
+ pRbu->mLock |= ((1<pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- /* This call is to open a *-wal file. Intead, open the *-oal. This
- ** code ensures that the string passed to xOpen() is terminated by a
- ** pair of '\0' bytes in case the VFS attempts to extract a URI
- ** parameter from it. */
- const char *zBase = zName;
- size_t nCopy;
- char *zCopy;
+ /* This call is to open a *-wal file. Intead, open the *-oal. */
+ size_t nOpen;
if( rbuIsVacuum(pDb->pRbu) ){
- zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = sqlite3_filename_wal(zBase);
- }
- nCopy = strlen(zBase);
- zCopy = sqlite3_malloc64(nCopy+2);
- if( zCopy ){
- memcpy(zCopy, zBase, nCopy);
- zCopy[nCopy-3] = 'o';
- zCopy[nCopy] = '\0';
- zCopy[nCopy+1] = '\0';
- zOpen = (const char*)(pFd->zDel = zCopy);
- }else{
- rc = SQLITE_NOMEM;
+ zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
+ zOpen = sqlite3_filename_wal(zOpen);
}
+ nOpen = strlen(zOpen);
+ ((char*)zOpen)[nOpen-3] = 'o';
pFd->pRbu = pDb->pRbu;
}
pDb->pWalFd = pFd;
diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c
index b1cff38ed..b7759bbb5 100644
--- a/ext/rtree/geopoly.c
+++ b/ext/rtree/geopoly.c
@@ -310,6 +310,10 @@ static GeoPoly *geopolyFuncParam(
){
const unsigned char *a = sqlite3_value_blob(pVal);
int nVertex;
+ if( a==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ return 0;
+ }
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
if( (a[0]==0 || a[0]==1)
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
@@ -683,7 +687,7 @@ static GeoPoly *geopolyBBox(
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
- }else{
+ }else if( aCoord ){
memset(aCoord, 0, sizeof(RtreeCoord)*4);
}
return pOut;
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index f5b57a5e2..2151d5af0 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -3890,11 +3890,16 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
+
){
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
- sqlite3_result_int(ctx, readInt16(zBlob));
+ if( zBlob ){
+ sqlite3_result_int(ctx, readInt16(zBlob));
+ }else{
+ sqlite3_result_error_nomem(ctx);
+ }
}
}
diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test
index bc9ff8429..b6dfe992a 100644
--- a/ext/rtree/rtree6.test
+++ b/ext/rtree/rtree6.test
@@ -79,47 +79,47 @@ do_eqp_test rtree6.2.1 {
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.2 {
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.3 {
SELECT * FROM t1,t2 WHERE k=ii
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test rtree6.2.4.1 {
SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
+ `--SEARCH t2 USING AUTOMATIC COVERING INDEX (v=?)
}
do_eqp_test rtree6.2.4.2 {
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
- `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
+ `--SEARCH t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
}
do_eqp_test rtree6.2.5 {
SELECT * FROM t1,t2 WHERE k=ii AND x1=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.2 {
@@ -39,8 +39,8 @@ do_eqp_test 1.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.3 {
@@ -48,16 +48,16 @@ do_eqp_test 1.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 1.5 {
SELECT * FROM t, r_tree
} {
QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
+ |--SCAN r_tree VIRTUAL TABLE INDEX 2:
+ `--SCAN t
}
do_execsql_test 2.0 {
@@ -87,8 +87,8 @@ do_eqp_test 2.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.2 {
@@ -96,8 +96,8 @@ do_eqp_test 2.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.3 {
@@ -105,16 +105,16 @@ do_eqp_test 2.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
QUERY PLAN
- |--SCAN TABLE t
- `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
+ |--SCAN t
+ `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}
do_eqp_test 2.5 {
SELECT * FROM t, r_tree
} {
QUERY PLAN
- |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t
+ |--SCAN r_tree VIRTUAL TABLE INDEX 2:
+ `--SCAN t
}
#-------------------------------------------------------------------------
@@ -128,24 +128,24 @@ do_execsql_test 3.1 {
do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t2
+ |--SCAN t1
+ `--SCAN t2
}
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
QUERY PLAN
- |--SCAN TABLE t2
- `--SCAN TABLE t1
+ |--SCAN t2
+ `--SCAN t1
}
do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
+ |--SCAN t1
+ `--SCAN t3 VIRTUAL TABLE INDEX 2:
}
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
QUERY PLAN
- |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
- `--SCAN TABLE t1
+ |--SCAN t3 VIRTUAL TABLE INDEX 2:
+ `--SCAN t1
}
#--------------------------------------------------------------------
@@ -203,8 +203,8 @@ do_eqp_test 5.2 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
@@ -220,8 +220,8 @@ do_eqp_test 5.4 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
- `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
+ |--SCAN rt VIRTUAL TABLE INDEX 2:
+ `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
}
# Delete the ANALYZE data. "t1" should be the outer loop again.
@@ -233,8 +233,8 @@ do_eqp_test 5.6 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
# This time create and attach a database that contains ANALYZE data for
@@ -258,8 +258,8 @@ do_eqp_test 5.8 {
SELECT * FROM t1, rt WHERE x==id;
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
+ |--SCAN t1
+ `--SCAN rt VIRTUAL TABLE INDEX 1:
}
#--------------------------------------------------------------------
@@ -327,9 +327,9 @@ do_eqp_execsql_test 7.1 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE ydir
- `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
+ |--SCAN xdir
+ |--SCAN ydir
+ `--SCAN rt VIRTUAL TABLE INDEX 2:B2D3B0D1
} {
2 4
}
@@ -340,9 +340,9 @@ do_eqp_execsql_test 7.2 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
5 1 2 7 12 14 {}
5 2 2 7 8 12 10
@@ -355,9 +355,9 @@ do_eqp_execsql_test 7.3 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
2 4
}
@@ -368,9 +368,9 @@ do_eqp_execsql_test 7.4 {
WHERE (x1 BETWEEN xmin AND xmax);
} {
QUERY PLAN
- |--SCAN TABLE xdir
- |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
- `--SCAN TABLE ydir
+ |--SCAN xdir
+ |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
+ `--SCAN ydir
} {
2 4
}
diff --git a/ext/rtree/rtreefuzz001.test b/ext/rtree/rtreefuzz001.test
index db9df205a..58fd179ab 100644
--- a/ext/rtree/rtreefuzz001.test
+++ b/ext/rtree/rtreefuzz001.test
@@ -1045,5 +1045,167 @@ do_test rtreefuzz001-500 {
catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}
+do_test rtreefuzz001-600 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 20480 pagesize 4096 filename crash-7b37d80f000235.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 10 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 05 0e 49 00 0f 99 0f 40 ..........I....@
+| 112: 0e da 0e 8f 0e 49 00 00 00 00 00 00 00 00 00 00 .....I..........
+| 3648: 00 00 00 00 00 00 00 00 00 44 05 06 17 15 15 08 .........D......
+| 3664: 6f 74 61 62 6c 65 67 65 6f 31 67 65 6f 31 43 52 otablegeo1geo1CR
+| 3680: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
+| 3696: 4c 45 20 67 65 6f 31 20 55 53 49 4e 47 20 67 65 LE geo1 USING ge
+| 3712: 6f 70 6f 6c 79 28 74 79 70 65 2c 63 6c 72 29 49 opoly(type,clr)I
+| 3728: 04 06 17 1f 1f 01 63 74 61 62 6c 65 71 75 65 72 ......ctablequer
+| 3744: 79 70 6f 6c 79 71 75 65 72 79 70 6f 6c 79 05 43 ypolyquerypoly.C
+| 3760: 52 45 41 54 45 20 54 41 42 4c 45 20 71 75 65 72 REATE TABLE quer
+| 3776: 79 70 6f 6c 79 28 70 6f 6c 79 20 4a 53 4f 4e 2c ypoly(poly JSON,
+| 3792: 20 63 6c 72 20 54 45 58 54 29 64 03 07 17 23 23 clr TEXT)d...##
+| 3808: 01 81 0f 74 61 62 6c 65 67 65 6f 31 5f 70 61 72 ...tablegeo1_par
+| 3824: 65 6e 74 67 65 6f 31 5f 70 61 72 65 6e 74 04 43 entgeo1_parent.C
+| 3840: 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 6f REATE TABLE .geo
+| 3856: 31 5f 70 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 1_parent.(nodeno
+| 3872: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
+| 3888: 20 4b 45 59 2c 70 61 72 65 6e 74 6e 6f 64 85 29 KEY,parentnod.)
+| 3904: 57 02 06 17 1f 1f 01 7f 74 61 62 6c 65 67 65 6f W.......tablegeo
+| 3920: 31 5f 6e 6f 64 65 67 65 6f 31 5f 6e 6f 64 65 03 1_nodegeo1_node.
+| 3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 CREATE TABLE .ge
+| 3952: 6f 31 5f 6e 6f 64 65 22 28 6e 6f 64 65 6e 6f 20 o1_node.(nodeno
+| 3968: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
+| 3984: 4b 45 59 2c 64 61 74 61 29 65 01 07 17 21 21 01 KEY,data)e...!!.
+| 4000: 81 15 74 61 62 6c 65 67 65 6f 31 5f 72 6f 77 69 ..tablegeo1_rowi
+| 4016: 64 67 65 6f 31 5f 72 6f 77 69 64 02 43 52 45 41 dgeo1_rowid.CREA
+| 4032: 54 45 20 54 41 42 4c 45 20 22 67 65 6f 31 5f 72 TE TABLE .geo1_r
+| 4048: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 4064: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 4080: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 2c 61 32 29 nodeno,a0,a1,a2)
+| page 2 offset 4096
+| 0: 0d 00 00 00 0a 0d ab 00 0f c9 0f 88 0f 48 0f 00 .............H..
+| 3488: 00 00 00 00 00 00 00 00 00 00 00 45 82 0a 06 00 ...........E....
+| 3504: 09 74 1d 13 01 00 00 06 00 80 b5 43 00 80 ac 43 .t.........C...C
+| 3520: 00 00 bd 43 8f 82 9f 43 71 fd c9 43 8f 02 a7 43 ...C...Cq..C...C
+| 3536: 71 fd c8 43 e4 bd a8 43 64 bb bd 43 f4 3d a2 43 q..C...Cd..C.=.C
+| 3552: 64 3b b7 43 00 80 ad 43 61 6e 67 6c 65 2d 33 30 d;.C...Cangle-30
+| 3568: 72 65 64 32 81 4e 06 00 09 44 23 17 01 00 00 03 red2.N...D#.....
+| 3584: 00 40 3f 44 00 c0 20 44 00 c0 46 44 00 c0 20 44 .@?D.. D..FD.. D
+| 3600: 00 00 43 44 00 40 28 44 74 72 69 61 6e 67 6c 65 ..CD.@(Dtriangle
+| 3616: 2d 33 30 62 6c 61 63 6b 35 82 3e 06 00 09 54 1d -30black5.>...T.
+| 3632: 13 01 00 00 04 00 40 54 44 00 80 1d 44 9a c9 5c ......@TD...D...
+| 3648: 44 66 36 1b 44 33 13 5f 44 00 c0 23 44 9a 89 5b Df6.D3._D..#D..[
+| 3664: 44 a4 60 1d 44 61 72 72 6f 77 2d 35 30 72 65 64 D.`.Darrow-50red
+| 3680: 36 74 06 00 09 54 1b 17 01 00 00 04 00 80 0d 44 6t...T.........D
+| 3696: 00 00 f2 42 0a d7 04 44 00 00 ca 42 0a 77 05 44 ...B...D...B.w.D
+| 3712: 0a 57 c1 42 00 20 0e 44 0a 57 e9 42 6c 69 6e 65 .W.B. .D.W.Bline
+| 3728: 2d 34 30 67 72 65 65 6e 36 72 06 00 09 54 1b 17 -40green6r...T..
+| 3744: 01 00 00 04 00 00 7b 43 00 00 ea 42 29 5c 58 43 .......C...B).XC
+| 3760: 00 00 c2 42 29 dc 5a 43 0a 57 b9 42 00 80 7d 43 ...B).ZC.W.B...C
+| 3776: 0a 57 e1 42 6c 69 6e 65 2d 34 30 67 72 65 65 6e .W.Bline-40green
+| 3792: 36 54 06 00 09 54 1b 17 01 00 00 04 00 00 a2 43 6T...T.........C
+| 3808: 00 00 24 44 00 00 b6 43 00 00 24 44 00 00 b6 43 ..$D...C..$D...C
+| 3824: 00 40 25 44 00 00 a2 43 00 40 25 44 6c 69 6e 65 .@%D...C.@%Dline
+| 3840: 2d 34 30 62 6c 61 63 6b 3e 37 06 00 09 64 1d 15 -40black>7...d..
+| 3856: 01 00 00 05 00 80 f0 43 00 00 54 43 66 16 01 44 .......C..TCf..D
+| 3872: 66 a6 30 43 cd ec 09 44 00 00 54 43 8f 0a 09 44 f.0C...D..TC...D
+| 3888: a4 d0 73 43 66 16 01 44 9a 59 77 43 68 6f 75 73 ..sCf..D.YwChous
+| 3904: 65 2d 37 30 62 6c 75 65 3e 35 06 00 09 64 1d 15 e-70blue>5...d..
+| 3920: 01 00 00 05 00 00 a2 43 00 00 5a 43 cd ac b3 43 .......C..ZC...C
+| 3936: 66 a6 36 43 9a 59 c5 43 00 00 5a 43 1f 95 c3 43 f.6C.Y.C..ZC...C
+| 3952: a4 d0 79 43 cd ac b3 43 9a 59 7d 43 68 6f 75 73 ..yC...C.Y.Chous
+| 3968: 65 2d 37 30 62 6c 75 65 3f 2c 06 00 09 64 1d 17 e-70blue?,...d..
+| 3984: 01 00 00 05 00 00 f5 43 00 00 2f 43 00 00 07 44 .......C../C...D
+| 4000: 00 00 2f 43 00 00 07 44 00 00 61 43 00 c0 00 44 ../C...D..aC...D
+| 4016: 00 00 75 43 00 00 f5 43 00 00 61 43 68 6f 75 73 ..uC...C..aChous
+| 4032: 65 2d 37 30 62 6c 61 63 6b 35 1f 06 10 09 54 19 e-70black5....T.
+| 4048: 17 01 00 00 04 00 00 9b 43 00 00 67 43 0a 57 92 ........C..gC.W.
+| 4064: 43 00 00 5d 43 0a 57 97 43 14 ae 4b 42 ff ff a0 C..]C.W.C..KB...
+| 4080: 43 14 ae 55 43 62 6f 78 2d 32 30 67 72 65 65 6e C..UCbox-20green
+| page 3 offset 8192
+| 0: 0d 00 00 00 01 0b 2d 00 0b 2e 00 00 00 00 00 00 ......-.........
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 ...............P
+| 2864: 01 04 00 93 24 00 00 00 0a 00 00 00 00 00 00 01 ....$...........
+| 2880: 0a 43 b5 80 00 43 c9 fd 71 43 9f 82 8f 43 ad 80 .C...C..qC...C..
+| 2896: 00 00 00 00 00 00 00 00 72 43 58 5c 29 43 7d 80 ........rCX.)C..
+| 2912: 00 42 b9 57 0a 42 ea 00 00 00 00 00 00 00 00 00 .B.W.B..........
+| 2928: 35 43 a2 00 00 43 c5 59 9a 43 36 a6 66 43 7d 59 5C...C.Y.C6.fC.Y
+| 2944: 9a 00 00 00 00 00 00 00 1f 43 92 57 0a 43 a0 00 .........C.W.C..
+| 2960: 00 43 4b ae 14 43 67 00 00 00 00 00 00 00 00 00 .CK..Cg.........
+| 2976: 37 43 f0 80 00 44 09 ec cd 43 30 a6 66 43 77 59 7C...D...C0.fCwY
+| 2992: 9a 00 00 00 00 00 00 00 2c 43 f5 00 00 44 07 00 ........,C...D..
+| 3008: 00 43 2f 00 00 43 75 00 00 00 00 00 00 00 00 00 .C/..Cu.........
+| 3024: 74 44 04 d7 0a 44 0e 20 00 42 c1 57 0a 42 f2 00 tD...D. .B.W.B..
+| 3040: 00 00 00 00 00 00 00 00 ce 44 3f 40 00 44 46 c0 .........D?@.DF.
+| 3056: 00 44 20 c0 00 44 28 40 00 00 00 00 00 00 00 00 .D ..D(@........
+| 3072: be 44 54 40 00 44 5f 13 33 44 1b 36 66 44 23 c0 .DT@.D_.3D.6fD#.
+| 3088: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3104: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3120: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3136: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3152: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3168: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3184: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3200: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3216: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3232: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3248: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3264: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3280: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3296: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00 .D$..D%@........
+| 3312: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40 TC...C...D$..D%@
+| 3328: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00 ........TC...C..
+| 3344: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 01 .D$..D%@........
+| 3360: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3376: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3392: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3408: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3424: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3440: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3456: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3472: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3488: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3504: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3520: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3536: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3552: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3568: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3584: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3600: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3616: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3632: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3648: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| 3664: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb ........6DS..DV.
+| 3680: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01 dCq4.C..........
+| 3696: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00 6DS..DV.dCq4.C..
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| page 5 offset 16384
+| 0: 0d 00 00 00 01 0f 8f 00 00 00 00 00 00 00 00 00 ................
+| 3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f ...............o
+| 3984: 01 04 81 57 19 5b 5b 33 30 30 2c 33 30 30 5d 2c ...W.[[300,300],
+| 4000: 5b 34 30 30 2c 33 35 30 5d 2c 5b 35 30 30 2c 32 [400,350],[500,2
+| 4016: 35 30 5d 2c 5b 34 38 30 2c 35 30 30 5d 2c 5b 34 50],[480,500],[4
+| 4032: 30 30 2c 34 38 30 5d 2c 5c 33 30 30 2c 35 35 30 00,480],.300,550
+| 4048: 5d 2c 5b 32 38 30 2c 34 35 30 5d 2c 5b 33 32 30 ],[280,450],[320
+| 4064: 2c 34 30 30 5d 2c 5b 32 38 30 2c 33 35 30 5d 2c ,400],[280,350],
+| 4080: 5b 33 30 30 2c 33 30 00 00 00 00 00 00 00 00 00 [300,30.........
+| end crash-7b37d80f000235.db
+}]} {}
+
+ifcapable geopoly {
+
+do_catchsql_test rtreefuzz001-601 {
+ SAVEPOINT one;
+ UPDATE geo1 SET clr=CASE WHEN rowid IN ( SELECT geo1.rowid FROM geo1, querypoly ) THEN 'e' ELSE 'blue' END;
+} {1 {database disk image is malformed}}
+
+do_catchsql_test rtreefuzz001-602 {
+ SELECT geopoly_svg(_shape, printf('j',geo1.clr))
+ FROM geo1, querypoly WHERE geopoly_overlap(_shape, poly);
+} {1 {database disk image is malformed}}
+
+} ;# ifcapable geopoly
finish_test
diff --git a/ext/session/session2.test b/ext/session/session2.test
index cd8c2869e..806687745 100644
--- a/ext/session/session2.test
+++ b/ext/session/session2.test
@@ -35,7 +35,7 @@ proc test_reset {} {
test_reset
do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b);
+ CREATE TABLE t1(a INT PRIMARY KEY, b);
INSERT INTO t1 VALUES('i', 'one');
}
do_iterator_test 1.1 t1 {
@@ -184,7 +184,7 @@ set set_of_tests {
test_reset
do_common_sql {
- CREATE TABLE t1(a PRIMARY KEY, b);
+ CREATE TABLE t1(a int PRIMARY KEY, b);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
@@ -206,17 +206,17 @@ sqlite3 db3 test.db3
do_test 3.0 {
execsql {
ATTACH 'test.db3' AS 'aux';
- CREATE TABLE t1(a, b PRIMARY KEY);
+ CREATE TABLE t1(a int, b PRIMARY KEY);
CREATE TABLE t2(x, y, z);
CREATE TABLE t3(a);
- CREATE TABLE aux.t1(a PRIMARY KEY, b);
+ CREATE TABLE aux.t1(a int PRIMARY KEY, b);
CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a));
}
execsql {
- CREATE TABLE t1(a PRIMARY KEY, b);
+ CREATE TABLE t1(a int PRIMARY KEY, b);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
@@ -588,4 +588,52 @@ do_execsql_test 10.2 {
} {0 0 1 1}
S delete
+#-------------------------------------------------------------------------
+test_reset
+do_common_sql {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f);
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<32
+ )
+ INSERT INTO t1 SELECT NULL, 0, 0, 0, 0, 0 FROM s
+}
+
+do_then_apply_sql {
+ UPDATE t1 SET f=f+1 WHERE a=1;
+ UPDATE t1 SET e=e+1 WHERE a=2;
+ UPDATE t1 SET e=e+1, f=f+1 WHERE a=3;
+ UPDATE t1 SET d=d+1 WHERE a=4;
+ UPDATE t1 SET d=d+1, f=f+1 WHERE a=5;
+ UPDATE t1 SET d=d+1, e=e+1 WHERE a=6;
+ UPDATE t1 SET d=d+1, e=e+1, f=f+1 WHERE a=7;
+ UPDATE t1 SET c=c+1 WHERE a=8;
+ UPDATE t1 SET c=c+1, f=f+1 WHERE a=9;
+ UPDATE t1 SET c=c+1, e=e+1 WHERE a=10;
+ UPDATE t1 SET c=c+1, e=e+1, f=f+1 WHERE a=11;
+ UPDATE t1 SET c=c+1, d=d+1 WHERE a=12;
+ UPDATE t1 SET c=c+1, d=d+1, f=f+1 WHERE a=13;
+ UPDATE t1 SET c=c+1, d=d+1, e=e+1 WHERE a=14;
+ UPDATE t1 SET c=c+1, d=d+1, e=e+1, f=f+1 WHERE a=15;
+ UPDATE t1 SET d=d+1 WHERE a=16;
+ UPDATE t1 SET d=d+1, f=f+1 WHERE a=17;
+ UPDATE t1 SET d=d+1, e=e+1 WHERE a=18;
+ UPDATE t1 SET d=d+1, e=e+1, f=f+1 WHERE a=19;
+ UPDATE t1 SET d=d+1, d=d+1 WHERE a=20;
+ UPDATE t1 SET d=d+1, d=d+1, f=f+1 WHERE a=21;
+ UPDATE t1 SET d=d+1, d=d+1, e=e+1 WHERE a=22;
+ UPDATE t1 SET d=d+1, d=d+1, e=e+1, f=f+1 WHERE a=23;
+ UPDATE t1 SET d=d+1, c=c+1 WHERE a=24;
+ UPDATE t1 SET d=d+1, c=c+1, f=f+1 WHERE a=25;
+ UPDATE t1 SET d=d+1, c=c+1, e=e+1 WHERE a=26;
+ UPDATE t1 SET d=d+1, c=c+1, e=e+1, f=f+1 WHERE a=27;
+ UPDATE t1 SET d=d+1, c=c+1, d=d+1 WHERE a=28;
+ UPDATE t1 SET d=d+1, c=c+1, d=d+1, f=f+1 WHERE a=29;
+ UPDATE t1 SET d=d+1, c=c+1, d=d+1, e=e+1 WHERE a=30;
+ UPDATE t1 SET d=d+1, c=c+1, d=d+1, e=e+1, f=f+1 WHERE a=31;
+}
+
+do_test 11.0 {
+ compare_db db db2
+} {}
+
finish_test
diff --git a/ext/session/sessionbig.test b/ext/session/sessionbig.test
new file mode 100644
index 000000000..80ce00a0f
--- /dev/null
+++ b/ext/session/sessionbig.test
@@ -0,0 +1,108 @@
+# 2014 August 16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements regression tests for sessions SQLite extension.
+# Specifically, this file contains tests for "patchset" changes.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+if {[permutation]=="session_strm" || [permutation]=="session_eec"} {
+ finish_test
+ return
+}
+
+if {$::tcl_platform(pointerSize)<8} {
+ finish_test
+ return
+}
+
+set testprefix sessionbig
+
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+}
+do_execsql_test -db db2 1.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+}
+
+do_test 1.2 {
+ do_then_apply_sql {
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ }
+} {}
+
+do_test 1.3 {
+ execsql { DELETE FROM t1 }
+ execsql2 { DELETE FROM t1 }
+} {}
+
+do_test 1.4 {
+ set rc [catch {
+ do_then_apply_sql {
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
+ }
+ } msg]
+ list $rc $msg
+} {1 SQLITE_NOMEM}
+
+
+finish_test
+
diff --git a/ext/session/sessionmem.test b/ext/session/sessionmem.test
new file mode 100644
index 000000000..75b48623d
--- /dev/null
+++ b/ext/session/sessionmem.test
@@ -0,0 +1,57 @@
+# 2020 December 23
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for the SQLite sessions module
+# Specifically, for the sqlite3session_memory_used() API.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+set testprefix sessionmem
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(i INTEGER PRIMARY KEY, x, y);
+ CREATE TABLE t2(i INTEGER, x, y, PRIMARY KEY(x, y));
+}
+
+do_test 1.1 {
+ sqlite3session S db main
+ S attach *
+} {}
+
+foreach {tn sql eRes} {
+ 1 { INSERT INTO t1 VALUES(1, 2, 3) } 1
+ 2 { UPDATE t1 SET x=5 } 0
+ 3 { UPDATE t1 SET i=5 } 1
+ 4 { DELETE FROM t1 } 0
+ 5 { INSERT INTO t1 VALUES(1, 2, 3) } 0
+ 6 { INSERT INTO t1 VALUES(5, 2, 3) } 0
+ 7 { INSERT INTO t2 VALUES('a', 'b', 'c') } 1
+ 8 { INSERT INTO t2 VALUES('d', 'e', 'f') } 1
+ 9 { UPDATE t2 SET i='e' } 0
+} {
+ set mem1 [S memory_used]
+ do_test 1.2.$tn.(mu=$mem1) {
+ execsql $sql
+ set mem2 [S memory_used]
+ expr {$mem2 > $mem1}
+ } $eRes
+}
+
+do_test 1.3 {
+ S delete
+} {}
+
+finish_test
diff --git a/ext/session/sessionnoop.test b/ext/session/sessionnoop.test
new file mode 100644
index 000000000..16c60b7ab
--- /dev/null
+++ b/ext/session/sessionnoop.test
@@ -0,0 +1,187 @@
+# 2021 Februar 20
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+set testprefix sessionnoop
+
+#-------------------------------------------------------------------------
+# Test plan:
+#
+# 1.*: Test that concatenating changesets cannot produce a noop UPDATE.
+# 2.*: Test that rebasing changesets cannot produce a noop UPDATE.
+# 3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
+#
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a PRIMARY KEY, b, c, d);
+ INSERT INTO t1 VALUES(1, 1, 1, 1);
+ INSERT INTO t1 VALUES(2, 2, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3, 3);
+}
+
+proc do_concat_test {tn sql1 sql2 res} {
+ uplevel [list do_test $tn [subst -nocommands {
+ set C1 [changeset_from_sql {$sql1}]
+ set C2 [changeset_from_sql {$sql2}]
+ set C3 [sqlite3changeset_concat [set C1] [set C2]]
+ set got [list]
+ sqlite3session_foreach elem [set C3] { lappend got [set elem] }
+ set got
+ }] [list {*}$res]]
+}
+
+do_concat_test 1.1 {
+ UPDATE t1 SET c=c+1;
+} {
+ UPDATE t1 SET c=c-1;
+} {
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.0 {
+ CREATE TABLE t1(a PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(2, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3);
+}
+
+proc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
+ proc xConflict {args} [list return $conflict_res]
+
+ uplevel [list \
+ do_test $tn [subst -nocommands {
+ execsql BEGIN
+ set c_remote [changeset_from_sql {$sql_remote}]
+ execsql ROLLBACK
+
+ execsql BEGIN
+ set c_local [changeset_from_sql {$sql_local}]
+ set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
+ execsql ROLLBACK
+
+ sqlite3rebaser_create R
+ R config [set base]
+ set res [list]
+ sqlite3session_foreach elem [R rebase [set c_local]] {
+ lappend res [set elem]
+ }
+ R delete
+ set res
+ }] [list {*}$expected]
+ ]
+}
+
+do_rebase_test 2.1 {
+ UPDATE t1 SET c=2 WHERE a=1; -- local
+} {
+ UPDATE t1 SET c=3 WHERE a=1; -- remote
+} OMIT {
+ {UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
+}
+
+do_rebase_test 2.2 {
+ UPDATE t1 SET c=2 WHERE a=1; -- local
+} {
+ UPDATE t1 SET c=3 WHERE a=1; -- remote
+} REPLACE {
+}
+
+do_rebase_test 2.3.1 {
+ UPDATE t1 SET c=4 WHERE a=1; -- local
+} {
+ UPDATE t1 SET c=4 WHERE a=1 -- remote
+} OMIT {
+ {UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
+}
+
+do_rebase_test 2.3.2 {
+ UPDATE t1 SET c=5 WHERE a=1; -- local
+} {
+ UPDATE t1 SET c=5 WHERE a=1 -- remote
+} REPLACE {
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(2, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3);
+ INSERT INTO t1 VALUES(4, 4, 4);
+}
+
+# Arg $pkstr contains one character for each column in the table. An
+# "X" for PK column, or a "." for a non-PK.
+#
+proc mk_tbl_header {name pkstr} {
+ set ret [binary format H2c 54 [string length $pkstr]]
+ foreach i [split $pkstr {}] {
+ if {$i=="X"} {
+ append ret [binary format H2 01]
+ } else {
+ if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
+ append ret [binary format H2 00]
+ }
+ }
+ append ret $name
+ append ret [binary format H2 00]
+ set ret
+}
+
+proc mk_update_change {args} {
+ set ret [binary format H2H2 17 00]
+ foreach a $args {
+ if {$a==""} {
+ append ret [binary format H2 00]
+ } else {
+ append ret [binary format H2W 01 $a]
+ }
+ }
+ set ret
+}
+
+proc xConflict {args} { return "ABORT" }
+do_test 3.1 {
+ set C [mk_tbl_header t1 X..]
+ append C [mk_update_change 1 {} 1 {} {} 500]
+ append C [mk_update_change 2 {} {} {} {} {}]
+ append C [mk_update_change 3 3 {} {} 600 {}]
+ append C [mk_update_change 4 {} {} {} {} {}]
+
+ sqlite3changeset_apply_v2 db $C xConflict
+} {}
+do_execsql_test 3.2 {
+ SELECT * FROM t1
+} {
+ 1 1 500
+ 2 2 2
+ 3 600 3
+ 4 4 4
+}
+
+
+
+
+
+
+finish_test
+
diff --git a/ext/session/sessionsize.test b/ext/session/sessionsize.test
new file mode 100644
index 000000000..04d05514d
--- /dev/null
+++ b/ext/session/sessionsize.test
@@ -0,0 +1,131 @@
+# 2021 April 22
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+set testprefix sessionsize
+
+proc do_changeset_size_test {tn sql} {
+ sqlite3session S db main
+ S attach *
+ db eval $sql
+
+ set sz [S changeset_size]
+ set C [S changeset]
+ set szC [string length $C]
+ S delete
+
+ do_test $tn "expr $sz" $szC
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 'abc', 'def');
+ INSERT INTO t1 VALUES(2, 'ghi', 'jkl');
+}
+
+do_changeset_size_test 1.1 {
+ INSERT INTO t1 VALUES(3, 'hello', 'world');
+}
+
+do_changeset_size_test 1.2 {
+ DELETE FROM t1 WHERE a=2;
+}
+
+do_changeset_size_test 1.3 {
+ DELETE FROM t1 WHERE a=3;
+ INSERT INTO t1 VALUES(3, 1, 2);
+}
+
+do_changeset_size_test 1.4 {
+ UPDATE t1 SET c='hello world' WHERE a=3;
+}
+
+#-------------------------------------------------------------------------
+
+do_execsql_test 2.0 {
+ CREATE TABlE t2(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
+ CREATE TABlE t3(a, b, c, d PRIMARY KEY);
+}
+
+do_changeset_size_test 2.1 {
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
+ )
+ INSERT INTO t2 SELECT i, i+1, i+2, i+3 FROM s;
+
+ UPDATE t2 SET c=randomblob(a) WHERE a>10
+}
+
+do_changeset_size_test 2.2 {
+ DELETE FROM t2 WHERE a=1;
+ INSERT INTO t2 VALUES(1, 4, 3, 4);
+}
+
+do_changeset_size_test 2.2 {
+ UPDATE t2 SET b=4 WHERE a=2
+}
+
+do_changeset_size_test 2.3 {
+ INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
+ UPDATE t2 SET c='qwertyuiop' WHERE a='a';
+}
+
+do_changeset_size_test 2.4 {
+ DELETE FROM t2 WHERE a='a';
+ INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
+}
+
+do_changeset_size_test 2.5 {
+ UPDATE t2 SET a='aa', b='bb' WHERE (a, b) = ('a', 'b');
+}
+
+do_changeset_size_test 2.6 {
+ UPDATE t2 SET a='a', b='b' WHERE (a, b) = ('aa', 'bb');
+}
+
+do_changeset_size_test 2.7 {
+ INSERT INTO t3 DEFAULT VALUES;
+ INSERT INTO t3 VALUES(1,2,3,4);
+}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+}
+
+do_test 3.1 {
+ sqlite3session S db main
+ S object_config_size -1
+} 1
+
+do_test 3.2.1 { S object_config_size 0 } 0
+do_test 3.2.2 { S object_config_size -1 } 0
+do_test 3.2.3 { S object_config_size 1 } 1
+do_test 3.2.4 { S object_config_size -1 } 1
+
+do_test 3.3 { S attach t1 } {}
+do_test 3.4 { S object_config_size 1 } {SQLITE_MISUSE}
+do_test 3.4 { S object_config_size -1 } {1}
+
+S delete
+
+finish_test
+
diff --git a/ext/session/sessionwor.test b/ext/session/sessionwor.test
index 0f0b429d7..7d9e5c6a8 100644
--- a/ext/session/sessionwor.test
+++ b/ext/session/sessionwor.test
@@ -69,7 +69,9 @@ foreach {tn wo} {
} {
reset_db
- do_execsql_test 2.$tn.0 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
+ do_execsql_test 2.$tn.0.1 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
+ do_execsql_test 2.$tn.0.2 "CREATE TABLE t2(a INTEGER PRIMARY KEY, b) $wo ;"
+ do_execsql_test 2.$tn.0.3 "CREATE TABLE t3(a INTEGER PRIMARY KEY, b) $wo ;"
do_iterator_test 1.1 t1 {
INSERT INTO t1 VALUES(1, 'two');
@@ -94,6 +96,27 @@ foreach {tn wo} {
} {
{DELETE t1 0 X. {i 1 t four} {}}
}
+
+ do_execsql_test 2.$tn.5 {
+ INSERT INTO t1 VALUES(1, 'one');
+ INSERT INTO t1 VALUES(2, 'two');
+ INSERT INTO t1 VALUES(3, 'three');
+ }
+
+ do_iterator_test 2.$tn.6 t2 {
+ INSERT INTO t2 SELECT a, b FROM t1
+ } {
+ {INSERT t2 0 X. {} {i 1 t one}}
+ {INSERT t2 0 X. {} {i 2 t two}}
+ {INSERT t2 0 X. {} {i 3 t three}}
+ }
+ do_iterator_test 2.$tn.7 t3 {
+ INSERT INTO t3 SELECT * FROM t1
+ } {
+ {INSERT t3 0 X. {} {i 1 t one}}
+ {INSERT t3 0 X. {} {i 2 t two}}
+ {INSERT t3 0 X. {} {i 3 t three}}
+ }
}
finish_test
diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c
index dae260471..c96363b60 100644
--- a/ext/session/sqlite3session.c
+++ b/ext/session/sqlite3session.c
@@ -42,12 +42,15 @@ struct SessionHook {
struct sqlite3_session {
sqlite3 *db; /* Database handle session is attached to */
char *zDb; /* Name of database session is attached to */
+ int bEnableSize; /* True if changeset_size() enabled */
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
+ i64 nMalloc; /* Number of bytes of data allocated */
+ i64 nMaxChangesetSize;
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
@@ -90,6 +93,7 @@ struct sqlite3_changeset_iter {
SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
int bPatchset; /* True if this is a patchset */
int bInvert; /* True to invert changeset */
+ int bSkipEmpty; /* Skip noop UPDATE changes */
int rc; /* Iterator error code */
sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
char *zTab; /* Current table */
@@ -289,8 +293,9 @@ struct SessionTable {
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
- int op; /* One of UPDATE, DELETE, INSERT */
- int bIndirect; /* True if this change is "indirect" */
+ u8 op; /* One of UPDATE, DELETE, INSERT */
+ u8 bIndirect; /* True if this change is "indirect" */
+ int nMaxSize; /* Max size of eventual changeset record */
int nRecord; /* Number of bytes in buffer aRecord[] */
u8 *aRecord; /* Buffer containing old.* record */
SessionChange *pNext; /* For hash-table collisions */
@@ -431,6 +436,26 @@ static int sessionSerializeValue(
return SQLITE_OK;
}
+/*
+** Allocate and return a pointer to a buffer nByte bytes in size. If
+** pSession is not NULL, increase the sqlite3_session.nMalloc variable
+** by the number of bytes allocated.
+*/
+static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){
+ void *pRet = sqlite3_malloc64(nByte);
+ if( pSession ) pSession->nMalloc += sqlite3_msize(pRet);
+ return pRet;
+}
+
+/*
+** Free buffer pFree, which must have been allocated by an earlier
+** call to sessionMalloc64(). If pSession is not NULL, decrease the
+** sqlite3_session.nMalloc counter by the number of bytes freed.
+*/
+static void sessionFree(sqlite3_session *pSession, void *pFree){
+ if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree);
+ sqlite3_free(pFree);
+}
/*
** This macro is used to calculate hash key values for data structures. In
@@ -898,13 +923,19 @@ static int sessionPreupdateEqual(
** Growing the hash table in this case is a performance optimization only,
** it is not required for correct operation.
*/
-static int sessionGrowHash(int bPatchset, SessionTable *pTab){
+static int sessionGrowHash(
+ sqlite3_session *pSession, /* For memory accounting. May be NULL */
+ int bPatchset,
+ SessionTable *pTab
+){
if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
int i;
SessionChange **apNew;
sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);
- apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
+ apNew = (SessionChange**)sessionMalloc64(
+ pSession, sizeof(SessionChange*) * nNew
+ );
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -925,7 +956,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
}
}
- sqlite3_free(pTab->apChange);
+ sessionFree(pSession, pTab->apChange);
pTab->nChange = nNew;
pTab->apChange = apNew;
}
@@ -959,6 +990,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
** be freed using sqlite3_free() by the caller
*/
static int sessionTableInfo(
+ sqlite3_session *pSession, /* For memory accounting. May be NULL */
sqlite3 *db, /* Database connection */
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
@@ -1013,7 +1045,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlite3_malloc64(nByte);
+ pAlloc = sessionMalloc64(pSession, nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -1056,7 +1088,7 @@ static int sessionTableInfo(
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
- sqlite3_free(azCol);
+ sessionFree(pSession, azCol);
}
sqlite3_finalize(pStmt);
return rc;
@@ -1078,7 +1110,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( pTab->nCol==0 ){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
- pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
+ pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
);
if( pSession->rc==SQLITE_OK ){
@@ -1092,6 +1124,12 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
pTab->bStat1 = 1;
}
+
+ if( pSession->bEnableSize ){
+ pSession->nMaxChangesetSize += (
+ 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1
+ );
+ }
}
}
return (pSession->rc || pTab->abPK==0);
@@ -1137,6 +1175,103 @@ static int sessionStat1Depth(void *pCtx){
return p->hook.xDepth(p->hook.pCtx);
}
+static int sessionUpdateMaxSize(
+ int op,
+ sqlite3_session *pSession, /* Session object pTab is attached to */
+ SessionTable *pTab, /* Table that change applies to */
+ SessionChange *pC /* Update pC->nMaxSize */
+){
+ i64 nNew = 2;
+ if( pC->op==SQLITE_INSERT ){
+ if( op!=SQLITE_DELETE ){
+ int ii;
+ for(ii=0; iinCol; ii++){
+ sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ sessionSerializeValue(0, p, &nNew);
+ }
+ }
+ }else if( op==SQLITE_DELETE ){
+ nNew += pC->nRecord;
+ if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){
+ nNew += pC->nRecord;
+ }
+ }else{
+ int ii;
+ u8 *pCsr = pC->aRecord;
+ for(ii=0; iinCol; ii++){
+ int bChanged = 1;
+ int nOld = 0;
+ int eType;
+ sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ eType = *pCsr++;
+ switch( eType ){
+ case SQLITE_NULL:
+ bChanged = sqlite3_value_type(p)!=SQLITE_NULL;
+ break;
+
+ case SQLITE_FLOAT:
+ case SQLITE_INTEGER: {
+ if( eType==sqlite3_value_type(p) ){
+ sqlite3_int64 iVal = sessionGetI64(pCsr);
+ if( eType==SQLITE_INTEGER ){
+ bChanged = (iVal!=sqlite3_value_int64(p));
+ }else{
+ double dVal;
+ memcpy(&dVal, &iVal, 8);
+ bChanged = (dVal!=sqlite3_value_double(p));
+ }
+ }
+ nOld = 8;
+ pCsr += 8;
+ break;
+ }
+
+ default: {
+ int nByte;
+ nOld = sessionVarintGet(pCsr, &nByte);
+ pCsr += nOld;
+ nOld += nByte;
+ assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
+ if( eType==sqlite3_value_type(p)
+ && nByte==sqlite3_value_bytes(p)
+ && (nByte==0 || 0==memcmp(pCsr, sqlite3_value_blob(p), nByte))
+ ){
+ bChanged = 0;
+ }
+ pCsr += nByte;
+ break;
+ }
+ }
+
+ if( bChanged && pTab->abPK[ii] ){
+ nNew = pC->nRecord + 2;
+ break;
+ }
+
+ if( bChanged ){
+ nNew += 1 + nOld;
+ sessionSerializeValue(0, p, &nNew);
+ }else if( pTab->abPK[ii] ){
+ nNew += 2 + nOld;
+ }else{
+ nNew += 2;
+ }
+ }
+ }
+
+ if( nNew>pC->nMaxSize ){
+ int nIncr = nNew - pC->nMaxSize;
+ pC->nMaxSize = nNew;
+ pSession->nMaxChangesetSize += nIncr;
+ }
+ return SQLITE_OK;
+}
/*
** This function is only called from with a pre-update-hook reporting a
@@ -1169,7 +1304,7 @@ static void sessionPreupdateOneChange(
}
/* Grow the hash table if required */
- if( sessionGrowHash(0, pTab) ){
+ if( sessionGrowHash(pSession, 0, pTab) ){
pSession->rc = SQLITE_NOMEM;
return;
}
@@ -1210,7 +1345,6 @@ static void sessionPreupdateOneChange(
/* Create a new change object containing all the old values (if
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
- SessionChange *pChange; /* New change object */
sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
@@ -1236,13 +1370,13 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sqlite3_malloc64(nByte);
- if( !pChange ){
+ pC = (SessionChange *)sessionMalloc64(pSession, nByte);
+ if( !pC ){
rc = SQLITE_NOMEM;
goto error_out;
}else{
- memset(pChange, 0, sizeof(SessionChange));
- pChange->aRecord = (u8 *)&pChange[1];
+ memset(pC, 0, sizeof(SessionChange));
+ pC->aRecord = (u8 *)&pC[1];
}
/* Populate the change object. None of the preupdate_old(),
@@ -1257,17 +1391,17 @@ static void sessionPreupdateOneChange(
}else if( pTab->abPK[i] ){
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
}
- sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte);
+ sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
}
/* Add the change to the hash-table */
if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
- pChange->bIndirect = 1;
+ pC->bIndirect = 1;
}
- pChange->nRecord = nByte;
- pChange->op = op;
- pChange->pNext = pTab->apChange[iHash];
- pTab->apChange[iHash] = pChange;
+ pC->nRecord = nByte;
+ pC->op = op;
+ pC->pNext = pTab->apChange[iHash];
+ pTab->apChange[iHash] = pC;
}else if( pC->bIndirect ){
/* If the existing change is considered "indirect", but this current
@@ -1278,8 +1412,14 @@ static void sessionPreupdateOneChange(
pC->bIndirect = 0;
}
}
+
+ assert( rc==SQLITE_OK );
+ if( pSession->bEnableSize ){
+ rc = sessionUpdateMaxSize(op, pSession, pTab, pC);
+ }
}
+
/* If an error has occurred, mark the session object as failed. */
error_out:
if( pTab->bStat1 ){
@@ -1609,7 +1749,7 @@ int sqlite3session_diff(
int nCol; /* Columns in zFrom.zTbl */
u8 *abPK;
const char **azCol = 0;
- rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
bMismatch = 1;
@@ -1707,7 +1847,7 @@ int sqlite3session_create(
** Free the list of table objects passed as the first argument. The contents
** of the changed-rows hash tables are also deleted.
*/
-static void sessionDeleteTable(SessionTable *pList){
+static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
SessionTable *pNext;
SessionTable *pTab;
@@ -1719,12 +1859,12 @@ static void sessionDeleteTable(SessionTable *pList){
SessionChange *pNextChange;
for(p=pTab->apChange[i]; p; p=pNextChange){
pNextChange = p->pNext;
- sqlite3_free(p);
+ sessionFree(pSession, p);
}
}
- sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */
- sqlite3_free(pTab->apChange);
- sqlite3_free(pTab);
+ sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */
+ sessionFree(pSession, pTab->apChange);
+ sessionFree(pSession, pTab);
}
}
@@ -1752,9 +1892,11 @@ void sqlite3session_delete(sqlite3_session *pSession){
/* Delete all attached table objects. And the contents of their
** associated hash-tables. */
- sessionDeleteTable(pSession->pTable);
+ sessionDeleteTable(pSession, pSession->pTable);
- /* Free the session object itself. */
+ /* Assert that all allocations have been freed and then free the
+ ** session object itself. */
+ assert( pSession->nMalloc==0 );
sqlite3_free(pSession);
}
@@ -1801,7 +1943,8 @@ int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
+ int nByte = sizeof(SessionTable) + nName + 1;
+ pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -1831,13 +1974,29 @@ int sqlite3session_attach(
** If successful, return zero. Otherwise, if an OOM condition is encountered,
** set *pRc to SQLITE_NOMEM and return non-zero.
*/
-static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){
- if( *pRc==SQLITE_OK && (size_t)(p->nAlloc-p->nBuf)nBuf + nByte;
+ if( *pRc==SQLITE_OK && nReq>p->nAlloc ){
u8 *aNew;
i64 nNew = p->nAlloc ? p->nAlloc : 128;
+
do {
nNew = nNew*2;
- }while( (size_t)(nNew-p->nBuf)SESSION_MAX_BUFFER_SZ ){
+ nNew = SESSION_MAX_BUFFER_SZ;
+ if( nNewaBuf, nNew);
if( 0==aNew ){
@@ -2398,7 +2557,7 @@ static int sessionGenerateChangeset(
int nNoop; /* Size of buffer after writing tbl header */
/* Check the table schema is still Ok. */
- rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
rc = SQLITE_SCHEMA;
}
@@ -2488,7 +2647,11 @@ int sqlite3session_changeset(
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
){
- return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
+ int rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
+ assert( rc || pnChangeset==0
+ || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
+ );
+ return rc;
}
/*
@@ -2573,6 +2736,46 @@ int sqlite3session_isempty(sqlite3_session *pSession){
return (ret==0);
}
+/*
+** Return the amount of heap memory in use.
+*/
+sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
+ return pSession->nMalloc;
+}
+
+/*
+** Configure the session object passed as the first argument.
+*/
+int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){
+ int rc = SQLITE_OK;
+ switch( op ){
+ case SQLITE_SESSION_OBJCONFIG_SIZE: {
+ int iArg = *(int*)pArg;
+ if( iArg>=0 ){
+ if( pSession->pTable ){
+ rc = SQLITE_MISUSE;
+ }else{
+ pSession->bEnableSize = (iArg!=0);
+ }
+ }
+ *(int*)pArg = pSession->bEnableSize;
+ break;
+ }
+
+ default:
+ rc = SQLITE_MISUSE;
+ }
+
+ return rc;
+}
+
+/*
+** Return the maximum size of sqlite3session_changeset() output.
+*/
+sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession){
+ return pSession->nMaxChangesetSize;
+}
+
/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
@@ -2582,7 +2785,8 @@ static int sessionChangesetStart(
void *pIn,
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset, /* Pointer to buffer containing changeset */
- int bInvert /* True to invert changeset */
+ int bInvert, /* True to invert changeset */
+ int bSkipEmpty /* True to skip empty UPDATE changes */
){
sqlite3_changeset_iter *pRet; /* Iterator to return */
int nByte; /* Number of bytes to allocate for iterator */
@@ -2603,6 +2807,7 @@ static int sessionChangesetStart(
pRet->in.pIn = pIn;
pRet->in.bEof = (xInput ? 0 : 1);
pRet->bInvert = bInvert;
+ pRet->bSkipEmpty = bSkipEmpty;
/* Populate the output variable and return success. */
*pp = pRet;
@@ -2617,7 +2822,7 @@ int sqlite3changeset_start(
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset /* Pointer to buffer containing changeset */
){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0, 0);
}
int sqlite3changeset_start_v2(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -2626,7 +2831,7 @@ int sqlite3changeset_start_v2(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert, 0);
}
/*
@@ -2637,7 +2842,7 @@ int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0, 0);
}
int sqlite3changeset_start_v2_strm(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -2646,7 +2851,7 @@ int sqlite3changeset_start_v2_strm(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert, 0);
}
/*
@@ -2772,11 +2977,14 @@ static int sessionReadRecord(
SessionInput *pIn, /* Input data */
int nCol, /* Number of values in record */
u8 *abPK, /* Array of primary key flags, or NULL */
- sqlite3_value **apOut /* Write values to this array */
+ sqlite3_value **apOut, /* Write values to this array */
+ int *pbEmpty
){
int i; /* Used to iterate through columns */
int rc = SQLITE_OK;
+ assert( pbEmpty==0 || *pbEmpty==0 );
+ if( pbEmpty ) *pbEmpty = 1;
for(i=0; iaData[pIn->iNext++];
assert( apOut[i]==0 );
if( eType ){
+ if( pbEmpty ) *pbEmpty = 0;
apOut[i] = sqlite3ValueNew(0);
if( !apOut[i] ) rc = SQLITE_NOMEM;
}
@@ -2967,31 +3176,27 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
}
/*
-** Advance the changeset iterator to the next change.
+** Advance the changeset iterator to the next change. The differences between
+** this function and sessionChangesetNext() are that
**
-** If both paRec and pnRec are NULL, then this function works like the public
-** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
-** sqlite3changeset_new() and old() APIs may be used to query for values.
-**
-** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
-** record is written to *paRec before returning and the number of bytes in
-** the record to *pnRec.
+** * If pbEmpty is not NULL and the change is a no-op UPDATE (an UPDATE
+** that modifies no columns), this function sets (*pbEmpty) to 1.
**
-** Either way, this function returns SQLITE_ROW if the iterator is
-** successfully advanced to the next change in the changeset, an SQLite
-** error code if an error occurs, or SQLITE_DONE if there are no further
-** changes in the changeset.
+** * If the iterator is configured to skip no-op UPDATEs,
+** sessionChangesetNext() does that. This function does not.
*/
-static int sessionChangesetNext(
+static int sessionChangesetNextOne(
sqlite3_changeset_iter *p, /* Changeset iterator */
u8 **paRec, /* If non-NULL, store record pointer here */
int *pnRec, /* If non-NULL, store size of record here */
- int *pbNew /* If non-NULL, true if new table */
+ int *pbNew, /* If non-NULL, true if new table */
+ int *pbEmpty
){
int i;
u8 op;
assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
+ assert( pbEmpty==0 || *pbEmpty==0 );
/* If the iterator is in the error-state, return immediately. */
if( p->rc!=SQLITE_OK ) return p->rc;
@@ -3064,13 +3269,13 @@ static int sessionChangesetNext(
/* If this is an UPDATE or DELETE, read the old.* record. */
if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
+ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld, 0);
if( p->rc!=SQLITE_OK ) return p->rc;
}
/* If this is an INSERT or UPDATE, read the new.* record. */
if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
+ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew, pbEmpty);
if( p->rc!=SQLITE_OK ) return p->rc;
}
@@ -3097,6 +3302,37 @@ static int sessionChangesetNext(
return SQLITE_ROW;
}
+/*
+** Advance the changeset iterator to the next change.
+**
+** If both paRec and pnRec are NULL, then this function works like the public
+** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the
+** sqlite3changeset_new() and old() APIs may be used to query for values.
+**
+** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
+** record is written to *paRec before returning and the number of bytes in
+** the record to *pnRec.
+**
+** Either way, this function returns SQLITE_ROW if the iterator is
+** successfully advanced to the next change in the changeset, an SQLite
+** error code if an error occurs, or SQLITE_DONE if there are no further
+** changes in the changeset.
+*/
+static int sessionChangesetNext(
+ sqlite3_changeset_iter *p, /* Changeset iterator */
+ u8 **paRec, /* If non-NULL, store record pointer here */
+ int *pnRec, /* If non-NULL, store size of record here */
+ int *pbNew /* If non-NULL, true if new table */
+){
+ int bEmpty;
+ int rc;
+ do {
+ bEmpty = 0;
+ rc = sessionChangesetNextOne(p, paRec, pnRec, pbNew, &bEmpty);
+ }while( rc==SQLITE_ROW && p->bSkipEmpty && bEmpty);
+ return rc;
+}
+
/*
** Advance an iterator created by sqlite3changeset_start() to the next
** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE
@@ -3369,9 +3605,9 @@ static int sessionChangesetInvert(
/* Read the old.* and new.* records for the update change. */
pInput->iNext += 2;
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[0], 0);
if( rc==SQLITE_OK ){
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol], 0);
}
/* Write the new old.* record. Consists of the PK columns from the
@@ -3472,16 +3708,25 @@ int sqlite3changeset_invert_strm(
return rc;
}
+
+typedef struct SessionUpdate SessionUpdate;
+struct SessionUpdate {
+ sqlite3_stmt *pStmt;
+ u32 *aMask;
+ SessionUpdate *pNext;
+};
+
typedef struct SessionApplyCtx SessionApplyCtx;
struct SessionApplyCtx {
sqlite3 *db;
sqlite3_stmt *pDelete; /* DELETE statement */
- sqlite3_stmt *pUpdate; /* UPDATE statement */
sqlite3_stmt *pInsert; /* INSERT statement */
sqlite3_stmt *pSelect; /* SELECT statement */
int nCol; /* Size of azCol[] and abPK[] arrays */
const char **azCol; /* Array of column names */
u8 *abPK; /* Boolean array - true if column is in PK */
+ u32 *aUpdateMask; /* Used by sessionUpdateFind */
+ SessionUpdate *pUp;
int bStat1; /* True if table is sqlite_stat1 */
int bDeferConstraints; /* True to defer constraints */
int bInvertConstraints; /* Invert when iterating constraints buffer */
@@ -3491,6 +3736,167 @@ struct SessionApplyCtx {
u8 bRebase; /* True to collect rebase information */
};
+/* Number of prepared UPDATE statements to cache. */
+#define SESSION_UPDATE_CACHE_SZ 12
+
+/*
+** Find a prepared UPDATE statement suitable for the UPDATE step currently
+** being visited by the iterator. The UPDATE is of the form:
+**
+** UPDATE tbl SET col = ?, col2 = ? WHERE pk1 IS ? AND pk2 IS ?
+*/
+static int sessionUpdateFind(
+ sqlite3_changeset_iter *pIter,
+ SessionApplyCtx *p,
+ int bPatchset,
+ sqlite3_stmt **ppStmt
+){
+ int rc = SQLITE_OK;
+ SessionUpdate *pUp = 0;
+ int nCol = pIter->nCol;
+ int nU32 = (pIter->nCol+33)/32;
+ int ii;
+
+ if( p->aUpdateMask==0 ){
+ p->aUpdateMask = sqlite3_malloc(nU32*sizeof(u32));
+ if( p->aUpdateMask==0 ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ memset(p->aUpdateMask, 0, nU32*sizeof(u32));
+ rc = SQLITE_CORRUPT;
+ for(ii=0; iinCol; ii++){
+ if( sessionChangesetNew(pIter, ii) ){
+ p->aUpdateMask[ii/32] |= (1<<(ii%32));
+ rc = SQLITE_OK;
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ if( bPatchset ) p->aUpdateMask[nCol/32] |= (1<<(nCol%32));
+
+ if( p->pUp ){
+ int nUp = 0;
+ SessionUpdate **pp = &p->pUp;
+ while( 1 ){
+ nUp++;
+ if( 0==memcmp(p->aUpdateMask, (*pp)->aMask, nU32*sizeof(u32)) ){
+ pUp = *pp;
+ *pp = pUp->pNext;
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ break;
+ }
+
+ if( (*pp)->pNext ){
+ pp = &(*pp)->pNext;
+ }else{
+ if( nUp>=SESSION_UPDATE_CACHE_SZ ){
+ sqlite3_finalize((*pp)->pStmt);
+ sqlite3_free(*pp);
+ *pp = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ if( pUp==0 ){
+ int nByte = sizeof(SessionUpdate) * nU32*sizeof(u32);
+ int bStat1 = (sqlite3_stricmp(pIter->zTab, "sqlite_stat1")==0);
+ pUp = (SessionUpdate*)sqlite3_malloc(nByte);
+ if( pUp==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ const char *zSep = "";
+ SessionBuffer buf;
+
+ memset(&buf, 0, sizeof(buf));
+ pUp->aMask = (u32*)&pUp[1];
+ memcpy(pUp->aMask, p->aUpdateMask, nU32*sizeof(u32));
+
+ sessionAppendStr(&buf, "UPDATE main.", &rc);
+ sessionAppendIdent(&buf, pIter->zTab, &rc);
+ sessionAppendStr(&buf, " SET ", &rc);
+
+ /* Create the assignments part of the UPDATE */
+ for(ii=0; iinCol; ii++){
+ if( p->abPK[ii]==0 && sessionChangesetNew(pIter, ii) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " = ?", &rc);
+ sessionAppendInteger(&buf, ii*2+1, &rc);
+ zSep = ", ";
+ }
+ }
+
+ /* Create the WHERE clause part of the UPDATE */
+ zSep = "";
+ sessionAppendStr(&buf, " WHERE ", &rc);
+ for(ii=0; iinCol; ii++){
+ if( p->abPK[ii] || (bPatchset==0 && sessionChangesetOld(pIter, ii)) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ if( bStat1 && ii==1 ){
+ assert( sqlite3_stricmp(p->azCol[ii], "idx")==0 );
+ sessionAppendStr(&buf,
+ "idx IS CASE "
+ "WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL "
+ "ELSE ?4 END ", &rc
+ );
+ }else{
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " IS ?", &rc);
+ sessionAppendInteger(&buf, ii*2+2, &rc);
+ }
+ zSep = " AND ";
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ char *zSql = (char*)buf.aBuf;
+ rc = sqlite3_prepare_v2(p->db, zSql, buf.nBuf, &pUp->pStmt, 0);
+ }
+
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pUp);
+ pUp = 0;
+ }else{
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ }
+ sqlite3_free(buf.aBuf);
+ }
+ }
+ }
+
+ assert( (rc==SQLITE_OK)==(pUp!=0) );
+ if( pUp ){
+ *ppStmt = pUp->pStmt;
+ }else{
+ *ppStmt = 0;
+ }
+ return rc;
+}
+
+/*
+** Free all cached UPDATE statements.
+*/
+static void sessionUpdateFree(SessionApplyCtx *p){
+ SessionUpdate *pUp;
+ SessionUpdate *pNext;
+ for(pUp=p->pUp; pUp; pUp=pNext){
+ pNext = pUp->pNext;
+ sqlite3_finalize(pUp->pStmt);
+ sqlite3_free(pUp);
+ }
+ p->pUp = 0;
+ sqlite3_free(p->aUpdateMask);
+ p->aUpdateMask = 0;
+}
+
/*
** Formulate a statement to DELETE a row from database db. Assuming a table
** structure like this:
@@ -3560,103 +3966,6 @@ static int sessionDeleteRow(
return rc;
}
-/*
-** Formulate and prepare a statement to UPDATE a row from database db.
-** Assuming a table structure like this:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The UPDATE statement looks like this:
-**
-** UPDATE x SET
-** a = CASE WHEN ?2 THEN ?3 ELSE a END,
-** b = CASE WHEN ?5 THEN ?6 ELSE b END,
-** c = CASE WHEN ?8 THEN ?9 ELSE c END,
-** d = CASE WHEN ?11 THEN ?12 ELSE d END
-** WHERE a = ?1 AND c = ?7 AND (?13 OR
-** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND
-** )
-**
-** For each column in the table, there are three variables to bind:
-**
-** ?(i*3+1) The old.* value of the column, if any.
-** ?(i*3+2) A boolean flag indicating that the value is being modified.
-** ?(i*3+3) The new.* value of the column, if any.
-**
-** Also, a boolean flag that, if set to true, causes the statement to update
-** a row even if the non-PK values do not match. This is required if the
-** conflict-handler is invoked with CHANGESET_DATA and returns
-** CHANGESET_REPLACE. This is variable "?(nCol*3+1)".
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionUpdateRow(
- sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int rc = SQLITE_OK;
- int i;
- const char *zSep = "";
- SessionBuffer buf = {0, 0, 0};
-
- /* Append "UPDATE tbl SET " */
- sessionAppendStr(&buf, "UPDATE main.", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " SET ", &rc);
-
- /* Append the assignments */
- for(i=0; inCol; i++){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = CASE WHEN ?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, " THEN ?", &rc);
- sessionAppendInteger(&buf, i*3+3, &rc);
- sessionAppendStr(&buf, " ELSE ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " END", &rc);
- zSep = ", ";
- }
-
- /* Append the PK part of the WHERE clause */
- sessionAppendStr(&buf, " WHERE ", &rc);
- for(i=0; inCol; i++){
- if( p->abPK[i] ){
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, " AND ", &rc);
- }
- }
-
- /* Append the non-PK part of the WHERE clause */
- sessionAppendStr(&buf, " (?", &rc);
- sessionAppendInteger(&buf, p->nCol*3+1, &rc);
- sessionAppendStr(&buf, " OR 1", &rc);
- for(i=0; inCol; i++){
- if( !p->abPK[i] ){
- sessionAppendStr(&buf, " AND (?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, "=0 OR ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, ")", &rc);
- }
- }
- sessionAppendStr(&buf, ")", &rc);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0);
- }
- sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-
/*
** Formulate and prepare an SQL statement to query table zTab by primary
** key. Assuming the following table structure:
@@ -3737,17 +4046,6 @@ static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
"?3)"
);
}
- if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pUpdate,
- "UPDATE main.sqlite_stat1 SET "
- "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
- "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
- "stat = CASE WHEN ?8 THEN ?9 ELSE stat END "
- "WHERE tbl=?1 AND idx IS "
- "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
- "AND (?10 OR ?8=0 OR stat IS ?7)"
- );
- }
if( rc==SQLITE_OK ){
rc = sessionPrepare(db, &p->pDelete,
"DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
@@ -4064,7 +4362,7 @@ static int sessionApplyOneOp(
int nCol;
int rc = SQLITE_OK;
- assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect );
+ assert( p->pDelete && p->pInsert && p->pSelect );
assert( p->azCol && p->abPK );
assert( !pbReplace || *pbReplace==0 );
@@ -4104,29 +4402,28 @@ static int sessionApplyOneOp(
}else if( op==SQLITE_UPDATE ){
int i;
+ sqlite3_stmt *pUp = 0;
+ int bPatchset = (pbRetry==0 || pIter->bPatchset);
+
+ rc = sessionUpdateFind(pIter, p, bPatchset, &pUp);
/* Bind values to the UPDATE statement. */
for(i=0; rc==SQLITE_OK && ipUpdate, i*3+2, !!pNew);
- if( pOld ){
- rc = sessionBindValue(p->pUpdate, i*3+1, pOld);
+ if( p->abPK[i] || (bPatchset==0 && pOld) ){
+ rc = sessionBindValue(pUp, i*2+2, pOld);
}
if( rc==SQLITE_OK && pNew ){
- rc = sessionBindValue(p->pUpdate, i*3+3, pNew);
+ rc = sessionBindValue(pUp, i*2+1, pNew);
}
}
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset);
- }
if( rc!=SQLITE_OK ) return rc;
/* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
** the result will be SQLITE_OK with 0 rows modified. */
- sqlite3_step(p->pUpdate);
- rc = sqlite3_reset(p->pUpdate);
+ sqlite3_step(pUp);
+ rc = sqlite3_reset(pUp);
if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
/* A NOTFOUND or DATA error. Search the table to see if it contains
@@ -4258,7 +4555,7 @@ static int sessionRetryConstraints(
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionChangesetStart(
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints
+ &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
@@ -4349,14 +4646,13 @@ static int sessionChangesetApply(
);
if( rc!=SQLITE_OK ) break;
+ sessionUpdateFree(&sApply);
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pSelect);
sApply.db = db;
sApply.pDelete = 0;
- sApply.pUpdate = 0;
sApply.pInsert = 0;
sApply.pSelect = 0;
sApply.nCol = 0;
@@ -4384,7 +4680,7 @@ static int sessionChangesetApply(
int i;
sqlite3changeset_pk(pIter, &abPK, 0);
- rc = sessionTableInfo(
+ rc = sessionTableInfo(0,
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
@@ -4420,11 +4716,10 @@ static int sessionChangesetApply(
}
sApply.bStat1 = 1;
}else{
- if((rc = sessionSelectRow(db, zTab, &sApply))
- || (rc = sessionUpdateRow(db, zTab, &sApply))
- || (rc = sessionDeleteRow(db, zTab, &sApply))
- || (rc = sessionInsertRow(db, zTab, &sApply))
- ){
+ if( (rc = sessionSelectRow(db, zTab, &sApply))
+ || (rc = sessionDeleteRow(db, zTab, &sApply))
+ || (rc = sessionInsertRow(db, zTab, &sApply))
+ ){
break;
}
sApply.bStat1 = 0;
@@ -4483,9 +4778,9 @@ static int sessionChangesetApply(
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
}
+ sessionUpdateFree(&sApply);
sqlite3_finalize(sApply.pInsert);
sqlite3_finalize(sApply.pDelete);
- sqlite3_finalize(sApply.pUpdate);
sqlite3_finalize(sApply.pSelect);
sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlite3_free((char*)sApply.constraints.aBuf);
@@ -4516,8 +4811,8 @@ int sqlite3changeset_apply_v2(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
+ int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -4575,7 +4870,7 @@ int sqlite3changeset_apply_v2_strm(
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
+ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -4863,7 +5158,7 @@ static int sessionChangesetToHash(
}
}
- if( sessionGrowHash(pIter->bPatchset, pTab) ){
+ if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
rc = SQLITE_NOMEM;
break;
}
@@ -5049,7 +5344,7 @@ int sqlite3changegroup_output_strm(
*/
void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
if( pGrp ){
- sessionDeleteTable(pGrp->pList);
+ sessionDeleteTable(0, pGrp->pList);
sqlite3_free(pGrp);
}
}
@@ -5195,7 +5490,7 @@ static void sessionAppendPartialUpdate(
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pIter->abPK[i] || a2[0]==0 ){
- if( !pIter->abPK[i] ) bData = 1;
+ if( !pIter->abPK[i] && a1[0] ) bData = 1;
memcpy(pOut, a1, n1);
pOut += n1;
}else if( a2[0]!=0xFF ){
@@ -5450,7 +5745,7 @@ int sqlite3rebaser_rebase_strm(
*/
void sqlite3rebaser_delete(sqlite3_rebaser *p){
if( p ){
- sessionDeleteTable(p->grp.pList);
+ sessionDeleteTable(0, p->grp.pList);
sqlite3_free(p);
}
}
diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h
index 1ed3b550f..10d013390 100644
--- a/ext/session/sqlite3session.h
+++ b/ext/session/sqlite3session.h
@@ -79,6 +79,38 @@ int sqlite3session_create(
*/
void sqlite3session_delete(sqlite3_session *pSession);
+/*
+** CAPIREF: Conigure a Session Object
+** METHOD: sqlite3_session
+**
+** This method is used to configure a session object after it has been
+** created. At present the only valid value for the second parameter is
+** [SQLITE_SESSION_OBJCONFIG_SIZE].
+**
+** Arguments for sqlite3session_object_config()
+**
+** The following values may passed as the the 4th parameter to
+** sqlite3session_object_config().
+**
+** SQLITE_SESSION_OBJCONFIG_SIZE
+** This option is used to set, clear or query the flag that enables
+** the [sqlite3session_changeset_size()] API. Because it imposes some
+** computational overhead, this API is disabled by default. Argument
+** pArg must point to a value of type (int). If the value is initially
+** 0, then the sqlite3session_changeset_size() API is disabled. If it
+** is greater than 0, then the same API is enabled. Or, if the initial
+** value is less than zero, no change is made. In all cases the (int)
+** variable is set to 1 if the sqlite3session_changeset_size() API is
+** enabled following the current call, or 0 otherwise.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
+
+/*
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -323,6 +355,22 @@ int sqlite3session_changeset(
void **ppChangeset /* OUT: Buffer containing changeset */
);
+/*
+** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
+** METHOD: sqlite3_session
+**
+** By default, this function always returns 0. For it to return
+** a useful result, the sqlite3_session object must have been configured
+** to enable this API using sqlite3session_object_config() with the
+** SQLITE_SESSION_OBJCONFIG_SIZE verb.
+**
+** When enabled, this function returns an upper limit, in bytes, for the size
+** of the changeset that might be produced if sqlite3session_changeset() were
+** called. The final changeset size might be equal to or smaller than the
+** size in bytes returned by this function.
+*/
+sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
+
/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session
@@ -440,6 +488,14 @@ int sqlite3session_patchset(
*/
int sqlite3session_isempty(sqlite3_session *pSession);
+/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
+
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlite3_changeset_iter
@@ -542,18 +598,23 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
diff --git a/ext/session/test_session.c b/ext/session/test_session.c
index 82f30979f..f2fc77eee 100644
--- a/ext/session/test_session.c
+++ b/ext/session/test_session.c
@@ -146,7 +146,10 @@ static int SQLITE_TCLAPI test_sql_exec_changeset(
static int test_tcl_integer(Tcl_Interp *interp, const char *zVar){
Tcl_Obj *pObj;
int iVal = 0;
- pObj = Tcl_ObjGetVar2(interp, Tcl_NewStringObj(zVar, -1), 0, TCL_GLOBAL_ONLY);
+ Tcl_Obj *pName = Tcl_NewStringObj(zVar, -1);
+ Tcl_IncrRefCount(pName);
+ pObj = Tcl_ObjGetVar2(interp, pName, 0, TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(pName);
if( pObj ) Tcl_GetIntFromObj(0, pObj, &iVal);
return iVal;
}
@@ -242,6 +245,9 @@ static int SQLITE_TCLAPI test_session_cmd(
{ "table_filter", 1, "SCRIPT", }, /* 6 */
{ "patchset", 0, "", }, /* 7 */
{ "diff", 2, "FROMDB TBL", }, /* 8 */
+ { "memory_used", 0, "", }, /* 9 */
+ { "changeset_size", 0, "", }, /* 10 */
+ { "object_config_size", 1, "INTEGER", }, /* 11 */
{ 0 }
};
int iSub;
@@ -347,6 +353,35 @@ static int SQLITE_TCLAPI test_session_cmd(
}
break;
}
+
+ case 9: { /* memory_used */
+ sqlite3_int64 nMalloc = sqlite3session_memory_used(pSession);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nMalloc));
+ break;
+ }
+
+ case 10: {
+ sqlite3_int64 nSize = sqlite3session_changeset_size(pSession);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
+ break;
+ }
+ case 11: {
+ int rc;
+ int iArg;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iArg) ){
+ return TCL_ERROR;
+ }
+ rc = sqlite3session_object_config(
+ pSession, SQLITE_SESSION_OBJCONFIG_SIZE, &iArg
+ );
+ if( rc!=SQLITE_OK ){
+ extern const char *sqlite3ErrName(int);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ }else{
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iArg));
+ }
+ break;
+ }
}
return TCL_OK;
@@ -372,6 +407,7 @@ static int SQLITE_TCLAPI test_sqlite3session(
Tcl_CmdInfo info;
int rc; /* sqlite3session_create() return code */
TestSession *p; /* New wrapper object */
+ int iArg = -1;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME");
@@ -392,6 +428,13 @@ static int SQLITE_TCLAPI test_sqlite3session(
return test_session_error(interp, rc, 0);
}
+ /* Query the SQLITE_SESSION_OBJCONFIG_SIZE option to ensure that it
+ ** is clear by default. Then set it. */
+ sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);
+ assert( iArg==0 );
+ iArg = 1;
+ sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);
+
Tcl_CreateObjCommand(
interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p,
test_session_del
diff --git a/main.mk b/main.mk
index e47e85fdf..16d72ff92 100644
--- a/main.mk
+++ b/main.mk
@@ -360,6 +360,7 @@ TESTSRC = \
#
TESTSRC += \
$(TOP)/ext/misc/amatch.c \
+ $(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/carray.c \
$(TOP)/ext/misc/cksumvfs.c \
$(TOP)/ext/misc/closure.c \
@@ -438,7 +439,8 @@ TESTSRC2 = \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/misc/stmt.c \
$(TOP)/ext/session/sqlite3session.c \
- $(TOP)/ext/session/test_session.c
+ $(TOP)/ext/session/test_session.c \
+ fts5.c
# Header files used by all library source files.
#
@@ -537,7 +539,6 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
-FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
@@ -550,13 +551,13 @@ ST_OPT = -DSQLITE_THREADSAFE=0
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
-all: sqlite3.h libsqlite3.a sqlite3$(EXE)
+all: sqlite3.h sqlite3ext.h libsqlite3.a sqlite3$(EXE)
-libsqlite3.a: $(LIBOBJ)
+libsqlite3.a: sqlite3.h $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a
-sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
+sqlite3$(EXE): sqlite3.h libsqlite3.a shell.c
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
@@ -590,7 +591,6 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
- -DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_BYTECODE_VTAB \
@@ -747,6 +747,7 @@ SHELL_SRC = \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
+ $(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/misc/uint.c \
@@ -824,13 +825,13 @@ fts3_unicode2.o: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
-fts5.o: fts5.c
+fts5.o: fts5.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c fts5.c
-json1.o: $(TOP)/ext/misc/json1.c
+json1.o: $(TOP)/ext/misc/json1.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
-stmt.o: $(TOP)/ext/misc/stmt.c
+stmt.o: $(TOP)/ext/misc/stmt.c sqlite3ext.h sqlite3.h
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
@@ -954,7 +955,7 @@ fuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-
./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
- valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
+ valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
# The veryquick.test TCL tests.
@@ -1079,6 +1080,9 @@ rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
loadfts: $(TOP)/tool/loadfts.c libsqlite3.a
$(TCC) $(TOP)/tool/loadfts.c libsqlite3.a -o loadfts $(THREADLIB)
+threadtest5: $(TOP)/test/threadtest5.c libsqlite3.a
+ $(TCC) $(TOP)/test/threadtest5.c libsqlite3.a -o threadtest5 $(THREADLIB)
+
# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
@@ -1141,3 +1145,4 @@ clean:
rm -f sqldiff sqldiff.exe
rm -f fts5.* fts5parse.*
rm -f lsm.h lsm1.c
+ rm -f threadtest5
diff --git a/manifest b/manifest
index 37ade307d..a20358755 100644
--- a/manifest
+++ b/manifest
@@ -1,13 +1,13 @@
-C Version\s3.34.1
-D 2021-01-20T14:10:07.150
+C Version\s3.36.0
+D 2021-06-18T18:36:39.378
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 0e88f5d095213a9ccd45c5bbd871c8ead498f886dff4493471fbf48b1f867f9d
+F Makefile.in ff5ac24ec9cb700135ee4453fa14c18ea371e94250d3673bda1f2cb56e1108ce
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc dd10dbf63b2f8ac3e2f0542963a21bc69058976ac4355165f212a31c83d17f44
-F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
-F VERSION 9633e2edacc7963299a285b89cbeb832f73316c9ccc58f9a70701a5e8b16513c
+F Makefile.msc 8285e1ea7264f32b08702866d69dd127c0f663bbc2002323d853c68c27c6b6e4
+F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110
+F VERSION 8c392f6d70d82e513a0eac622bdf23c43df3e084cb630288beba8cef3012c812
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -15,10 +15,10 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc e0f1dafc48d000fd6ddfdb01815271528db55cbc7299ca888df5b93367f0d5a4
+F autoconf/Makefile.msc d146a08ebbdf7f881ba600a49cd8dce40c4c807addcdb4b9b6a507e4b40ce837
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
-F autoconf/configure.ac 3cd933b959fe514eebd1ca1717dfddbf2c9b825b6bc2c5f744deaf5d63af9288
+F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -29,16 +29,16 @@ F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
F autoconf/tea/win/makefile.vc a5ff708245260c2794c6aaa0151efe5403d5896566eaf096747be0d9075284e4
-F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291
+F autoconf/tea/win/nmakehlp.c 190bf8b40f6f90eeb6cbc1e5c13a19fc7ad870e479e0314c88174f71bf9e28a7
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure 10bbf6fa13320dc9b6197aa9574bd7360f379f904a53ad632ddb310099cf148d x
-F configure.ac 73545c21eebcef9398d85c982c7be260f07708256778221b541f83ae8c6f61eb
+F configure c658869fc056a2460a2212fb2960e410cd24e3fb9c55640fbc78d15b48810936 x
+F configure.ac 4e4b58b32f88c8da9914a2f2c3158f80e69907eccc019fcc7e3ba14ffd91c640
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
-F doc/lemon.html c5d8ba85ac1daef7be8c2d389899480eb62451ff5c09b0c28ff8157bb8770746
+F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
@@ -50,8 +50,8 @@ F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test dba6e752cc701621771f925f3872b183fa688f7b4a9f4822631fc02bdbffc45a
-F ext/expert/sqlite3expert.c 216e250acc54b8aaa9ff5c1e1b2256788abc3994dd1d757626102718122e6a91
+F ext/expert/expert1.test 6703fd74711daf8230240680b0a348d0720e28819b602701adfbd32457fdcddd
+F ext/expert/sqlite3expert.c de51b187c629a4c4264d5de0b77862641e11426f7a963a92abf2d4077085fc8c
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -84,25 +84,25 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 4809e0b05af4519ad8bfa13d684f7ad635d1390a758299d2302f7e85c48ec160
+F ext/fts3/fts3.c 95f55e24550c01c2a325d09c9ea8fdff61e923a4675f8545b28bf3c470e57dfb
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 045179f538c478ced266ca14327269cde8ad8d573c5be902230a5ebaa5636c59
-F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
-F ext/fts3/fts3_expr.c f081e38da641724cd72c20e23b71db2bf4d0c9517c14637442f6910259f11a34
+F ext/fts3/fts3Int.h bde280294d56ff50ee29d03e5140f0b6953b44d1c969bb5831e8ae85e3e76715
+F ext/fts3/fts3_aux.c 1af58af8f2b00a49f4fb1c2602f8da2054ad60076f46c8ebf85c5410eccccb65
+F ext/fts3/fts3_expr.c 5853cd7a35a79d193614add9b4c461b2d56f465d90899ca4309f05d9d1536558
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
-F ext/fts3/fts3_snippet.c 86e7e947a176f0f005720b3ca17631aca2fd2f9daa6729d4adbf2d16ab1b9613
+F ext/fts3/fts3_snippet.c 57e1965906f3ecfcb5251a14aea98ac2d2dd1868a123bcd5a569601719ab9ead
F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
-F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39
+F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454
F ext/fts3/fts3_tokenize_vtab.c 8d15b148e7d88a4280389a200b26e8d52abda4c4ec2e9a35e9d7a1fa50e5aa03
F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
-F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
+F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
-F ext/fts3/fts3_write.c 723ed1b11ed46ad1b3a23c0d69fa39e77986783a82d5711bf87a5ce29e0a3b52
+F ext/fts3/fts3_write.c 98edfd77aeb53afcb26d8de3ed0a87f16468ee05f84f8c1752e6e378c354cd7a
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
@@ -115,16 +115,16 @@ F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a
F ext/fts5/fts5Int.h 26c74dd5776f798436fbf604a0bf0e8de263b35b5060b05c15f9085845d9fda2
F ext/fts5/fts5_aux.c f558e1fb9f0f86a4f7489e258c162e1f947de5ff2709087fbb465fddb7092f98
-F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
-F ext/fts5/fts5_config.c be54f44fca491e96c6923a4b9a736f2da2b13811600eb6e38d1bcc91c4ea2e61
-F ext/fts5/fts5_expr.c e527e3a7410393075598cec544e3831798a8c88b3e8878e2cfb7cb147113e925
+F ext/fts5/fts5_buffer.c 605f509f88c73e9ab41323cb6cf74932f936acf3f7d9c87bd0d3c599b4c90281
+F ext/fts5/fts5_config.c 8336d0ff6db0933f63cfec8ae0ab76e68393259cbccc0b46e1f79f7fa1842ff3
+F ext/fts5/fts5_expr.c 9462249a3bb82d0e49b163500f9d2197c2e4cd95bf440a9bbfc3906b22ea1e1b
F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
-F ext/fts5/fts5_index.c 9f152a596df3a2227ddd59adb82549c2b6858ab36bc1d26fd8933f43d3d63d36
-F ext/fts5/fts5_main.c b4e4931c7fcc9acfa0c3b8b5e5e80b5b424b8d9207aae3a22b674bd35ccf149d
+F ext/fts5/fts5_index.c eb1864c6abacf08d959956183a55a4f9767af76be289f2bb519bb0f197b3fd72
+F ext/fts5/fts5_main.c 35ebbcae681a4a40027c47bc2e94d7e7c81e331dc406bb9b23c546454ee8f98a
F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
-F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
+F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
-F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7
+F ext/fts5/fts5_test_tok.c a2bed8edb25f6432e8cdb62aad5916935c19dba8dac2b8324950cfff397e25ff
F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
@@ -160,13 +160,13 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test dd5435659d5363fc3b3ac32175e2fc793fdc17980b47e3d598695d867eaa77a2
-F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91
-F ext/fts5/test/fts5delete.test 4a15fb03b6c7eac62ac807a3a32b7f0dc74f0d479c410e3e3568ae96b9469290
+F ext/fts5/test/fts5corrupt3.test 79467b7c69a9c45ee3260507c4648d6449323aaa3c1e05b360c9479f1aa7dcce
+F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
+F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
-F ext/fts5/test/fts5doclist.test e39a6001495f1dc68e20323586ac965787986c2bf6f515b9b0285627b089d9e6
+F ext/fts5/test/fts5doclist.test faa9e9cc3c0645fa6203667cb5f007c359447c6ee66753f71a58175c2497cacd
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
F ext/fts5/test/fts5eb.test 239bb2f02571f8cccfc7018d08f502df1cd8cc6a69b65ed1dde5f6a070e3f669
F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd
@@ -200,10 +200,11 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
-F ext/fts5/test/fts5plan.test 79d35b5e83bbdcba48d946a7f008df161f6b0ede1a966892d0aa6c8dd0b6e773
+F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
+F ext/fts5/test/fts5prefix2.test 3847ce46f70b82d61c6095103a9d7c53f2952c40a4704157bc079c04d9c8b18b
F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee7e017ce46f2416
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
@@ -218,7 +219,7 @@ F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947e
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
-F ext/fts5/test/fts5trigram.test e2ce256fd0ccd6707e740aa3596206aedb0d5834b100c0cb49e344dcd1d8463c
+F ext/fts5/test/fts5trigram.test 5b4feb53a4d5aca70c841f6919c8719b5a9c805474727dda99285fccdd2e9cce
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
@@ -285,42 +286,42 @@ F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f607
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/appendvfs.c 55121d311d408ba9c62c3cfa367408887638f02f9522dd9859891d0ee69a7eba
+F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
-F ext/misc/cksumvfs.c c4e7ebeae5aa578df98f23bddb63ecbcbe913ee3c32b8b769525af100d752061
+F ext/misc/cksumvfs.c b42ef52eaaa510d54ec320c87bea149e934a3b06cd232be2093562bf669bd572
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
-F ext/misc/decimal.c 3ddbf8162015be4d5ec2395dee4538f1e638bb517174bb148274b132df6e1d08
+F ext/misc/decimal.c 09f967dcf4a1ee35a76309829308ec278d3648168733f4a1147820e11ebefd12
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
F ext/misc/fileio.c 9b69e25da3b51d4a1d905a464ccb96709792ad627a742ba09215bc0d1447e7bd
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
-F ext/misc/ieee754.c 5c7ca326361c7368f95f5743972eade3b8b24f60359ed7cba4706668a5682896
-F ext/misc/json1.c f31e89171f932d1821c91f10d2cb4979fc0447030030a8bce70420cd43d074c0
+F ext/misc/ieee754.c cd6ab89f85fda8a020559b3f4d03001a8a62dd856beda5af3f558621d12be913
+F ext/misc/json1.c 76c5d9e0960fd15b4be79dacb76d872b4d0d983ce13e72ebfe9481d82cb9345d
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
-F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
+F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
F ext/misc/mmapwarm.c 347caa99915fb254e8949ec131667b7fae99e2a9ce91bd468efb6dc372d9b7a9
F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1ab
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
-F ext/misc/regexp.c 246244c714267f303df76acf73dcf110cf2eaf076896aaaba8db6d6d21a129db
+F ext/misc/regexp.c 5853b0e5ed40c47f7ded2b0bf2ff73796f7cb21543089c5f07308e0032647b76
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c fbb8e6be97b54d10d2f235e163fa2f53a8f4421c66ebd532a233fd1c69c3f522
+F ext/misc/series.c c6bd5d249e5199a1b55aeee4d0e6576ff3a68702fc475dbd64503a32903516c7
F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
-F ext/misc/shathree.c 86bee126b89dc7f3a9edc6d31497588a0f1e78ab867025a766b67f52bcf1f656
+F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
@@ -331,15 +332,15 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03
F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
-F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
-F ext/misc/vfsstat.c 389ea13983d3af926504c314f06a83cc858d5adc24b40af74aaed1fece00c118
+F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
+F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
-F ext/misc/wholenumber.c 520f34c3099e5b7d546f13708607dc2fa173c46b68952eecf0d19cd675fec85e
-F ext/misc/zipfile.c e35e035bc2765b1ccdcb15f9815c2112843fcbc8f36aa071f0e5935df7072228
+F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
+F ext/misc/zipfile.c b7261ef6dbc2d18924ff80c40fb5d56c9ccfee3f822a7d3d43b7c87af3d27218
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
-F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
-F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
+F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
+F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc
@@ -358,7 +359,7 @@ F ext/rbu/rbu_common.tcl 60d904133ff843fe72cc0514e9dd2486707181e6e0fbab20979da28
F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
-F ext/rbu/rbudiff.test 156957851136b63c143478518dc1bda6c832103cdbe8ac1d7cdd47edb3cbe0a3
+F ext/rbu/rbudiff.test abe895a8d479e4d33acb40e244e3d8e2cd25f55a18dfa8b9f83e13d00073f600
F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20
F ext/rbu/rbuexpr.test 10d0420537c3bc7666e576d72adeffe7e86cfbb00dcc30aa9ce096c042415190
F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8
@@ -378,7 +379,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 05c457c27e9340c944f34e850871a915a6b5ee1d823f7a0bb2b482ac6b1e1464
+F ext/rbu/sqlite3rbu.c badb52388467f58e67ef104c5276d1ac68b316a30f8ccb2f74eac733625ae236
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -391,21 +392,21 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c 1b1ddecb79877b12331d35de9f393b80bbb731e0bf6db6c572f23191987ea803
-F ext/rtree/rtree.c 60f6f1675134201974be4189dbd219494c13e1ed30e80bd92ae0dcc86df1b035
+F ext/rtree/geopoly.c 98d45533989e908bf65b43f36ff6eaad95a9ffe6f3b6b8658fbd47d45c58b10b
+F ext/rtree/rtree.c f1ce6a86f7cbff634900653bec2dfeba732dd4450eec921c0ac3851d41f462b9
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
-F ext/rtree/rtree6.test 1252a0439da01d2f1f5cbbdeeb80455a2d68b9bae2a9787937b167a5e3957828
+F ext/rtree/rtree6.test 9ce3691c1aac43070a9f194f0ebf54372db346c5a82241fd11b525ed53ce9f3f
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
-F ext/rtree/rtreeC.test 6aa87eba4d9a3003b941a1ba77db259c5cabc3fd92fc5a6360f5369520eb9a4d
+F ext/rtree/rtreeC.test c4bfa9a61c6788c03e4a9ce40ab2cfc6100982559effd9842d1b658e1d47aa5f
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
@@ -417,7 +418,7 @@ F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b5879
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
-F ext/rtree/rtreefuzz001.test eef1ed593bb15886cd5d5367a2f2492f81e315848896cdf7afb6e21454978827
+F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
@@ -427,7 +428,7 @@ F ext/session/changeset.c 7a1e6a14c7e92d36ca177e92e88b5281acd709f3b726298dc34ec0
F ext/session/changesetfuzz.c 227076ab0ae4447d742c01ee88a564da6478bbf26b65108bf8fac9cd8b0b24aa
F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a
F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e
-F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
+F ext/session/session2.test 7f53d755d921e0baf815c4258348e0ed460dfd8a772351bca5ad3ccbb1dc786e
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
@@ -445,23 +446,27 @@ F ext/session/sessionH.test b17afdbd3b8f17e9bab91e235acf167cf35485db2ab2df0ea889
F ext/session/session_common.tcl f613174665456b2d916ae8df3e5735092a1c1712f36f46840172e9a01e8cc53e
F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
+F ext/session/sessionbig.test 890ade19e3f80f3d3a3e83821ff79c5e2af906a67ecb5450879f0015cadf101e
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb
F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
+F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
+F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
+F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a347ea9820a002dd8
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
-F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
-F ext/session/sqlite3session.c 2c76b8c3a5d6dab736686f8a48833b8bdac0871ecc6f447f9839d28bd4a63d6c
-F ext/session/sqlite3session.h a2db5b72b938d12c727b4b4ec632254ca493670a9c0de597af3271a7f774fc57
-F ext/session/test_session.c 24286d958dc6f4ca4d7e710f09bc0fa9d50956a40dd99fd8223e7488024c71fe
+F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
+F ext/session/sqlite3session.c af0cb1163e224b286a9cba3c1ad877d927821e6a0e317c29b289a16e5da378a8
+F ext/session/sqlite3session.h 0907de79bc13a2e3af30a6dc29acc60792a3eaf7d33d44cf52500d0f3c2b2171
+F ext/session/test_session.c f433f68a8a8c64b0f5bc74dc725078f12483301ad4ae8375205eef790274a787
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 57451ea5b3d5cd86e9c5324b10c9de184b12e8dcccc31c65d24fbcb55ccd9c53
+F main.mk c0c95f0aa2e3b731eb0c5a85869d4d6abef91647ec8e87a4013059bd1b910c0a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -473,45 +478,45 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c b6de60d59419e34f5b48ff2b21fe0f9bb66fc714e5545a6ac790ac7a0c46548c
+F src/alter.c 774a2a175ec747b55046ec62f5c1208d730ee22b10bdad5f182591fa247946a8
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
-F src/attach.c 0f497c15c4cfe3bdcb214f0dbdbbb6c5ed7e8a9308ac445c7959f5e5780437a9
-F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
+F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929
+F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c ee14224322b9e4172d01e691e2f289f6c630ae39b7906f84b72dc780b9e42a76
-F src/btree.h dcdff4037d75b3f032a5de0d922fcfaf35d48589417f634fa8627362709315f9
-F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
-F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
+F src/btree.c 399e1ebcd6c4f9ad47f5457bfe3623441db287f0923433cf6539497791557be8
+F src/btree.h 096cc53baa58be22b02c896d1cf933c38cfc6d65f9253c1367ece8cc88a24de5
+F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
+F src/build.c ea28944f65b04f771e7aa5d614d406faa1bde5fe4ce882e2ead73049f03ed568
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
-F src/date.c dace306a10d9b02ee553d454c8e1cf8d3c9b932e137738a6b15b90253a9bfc10
+F src/ctime.c 3052b6b05ed9ef547a3dd66b8e01bfa9d582e78752ad6ed327da84652641e038
+F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
-F src/delete.c 927cf8f900583e79aca8f1a321979e0a8f053babd9a690b44b38f79de2cc09fe
-F src/expr.c 0d196ed5a2ebf96be7e8df88add4fabfad0dce16c0fed81a4b8f6a26e259797f
+F src/delete.c 62451bba9fe641159e9c0b7d9d2bab1c48d0cff11e16de2d14000603d2af1fcf
+F src/expr.c 30a2abf526531ce6bd45fbc85bfec0fc3f6e5a0fb490cd2350855f2fc34dd789
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72
-F src/func.c 574f7e5a67e4b7a7855cf3478037717c8f44686c0cd727e1d7f7773414165c03
-F src/global.c 943256ac44f333039d35a9830c18d075a81fa6b6bf2af05771494a9acfb9a40b
+F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
+F src/func.c 9eb67f0aaf1cf439c21d6fc8afe270973d6e8345af3f1ebda98ad42186d30f5b
+F src/global.c 25ba4d58476f6be29bba9d9d14f7f146b78476d3a4d75ebb8c3b736328afe0f9
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 7e081d33aab4a9d761c39dccf3c3872c35501565d2ed9db66301918d23bc7901
+F src/insert.c 2189e0e596010a0dc5405d9f14f78db1ee2fa71138c931f5b6ea96610b95bfc1
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
-F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
-F src/main.c 54d61d1e94f225636053c862c930d7dd7b29162b93d3f3ecb00439910ccba02a
-F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
+F src/loadext.c 12684b3f19cd103cea97cdf14d0758196d0c646e12a898d7245141a9abfde9a4
+F src/main.c 9c06f8dc6137aaa990692ce30db1c00c3e6a574c5a4756640625c19b507c65ec
+F src/malloc.c cbc93cdd429c4594912017d92ab656e2579aca64dbd1c6888551275bed46f25b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c ab0632d42407e866d2b616bd19d4211ac0ad1b430f04c4e187d60005b8700b98
-F src/memjournal.c 90b2ca7e2f465d57c16b69d15a9f3e3294af61088eb4938f2f7664d5ac50f813
+F src/memdb.c 2f2e8efc6e531c59cf8255f0bf4ad81f2e88e0a394581244154c8cf5141757ce
+F src/memjournal.c a85f0dc5c02a42453d0bc3819ecfb5666cb6433e5deefcd93ccbe05c9f088b83
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
@@ -519,44 +524,44 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f956d
F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
-F src/os.c 80e4cf3e5da06be03ca641661e331ce60eeeeabf0d7354dbb1c0e166d0eedbbe
-F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
+F src/os.c 59ed1f503347e8b5434c0ce7d7d0f02a3f24a72fea8b26d0bba2de8dfaef778b
+F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c adbbcea4c63d3b400d405f60a5da4c01433753ec4a12e2dc695beb2bbd671fe9
+F src/os_unix.c feac74a0ba7652c405ba30f61d9e738be717d15899f2915a129ef160a3e5b26b
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c c49952ac5e9cc536778eff528091d79d38b3e45cbeeed4695dc05e207dc6547d
+F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
-F src/parse.y 9ce4dfb772608ed5bd3c32f33e943e021e3b06cfd2c01932d4280888fdd2ebed
+F src/parse.y 8920f4444957d7827ca458029b2e41ffa32dd3b72917be0b52cae0aace3eadb5
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
-F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
+F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
+F src/pragma.c eb42cb9bec189cf18cef5d8fcae56e13bb73ef2b019b198fb48740ced81bce95
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
-F src/prepare.c 270170a239c0f66bd3c228f373afe24447c2614a6829ae22080babc64f241931
-F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
-F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
+F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67
+F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
+F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
+F src/resolve.c 35630effd4d16d2373caa41bae40a3d71f853f3ad0cb4f572f2ed4b8c350c1e9
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 847062694ac9a6add162d39182584b7ca53948ad821c52512a125cd845904e71
-F src/shell.c.in 55113760ae91a05c6ce4558714a1c8fc7a44bf266f735de6e71ea40f79e69830
-F src/sqlite.h.in 843471c794810d090b7bc1a31ff1d7c6fed5d029dc47ccc54605bd418df5d294
+F src/select.c 4fa607bab6bcc580f12dbaf9c800b2250a1e408f10321a1d3bcb1dd30c447e62
+F src/shell.c.in f3e91c697f33daae14923355dcadfc26bb0c1eabdb343e5508706893e017a0a6
+F src/sqlite.h.in 8549395aa13361d5dcea04e3a57d680af10f7ee0989c45ebfffe3a3bcb2cdc3d
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h c01115c8dd967f7d334a98ba37ac821eafb04144c8085a795daaf2185743d27a
+F src/sqliteInt.h ab37a8dd95884fc25ef1eb7b6d53d6674905c67298affc2b5bf947f739096504
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
-F src/test1.c 465b7a35b7e231bf2833e47c1371b5dfc99bd803ebe73783862399d479d696a5
+F src/tclsqlite.c 97645e4a15dde6a6ad6de8d81057ff9869413b866015a89e208fedacd709493e
+F src/test1.c 2100f4c28bae21ce83a9a0c5ec6827efd0e15d11b93b569b614daa5654b3fcf6
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 7fb971777c2c79c734bb52757191d68d4af659b8de9b4a071be3f527a9d19a02
+F src/test8.c 0c856d6ff6b0d2ff6696addc467a15ed17c6910f14475302cd5b3b4e54406161
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
@@ -564,7 +569,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c 5ea19bf0972a9d91728518b4d30e91477acce80496003ecbef3a7fb18d0bd081
+F src/test_config.c 9c8e12823c46082a01765addf43be9309889f4e9dfb5a512a6c974e1c4efb413
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -603,34 +608,34 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
-F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
-F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
-F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
-F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
+F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
+F src/treeview.c 21449a944d5abd3ac07b7eab76f7221e20c9480d06f01798f8dc66d9bc361769
+F src/trigger.c e0fd347b2571a2d956318cdc6d011ccca7ce862d10a0ca04188a37920ef5440c
+F src/update.c 56fa0458b1ffc1042629f926443e8ed44203983df3ab2b0db2ba556e6ceed68c
+F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
-F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
+F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c d24a43b6b1ed2dba893636a14f5e56001444ab3fd5465e3bca8ab01799840acd
-F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
-F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e
-F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
-F src/vdbeaux.c c76b7e96e189f5056d1de914d33d07bd03d3b88741f75375c8e18c9b11ffd379
-F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
-F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
-F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
-F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
+F src/vdbe.c 6ece0ee94fa3a95601372efdc4ec6d068cd6cc58e28af8852f3407b90be4b7f8
+F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
+F src/vdbeInt.h 465fcb494db4ca6630fb9c19b2f3dfed597fbe885b0d4204193a5093b0dd7dc6
+F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
+F src/vdbeaux.c 065a10392378109f08435bd50d03dff315e384cde2831d6b8dbaec05f33b10af
+F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193
+F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64
+F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2
+F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
-F src/vtab.c 5f5fc793092f53bbdfde296c50f563fb7bda58cf48e9cf6a8bdfbc5abd409845
+F src/vtab.c b928405ccb66040fc6c3a11eaa93ddb02cbf20f9ab6860b301b222b9b50dc089
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
+F src/wal.c c8ec20a1ca161d5635a4f19c2a4efec2e006e19a8a61f272bf6bce1c80ab7436
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
-F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
-F src/where.c ad738741bf45999188a3047f6277063e3f6843304d581e3ad5875419afdeb6b2
-F src/whereInt.h 59077fbd0b3d01bc8715e746c86a99ebf4c85bde8a57077ec04d2a23e59666ec
-F src/wherecode.c a3a1aff30fe99a818d8e7c607980f033f40c68d890e03ed25838b9dbb7908bee
-F src/whereexpr.c 3a463e156ea388083c501502229c2c7f4f5c6b5330ea59bdf40d6eb6e155a25f
-F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
+F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
+F src/where.c 4caf843825c6292440113258fefaa6f747fd570c6915628957e42e39529988f5
+F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
+F src/wherecode.c 9f1f65d11437b25cd0a1497a170514c785f19ce6ad9d3e6fc73719cb5a49012f
+F src/whereexpr.c 5a9c9f5d2dac4bcdcaae3035034b4667523f731df228e0bb1d4efc669efa9da5
+F src/window.c a6d624d83b2d5b3cfb82bb437a2fbae759c928d47dc9ad1338a9419269181bb2
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
@@ -638,33 +643,38 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 2f65ec8132e0ca896de550b9908094d49ad65a99116a9d79deeb6017604ad4f6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
-F test/alter.test 25e109787dc5e631e117eb6e1c57f96a572bb51228db3b4f8b5f41d665e2ccaa
+F test/alter.test f53d8a4ecd35f051c07e54a36beec5d0a30d30a9d98bc723f6cde6afbfb3c5ca
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
-F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
+F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
-F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
-F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f117ddf
-F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
+F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d
+F test/altercol.test b11fa1b131e80ab5b6ecfb3b725fb0419c14ca6efba5adb57aeabfc9baa0c8f3
+F test/altercorrupt.test 584d707a80e106952d6382790c8919bcf9f0db678ed3a1c09fd98b7f9d1d3a10
+F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
+F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
+F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
-F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altertab.test 6d7bbac2c4a6ef71b775094a3298fa3a92274d95034ee23157ffba92768e47e6
+F test/altermalloc2.test ca3ebc01670d9313953a2b7628d8cc00dc5ea9988f229b3cbbbe1cca506dae45
+F test/altermalloc3.test 059841a3de6b6780efd9f0b30bf1d9b4443c555f68d39975cbcac2583167b239
+F test/alterqf.test 67568ad152db8c1187b15633b801242cf960f1beafc51261a3d1725d910baeb2
+F test/altertab.test 466b9757630d68455080690b6e99c5ff11b199df4b3530e17f3df10a63aa05d3
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
-F test/altertab3.test 1db384eb85b4a30b0b332842f5c596b0dc0126f7c61959be3f85ae8b1c271d9a
+F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
-F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49
-F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
+F test/analyze3.test 4440c4932247adb2b4e0c838f657c19dc7af4f56859255436dc4e855f39b9324
+F test/analyze4.test 293ec8ea21525f3435beaf9d6b1efb29e719415f03a0cd2a70589d59098e8464
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
-F test/analyze6.test 6c3f7df2996cb6872f355a6ac1eb6d5de00a5a9288214bad7ef25c97d9cc72dc
-F test/analyze7.test 6ef0b12369f61ddeadc7d8a705c40e6b52cb29f63de3a4c56581b510b46b5783
-F test/analyze8.test 36ce54947710bd44e4f9484e1ad07e725ef01a9d7078b417c1bc884356febe4d
-F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54
-F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46eac710
-F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
-F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
-F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
-F test/analyzeG.test a48c0f324dd14de9a40d52abe5ca2637f682b9a791d2523dd619f6efa14e345b
+F test/analyze6.test 028f5bdfc9e5b5294768fa9a7185b8cd1d019aa7aab5b2f8ee42d7271d9a3b28
+F test/analyze7.test 079d17c495e396bdbd6cc6a083112788a6fbfb3b95c42e760e4270a53c9ead8f
+F test/analyze8.test 29ef237d8a59b39cc31c3310134fefe96a690b195e3deed5ecb652839089f15c
+F test/analyze9.test 162cd40d713310fbe7a63a5ecff5d3a013777d86809618838177d9b2af4dd09c
+F test/analyzeC.test 1111830ad355d29a294a5dda654dd5f6a8622c6a223a4f7b7b3d091df7a7a42b
+F test/analyzeD.test 485f621cfd2ef0a8f8ac79672586651bfa495bd899db50461bb4b558400ab3c1
+F test/analyzeE.test 69d130f9ba78c9853dcd5a18317e81f462a72d704cec0c4c30afb220213acd29
+F test/analyzeF.test 40b5cc3ad7b10e81020d7ca86f1417647ecfae7477cfd88acc5aa7ae1068f949
+F test/analyzeG.test 623be33038c49648872746c8dd8b23b5792c08fef173c55e82f1b12fca259852
F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
@@ -675,27 +685,28 @@ F test/atof1.test 10049623e77006691c4c2978c1dc8a3f75276377a53417811aa85bda7493f9
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
-F test/attach.test d42862c72fef3d54367d962d41dcfb5363442a4a1bd898c22ae950cea1aa0dd3
+F test/attach.test 54f8e49e88d0de48f6428267a678465863d2b8f72320612f35bd5c02e240bc2f
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
-F test/attach4.test aa05b1d8218b24eba5a7cccf4f224f514ba57ba705c9267f09d2bb63fed0eea1
+F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
-F test/auth.test 2154625c05bc79f0e0ea72cb2358395a8041243caa0fd7ce7617d50da4331794
+F test/auth.test 567d917e0baddb6d0026a251cff977a3ab2c805a3cef906ba8653aafe7ad7240
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
-F test/autoindex1.test 96185415f5faacd5b8d7a7f505efddd5abb1f111d58338e9c0b1dc40b87cd3cc
+F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
-F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
+F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
-F test/autoindex5.test a5d72fe8c217cc0ea356dc6fa06a282a8a3fc53aa807709d79dba07a8f248102
+F test/autoindex5.test ee0aa95e3f44190347a29a672c3d4ecf042e3f33c5fa3dc29f0ab6be057bbded
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
+F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
-F test/backup2.test 1fd1ad8c5b3d2d5b9c0cce4143a4fc610d51ddc6ae16a7a122973d43e6b50bbd
+F test/backup2.test 8facb54df1388419d34b362ab1f7e233310ff3a3af64e8ad5ec47ba3c2bbe5cf
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
@@ -703,17 +714,17 @@ F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
-F test/bestindex1.test 705b57d7f51d53ee5fd043dd9666236e1fc18f4d59abf51da0ea5ea1b4804947
-F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
-F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b7920b47b84
-F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
+F test/bestindex1.test 2e92e046148b3f8a2be62af9c0f307413547a33677af0df159c0fcc76e5134a2
+F test/bestindex2.test 60266e2854055788459cbfd86cef575601eabe74a2c61faba72601739fea4398
+F test/bestindex3.test e061a6ed0f519beee037ba7e7a4c37f80c8a7e4a303e2559ed1f760e4b0235eb
+F test/bestindex4.test 82250e7dcc6d5b15244edc9d6554b1760583af1b8548c2a255a1c4f28e744c0e
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
-F test/bestindex7.test f36ada201973d3022cf7afffffe08de9e58341996020e7a2df9a1d2f2be20132
-F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802
+F test/bestindex7.test a11348824aed0de2bb9030f092636929000cd72882bdf919adacc3792f67ccbd
+F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
-F test/bigmmap.test e906cf9729d7c362270ffe9fa6471f4c39c28ba83f0f77fb795e1b4d38a22ba0
+F test/bigmmap.test b820c234daa56d24bc3bf006e3ac7aa9d9623c8ac656a38f59063b444a2d65d1
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
@@ -732,7 +743,7 @@ F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1d6cc
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
-F test/busy2.test 0a1633fef7987fc8ea25ed5838f7eef2f08fc6d2a3dcc77d23e6402e53946a7a
+F test/busy2.test dbfb61b3265e7a962d3bcd32cd542bbe3d7801edbda6438d35af5aa707cae981
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -764,6 +775,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
+F test/columncount.test d86fb6307261186370698962790ad2088ed419e4a4e823512b502f17d443b1b7
F test/conflict.test ac0667090f66130ac77d5fb764655558ca6600dd6d88f670ca9123b61c448337
F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87282dd1
F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac
@@ -771,7 +783,7 @@ F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
F test/corrupt3.test 2520432b1fbf99994841e69804a3c59fb828183f4d09b85a1631bc7adca17e31
-F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
+F test/corrupt4.test b5ae41607e8d17d9c1f3e94fdb572ce061ed3beeebdb46fb3a348181b8c8a097
F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
@@ -788,17 +800,18 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
-F test/corruptL.test 22589f503602cc5984e80f27f46c4de2134f24f1515ba2440513c377cb692258
+F test/corruptL.test df132ba9ffd6fa15038380b4154998b9904ab8f1ea78400d7da53c920cb3b13d
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
-F test/cost.test 1d156ce9858780a966c062694687afe0343a0ed12d081d071fb57027e726bafc
-F test/count.test e0699a15712bc2a4679d60e408921c2cce7f6365a30340e790c98e0f334a9c77
+F test/corruptN.test c2a96ff81386027f7d7e95858783aa36f82ba1532106969575e3c8f90903a5bb
+F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
+F test/count.test 5364003488249957750a5f15ee42ca1cd7b100b1131c2dc71fff266a1250bf55
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
-F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
+F test/coveridxscan.test f35c7208dedc4f98e471c569df64c0f95a49f6e072d8dc7c8f99bdee2697de1b
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
-F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
+F test/crash5.test 4aa55e7ac3c4bc511873e457aa65d2827d52da9b51e061511899dadcfe22b1e8
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
@@ -812,45 +825,45 @@ F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
-F test/date2.test 520a1708e4e14c682cf514560f3e9f2e5affa9d66560fbc2a6941ae291260daf
+F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
-F test/dbfuzz2.c 40cc4600947f30600f0ab365a2714ec76a899c9adb2c0ccd63ba583b2f71390e
+F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
F test/decimal.test fcf403fd5585f47342234e153c4a4338cd737b8e0884ac66fc484df47dbcf1a7
F test/default.test 9687cfb16717e4b8238c191697c98be88c0b16e568dd5368cd9284154097ef50
-F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0
+F test/delete.test 438c14fdf2f2a520b63f892ea645896acf8832e2a2308578593d8e05274314b1
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
-F test/delete4.test 6aa279f459f4aa792cc251435c3809415c1ecaf9f27dce91675e26f05b503db3
+F test/delete4.test 51fafebe9503a40796d1aae1565c60524cada720e50eecac01b7fd0419d9ea0b
F test/delete_db.test 096d828493c7907f9ea11a7098ea6a0f73edba89406487d5d6cc2228dc4ab8b0
F test/descidx1.test edc8adee58d491b06c7157c50364eaf1c3605c9c19f8093cb1ea2b6184f3ac13
F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad78298
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
-F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
+F test/distinct.test 3e4210ef9cd1985aeec44939ad912c4621fbea9bb4a9c565696cebfe184b2ec5
F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1
-F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
+F test/distinctagg.test d76ef2e91fe810630c176d6bd0a58c14d5851c3125f0a1d977db87ba76359639
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
-F test/e_createtable.test 7107f5deda2324ea12dbf105044dc9265195401e9dbb3eead6a2c1a3da4bb5b7
+F test/e_createtable.test 7997c0106c181243e0ac7db7ba8b9ae7233d0bfb0188605650322a7a02ea326e
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
F test/e_expr.test 6ba7a51ece7b3e7fc145f14f924eed25ebb5a24e7b8596c78f3838d372cf0385
-F test/e_fkey.test 0b458b85f192cdb9e9933d5891848bb19bcc44d3f49faf111a375f2844a164d3
+F test/e_fkey.test 351c7b989e5aefcc339ef5fc78dc4738442bd247a392cd67d81c2881000c369e
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
-F test/e_select.test f9474205669a7736ef725b29cc7ae9e8601919a3d0ffc0ab30745a028f2a4b61
+F test/e_select.test c5425a423da06d0494119db8361ebfc6de302929f7546ca596d56224137e0360
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
@@ -865,7 +878,7 @@ F test/enc.test 9a7be5479da985381d740b15f432800f65e2c87029ee57a318f42cb2eb43763a
F test/enc2.test 848bf05f15b011719f478dddb7b5e9aea35e39e457493cba4c4eef75d849a5ec
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 84879b63e3110552bf8ce648a3507dc3ceb72109ecec83c2aef0db37a27f6382
+F test/eqp.test bfe979eb1f4b8ab7a3bd7db6d16c2e6c6be0e5a3aada2227716f3fd3a9d76b69
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747
@@ -874,7 +887,9 @@ F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
+F test/exprfault.test 497cc0b8fe6a677f49b55cb485e040f709ec2834b84f25912fe9c2dfeeda33db
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
+F test/external_reader.test c7d34694f1b25c32d866f56ac80c1e29edddc42b4ef90cad589263ffac2cde0c
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
@@ -948,7 +963,7 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220
F test/fts3atoken.test dc2078ce464914efe3a8dfc545dd034a0fc14f2ab425c240471d5a5f1c721400
F test/fts3auto.test 649aa4c198d7acc5cd6355e19ee073d051c40d9e88a43fc3d88af46bdf3e99d5
-F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
+F test/fts3aux1.test 1880eaa75c586cd10f53080479a2b819b3915ae7ce55c4e0ba8f1fe05ac0a6a7
F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977bf907f
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
@@ -957,9 +972,9 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6
F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test e4662d37f02248301d8b58778eac380663e09a17a38dd5d6bb5ea4c927b9a575
+F test/fts3corrupt4.test 1b3333822577b0888c95de8490a1a6152c47cb33a763fe62c54825202c31812f
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
-F test/fts3corrupt6.test b6c55218b704b0cef224b284c756f9c55d0afd0b3c3837618bffeaa8c31e0d8e
+F test/fts3corrupt6.test 657b4b8e5791d8d4adc93c90588fb25f1c7346544dd877c6c298a0746749146d
F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -976,7 +991,7 @@ F test/fts3fault.test 798e45af84be7978ca33d5bdc94246eb44724db24174b5d8e9b1ac46c5
F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11eb18aaf56
-F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
+F test/fts3join.test b285c919559af5b093c51abb2c07ce7ec0156dbc9573f444b78dabd9f3040db2
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
@@ -985,12 +1000,12 @@ F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
-F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba1654e78f
+F test/fts3query.test 45806a302921b245a9dba5d85c9d51fb98b3f137eea6e6bf6eae4883e041ab72
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 0887196d67cffbe365edde535b95ecc642a532ce8551ccd9a73aab5999c3ffae
-F test/fts3snippet2.test 2dabb5889eda4c9980aad325e688b470781f97ce7c0fca0db125616fae0a2cdd
+F test/fts3snippet2.test e79afeb1f673713f96d7fc5655726081975399d11e659d15553207be43301dc4
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
@@ -1014,17 +1029,18 @@ F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb
-F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3cfd0c880
+F test/fts4rename.test 2e0565ffd92b2c51f1a757df0b8f2ca30537197106fec09e943919801d173692
F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
-F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
-F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
+F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
+F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
-F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
+F test/func.test 77f6ea02c97d9ea64074461d347276a75df22d2cf51045a40f90857569e985f0
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
+F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
@@ -1032,7 +1048,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 5f81f2cc65f13068620245f2e2c6059657d3b26be476df379ae2da539f17676d
+F test/fuzzcheck.c 37f09efcd982048694d8b06fa3ef817df17f2a82e90af85cb3fb8eddd0f57ec4
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1040,17 +1056,17 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
-F test/fuzzdata8.db f8451a1fd38efbea8c1a7cdf5d02259c4702446a9fabf566becd306b64a50236
+F test/fuzzdata8.db 9e0123ce3df47d1f159f7b71d60b96bd8b89800a40ab081c5402167d7239ead7
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
-F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
+F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
-F test/having.test ea5cb01cdf3d90fd1b516ef36b1fbde518dbbd61c50141f5eb830d8101844040
+F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
-F test/hook.test e97382e68e4379838e888756d653afd159f5f14780315ff97b70360d3d8485bc
+F test/hook.test 55b6d605d06dadbb04416eae8ad79889aea3521d119c87f04353c25f9c1450a4
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
@@ -1058,9 +1074,9 @@ F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test 65460600d48933adba4283c6ebd089aae173d16136ab9d01f74c89089090c5a5
+F test/in4.test addf1416fdbbcf2f082ab7974e4813f38b4759b95699a683a31c37a3fffe7b57
F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f
-F test/in6.test 8562d0945195cab3cc4ab3794e9118e72cb44c43f785c2b04d48a9d06ca6b4ec
+F test/in6.test f5f40d6816a8bb7c784424b58a10ac38efb76ab29127a2c17399e0cbeeda0e4b
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1068,7 +1084,7 @@ F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
-F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f97d4a2b
+F test/incrvacuum.test 3fa6145f5e71f603554fd7b8ec3da4290b1341029682313285cb5f9e1893d6ba
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
@@ -1077,13 +1093,13 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
-F test/index6.test f172653b35b20233e59200e8b92a76db61bf7285437bf777b93b306ba26a47e7
-F test/index7.test b8a0ba2110fd517bb48c4e76d26d60f1ab2ed9e257b18d71f820d7e71e9f8570
-F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
+F test/index6.test 5a7ab531c692ff3b3d139ef8ea6709fab40f9c6862ed418b4976752a5481da3a
+F test/index7.test b238344318e0b4e42126717f6554f0e7dfd0b39cecad4b736039b43e1e3b6eb3
+F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a912a3
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
-F test/indexedby.test f54aac21c06948872010a956fd02de5178c362c7785a9887cf0b8616be17883b
-F test/indexexpr1.test 284e119999d132cc8bf37735a928c9859b28e8e295d02b7a6a4f93977c7f9ba5
-F test/indexexpr2.test dba11dbb0a58fcba4cd694f46b4004976123b81b0501f525d43c9be59f0207b1
+F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
+F test/indexexpr1.test 7e0e7a33acb4d9b3524398e6ce90cc05c26603fabbaf3062083a036c8874bc12
+F test/indexexpr2.test 2c7abe3c48f8aaa5a448615ab4d13df3662185d28419c00999670834a3f0b484
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
@@ -1097,7 +1113,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
-F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
+F test/intpkey.test aee694afed1a65c86c4e69ad030224b3fc268113d00685234d40079fca16bad3
F test/intreal.test 2a87e85a5949bd55e41ef04c58f5800587c5380bdbc559ff1c79b614b0e6a533
F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc
F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b
@@ -1108,10 +1124,10 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test 9619a2d77580f676048aaff7a16a0bcfea2b96c6c660dfaded2e53c873418899
F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238
-F test/join2.test 21fc30e54ab35ed66bf51b89cec18729205497f5cc43c83bc042f96a73721593
+F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
+F test/join5.test f418fccdfefa41f1659663463aa517431ddcf3e30ccbb80e64173b7d615a03f4
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
@@ -1129,10 +1145,10 @@ F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
-F test/like.test 47b81d5de2ff19d996d49a65d50ec9754246aacbe0e950b48d186d9d8171eaf0
+F test/like.test 5fe0bc37f307aef0a453ce2de4632bdfc0759448f0421c39f6d53caefe905fac
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
-F test/like3.test 03d1bdf848483b78d2cfd1db283d75c4ec2e37c8b8eccc006813f3978d78fbbd
-F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
+F test/like3.test a76e5938fadbe6d32807284c796bafd869974a961057bc5fc5a28e06de98745c
+F test/limit.test 350f5d03c29e7dff9a2cde016f84f8d368d40bcd02fa2b2a52fa10c4bf3cbfaf
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
@@ -1166,7 +1182,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
-F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c083707ab
+F test/mallocK.test 25897506da0098cea09b302ff432b0fb6d8002773c1e0fc9732aa8b444bfd455
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
@@ -1174,22 +1190,23 @@ F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0f
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
-F test/memdb1.test 58d92c2bf622cc5f0f41461e1b35cf64f3f787199544c2c1dada37d88753f9d4
+F test/memdb1.test 7b76c3262d63c46dd6b408d18f5721071776f2df4ffeb11e668824e427127594
+F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
-F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
-F test/minmax2.test 1edf66901ddfab26ae1e04165e8da834c8d3284e2b20aefb26b80ef217962eab
+F test/minmax.test 0015e5cd5e7af48bb3364f26d9f3a9cdbea2a442d4774281c39e2229591b7351
+F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599
-F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
+F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 7b4c88c1d5ea8c8b9d537d212c08a0343d345fdd5c789598692c1c0e60fbda69
-F test/misc8.test 8782708f4c8a459591c3e8fe1215bd2048bffb4024b3df249e9b9ed407dc61ed
+F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
+F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626
@@ -1212,16 +1229,18 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
+F test/notnull2.test 131365171d973c57fe694fcc46c1e645f6e24ceb43b230ad5011a0ea2182f215
+F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
-F test/nulls1.test 82c5bc33148405f21205865abf13c786084438d573a4ac4e87e11b6091cde526
+F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/optfuzz-db01.c 9f2fa80b8f84ebbf1f2e8b13421a4e0477fe300f6686fbd76cac1d2db66e0fdc
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
-F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
-F test/orderby1.test 6bf0ce45cbfb1cf4779dd418ac5e8cf66abfa04de2c1d2edf1e0e85f1520d8f3
+F test/optfuzz.c 690430a0bf0ad047d5a168bf52b05b2ee97aedaad8c14337e9eb5050faa64994
+F test/orderby1.test a4bba04b9c60a21e53486fbc173a596b29641a3b3a57a0f26a1cbef1360358e9
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
@@ -1235,7 +1254,7 @@ F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6a
F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test 293c7ad1f19a07e548179b97534c6588249d4e40058b378ea26e75cc84d936f5
+F test/pager1.test a4e438c344663ad7f0bf6e880cacae7531bdf7d960db15a3db4751273ecee06d
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -1248,7 +1267,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 661a4325a5717957a77836910ee164ba26594a502d7a3df0e1ae7b9cba829c5d
+F test/permutations.test 63da39a4234eed2ccd10bf7872de58e24d53a50d11014dc8a8ab9f252368e880
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test 50b91bedea9324d3ab48e793f908ee7d2c7dcf84bfa2281e792838be59641ec8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1267,35 +1286,36 @@ F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
-F test/quote.test 3f9238ab0e1db70dea89af9afa5859dbd759b0ce0a63da67d547553e2c316475
+F test/quote.test b8ddaba6b81dcf63bb31243219e28a2f96e04396adc50108cc7e5593019c3eb5
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79070d
-F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
-F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
+F test/regexp1.test 0c3ff80f66b0eff80e623eb5db7a3dad512095c573d78ac23009785f6d8f51ce
+F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
-F test/releasetest.tcl fb76d8fcc95ac29d6356cd9e52b726ab9e43a24082897618dfbcb7c2b0049153 x
-F test/releasetest_data.tcl b9cb30360759b80d92d4ea86b84ebfd8035b97f9078a482deb3cf9d0b2442655
+F test/releasetest.tcl 6f803ef0b896f8f3f4c26eb072c0399963a5987a509a64d45f5dfbc1ebae2951 x
+F test/releasetest_data.tcl f88ed29aa18366ed3956ace36c96ec6868ef5b9ee04cc05d32f4d81031e19e28
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
+F test/returning1.test 52b4ed60f104a4ce85b38417e5319b2078b2b908c71a768d539cee3c0ce8bdc9
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
-F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
+F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab21e
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3
-F test/rowvalue.test 8964f95b253d3b5cc8dc1cfd0cdb7529bce3ecc6b6259e23c5f829f80f4d51cd
+F test/rowvalue.test 37effea4dd83555ea969a9461dfcffb25e6731a5db7c388e232410999c100853
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
-F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
+F test/rowvalue4.test 441e7e366ac6d939a3a95a574031c56ec2a854077a91d66eee5ff1d86cb5be58
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
-F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
+F test/rowvalue9.test cb5380df82dca9db463081e26952c1e097b34fc2c2ac87453970c048d97df687
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
@@ -1307,7 +1327,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test 874e35011779b07725a47dbf1dd6282b0ca04af7e028fb0b534ee544b571be42
+F test/scanstatus.test 9a0ed37ab6d57b50567282788fffdf832d9b16739ecc41bff9d77a8d767cf317
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
@@ -1317,19 +1337,19 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce
F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e
F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 0ed936740777f52858b6607f39ffac4b2b63b8fc7edf3ab2ebad3c3553ceecee
+F test/select1.test 3d23f66bf9ba77570acfe2ca5f1540ece17037cc64ab1a00efec9758ac29c268
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
-F test/select4.test e8a2502e3623f3058871030599a48abb35789d2244d5b380ecf3696873fdd4a4
-F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
+F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
+F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae
F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
-F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
-F test/selectA.test 68de52409e45a3313d00b8461b48bef4fb729faf36ade9067a994eae55cc86f4
+F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812
+F test/selectA.test 985df11dfc58dedd6f8124dea32754566346b93e294f26291b5c96d10c8cc889
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
-F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
-F test/selectD.test fc20452847a01775710090383cfb4423275d2f745fed61f34fbf37573ac0d214
+F test/selectC.test fec14c9015ed4ec941508bbc144f30b42e40ac34a4bb33001450369865dd0b75
+F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d32189bfb
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
@@ -1349,10 +1369,10 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test 0ba53c72545de142e1b76fa793ee33293134aa02abb9b50b35398670481ea661
+F test/shell1.test 56a7358a2a05e850e9e4aa24629db9c8975e8038dbe8debd2d95be22a5f03612
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
-F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
+F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
F test/shell5.test 84a30b55722a95a5b72989e691c469a999ca7591e7aa00b7fabc783ea5c9a6fe
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
@@ -1362,11 +1382,11 @@ F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
-F test/skipscan1.test ed524bc86f27646b3a297f45d6557b55db338977b6838f8064b196b35848b31b
-F test/skipscan2.test 3eb703ce794f139e7b83567911046298bcde29606116727f9b700ce34f559d2d
+F test/skipscan1.test 1a9972e1dc15ca3887f306d3cd9a29679afb382eca0f3539f3b746f3c2ccaf68
+F test/skipscan2.test c588cb7ed947db724d300f2a0dc537dd2ad292b0f812641d8481bc0b95dd3f49
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
-F test/skipscan5.test 980875ad45d8aacfe7bdec7c288343520cd1d14e84befdcfe50c785f9e6c8709
-F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
+F test/skipscan5.test 0672103fd2c8f96bd114133f356192b35ece45c794fe3677e1d9e5e3104a608e
+F test/skipscan6.test bddbb35dd335e2d21b7791a61e3b2e1f3255dc307ce80aa6fe19cc298e6feb13
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
@@ -1390,14 +1410,15 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
-F test/speedtest1.c 849dbcb0bded9f966e43f28e8ce824b2915cb5dd0031a2e85996f7e3de36c2b1
+F test/speedtest1.c 5e5b805f24cc939656058f6a498f5a2160f9142e4815c54faf758ec798d4cdad
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
-F test/sqllimits1.test 264f4b0f941800ba139d25e33ee919c5d95fea06dfbe8ac291d6811a30984ca5
+F test/sqllimits1.test 3f9030e5d35375ad3b912b4908094aa806335c8e9d804b8ffff70c5e9c664ab2
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
+F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
F test/stat.test 15a3106eddedfc882f64bc09f237b4169be4b92dd57c93031b8ff8b13af3e7c5
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
@@ -1419,7 +1440,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 5ca6d004157a3e886a55a9387b960cc0db41acd88753eb597ff409ec6cfb1be0
+F test/tabfunc01.test acb5be558868c65d8cf3495539fff23093d77139eb1e4e8c4580568099f98645
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1431,7 +1452,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl 754521f0db534d51ab504b2d14fe0bdca1f1c15de731ceb8ee5bfd78372a2a5f
+F test/tester.tcl 19d2a19a6dd55a2b4e2b943963959a05a2c088495dd5f5274b04e0494ce86d66
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1444,6 +1465,7 @@ F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
F test/threadtest3.c e63013af10cf236c7610eb06d33bde08c861806dc64be811940ff4d9ddd34a4f
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
+F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-18458b1a.test 6a62cb1ee50fa3c620da59e3a6f531eb38fceaf7e2166203816b724524e6f1d6
@@ -1453,7 +1475,7 @@ F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
-F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1
+F test/tkt-385a5b56b9.test 81d7c8ef2d2a378323ba2190c1f02f91022fdff0d8d0b84c04954d02c85ef374
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3a77c9714e.test 90e3e8455ee945a4076d4c44062b8845708af24a880355328fe7008f2047c9f0
@@ -1468,7 +1490,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
-F test/tkt-78e04e52ea.test cb44d0f5e7940223be740a39913a1b9b9b30d7e4a17ed3349141f893bae1b8f2
+F test/tkt-78e04e52ea.test b731f2ab7d1c2482ac5152097da02ef4805a45147ba9498d3cd9da27072f34d1
F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
@@ -1487,7 +1509,7 @@ F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
-F test/tkt-b75a9ca6b0.test ade89229d853a67a21bbd5e6e1e787a8f9d21f19908d1b7fca6bf3d4d5aa0767
+F test/tkt-b75a9ca6b0.test dc6a853c242f7d0326564ae32e9e5eb462b5e8d2bc5b01ea3b18fd24f8e5894b
F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
@@ -1553,7 +1575,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
-F test/tkt3442.test a1fc47c669e651d16494de3ff349bcb53281456f2ca02c8bc14220b6044bbfe8
+F test/tkt3442.test 6287173de5bb2d43693b1f822426018a209f9df49ce2f454808bac1771852330
F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
@@ -1589,31 +1611,31 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
-F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
+F test/tpch01.test 4479008f85f6f8f25f7ab2cb305d665752b4727fa28a8df3d8e0ad46520c62ff
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
-F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
+F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047f31
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
-F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
+F test/transitive1.test 06bcfeeb2ed719abf6ae582f9f65a6b07642dd1363fa648ae9a74a35e83a825c
F test/trigger1.test d30cd09ae8ac365a088f09daba583cc5c0b8fc7d4e1d70809d0b4be3bf6ae2ab
-F test/trigger2.test d15da46f7012832faf3e0c536b47024409d5fb1722d2bb77e29c06d96d704bb1
+F test/trigger2.test 6e35bd7321c49e63d540aee980eb95dec63e1d1caca175224101045bcc80871f
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
F test/trigger7.test e7ce54bfda67a88d778aea42544e151c465547a7e617127b6914c2221a6d53c1
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
-F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
+F test/trigger9.test fd49aff8b724ae1a6238989ecf84320d88c0e8f8d9142a891b93f826dfe37b59
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
-F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d
+F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
-F test/triggerupfrom.test d25961fa70a99b6736193da7b49a36d8c1d28d56188f0be6406d4366315cd6e4
+F test/triggerupfrom.test d1f9e56090408115c522bee626cc33a2f3370f627a5e341d832589d72e3aa271
F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f49edef1494
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
@@ -1624,23 +1646,27 @@ F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
+F test/unionall.test fee6e6adebe5446938475432ae8b042835a286c7e2efdc1b186d2182dfb93ffb
+F test/unionall2.test 71e8fa08d5699d50dc9f9dc0c9799c2e7a6bb7931a330d369307a4df7f157fa1
+F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
-F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
+F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
F test/update.test e906ca7cb1dc6f52af1ea243e08f727edfa79f924c2691f2f9e72481f847310d
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
-F test/upfrom1.test d18f69f7c691bc791e7f31bf0e354eeff04cf2f44edc32d6b1928bad71697073
-F test/upfrom2.test 6ebd3be8c3fac984e89a177d823686f04605b512fc167392bce6d8ba2ba63325
-F test/upfrom3.test 7dab379d128e8dd7beb2055b295fb113c7ba93e8c2038f5ddb7a4a10f0ebb348
-F test/upfromfault.test 70ecf8eb85559727a487283f69374e3ae39879e994d8a2437c49d7c05ecb70c9
+F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
+F test/upfrom2.test f92e47bfc35e9410d3e8716ee626384e89ad026c55fd6148508ca9d707521673
+F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
+F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
+F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
@@ -1648,15 +1674,17 @@ F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum-into.test 48f4cec354fb6f27c98ef58d2fe49a11b71ff131af0cd9140efacc9858b9f670
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
-F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
+F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
+F test/vacuum6.test d3173a54edc81d13d99e4cf4972232b3cbb52f1d56ed48c3a939ef4e751c1ee8
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
-F test/view.test fd48eddb32a35a98c3de70062ebac66ebf4a2bbfc75a1cc1109159ef8bfc47a9
-F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f
+F test/view.test ea88361d5e9bc8eabf9f573185a16aea73a885be9b6c6a95ae84908913416a80
+F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
+F test/vtab1.test 99c0c13b5336ca7f87f137459de144b2f396bb8563fbd602e46bfaa425e3d8cc
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1678,7 +1706,7 @@ F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c37
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
-F test/wal.test 16180bc4becda176428ad02eaea437b4b8f5ae099314de443a4e12b2dcc007a2
+F test/wal.test b7cc6984709f54afbf8441747ced1f646af120bf0c1b1d847bfa39306fbea089
F test/wal2.test 31f6e2c404b9f2cdf9ca19b105a1742fdc19653c2c936da39e3658c617524046
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
@@ -1709,43 +1737,44 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8
F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20
F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
-F test/walsetlk.test 11f7fe792fdce54cf09874dab824e0627f2eedecfb9f7983e325606ec5184e0c
+F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
-F test/walvfs.test a2913001a83b19c1d20220e556cee14d87d47ecb6949b5e0a2e9e2590abecf1e
+F test/walvfs.test bccb3e0d235ef85e276f491d34db32c9ada1ea67be8d9f10aabe7b30319ec656
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
-F test/where.test e713c0c64e3e6b062235e39a2f7e5508c517df16b63d69fd786e26bc7330b1c6
-F test/where2.test 478d2170637b9211f593120648858593bf2445a1
-F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
+F test/where.test 4f7a3939e5190845ef42142031a1819070f65e065e6a840a09adc54dccfef01f
+F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
+F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
+F test/where7.test ab41d53ce8f2a6919ea3d5b13cd1153c1375a8e3ddaa129b81781f9033981383
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test 8e3e0ff42cc17156f52361a1c012281550d0d632912fec92d1d6df74db7a8e6d
+F test/where9.test 1ffb75edc50a8faa6e7bd77f8221d783febb00b44b0bdb32fb48cec6e38eca95
F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
-F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
-F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 77127a4d214bb21da3b5c695cf4106cd9e418c60d9c24471ba55d3772067cd35
+F test/whereE.test 0ac7e61c6225354a980666996539da154991b4325af943a25a9079079c82fb03
+F test/whereF.test 926b65519608e3f2aa28720822b9154fb5c7b13519dd78194f434a511ab3dac5
+F test/whereG.test b2a479f425f7d0a432df7e842e8484560908ef703fe0fd407888ff85e7097238
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
-F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
-F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
-F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
-F test/whereL.test e05cedc9389c6f09ad55bd5999a3fddccebec90672fb989433c145dcdaf26996
-F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
+F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581
+F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf
+F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a
+F test/whereL.test 50171e3ec00b4c8ad5ec773119a35d9e9642cec45154b44c366d628326479f4d
+F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250
+F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
-F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
+F test/wherelimit.test afb46397c6d7e964e6e294ba3569864a0c570fe3807afc634236c2b752372f31
F test/wherelimit2.test 657a3f24aadee62d058c5091ea682dc4af4b95ffe32f137155be49799a58e721
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test e52b81fff0c3cb122a1240f336688eb81bea2967a99c4ddb78969adec7aadc2a
+F test/window1.test 49eadb28b0bae0f916518c9983b1fb7450c198915664f323b2bfc480cc98c431
F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1756,32 +1785,34 @@ F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652
F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
-F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2
-F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b
-F test/window9.test 4d8c875b73febdbac9b8f2b52ec132b98f48261cdafd6b08db62bc6d8ff913fc
+F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c
+F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
+F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
-F test/windowB.test 7a983ea1cc1cf72be7f378e4b32f6cb2d73014c5cd8b25aaee825164cd4269e5
+F test/windowB.test 6e601f8178ba8ba28b2f19e74fe613815084bb4a8d2ad942defc7d42e191e521
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
-F test/windowfault.test 72375ae71031eabf96bc88d0af128c8628a091ddc99b5a394e848b3df5fc17ad
-F test/with1.test 780be387f01e290e768bdfd1827280f9e37ba37223eb4736aba386864fac5a94
-F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
-F test/with3.test a261f0ea225c4af0ce6447f1157bb603959b2a665f14a03951c2883d2ef1c0f0
+F test/windowfault.test 21919e601f20b976ea2a73aa401220c89ed0e8d203c4f69476ea55bce3726496
+F test/windowpushd.test d8895d08870b7226f7693665bd292eb177e62ca06799184957b3ca7dc03067df
+F test/with1.test 7bc5abfe4c80c0cef8a90f5a66d60b9982e8ccd7350c8eb70611323a3b8e07ba
+F test/with2.test bbf82609bbacc0a7a01d822022aed7b2fa702436dd3d0ecf942023564d2bba13
+F test/with3.test ad32d13ad50661e6fa305f62a0717649c348792e7b658bf2644976227a9e0373
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
+F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test e4034c0849ccc2e8bb749c69f15bd69bb9fcf8fe77e8d17ce02369604242fe83
+F test/without_rowid1.test 6abc5d497f634520944dac0a89a6c240a48d2ee0f8353356a750eb70dc1db41a
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
-F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e
+F test/without_rowid6.test efbd7add62c59bf5ca97bf8da674e734e6a70ef979234e816166824b4d258f68
F test/without_rowid7.test d7c59a93d726b55812d620f8f284e01904a5b85f9ee9eea8f2f68571a5e8c40e
F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test 429cb81c518487fa1b644b6b04b6e9af704a4fa767bd1a110204c5f03b2e8616
+F test/zipfile.test 0d8758d8c0d63f16644f959689f78969d223789d998964276554039f067b4548
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
@@ -1805,22 +1836,23 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 70eedc31614a58fe31a71025c17ebd1502a6ce9cfef0ed5e33acb0b5b737b291
-F tool/lempar.c 0e1d5eeb9736108d3dba782a9dd56f4e7cb69006b6ee181308b7ebfb15313a12
+F tool/lemon.c a5acddd3eec6a388872aae6efc7563336348a9c45e5563642f77e8e3a50e859d
+F tool/lempar.c 1d3d075da18681c67ecc66c1f171e7094e18cd2cfba6a8a1bd4f3f639d6656e1
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
+F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
-F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
-F tool/mkkeywordhash.c 11a3f3af8e787d0c5ca459ed66fe80fd09e661876506e7b978ec08c19477bdc2
+F tool/mkctimec.tcl 06b0d503ee0e6c2d4abe83563b43d4925a12e31ec9fb3249ce39661f53fbd1ce
+F tool/mkkeywordhash.c 08b6e4d7a482a7f37a9a0032e7ba968e26624a027b6b2e9ba589be6f5e3d8c2c
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
-F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
+F tool/mkopcodeh.tcl 130b88697da6ec5b89b41844d955d08fb62c2552e889dec8c7bcecb28d8f50bd
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
-F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
+F tool/mkshellc.tcl 5fe7e518112b262e25726f248c0f33dd153192867453984b6af0a76a88e97cb2
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
@@ -1829,14 +1861,14 @@ F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
-F tool/omittest.tcl 6616fbf384f0f630113eab27d41d4530435dd94e2883307759988b45f0604a3b
+F tool/omittest.tcl 3d222272b1d840b4e3d67bff0cb743ce3f633faddadb3702b2056b726775db8f
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
-F tool/showdb.c 49e810f5c414c792b5bf38cd5557ca9639713ebfef32aaff32faf7cb7ccce513
+F tool/showdb.c 7cc12c6deeddfe40ba5d948b408730696d8365988da05fcb6b6a90ea4965e2b4
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809
@@ -1851,7 +1883,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
-F tool/sqldiff.c 4151108387cb56c08906e5ac8d6a353dcfe8fc6014eeded0f0910e2230ea0f5b
+F tool/sqldiff.c 21226ef092ec1e543b237c5d3d2d32d344a60f2437eadfea04f65b348fbd00e4
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@@ -1886,11 +1918,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a1a7a5f238fcfdcd56faba063e381258c9e2944d9b02b31d402a4207a607fc1c
-R 58ed0e2a70acf908b3c6a7c54bbafc77
-T +bgcolor * #d0c0ff
+P 7bd55eee1ac63cf6d5699ce85bc5a29bf51afdf7a80bce44937fa833947a40f4
+R 6b8a0a7cf847af9edb1fb9387491b821
T +sym-release *
-T +sym-version-3.34.1 *
+T +sym-version-3.36.0 *
U drh
-Z 11054c73a336ca8fa32ae8cddcafd46b
+Z 05ee2bbc3eef4148ab2800c954a168c4
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 4bea651fb..ef5b50a93 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f
+5c9a6c06871cb9fe42814af9c039eb6da5427a6ec28f187af7ebfb62eafa66e5
diff --git a/src/alter.c b/src/alter.c
index f4098863d..f998b893c 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -29,8 +29,9 @@
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
- if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
+ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || (pTab->tabFlags & TF_Eponymous)!=0
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlite3ReadOnlyShadowTables(pParse->db)
)
@@ -49,15 +50,22 @@ static int isAlterableTable(Parse *pParse, Table *pTab){
** statement to ensure that the operation has not rendered any schema
** objects unusable.
*/
-static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
+static void renameTestSchema(
+ Parse *pParse, /* Parse context */
+ const char *zDb, /* Name of db to verify schema of */
+ int bTemp, /* True if this is the temp db */
+ const char *zWhen, /* "when" part of error message */
+ int bNoDQS /* Do not allow DQS in the schema */
+){
+ pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
+ " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
zDb,
- zDb, bTemp
+ zDb, bTemp, zWhen, bNoDQS
);
if( bTemp==0 ){
@@ -66,8 +74,32 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
"FROM temp." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
- zDb
+ " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
+ zDb, zWhen, bNoDQS
+ );
+ }
+}
+
+/*
+** Generate VM code to replace any double-quoted strings (but not double-quoted
+** identifiers) within the "sql" column of the sqlite_schema table in
+** database zDb with their single-quoted equivalents. If argument bTemp is
+** not true, similarly update all SQL statements in the sqlite_schema table
+** of the temp db.
+*/
+static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." DFLT_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix(%Q, sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
+ );
+ if( bTemp==0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE temp." DFLT_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix('temp', sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'"
);
}
}
@@ -76,12 +108,12 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
*/
-static void renameReloadSchema(Parse *pParse, int iDb){
+static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
Vdbe *v = pParse->pVdbe;
if( v ){
sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
- if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
+ sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
+ if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
}
}
@@ -230,7 +262,7 @@ void sqlite3AlterRenameTable(
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
- " sqlite_rename_test(%Q, sql, type, name, 1) "
+ " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
"THEN %Q ELSE tbl_name END "
"WHERE type IN ('view', 'trigger')"
, zDb, zTabName, zName, zTabName, zDb, zName);
@@ -249,8 +281,8 @@ void sqlite3AlterRenameTable(
}
#endif
- renameReloadSchema(pParse, iDb);
- renameTestSchema(pParse, zDb, iDb==1);
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
@@ -381,11 +413,14 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*zEnd-- = '\0';
}
db->mDbFlags |= DBFLAG_PreferBuiltin;
+ /* substr() operations on characters, but addColOffset is in bytes. So we
+ ** have to use printf() to translate between these units: */
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
+ "sql = printf('%%.%ds, ',sql) || %Q"
+ " || substr(sql,1+length(printf('%%.%ds',sql))) "
"WHERE type = 'table' AND name = %Q",
- zDb, pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zDb, pNew->addColOffset, zCol, pNew->addColOffset,
zTab
);
sqlite3DbFree(db, zCol);
@@ -409,7 +444,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
/* Reload the table definition */
- renameReloadSchema(pParse, iDb);
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
}
/*
@@ -509,7 +544,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
** Or, if pTab is not a view or virtual table, zero is returned.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
-static int isRealTable(Parse *pParse, Table *pTab){
+static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){
@@ -522,15 +557,16 @@ static int isRealTable(Parse *pParse, Table *pTab){
}
#endif
if( zType ){
- sqlite3ErrorMsg(
- pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName
+ sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"",
+ (bDrop ? "drop column from" : "rename columns of"),
+ zType, pTab->zName
);
return 1;
}
return 0;
}
#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
-# define isRealTable(x,y) (0)
+# define isRealTable(x,y,z) (0)
#endif
/*
@@ -559,7 +595,7 @@ void sqlite3AlterRenameColumn(
/* Cannot alter a system table */
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
- if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -585,6 +621,10 @@ void sqlite3AlterRenameColumn(
goto exit_rename_column;
}
+ /* Ensure the schema contains no double-quoted strings */
+ renameTestSchema(pParse, zDb, iSchema==1, "", 0);
+ renameFixQuotes(pParse, zDb, iSchema==1);
+
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_schema table.
@@ -613,8 +653,8 @@ void sqlite3AlterRenameColumn(
);
/* Drop and reload the database schema. */
- renameReloadSchema(pParse, iSchema);
- renameTestSchema(pParse, zDb, iSchema==1);
+ renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);
exit_rename_column:
sqlite3SrcListDelete(db, pSrc);
@@ -760,15 +800,30 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
static void renameWalkWith(Walker *pWalker, Select *pSelect){
With *pWith = pSelect->pWith;
if( pWith ){
+ Parse *pParse = pWalker->pParse;
int i;
+ With *pCopy = 0;
+ assert( pWith->nCte>0 );
+ if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){
+ /* Push a copy of the With object onto the with-stack. We use a copy
+ ** here as the original will be expanded and resolved (flags SF_Expanded
+ ** and SF_Resolved) below. And the parser code that uses the with-stack
+ ** fails if the Select objects on it have already been expanded and
+ ** resolved. */
+ pCopy = sqlite3WithDup(pParse->db, pWith);
+ pCopy = sqlite3WithPush(pParse, pCopy, 1);
+ }
for(i=0; inCte; i++){
Select *p = pWith->a[i].pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pWalker->pParse;
- sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ sNC.pParse = pParse;
+ if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC);
sqlite3WalkSelect(pWalker, p);
- sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols);
+ sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols);
+ }
+ if( pCopy && pParse->pWith==pCopy ){
+ pParse->pWith = pCopy->pOuter;
}
}
}
@@ -795,7 +850,11 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
- if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
+ if( p->selFlags & (SF_View|SF_CopyCte) ){
+ testcase( p->selFlags & SF_View );
+ testcase( p->selFlags & SF_CopyCte );
+ return WRC_Prune;
+ }
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; inExpr; i++){
@@ -866,23 +925,35 @@ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
/*
** Search the Parse object passed as the first argument for a RenameToken
-** object associated with parse tree element pPtr. If found, remove it
-** from the Parse object and add it to the list maintained by the
-** RenameCtx object passed as the second argument.
+** object associated with parse tree element pPtr. If found, return a pointer
+** to it. Otherwise, return NULL.
+**
+** If the second argument passed to this function is not NULL and a matching
+** RenameToken object is found, remove it from the Parse object and add it to
+** the list maintained by the RenameCtx object.
*/
-static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
+static RenameToken *renameTokenFind(
+ Parse *pParse,
+ struct RenameCtx *pCtx,
+ void *pPtr
+){
RenameToken **pp;
- assert( pPtr!=0 );
+ if( NEVER(pPtr==0) ){
+ return 0;
+ }
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
if( (*pp)->p==pPtr ){
RenameToken *pToken = *pp;
- *pp = pToken->pNext;
- pToken->pNext = pCtx->pList;
- pCtx->pList = pToken;
- pCtx->nList++;
- break;
+ if( pCtx ){
+ *pp = pToken->pNext;
+ pToken->pNext = pCtx->pList;
+ pCtx->pList = pToken;
+ pCtx->nList++;
+ }
+ return pToken;
}
}
+ return 0;
}
/*
@@ -891,7 +962,11 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
- if( p->selFlags & SF_View ) return WRC_Prune;
+ if( p->selFlags & (SF_View|SF_CopyCte) ){
+ testcase( p->selFlags & SF_View );
+ testcase( p->selFlags & SF_CopyCte );
+ return WRC_Prune;
+ }
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -953,7 +1028,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
*/
static void renameColumnParseError(
sqlite3_context *pCtx,
- int bPost,
+ const char *zWhen,
sqlite3_value *pType,
sqlite3_value *pObject,
Parse *pParse
@@ -962,8 +1037,8 @@ static void renameColumnParseError(
const char *zN = (const char*)sqlite3_value_text(pObject);
char *zErr;
- zErr = sqlite3_mprintf("error in %s %s%s: %s",
- zT, zN, (bPost ? " after rename" : ""),
+ zErr = sqlite3_mprintf("error in %s %s%s%s: %s",
+ zT, zN, (zWhen[0] ? " " : ""), zWhen,
pParse->zErrMsg
);
sqlite3_result_error(pCtx, zErr, -1);
@@ -1042,7 +1117,7 @@ static int renameParseSql(
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
- rc = sqlite3RunParser(p, zSql, &zErr);
+ rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM;
assert( p->zErrMsg==0 );
assert( rc!=SQLITE_OK || zErr==0 );
p->zErrMsg = zErr;
@@ -1085,51 +1160,76 @@ static int renameEditSql(
const char *zNew, /* New token text */
int bQuote /* True to always quote token */
){
- int nNew = sqlite3Strlen30(zNew);
- int nSql = sqlite3Strlen30(zSql);
+ i64 nNew = sqlite3Strlen30(zNew);
+ i64 nSql = sqlite3Strlen30(zSql);
sqlite3 *db = sqlite3_context_db_handle(pCtx);
int rc = SQLITE_OK;
- char *zQuot;
+ char *zQuot = 0;
char *zOut;
- int nQuot;
-
- /* Set zQuot to point to a buffer containing a quoted copy of the
- ** identifier zNew. If the corresponding identifier in the original
- ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
- ** point to zQuot so that all substitutions are made using the
- ** quoted version of the new column name. */
- zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
- if( zQuot==0 ){
- return SQLITE_NOMEM;
+ i64 nQuot = 0;
+ char *zBuf1 = 0;
+ char *zBuf2 = 0;
+
+ if( zNew ){
+ /* Set zQuot to point to a buffer containing a quoted copy of the
+ ** identifier zNew. If the corresponding identifier in the original
+ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
+ ** point to zQuot so that all substitutions are made using the
+ ** quoted version of the new column name. */
+ zQuot = sqlite3MPrintf(db, "\"%w\" ", zNew);
+ if( zQuot==0 ){
+ return SQLITE_NOMEM;
+ }else{
+ nQuot = sqlite3Strlen30(zQuot)-1;
+ }
+
+ assert( nQuot>=nNew );
+ zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
}else{
- nQuot = sqlite3Strlen30(zQuot);
- }
- if( bQuote ){
- zNew = zQuot;
- nNew = nQuot;
+ zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ if( zOut ){
+ zBuf1 = &zOut[nSql*2+1];
+ zBuf2 = &zOut[nSql*4+2];
+ }
}
/* At this point pRename->pList contains a list of RenameToken objects
** corresponding to all tokens in the input SQL that must be replaced
- ** with the new column name. All that remains is to construct and
- ** return the edited SQL string. */
- assert( nQuot>=nNew );
- zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ ** with the new column name, or with single-quoted versions of themselves.
+ ** All that remains is to construct and return the edited SQL string. */
if( zOut ){
int nOut = nSql;
memcpy(zOut, zSql, nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- RenameToken *pBest = renameColumnTokenNext(pRename);
-
u32 nReplace;
const char *zReplace;
- if( sqlite3IsIdChar(*pBest->t.z) ){
- nReplace = nNew;
- zReplace = zNew;
+ RenameToken *pBest = renameColumnTokenNext(pRename);
+
+ if( zNew ){
+ if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
+ nReplace = nNew;
+ zReplace = zNew;
+ }else{
+ nReplace = nQuot;
+ zReplace = zQuot;
+ if( pBest->t.z[pBest->t.n]=='"' ) nReplace++;
+ }
}else{
- nReplace = nQuot;
- zReplace = zQuot;
+ /* Dequote the double-quoted token. Then requote it again, this time
+ ** using single quotes. If the character immediately following the
+ ** original token within the input SQL was a single quote ('), then
+ ** add another space after the new, single-quoted version of the
+ ** token. This is so that (SELECT "string"'alias') maps to
+ ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
+ memcpy(zBuf1, pBest->t.z, pBest->t.n);
+ zBuf1[pBest->t.n] = 0;
+ sqlite3Dequote(zBuf1);
+ sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ pBest->t.z[pBest->t.n]=='\'' ? " " : ""
+ );
+ zReplace = zBuf2;
+ nReplace = sqlite3Strlen30(zReplace);
}
iOff = pBest->t.z - zSql;
@@ -1195,7 +1295,7 @@ static int renameResolveTrigger(Parse *pParse){
if( pSrc ){
int i;
for(i=0; inSrc && rc==SQLITE_OK; i++){
- struct SrcList_item *p = &pSrc->a[i];
+ SrcItem *p = &pSrc->a[i];
p->iCursor = pParse->nTab++;
if( p->pSelect ){
sqlite3SelectPrep(pParse, p->pSelect, 0);
@@ -1221,9 +1321,8 @@ static int renameResolveTrigger(Parse *pParse){
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
}
assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
- if( pStep->pUpsert ){
+ if( pStep->pUpsert && rc==SQLITE_OK ){
Upsert *pUpsert = pStep->pUpsert;
- assert( rc==SQLITE_OK );
pUpsert->pUpsertSrc = pSrc;
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
@@ -1397,9 +1496,11 @@ static void renameColumnFunc(
assert( sParse.pNewTable->pSelect==0 );
sCtx.pTab = sParse.pNewTable;
if( bFKOnly==0 ){
- renameTokenFind(
- &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
- );
+ if( iColnCol ){
+ renameTokenFind(
+ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
+ );
+ }
if( sCtx.iCol<0 ){
renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
}
@@ -1410,12 +1511,12 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
- }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- for(i=0; inCol; i++){
- sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
- }
+ for(i=0; inCol; i++){
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
+ }
#endif
+ }
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; inCol; i++){
@@ -1469,7 +1570,7 @@ static void renameColumnFunc(
renameColumnFunc_done:
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
}
@@ -1501,13 +1602,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
- if( pSelect->selFlags & SF_View ) return WRC_Prune;
- if( pSrc==0 ){
+ if( pSelect->selFlags & (SF_View|SF_CopyCte) ){
+ testcase( pSelect->selFlags & SF_View );
+ testcase( pSelect->selFlags & SF_CopyCte );
+ return WRC_Prune;
+ }
+ if( NEVER(pSrc==0) ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
for(i=0; inSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
@@ -1658,7 +1763,7 @@ static void renameTableFunc(
}
if( rc!=SQLITE_OK ){
if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlite3_result_error_code(context, rc);
}
@@ -1675,6 +1780,119 @@ static void renameTableFunc(
return;
}
+static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
+ renameTokenFind(pWalker->pParse, pWalker->u.pRename, (void*)pExpr);
+ }
+ return WRC_Continue;
+}
+
+/*
+** The implementation of an SQL scalar function that rewrites DDL statements
+** so that any string literals that use double-quotes are modified so that
+** they use single quotes.
+**
+** Two arguments must be passed:
+**
+** 0: Database name ("main", "temp" etc.).
+** 1: SQL statement to edit.
+**
+** The returned value is the modified SQL statement. For example, given
+** the database schema:
+**
+** CREATE TABLE t1(a, b, c);
+**
+** SELECT sqlite_rename_quotefix('main',
+** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
+** );
+**
+** returns the string:
+**
+** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
+*/
+static void renameQuotefixFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ char const *zDb = (const char*)sqlite3_value_text(argv[0]);
+ char const *zInput = (const char*)sqlite3_value_text(argv[1]);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ sqlite3BtreeEnterAll(db);
+
+ UNUSED_PARAMETER(NotUsed);
+ if( zDb && zInput ){
+ int rc;
+ Parse sParse;
+ rc = renameParseSql(&sParse, zDb, db, zInput, 0);
+
+ if( rc==SQLITE_OK ){
+ RenameCtx sCtx;
+ Walker sWalker;
+
+ /* Walker to find tokens that need to be replaced. */
+ memset(&sCtx, 0, sizeof(RenameCtx));
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = &sParse;
+ sWalker.xExprCallback = renameQuotefixExprCb;
+ sWalker.xSelectCallback = renameColumnSelectCb;
+ sWalker.u.pRename = &sCtx;
+
+ if( sParse.pNewTable ){
+ Select *pSelect = sParse.pNewTable->pSelect;
+ if( pSelect ){
+ pSelect->selFlags &= ~SF_View;
+ sParse.rc = SQLITE_OK;
+ sqlite3SelectPrep(&sParse, pSelect, 0);
+ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
+ if( rc==SQLITE_OK ){
+ sqlite3WalkSelect(&sWalker, pSelect);
+ }
+ }else{
+ int i;
+ sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ for(i=0; inCol; i++){
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
+ }
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+ }
+ }else if( sParse.pNewIndex ){
+ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
+ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
+ }else{
+#ifndef SQLITE_OMIT_TRIGGER
+ rc = renameResolveTrigger(&sParse);
+ if( rc==SQLITE_OK ){
+ renameWalkTrigger(&sWalker, sParse.pNewTrigger);
+ }
+#endif /* SQLITE_OMIT_TRIGGER */
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = renameEditSql(context, &sCtx, zInput, 0, 0);
+ }
+ renameTokenFree(db, sCtx.pList);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(context, rc);
+ }
+ renameParseCleanup(&sParse);
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+
+ sqlite3BtreeLeaveAll(db);
+}
+
/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
@@ -1687,6 +1905,8 @@ static void renameTableFunc(
** 2: Object type ("view", "table", "trigger" or "index").
** 3: Object name.
** 4: True if object is from temp schema.
+** 5: "when" part of error message.
+** 6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
@@ -1704,6 +1924,8 @@ static void renameTableTest(
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
+ char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
+ int bNoDQS = sqlite3_value_int(argv[6]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
@@ -1711,10 +1933,14 @@ static void renameTableTest(
#endif
UNUSED_PARAMETER(NotUsed);
+
if( zDb && zInput ){
int rc;
Parse sParse;
+ int flags = db->flags;
+ if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
+ db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
@@ -1736,8 +1962,8 @@ static void renameTableTest(
}
}
- if( rc!=SQLITE_OK ){
- renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
+ if( rc!=SQLITE_OK && zWhen ){
+ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
}
renameParseCleanup(&sParse);
}
@@ -1747,14 +1973,219 @@ static void renameTableTest(
#endif
}
+/*
+** The implementation of internal UDF sqlite_drop_column().
+**
+** Arguments:
+**
+** argv[0]: An integer - the index of the schema containing the table
+** argv[1]: CREATE TABLE statement to modify.
+** argv[2]: An integer - the index of the column to remove.
+**
+** The value returned is a string containing the CREATE TABLE statement
+** with column argv[2] removed.
+*/
+static void dropColumnFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ int iSchema = sqlite3_value_int(argv[0]);
+ const char *zSql = (const char*)sqlite3_value_text(argv[1]);
+ int iCol = sqlite3_value_int(argv[2]);
+ const char *zDb = db->aDb[iSchema].zDbSName;
+ int rc;
+ Parse sParse;
+ RenameToken *pCol;
+ Table *pTab;
+ const char *zEnd;
+ char *zNew = 0;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ UNUSED_PARAMETER(NotUsed);
+ rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
+ if( rc!=SQLITE_OK ) goto drop_column_done;
+ pTab = sParse.pNewTable;
+ if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
+ /* This can happen if the sqlite_schema table is corrupt */
+ rc = SQLITE_CORRUPT_BKPT;
+ goto drop_column_done;
+ }
+
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName);
+ if( iColnCol-1 ){
+ RenameToken *pEnd;
+ pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
+ zEnd = (const char*)pEnd->t.z;
+ }else{
+ zEnd = (const char*)&zSql[pTab->addColOffset];
+ while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
+ }
+
+ zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
+ sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
+ sqlite3_free(zNew);
+
+drop_column_done:
+ renameParseCleanup(&sParse);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(context, rc);
+ }
+}
+
+/*
+** This function is called by the parser upon parsing an
+**
+** ALTER TABLE pSrc DROP COLUMN pName
+**
+** statement. Argument pSrc contains the possibly qualified name of the
+** table being edited, and token pName the name of the column to drop.
+*/
+void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
+ sqlite3 *db = pParse->db; /* Database handle */
+ Table *pTab; /* Table to modify */
+ int iDb; /* Index of db containing pTab in aDb[] */
+ const char *zDb; /* Database containing pTab ("main" etc.) */
+ char *zCol = 0; /* Name of column to drop */
+ int iCol; /* Index of column zCol in pTab->aCol[] */
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ if( NEVER(db->mallocFailed) ) goto exit_drop_column;
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_drop_column;
+
+ /* Make sure this is not an attempt to ALTER a view, virtual table or
+ ** system table. */
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column;
+
+ /* Find the index of the column being dropped. */
+ zCol = sqlite3NameFromToken(db, pName);
+ if( zCol==0 ){
+ assert( db->mallocFailed );
+ goto exit_drop_column;
+ }
+ iCol = sqlite3ColumnIndex(pTab, zCol);
+ if( iCol<0 ){
+ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol);
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the user to drop a PRIMARY KEY column or a column
+ ** constrained by a UNIQUE constraint. */
+ if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){
+ sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"",
+ (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE",
+ zCol
+ );
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the number of columns to go to zero */
+ if( pTab->nCol<=1 ){
+ sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol);
+ goto exit_drop_column;
+ }
+
+ /* Edit the sqlite_schema table */
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=0 );
+ zDb = db->aDb[iDb].zDbSName;
+ renameTestSchema(pParse, zDb, iDb==1, "", 0);
+ renameFixQuotes(pParse, zDb, iDb==1);
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
+ "sql = sqlite_drop_column(%d, sql, %d) "
+ "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
+ , zDb, iDb, iCol, pTab->zName
+ );
+
+ /* Drop and reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
+ renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);
+
+ /* Edit rows of table on disk */
+ if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int i;
+ int addr;
+ int reg;
+ int regRec;
+ Index *pPk = 0;
+ int nField = 0; /* Number of non-virtual columns after drop */
+ int iCur;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ iCur = pParse->nTab++;
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+ reg = ++pParse->nMem;
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
+ pParse->nMem += pTab->nCol;
+ }else{
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ pParse->nMem += pPk->nColumn;
+ for(i=0; inKeyCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
+ }
+ nField = pPk->nKeyCol;
+ }
+ regRec = ++pParse->nMem;
+ for(i=0; inCol; i++){
+ if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int regOut;
+ if( pPk ){
+ int iPos = sqlite3TableColumnToIndex(pPk, i);
+ int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
+ if( iPosnKeyCol ) continue;
+ regOut = reg+1+iPos-(iPos>iColPos);
+ }else{
+ regOut = reg+1+nField;
+ }
+ if( i==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
+ }else{
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ }
+ nField++;
+ }
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
+ if( pPk ){
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
+ }
+ sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
+
+ sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addr);
+ }
+
+exit_drop_column:
+ sqlite3DbFree(db, zCol);
+ sqlite3SrcListDelete(db, pSrc);
+}
+
/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
- INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
- INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
diff --git a/src/attach.c b/src/attach.c
index 3b5c57f0c..2fc84e5b8 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -95,7 +95,7 @@ static void attachFunc(
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db) (0)
@@ -433,6 +433,65 @@ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
}
#endif /* SQLITE_OMIT_ATTACH */
+/*
+** Expression callback used by sqlite3FixAAAA() routines.
+*/
+static int fixExprCb(Walker *p, Expr *pExpr){
+ DbFixer *pFix = p->u.pFix;
+ if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
+ if( pExpr->op==TK_VARIABLE ){
+ if( pFix->pParse->db->init.busy ){
+ pExpr->op = TK_NULL;
+ }else{
+ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
+ return WRC_Abort;
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Select callback used by sqlite3FixAAAA() routines.
+*/
+static int fixSelectCb(Walker *p, Select *pSelect){
+ DbFixer *pFix = p->u.pFix;
+ int i;
+ SrcItem *pItem;
+ sqlite3 *db = pFix->pParse->db;
+ int iDb = sqlite3FindDbName(db, pFix->zDb);
+ SrcList *pList = pSelect->pSrc;
+
+ if( NEVER(pList==0) ) return WRC_Continue;
+ for(i=0, pItem=pList->a; inSrc; i++, pItem++){
+ if( pFix->bTemp==0 ){
+ if( pItem->zDatabase ){
+ if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return WRC_Abort;
+ }
+ sqlite3DbFree(db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->fg.notCte = 1;
+ }
+ pItem->pSchema = pFix->pSchema;
+ pItem->fg.fromDDL = 1;
+ }
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
+ if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
+#endif
+ }
+ if( pSelect->pWith ){
+ for(i=0; ipWith->nCte; i++){
+ if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
@@ -444,9 +503,7 @@ void sqlite3FixInit(
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
- sqlite3 *db;
-
- db = pParse->db;
+ sqlite3 *db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zDbSName;
@@ -454,6 +511,13 @@ void sqlite3FixInit(
pFix->zType = zType;
pFix->pName = pName;
pFix->bTemp = (iDb==1);
+ pFix->w.pParse = pParse;
+ pFix->w.xExprCallback = fixExprCb;
+ pFix->w.xSelectCallback = fixSelectCb;
+ pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback;
+ pFix->w.walkerDepth = 0;
+ pFix->w.eCode = 0;
+ pFix->w.u.pFix = pFix;
}
/*
@@ -474,115 +538,27 @@ int sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
- int i;
- struct SrcList_item *pItem;
- sqlite3 *db = pFix->pParse->db;
- int iDb = sqlite3FindDbName(db, pFix->zDb);
-
- if( NEVER(pList==0) ) return 0;
-
- for(i=0, pItem=pList->a; inSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
- sqlite3ErrorMsg(pFix->pParse,
- "%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
- return 1;
- }
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
- pItem->pSchema = pFix->pSchema;
- pItem->fg.fromDDL = 1;
- }
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
- if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
- if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
-#endif
- if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
- return 1;
- }
+ int res = 0;
+ if( pList ){
+ Select s;
+ memset(&s, 0, sizeof(s));
+ s.pSrc = pList;
+ res = sqlite3WalkSelect(&pFix->w, &s);
}
- return 0;
+ return res;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
- while( pSelect ){
- if( sqlite3FixExprList(pFix, pSelect->pEList) ){
- return 1;
- }
- if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
- return 1;
- }
- if( pSelect->pWith ){
- int i;
- for(i=0; ipWith->nCte; i++){
- if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
- return 1;
- }
- }
- }
- pSelect = pSelect->pPrior;
- }
- return 0;
+ return sqlite3WalkSelect(&pFix->w, pSelect);
}
int sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
- while( pExpr ){
- if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
- if( pExpr->op==TK_VARIABLE ){
- if( pFix->pParse->db->init.busy ){
- pExpr->op = TK_NULL;
- }else{
- sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
- return 1;
- }
- }
- if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
- }else{
- if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
- }
- if( sqlite3FixExpr(pFix, pExpr->pRight) ){
- return 1;
- }
- pExpr = pExpr->pLeft;
- }
- return 0;
-}
-int sqlite3FixExprList(
- DbFixer *pFix, /* Context of the fixation */
- ExprList *pList /* The expression to be fixed to one database */
-){
- int i;
- struct ExprList_item *pItem;
- if( pList==0 ) return 0;
- for(i=0, pItem=pList->a; inExpr; i++, pItem++){
- if( sqlite3FixExpr(pFix, pItem->pExpr) ){
- return 1;
- }
- }
- return 0;
+ return sqlite3WalkExpr(&pFix->w, pExpr);
}
#endif
@@ -592,32 +568,30 @@ int sqlite3FixTriggerStep(
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
- if( sqlite3FixSelect(pFix, pStep->pSelect) ){
- return 1;
- }
- if( sqlite3FixExpr(pFix, pStep->pWhere) ){
- return 1;
- }
- if( sqlite3FixExprList(pFix, pStep->pExprList) ){
- return 1;
- }
- if( pStep->pFrom && sqlite3FixSrcList(pFix, pStep->pFrom) ){
+ if( sqlite3WalkSelect(&pFix->w, pStep->pSelect)
+ || sqlite3WalkExpr(&pFix->w, pStep->pWhere)
+ || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
+ || sqlite3FixSrcList(pFix, pStep->pFrom)
+ ){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
- if( pStep->pUpsert ){
- Upsert *pUp = pStep->pUpsert;
- if( sqlite3FixExprList(pFix, pUp->pUpsertTarget)
- || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
- || sqlite3FixExprList(pFix, pUp->pUpsertSet)
- || sqlite3FixExpr(pFix, pUp->pUpsertWhere)
- ){
- return 1;
+ {
+ Upsert *pUp;
+ for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
+ if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
+ || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
+ || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
+ ){
+ return 1;
+ }
}
}
#endif
pStep = pStep->pNext;
}
+
return 0;
}
#endif
diff --git a/src/auth.c b/src/auth.c
index 40673d5ea..33420f583 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -143,7 +143,6 @@ void sqlite3AuthRead(
Schema *pSchema, /* The schema of the expression */
SrcList *pTabList /* All table that pExpr might refer to */
){
- sqlite3 *db = pParse->db;
Table *pTab = 0; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
@@ -151,8 +150,8 @@ void sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
- assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->xAuth==0 ) return;
+ assert( !IN_RENAME_OBJECT );
+ assert( pParse->db->xAuth!=0 );
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
@@ -164,7 +163,7 @@ void sqlite3AuthRead(
pTab = pParse->pTriggerTab;
}else{
assert( pTabList );
- for(iSrc=0; ALWAYS(iSrcnSrc); iSrc++){
+ for(iSrc=0; iSrcnSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
pTab = pTabList->a[iSrc].pTab;
break;
@@ -172,7 +171,7 @@ void sqlite3AuthRead(
}
}
iCol = pExpr->iColumn;
- if( NEVER(pTab==0) ) return;
+ if( pTab==0 ) return;
if( iCol>=0 ){
assert( iColnCol );
@@ -183,7 +182,7 @@ void sqlite3AuthRead(
}else{
zCol = "ROWID";
}
- assert( iDb>=0 && iDbnDb );
+ assert( iDb>=0 && iDbdb->nDb );
if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
pExpr->op = TK_NULL;
}
@@ -209,11 +208,7 @@ int sqlite3AuthCheck(
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->init.busy || IN_SPECIAL_PARSE ){
- return SQLITE_OK;
- }
-
- if( db->xAuth==0 ){
+ if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
diff --git a/src/btree.c b/src/btree.c
index 4ac283101..d1e84d0a6 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -547,7 +547,7 @@ static void invalidateIncrblobCursors(
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
+ assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
@@ -1143,6 +1143,24 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
}
+/*
+** Given a record with nPayload bytes of payload stored within btree
+** page pPage, return the number of bytes of payload stored locally.
+*/
+static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
+ int maxLocal; /* Maximum amount of payload held locally */
+ maxLocal = pPage->maxLocal;
+ if( nPayload<=maxLocal ){
+ return nPayload;
+ }else{
+ int minLocal; /* Minimum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+ minLocal = pPage->minLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
+ return ( surplus <= maxLocal ) ? surplus : minLocal;
+ }
+}
+
/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
@@ -1430,6 +1448,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
unsigned char *src; /* Source of content */
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
+ int iCellStart; /* First cell offset in input */
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
@@ -1471,7 +1490,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
- }else if( NEVER(iFree+sz>usableSize) ){
+ }else if( iFree+sz>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -1490,6 +1509,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
cbrk = usableSize;
iCellLast = usableSize - 4;
+ iCellStart = get2byte(&data[hdr+5]);
for(i=0; iiCellLast ){
+ if( pciCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( pc>=iCellFirst && pc<=iCellLast );
+ assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
- if( cbrkusableSize ){
+ if( cbrkusableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+ assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
- int x;
if( cbrk==pc ) continue;
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
- x = get2byte(&data[hdr+5]);
- memcpy(&temp[x], &data[x], (cbrk+size) - x);
+ memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
@@ -2719,19 +2737,23 @@ static void freeTempSpace(BtShared *pBt){
*/
int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
- BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
+
+ /* Verify that no other cursors have this Btree open */
+#ifdef SQLITE_DEBUG
+ {
+ BtCursor *pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ assert( pTmp->pBtree!=p );
+
}
}
+#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
@@ -2883,6 +2905,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
+ if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -4112,7 +4135,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeLeave(p);
return rc;
}
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
+ p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -4522,7 +4545,14 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
- sqlite3BtreeLeave(pBtree);
+ if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
+ /* Since the BtShared is not sharable, there is no need to
+ ** worry about the missing sqlite3BtreeLeave() call here. */
+ assert( pBtree->sharable==0 );
+ sqlite3BtreeClose(pBtree);
+ }else{
+ sqlite3BtreeLeave(pBtree);
+ }
pCur->pBtree = 0;
}
return SQLITE_OK;
@@ -5364,7 +5394,9 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; iiiPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
+ testcase( pCur->ix!=pCur->pPage->nCell-1 );
+ /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
*pRes = 0;
@@ -6131,7 +6163,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
- if( iPage>mxPage ){
+ if( iPage>mxPage || iPage<2 ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
@@ -6387,10 +6419,9 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
+** Free the overflow pages associated with the given Cell.
*/
-static int clearCell(
+static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
@@ -6402,10 +6433,7 @@ static int clearCell(
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
+ assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
@@ -6461,6 +6489,21 @@ static int clearCell(
return SQLITE_OK;
}
+/* Call xParseCell to compute the size of a cell. If the cell contains
+** overflow, then invoke cellClearOverflow to clear out that overflow.
+** STore the result code (SQLITE_OK or some error code) in rc.
+**
+** Implemented as macro to force inlining for performance.
+*/
+#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
+ pPage->xParseCell(pPage, pCell, &sInfo); \
+ if( sInfo.nLocal!=sInfo.nPayload ){ \
+ rc = clearCellOverflow(pPage, pCell, &sInfo); \
+ }else{ \
+ rc = SQLITE_OK; \
+ }
+
+
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
@@ -6983,7 +7026,7 @@ static int rebuildPage(
u8 *pCell = pCArray->apCell[i];
u16 sz = pCArray->szCell[i];
assert( sz>0 );
- if( SQLITE_WITHIN(pCell,aData,pEnd) ){
+ if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
}else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
@@ -6996,9 +7039,8 @@ static int rebuildPage(
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, sz);
+ memmove(pData, pCell, sz);
assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( sz!=pPg->xCellSize(pPg,pCell) )
i++;
if( i>=iEnd ) break;
if( pCArray->ixNx[k]<=i ){
@@ -7137,7 +7179,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( pFree+sz>pEnd ){
+ return 0;
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -7618,7 +7662,9 @@ static int balance_nonroot(
}
pgno = get4byte(pRight);
while( 1 ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ }
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
@@ -7657,12 +7703,10 @@ static int balance_nonroot(
if( pBt->btsFlags & BTS_FAST_SECURE ){
int iOff;
+ /* If the following if() condition is not true, the db is corrupted.
+ ** The call to dropCell() below will detect this. */
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
- if( (iOff+szNew[i])>(int)pBt->usableSize ){
- rc = SQLITE_CORRUPT_BKPT;
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }else{
+ if( (iOff+szNew[i])<=(int)pBt->usableSize ){
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
}
@@ -7790,7 +7834,7 @@ static int balance_nonroot(
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
if( !pOld->leaf ){
assert( leafCorrection==0 );
- assert( pOld->hdrOffset==0 );
+ assert( pOld->hdrOffset==0 || CORRUPT_DB );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
@@ -7956,6 +8000,9 @@ static int balance_nonroot(
apOld[i] = 0;
rc = sqlite3PagerWrite(pNew->pDbPage);
nNew++;
+ if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
@@ -7992,7 +8039,7 @@ static int balance_nonroot(
aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
aPgFlags[i] = apNew[i]->pDbPage->flags;
for(j=0; jmaxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(kpgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -8660,7 +8714,8 @@ int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
- assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
+ assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
@@ -8678,7 +8733,7 @@ int sqlite3BtreeInsert(
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+ assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
@@ -8694,13 +8749,23 @@ int sqlite3BtreeInsert(
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
+ if( loc && pCur->iPage<0 ){
+ /* This can only happen if the schema is corrupt such that there is more
+ ** than one table or index with the same root page as used by the cursor.
+ ** Which can only happen if the SQLITE_NoSchemaError flag was set when
+ ** the schema was loaded. This cannot be asserted though, as a user might
+ ** set the flag, load the schema, and then unset the flag. */
+ return SQLITE_CORRUPT_BKPT;
+ }
}
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ }
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
@@ -8781,17 +8846,16 @@ int sqlite3BtreeInsert(
return btreeOverwriteCell(pCur, &x2);
}
}
-
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc)
|| CORRUPT_DB );
pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
+ assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
- if( pCur->eState>CURSOR_INVALID ){
+ if( NEVER(pCur->eState>CURSOR_INVALID) ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
@@ -8805,7 +8869,21 @@ int sqlite3BtreeInsert(
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
+ if( flags & BTREE_PREFORMAT ){
+ rc = SQLITE_OK;
+ szNew = pBt->nPreformatSize;
+ if( szNew<4 ) szNew = 4;
+ if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+ CellInfo info;
+ pPage->xParseCell(pPage, newCell, &info);
+ if( info.nPayload!=info.nLocal ){
+ Pgno ovfl = get4byte(&newCell[szNew-4]);
+ ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+ }
+ }
+ }else{
+ rc = fillInCell(pPage, newCell, pX, &szNew);
+ }
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
@@ -8821,7 +8899,7 @@ int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
@@ -8912,6 +8990,114 @@ int sqlite3BtreeInsert(
return rc;
}
+/*
+** This function is used as part of copying the current row from cursor
+** pSrc into cursor pDest. If the cursors are open on intkey tables, then
+** parameter iKey is used as the rowid value when the record is copied
+** into pDest. Otherwise, the record is copied verbatim.
+**
+** This function does not actually write the new value to cursor pDest.
+** Instead, it creates and populates any required overflow pages and
+** writes the data for the new cell into the BtShared.pTmpSpace buffer
+** for the destination database. The size of the cell, in bytes, is left
+** in BtShared.nPreformatSize. The caller completes the insertion by
+** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
+ int rc = SQLITE_OK;
+ BtShared *pBt = pDest->pBt;
+ u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
+ const u8 *aIn; /* Pointer to next input buffer */
+ u32 nIn; /* Size of input buffer aIn[] */
+ u32 nRem; /* Bytes of data still to copy */
+
+ getCellInfo(pSrc);
+ aOut += putVarint32(aOut, pSrc->info.nPayload);
+ if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ nIn = pSrc->info.nLocal;
+ aIn = pSrc->info.pPayload;
+ if( aIn+nIn>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nRem = pSrc->info.nPayload;
+ if( nIn==nRem && nInpPage->maxLocal ){
+ memcpy(aOut, aIn, nIn);
+ pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ }else{
+ Pager *pSrcPager = pSrc->pBt->pPager;
+ u8 *pPgnoOut = 0;
+ Pgno ovflIn = 0;
+ DbPage *pPageIn = 0;
+ MemPage *pPageOut = 0;
+ u32 nOut; /* Size of output buffer aOut[] */
+
+ nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+ pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ if( nOutinfo.nPayload ){
+ pPgnoOut = &aOut[nOut];
+ pBt->nPreformatSize += 4;
+ }
+
+ if( nRem>nIn ){
+ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+ }
+
+ do {
+ nRem -= nOut;
+ do{
+ assert( nOut>0 );
+ if( nIn>0 ){
+ int nCopy = MIN(nOut, nIn);
+ memcpy(aOut, aIn, nCopy);
+ nOut -= nCopy;
+ nIn -= nCopy;
+ aOut += nCopy;
+ aIn += nCopy;
+ }
+ if( nOut>0 ){
+ sqlite3PagerUnref(pPageIn);
+ pPageIn = 0;
+ rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+ if( rc==SQLITE_OK ){
+ aIn = (const u8*)sqlite3PagerGetData(pPageIn);
+ ovflIn = get4byte(aIn);
+ aIn += 4;
+ nIn = pSrc->pBt->usableSize - 4;
+ }
+ }
+ }while( rc==SQLITE_OK && nOut>0 );
+
+ if( rc==SQLITE_OK && nRem>0 ){
+ Pgno pgnoNew;
+ MemPage *pNew = 0;
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+ put4byte(pPgnoOut, pgnoNew);
+ if( ISAUTOVACUUM && pPageOut ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+ }
+ releasePage(pPageOut);
+ pPageOut = pNew;
+ if( pPageOut ){
+ pPgnoOut = pPageOut->aData;
+ put4byte(pPgnoOut, 0);
+ aOut = &pPgnoOut[4];
+ nOut = MIN(pBt->usableSize - 4, nRem);
+ }
+ }
+ }while( nRem>0 && rc==SQLITE_OK );
+
+ releasePage(pPageOut);
+ sqlite3PagerUnref(pPageIn);
+ }
+
+ return rc;
+}
+
/*
** Delete the entry that the cursor is pointing to.
**
@@ -8950,9 +9136,10 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
- if( rc ) return rc;
+ assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
+ if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}
- assert( pCur->eState==CURSOR_VALID );
+ assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
@@ -9005,7 +9192,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
+ if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
@@ -9014,7 +9201,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
@@ -9301,14 +9488,14 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
- }else if( pnChange ){
- assert( pPage->intKey || CORRUPT_DB );
+ }
+ if( pnChange ){
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
@@ -9333,9 +9520,8 @@ static int clearDatabasePage(
** read cursors on the table. Open write cursors are moved to the
** root of the table.
**
-** If pnChange is not NULL, then table iTable must be an intkey table. The
-** integer value pointed to by pnChange is incremented by the number of
-** entries in the table.
+** If pnChange is not NULL, then the integer value pointed to by pnChange
+** is incremented by the number of entries in the table.
*/
int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
@@ -9349,7 +9535,9 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ }
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
@@ -9509,7 +9697,7 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+ *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
diff --git a/src/btree.h b/src/btree.h
index 7a9ed2e3c..b7afecc42 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -262,6 +262,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags);
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
+#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -361,6 +362,8 @@ void sqlite3BtreeCursorList(Btree*);
int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
+int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
+
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
diff --git a/src/btreeInt.h b/src/btreeInt.h
index c09699fbb..37c07fe93 100644
--- a/src/btreeInt.h
+++ b/src/btreeInt.h
@@ -350,7 +350,7 @@ struct Btree {
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
int nBackup; /* Number of backup operations reading this btree */
- u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
+ u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
#ifdef SQLITE_DEBUG
@@ -455,6 +455,7 @@ struct BtShared {
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
+ int nPreformatSize; /* Size of last cell written by TransferRow() */
};
/*
diff --git a/src/build.c b/src/build.c
index 9779e9373..5bf5680d4 100644
--- a/src/build.c
+++ b/src/build.c
@@ -46,7 +46,7 @@ struct TableLock {
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
-void sqlite3TableLock(
+static SQLITE_NOINLINE void lockTable(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
@@ -59,8 +59,6 @@ void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
- if( iDb==1 ) return;
- if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; inTableLock; i++){
p = &pToplevel->aTableLock[i];
@@ -84,6 +82,17 @@ void sqlite3TableLock(
sqlite3OomFault(pToplevel->db);
}
}
+void sqlite3TableLock(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database containing the table to lock */
+ Pgno iTab, /* Root page number of the table to be locked */
+ u8 isWriteLock, /* True for a write lock */
+ const char *zName /* Name of the table to be locked */
+){
+ if( iDb==1 ) return;
+ if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ lockTable(pParse, iDb, iTab, isWriteLock, zName);
+}
/*
** Code an OP_TableLock instruction for each table locked by the
@@ -143,10 +152,36 @@ void sqlite3FinishCoding(Parse *pParse){
/* Begin by generating some termination code at the end of the
** vdbe program
*/
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
+ if( v==0 ){
+ if( db->init.busy ){
+ pParse->rc = SQLITE_DONE;
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) pParse->rc = SQLITE_ERROR;
+ }
assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
+ if( pParse->bReturning ){
+ Returning *pReturning = pParse->u1.pReturning;
+ int addrRewind;
+ int i;
+ int reg;
+
+ addrRewind =
+ sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
+ VdbeCoverage(v);
+ reg = pReturning->iRetReg;
+ for(i=0; inRetCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
+ sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
+ VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addrRewind);
+ }
sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
@@ -224,12 +259,16 @@ void sqlite3FinishCoding(Parse *pParse){
}
}
+ if( pParse->bReturning ){
+ Returning *pRet = pParse->u1.pReturning;
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
+ }
+
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
}
-
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
@@ -408,7 +447,7 @@ Table *sqlite3LocateTable(
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
- if( pParse->disableVtab==0 ){
+ if( pParse->disableVtab==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
@@ -431,6 +470,8 @@ Table *sqlite3LocateTable(
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
+ }else{
+ assert( HasRowid(p) || p->iPKey<0 );
}
return p;
@@ -448,7 +489,7 @@ Table *sqlite3LocateTable(
Table *sqlite3LocateTableItem(
Parse *pParse,
u32 flags,
- struct SrcList_item *p
+ SrcItem *p
){
const char *zDb;
assert( p->pSchema==0 || p->zDatabase==0 );
@@ -847,7 +888,7 @@ int sqlite3TwoPartName(
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT
+ assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE
|| (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
@@ -1016,6 +1057,23 @@ i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
}
#endif
+/*
+** Insert a single OP_JournalMode query opcode in order to force the
+** prepared statement to return false for sqlite3_stmt_readonly(). This
+** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
+** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
+** will return false for sqlite3_stmt_readonly() even if that statement
+** is a read-only no-op.
+*/
+static void sqlite3ForceNotReadOnly(Parse *pParse){
+ int iReg = ++pParse->nMem;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
+ sqlite3VdbeUsesBtree(v, 0);
+ }
+}
+
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -1115,6 +1173,7 @@ void sqlite3StartTable(
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
@@ -1143,17 +1202,6 @@ void sqlite3StartTable(
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
- /* If this is the magic sqlite_sequence table used by autoincrement,
- ** then record a pointer to this table in the main database structure
- ** so that INSERT can find the table easily.
- */
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- pTable->pSchema->pSeqTab = pTable;
- }
-#endif
-
/* Begin generating the code that will insert the table record into
** the schema table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
@@ -1206,7 +1254,8 @@ void sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab =
+ assert( !pParse->bReturning );
+ pParse->u1.addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenSchemaTable(pParse, iDb);
@@ -1233,12 +1282,86 @@ void sqlite3StartTable(
void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
pCol->colFlags |= COLFLAG_HIDDEN;
+ if( pTab ) pTab->tabFlags |= TF_HasHidden;
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
pTab->tabFlags |= TF_OOOHidden;
}
}
#endif
+/*
+** Name of the special TEMP trigger used to implement RETURNING. The
+** name begins with "sqlite_" so that it is guaranteed not to collide
+** with any application-generated triggers.
+*/
+#define RETURNING_TRIGGER_NAME "sqlite_returning"
+
+/*
+** Clean up the data structures associated with the RETURNING clause.
+*/
+static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
+ Hash *pHash;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+ sqlite3ExprListDelete(db, pRet->pReturnEL);
+ sqlite3DbFree(db, pRet);
+}
+
+/*
+** Add the RETURNING clause to the parse currently underway.
+**
+** This routine creates a special TEMP trigger that will fire for each row
+** of the DML statement. That TEMP trigger contains a single SELECT
+** statement with a result set that is the argument of the RETURNING clause.
+** The trigger has the Trigger.bReturning flag and an opcode of
+** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
+** knows to handle it specially. The TEMP trigger is automatically
+** removed at the end of the parse.
+**
+** When this routine is called, we do not yet know if the RETURNING clause
+** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
+** RETURNING trigger instead. It will then be converted into the appropriate
+** type on the first call to sqlite3TriggersExist().
+*/
+void sqlite3AddReturning(Parse *pParse, ExprList *pList){
+ Returning *pRet;
+ Hash *pHash;
+ sqlite3 *db = pParse->db;
+ if( pParse->pNewTrigger ){
+ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger");
+ }else{
+ assert( pParse->bReturning==0 );
+ }
+ pParse->bReturning = 1;
+ pRet = sqlite3DbMallocZero(db, sizeof(*pRet));
+ if( pRet==0 ){
+ sqlite3ExprListDelete(db, pList);
+ return;
+ }
+ pParse->u1.pReturning = pRet;
+ pRet->pParse = pParse;
+ pRet->pReturnEL = pList;
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
+ testcase( pParse->earlyCleanup );
+ if( db->mallocFailed ) return;
+ pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+ pRet->retTrig.op = TK_RETURNING;
+ pRet->retTrig.tr_tm = TRIGGER_AFTER;
+ pRet->retTrig.bReturning = 1;
+ pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.pTabSchema = db->aDb[1].pSchema;
+ pRet->retTrig.step_list = &pRet->retTStep;
+ pRet->retTStep.op = TK_RETURNING;
+ pRet->retTStep.pTrig = &pRet->retTrig;
+ pRet->retTStep.pExprList = pList;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
+ if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ ==&pRet->retTrig ){
+ sqlite3OomFault(db);
+ }
+}
/*
** Add a new column to the table currently being constructed.
@@ -1255,6 +1378,8 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
+ u8 hName;
+
if( (p = pParse->pNewTable)==0 ) return;
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
@@ -1266,8 +1391,9 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3Dequote(z);
+ hName = sqlite3StrIHash(z);
for(i=0; inCol; i++){
- if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
+ if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlite3DbFree(db, z);
return;
@@ -1285,7 +1411,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
- pCol->hName = sqlite3StrIHash(z);
+ pCol->hName = hName;
sqlite3ColumnPropertiesFromName(p, pCol);
if( pType->n==0 ){
@@ -2068,9 +2194,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
- if( pParse->addrCrTab ){
+ assert( !pParse->bReturning );
+ if( pParse->u1.addrCrTab ){
assert( v );
- sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
+ sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -2082,7 +2209,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
- if( pList==0 ) return;
+ if( pList==0 ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
@@ -2091,7 +2221,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
- if( db->mallocFailed || pParse->nErr ) return;
+ if( db->mallocFailed || pParse->nErr ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
@@ -2295,7 +2428,6 @@ void sqlite3EndTable(
if( pEnd==0 && pSelect==0 ){
return;
}
- assert( !db->mallocFailed );
p = pParse->pNewTable;
if( p==0 ) return;
@@ -2520,7 +2652,7 @@ void sqlite3EndTable(
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( (p->tabFlags & TF_Autoincrement)!=0 ){
+ if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){
Db *pDb = &db->aDb[iDb];
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->pSeqTab==0 ){
@@ -2534,7 +2666,7 @@ void sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
+ sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
}
/* Add the table to the in-memory representation of the database.
@@ -2543,6 +2675,7 @@ void sqlite3EndTable(
Table *pOld;
Schema *pSchema = p->pSchema;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ assert( HasRowid(p) || p->iPKey<0 );
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
@@ -2552,19 +2685,27 @@ void sqlite3EndTable(
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
-#ifndef SQLITE_OMIT_ALTERTABLE
- if( !p->pSelect ){
- const char *zName = (const char *)pParse->sNameToken.z;
- int nName;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ){
- pCons = pEnd;
- }
- nName = (int)((const char *)pCons->z - zName);
- p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
+ /* If this is the magic sqlite_sequence table used by autoincrement,
+ ** then record a pointer to this table in the main database structure
+ ** so that INSERT can find the table easily. */
+ assert( !pParse->nested );
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( strcmp(p->zName, "sqlite_sequence")==0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ p->pSchema->pSeqTab = p;
}
#endif
}
+
+#ifndef SQLITE_OMIT_ALTERTABLE
+ if( !pSelect && !p->pSelect ){
+ assert( pCons && pEnd );
+ if( pCons->z==0 ){
+ pCons = pEnd;
+ }
+ p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
+ }
+#endif
}
#ifndef SQLITE_OMIT_VIEW
@@ -2597,6 +2738,16 @@ void sqlite3CreateView(
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ) goto create_view_fail;
+
+ /* Legacy versions of SQLite allowed the use of the magic "rowid" column
+ ** on a view, even though views do not have rowids. The following flag
+ ** setting fixes this problem. But the fix can be disabled by compiling
+ ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
+ ** depend upon the old buggy behavior. */
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ p->tabFlags |= TF_NoVisibleRowid;
+#endif
+
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
@@ -2755,6 +2906,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
+ pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
@@ -3072,7 +3224,10 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
if( noErr ) db->suppressErr--;
if( pTab==0 ){
- if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ if( noErr ){
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
+ }
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -3642,6 +3797,7 @@ void sqlite3CreateIndex(
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
@@ -4022,7 +4178,7 @@ void sqlite3CreateIndex(
sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
@@ -4043,7 +4199,11 @@ 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 */
+ if( pTab ){
+ /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list.
+ ** The list was already ordered when this routine was entered, so at this
+ ** point at most a single index (the newly added index) will be out of
+ ** order. So we have to reorder at most one index. */
Index **ppFrom = &pTab->pIndex;
Index *pThis;
for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
@@ -4057,6 +4217,16 @@ void sqlite3CreateIndex(
}
break;
}
+#ifdef SQLITE_DEBUG
+ /* Verify that all REPLACE indexes really are now at the end
+ ** of the index list. In other words, no other index type ever
+ ** comes after a REPLACE index on the list. */
+ for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){
+ assert( pThis->onError!=OE_Replace
+ || pThis->pNext==0
+ || pThis->pNext->onError==OE_Replace );
+ }
+#endif
}
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
@@ -4108,7 +4278,7 @@ void sqlite3DefaultRowEst(Index *pIdx){
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
- if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
+ if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlite3LogEst(2) ); }
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
@@ -4143,9 +4313,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
if( !ifExists ){
- sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
+ sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
@@ -4165,7 +4336,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto exit_drop_index;
}
- if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
+ if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX;
if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
goto exit_drop_index;
}
@@ -4415,7 +4586,7 @@ SrcList *sqlite3SrcListAppend(
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
assert( pParse!=0 );
@@ -4456,9 +4627,9 @@ SrcList *sqlite3SrcListAppend(
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
- struct SrcList_item *pItem;
- assert(pList || pParse->db->mallocFailed );
- if( pList ){
+ SrcItem *pItem;
+ assert( pList || pParse->db->mallocFailed );
+ if( ALWAYS(pList) ){
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
@@ -4474,7 +4645,7 @@ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
*/
void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; inSrc; i++, pItem++){
if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
@@ -4516,7 +4687,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
Expr *pOn, /* The ON clause of a join */
IdList *pUsing /* The USING clause of a join */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
@@ -4560,7 +4731,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && pIndexedBy->n>0 ){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
@@ -4590,7 +4761,7 @@ SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
- memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(struct SrcList_item));
+ memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlite3DbFree(pParse->db, p2);
}
}
@@ -4603,7 +4774,7 @@ SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
*/
void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
if( p ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ SrcItem *pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -4758,7 +4929,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
assert( iDb>=0 && iDbdb->nDb );
assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
- assert( iDbdb, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
@@ -5100,24 +5271,76 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
}
#ifndef SQLITE_OMIT_CTE
+/*
+** Create a new CTE object
+*/
+Cte *sqlite3CteNew(
+ Parse *pParse, /* Parsing context */
+ Token *pName, /* Name of the common-table */
+ ExprList *pArglist, /* Optional column name list for the table */
+ Select *pQuery, /* Query used to initialize the table */
+ u8 eM10d /* The MATERIALIZED flag */
+){
+ Cte *pNew;
+ sqlite3 *db = pParse->db;
+
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
+ assert( pNew!=0 || db->mallocFailed );
+
+ if( db->mallocFailed ){
+ sqlite3ExprListDelete(db, pArglist);
+ sqlite3SelectDelete(db, pQuery);
+ }else{
+ pNew->pSelect = pQuery;
+ pNew->pCols = pArglist;
+ pNew->zName = sqlite3NameFromToken(pParse->db, pName);
+ pNew->eM10d = eM10d;
+ }
+ return pNew;
+}
+
+/*
+** Clear information from a Cte object, but do not deallocate storage
+** for the object itself.
+*/
+static void cteClear(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ sqlite3ExprListDelete(db, pCte->pCols);
+ sqlite3SelectDelete(db, pCte->pSelect);
+ sqlite3DbFree(db, pCte->zName);
+}
+
+/*
+** Free the contents of the CTE object passed as the second argument.
+*/
+void sqlite3CteDelete(sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ cteClear(db, pCte);
+ sqlite3DbFree(db, pCte);
+}
+
/*
** This routine is invoked once per CTE by the parser while parsing a
-** WITH clause.
+** WITH clause. The CTE described by teh third argument is added to
+** the WITH clause of the second argument. If the second argument is
+** NULL, then a new WITH argument is created.
*/
With *sqlite3WithAdd(
Parse *pParse, /* Parsing context */
With *pWith, /* Existing WITH clause, or NULL */
- Token *pName, /* Name of the common-table */
- ExprList *pArglist, /* Optional column name list for the table */
- Select *pQuery /* Query used to initialize the table */
+ Cte *pCte /* CTE to add to the WITH clause */
){
sqlite3 *db = pParse->db;
With *pNew;
char *zName;
+ if( pCte==0 ){
+ return pWith;
+ }
+
/* Check that the CTE name is unique within this WITH clause. If
** not, store an error in the Parse structure. */
- zName = sqlite3NameFromToken(pParse->db, pName);
+ zName = pCte->zName;
if( zName && pWith ){
int i;
for(i=0; inCte; i++){
@@ -5136,16 +5359,11 @@ With *sqlite3WithAdd(
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
if( db->mallocFailed ){
- sqlite3ExprListDelete(db, pArglist);
- sqlite3SelectDelete(db, pQuery);
- sqlite3DbFree(db, zName);
+ sqlite3CteDelete(db, pCte);
pNew = pWith;
}else{
- pNew->a[pNew->nCte].pSelect = pQuery;
- pNew->a[pNew->nCte].pCols = pArglist;
- pNew->a[pNew->nCte].zName = zName;
- pNew->a[pNew->nCte].zCteErr = 0;
- pNew->nCte++;
+ pNew->a[pNew->nCte++] = *pCte;
+ sqlite3DbFree(db, pCte);
}
return pNew;
@@ -5158,10 +5376,7 @@ void sqlite3WithDelete(sqlite3 *db, With *pWith){
if( pWith ){
int i;
for(i=0; inCte; i++){
- struct Cte *pCte = &pWith->a[i];
- sqlite3ExprListDelete(db, pCte->pCols);
- sqlite3SelectDelete(db, pCte->pSelect);
- sqlite3DbFree(db, pCte->zName);
+ cteClear(db, &pWith->a[i]);
}
sqlite3DbFree(db, pWith);
}
diff --git a/src/ctime.c b/src/ctime.c
index e3e1e79a9..fa69216c6 100644
--- a/src/ctime.c
+++ b/src/ctime.c
@@ -58,8 +58,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_64BIT_STATS
"64BIT_STATS",
#endif
-#if SQLITE_ALLOW_COVERING_INDEX_SCAN
- "ALLOW_COVERING_INDEX_SCAN",
+#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
+ "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
+# endif
#endif
#if SQLITE_ALLOW_URI_AUTHORITY
"ALLOW_URI_AUTHORITY",
@@ -121,8 +123,10 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_DEFAULT_LOOKASIDE
"DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
-#if SQLITE_DEFAULT_MEMSTATUS
- "DEFAULT_MEMSTATUS",
+#ifdef SQLITE_DEFAULT_MEMSTATUS
+# if SQLITE_DEFAULT_MEMSTATUS != 1
+ "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
+# endif
#endif
#ifdef SQLITE_DEFAULT_MMAP_SIZE
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
@@ -196,7 +200,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_BYTECODE_VTAB
"ENABLE_BYTECODE_VTAB",
#endif
-#if SQLITE_ENABLE_CEROD
+#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
@@ -211,17 +215,17 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_CURSOR_HINTS
"ENABLE_CURSOR_HINTS",
#endif
+#if SQLITE_ENABLE_DBPAGE_VTAB
+ "ENABLE_DBPAGE_VTAB",
+#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
"ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
+#if SQLITE_ENABLE_EXPLAIN_COMMENTS
+ "ENABLE_EXPLAIN_COMMENTS",
#endif
#if SQLITE_ENABLE_FTS3
"ENABLE_FTS3",
@@ -259,6 +263,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
+#if SQLITE_ENABLE_MATH_FUNCTIONS
+ "ENABLE_MATH_FUNCTIONS",
+#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
@@ -277,6 +284,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_NULL_TRIM
"ENABLE_NULL_TRIM",
#endif
+#if SQLITE_ENABLE_OFFSET_SQL_FUNC
+ "ENABLE_OFFSET_SQL_FUNC",
+#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
@@ -307,7 +317,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_SQLLOG
"ENABLE_SQLLOG",
#endif
-#if defined(SQLITE_ENABLE_STAT4)
+#if SQLITE_ENABLE_STAT4
"ENABLE_STAT4",
#endif
#if SQLITE_ENABLE_STMTVTAB
@@ -361,8 +371,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
"HAVE_ISNAN",
#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
+ "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
+# endif
#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
"IGNORE_AFP_LOCK_ERRORS",
@@ -460,9 +472,6 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_MUTEX_NOOP
"MUTEX_NOOP",
#endif
-#if SQLITE_MUTEX_NREF
- "MUTEX_NREF",
-#endif
#if SQLITE_MUTEX_OMIT
"MUTEX_OMIT",
#endif
@@ -532,7 +541,7 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_CTE
"OMIT_CTE",
#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
"OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
@@ -541,6 +550,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_DEPRECATED
"OMIT_DEPRECATED",
#endif
+#if SQLITE_OMIT_DESERIALIZE
+ "OMIT_DESERIALIZE",
+#endif
#if SQLITE_OMIT_DISKIO
"OMIT_DISKIO",
#endif
@@ -568,6 +580,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_INTEGRITY_CHECK
"OMIT_INTEGRITY_CHECK",
#endif
+#if SQLITE_OMIT_INTROSPECTION_PRAGMAS
+ "OMIT_INTROSPECTION_PRAGMAS",
+#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
"OMIT_LIKE_OPTIMIZATION",
#endif
@@ -631,8 +646,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_OMIT_TEST_CONTROL
"OMIT_TEST_CONTROL",
#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
+#ifdef SQLITE_OMIT_TRACE
+# if SQLITE_OMIT_TRACE != 1
+ "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
+# endif
#endif
#if SQLITE_OMIT_TRIGGER
"OMIT_TRIGGER",
@@ -667,8 +684,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_PERFORMANCE_TRACE
"PERFORMANCE_TRACE",
#endif
-#if SQLITE_POWERSAFE_OVERWRITE
- "POWERSAFE_OVERWRITE",
+#ifdef SQLITE_POWERSAFE_OVERWRITE
+# if SQLITE_POWERSAFE_OVERWRITE != 1
+ "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
+# endif
#endif
#if SQLITE_PREFER_PROXY_LOCKING
"PREFER_PROXY_LOCKING",
@@ -703,7 +722,10 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_SUBSTR_COMPATIBILITY
"SUBSTR_COMPATIBILITY",
#endif
-#if SQLITE_SYSTEM_MALLOC
+#if (!defined(SQLITE_WIN32_MALLOC) \
+ && !defined(SQLITE_ZERO_MALLOC) \
+ && !defined(SQLITE_MEMDEBUG) \
+ ) || defined(SQLITE_SYSTEM_MALLOC)
"SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
diff --git a/src/date.c b/src/date.c
index 1db26b1c6..f88f544e3 100644
--- a/src/date.c
+++ b/src/date.c
@@ -881,6 +881,7 @@ static int isDate(
int eType;
memset(p, 0, sizeof(*p));
if( argc==0 ){
+ if( !sqlite3NotPureFunc(context) ) return 1;
return setDateTimeToCurrent(context, p);
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
diff --git a/src/delete.c b/src/delete.c
index 064ae7325..dd074bb35 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -29,7 +29,7 @@
**
*/
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
@@ -37,9 +37,9 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
pItem->pTab = pTab;
if( pTab ){
pTab->nTabRef++;
- }
- if( sqlite3IndexedByLookup(pParse, pItem) ){
- pTab = 0;
+ if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
+ pTab = 0;
+ }
}
return pTab;
}
@@ -207,9 +207,15 @@ Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pTab = 0;
- pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
+ pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pTab = pTab;
- pSrc->a[0].pIBIndex = 0;
+ if( pSrc->a[0].fg.isIndexedBy ){
+ pSrc->a[0].u2.pIBIndex = 0;
+ pSrc->a[0].fg.isIndexedBy = 0;
+ sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
+ }else if( pSrc->a[0].fg.isCte ){
+ pSrc->a[0].u2.pCteUse->nUse++;
+ }
/* generate the SELECT expression tree. */
pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
@@ -387,6 +393,7 @@ void sqlite3DeleteFrom(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
memCnt = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
@@ -421,6 +428,9 @@ void sqlite3DeleteFrom(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
+ if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
+ sqlite3VdbeChangeP3(v, -1, memCnt ? memCnt : -1);
+ }
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
@@ -608,7 +618,7 @@ void sqlite3DeleteFrom(
** invoke the callback function.
*/
if( memCnt ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
}
@@ -932,13 +942,15 @@ int sqlite3GenerateIndexKey(
continue;
}
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
- /* If the column affinity is REAL but the number is an integer, then it
- ** might be stored in the table as an integer (using a compact
- ** representation) then converted to REAL by an OP_RealAffinity opcode.
- ** But we are getting ready to store this value back into an index, where
- ** it should be converted by to INTEGER again. So omit the OP_RealAffinity
- ** opcode if it is present */
- sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
+ if( pIdx->aiColumn[j]>=0 ){
+ /* If the column affinity is REAL but the number is an integer, then it
+ ** might be stored in the table as an integer (using a compact
+ ** representation) then converted to REAL by an OP_RealAffinity opcode.
+ ** But we are getting ready to store this value back into an index, where
+ ** it should be converted by to INTEGER again. So omit the
+ ** OP_RealAffinity opcode if it is present */
+ sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
+ }
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
diff --git a/src/expr.c b/src/expr.c
index 685f04175..b751f51a6 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -52,6 +52,10 @@ char sqlite3ExprAffinity(const Expr *pExpr){
assert( pExpr!=0 );
}
op = pExpr->op;
+ if( op==TK_REGISTER ) op = pExpr->op2;
+ if( (op==TK_COLUMN || op==TK_AGG_COLUMN) && pExpr->y.pTab ){
+ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
+ }
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
assert( pExpr->x.pSelect!=0 );
@@ -59,16 +63,12 @@ char sqlite3ExprAffinity(const Expr *pExpr){
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
- if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
- return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
- }
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft->flags&EP_xIsSelect );
return sqlite3ExprAffinity(
@@ -445,7 +445,7 @@ int sqlite3ExprVectorSize(Expr *pExpr){
** been positioned.
*/
Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
- assert( iop==TK_ERROR );
if( sqlite3ExprIsVector(pVector) ){
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
@@ -561,7 +561,7 @@ static int exprVectorRegister(
int *pRegFree /* OUT: Temp register to free */
){
u8 op = pVector->op;
- assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT );
+ assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR );
if( op==TK_REGISTER ){
*ppExpr = sqlite3VectorFieldSubexpr(pVector, iField);
return pVector->iTable+iField;
@@ -570,8 +570,11 @@ static int exprVectorRegister(
*ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
return regSelect+iField;
}
- *ppExpr = pVector->x.pList->a[iField].pExpr;
- return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
+ if( op==TK_VECTOR ){
+ *ppExpr = pVector->x.pList->a[iField].pExpr;
+ return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
+ }
+ return 0;
}
/*
@@ -600,6 +603,7 @@ static void codeVectorCompare(
int regLeft = 0;
int regRight = 0;
u8 opx = op;
+ int addrCmp = 0;
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
@@ -619,21 +623,24 @@ static void codeVectorCompare(
assert( p5==0 || pExpr->op!=op );
assert( p5==SQLITE_NULLEQ || pExpr->op==op );
- p5 |= SQLITE_STOREP2;
- if( opx==TK_LE ) opx = TK_LT;
- if( opx==TK_GE ) opx = TK_GT;
+ if( op==TK_LE ) opx = TK_LT;
+ if( op==TK_GE ) opx = TK_GT;
+ if( op==TK_NE ) opx = TK_EQ;
regLeft = exprCodeSubselect(pParse, pLeft);
regRight = exprCodeSubselect(pParse, pRight);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, dest);
for(i=0; 1 /*Loop exits by "break"*/; i++){
int regFree1 = 0, regFree2 = 0;
- Expr *pL, *pR;
+ Expr *pL = 0, *pR = 0;
int r1, r2;
assert( i>=0 && i0
@@ -947,8 +960,8 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
- sqlite3ExprDelete(db, pLeft);
- sqlite3ExprDelete(db, pRight);
+ sqlite3ExprDeferredDelete(pParse, pLeft);
+ sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
@@ -1145,6 +1158,22 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
+
+/*
+** Arrange to cause pExpr to be deleted when the pParse is deleted.
+** This is similar to sqlite3ExprDelete() except that the delete is
+** deferred untilthe pParse is deleted.
+**
+** The pExpr might be deleted immediately on an OOM error.
+**
+** The deferred delete is (currently) implemented by adding the
+** pExpr to the pParse->pConstExpr list with a register number of 0.
+*/
+void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ pParse->pConstExpr =
+ sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+}
+
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
@@ -1287,6 +1316,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
+ assert( zAlloc!=0 );
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
@@ -1365,7 +1395,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
- assert( p->pRight==0 || p->pRight==p->pLeft );
+ assert( p->pRight==0 || p->pRight==p->pLeft
+ || ExprHasProperty(p->pLeft, EP_Subquery) );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -1382,7 +1413,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
** and the db->mallocFailed flag set.
*/
#ifndef SQLITE_OMIT_CTE
-static With *withDup(sqlite3 *db, With *p){
+With *sqlite3WithDup(sqlite3 *db, With *p){
With *pRet = 0;
if( p ){
sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
@@ -1400,7 +1431,7 @@ static With *withDup(sqlite3 *db, With *p){
return pRet;
}
#else
-# define withDup(x,y) 0
+# define sqlite3WithDup(x,y) 0
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -1467,6 +1498,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
+ pNew->nAlloc = p->nAlloc;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; inExpr; i++, pItem++, pOldItem++){
@@ -1479,7 +1511,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
- assert( pOldExpr->pLeft==pOldExpr->pRight );
+ assert( pOldExpr->pLeft==pOldExpr->pRight
+ || ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
}else{
assert( i>0 );
@@ -1519,8 +1552,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; inSrc; i++){
- struct SrcList_item *pNewItem = &pNew->a[i];
- struct SrcList_item *pOldItem = &p->a[i];
+ SrcItem *pNewItem = &pNew->a[i];
+ SrcItem *pOldItem = &p->a[i];
Table *pTab;
pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
@@ -1533,7 +1566,10 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}
- pNewItem->pIBIndex = pOldItem->pIBIndex;
+ pNewItem->u2 = pOldItem->u2;
+ if( pNewItem->fg.isCte ){
+ pNewItem->u2.pCteUse->nUse++;
+ }
if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
@@ -1599,13 +1635,21 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
- pNew->pWith = withDup(db, p->pWith);
+ pNew->pWith = sqlite3WithDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
+ if( db->mallocFailed ){
+ /* Any prior OOM might have left the Select object incomplete.
+ ** Delete the whole thing rather than allow an incomplete Select
+ ** to be used by the code generator. */
+ pNew->pNext = 0;
+ sqlite3SelectDelete(db, pNew);
+ break;
+ }
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
@@ -1636,41 +1680,64 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
+static const struct ExprList_item zeroItem = {0};
+SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
+ sqlite3 *db, /* Database handle. Used for memory allocation */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pList;
+
+ pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ if( pList==0 ){
+ sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }
+ pList->nAlloc = 4;
+ pList->nExpr = 1;
+ pItem = &pList->a[0];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
+SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
+ sqlite3 *db, /* Database handle. Used for memory allocation */
+ ExprList *pList, /* List to which to append. Might be NULL */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pNew;
+ pList->nAlloc *= 2;
+ pNew = sqlite3DbRealloc(db, pList,
+ sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ if( pNew==0 ){
+ sqlite3ExprListDelete(db, pList);
+ sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }else{
+ pList = pNew;
+ }
+ pItem = &pList->a[pList->nExpr++];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
ExprList *sqlite3ExprListAppend(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
- sqlite3 *db = pParse->db;
- assert( db!=0 );
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
- if( pList==0 ){
- goto no_mem;
- }
- pList->nExpr = 0;
- }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- ExprList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0]));
- if( pNew==0 ){
- goto no_mem;
- }
- pList = pNew;
+ return sqlite3ExprListAppendNew(pParse->db,pExpr);
+ }
+ if( pList->nAllocnExpr+1 ){
+ return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr);
}
pItem = &pList->a[pList->nExpr++];
- assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
- assert( offsetof(struct ExprList_item,pExpr)==0 );
- memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
+ *pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
-
-no_mem:
- /* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(db, pExpr);
- sqlite3ExprListDelete(db, pList);
- return 0;
}
/*
@@ -2283,8 +2350,10 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
*/
int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
+ assert( p!=0 );
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
+ assert( p!=0 );
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
@@ -2571,7 +2640,7 @@ int sqlite3FindInIndex(
/* Code an OP_Transaction and OP_TableLock for . */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb>=0 && iDb=0 && iDbtnum, 0, pTab->zName);
@@ -2916,19 +2985,23 @@ void sqlite3CodeRhsOfIN(
/* If the LHS and RHS of the IN operator do not match, that
** error will have been caught long before we reach this point. */
if( ALWAYS(pEList->nExpr==nVal) ){
+ Select *pCopy;
SelectDest dest;
int i;
+ int rc;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
- if( sqlite3Select(pParse, pSelect, &dest) ){
- sqlite3DbFree(pParse->db, dest.zAffSdst);
+ pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
+ rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
+ sqlite3SelectDelete(pParse->db, pCopy);
+ sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
- }
- sqlite3DbFree(pParse->db, dest.zAffSdst);
+ }
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
@@ -3027,12 +3100,30 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
+ if( pParse->nErr ) return 0;
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
pSel = pExpr->x.pSelect;
+ /* If this routine has already been coded, then invoke it as a
+ ** subroutine. */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
+ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ return pExpr->iTable;
+ }
+
+ /* Begin coding the subroutine */
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
+ VdbeComment((v, "return address"));
+
+
/* The evaluation of the EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
**
@@ -3044,22 +3135,6 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
- /* If this routine has already been coded, then invoke it as a
- ** subroutine. */
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
- ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
- sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
- pExpr->y.sub.iAddr);
- return pExpr->iTable;
- }
-
- /* Begin coding the subroutine */
- ExprSetProperty(pExpr, EP_Subrtn);
- pExpr->y.sub.regReturn = ++pParse->nMem;
- pExpr->y.sub.iAddr =
- sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
- VdbeComment((v, "return address"));
-
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -3108,19 +3183,22 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
+ if( pParse->nErr ){
+ pExpr->op2 = pExpr->op;
+ pExpr->op = TK_ERROR;
+ }
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
-
- /* Subroutine return */
- sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
- sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
- sqlite3ClearTempRegCache(pParse);
}
+ /* Subroutine return */
+ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
+ sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
+ sqlite3ClearTempRegCache(pParse);
return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -3134,7 +3212,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
*/
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
- if( (pIn->flags & EP_xIsSelect) ){
+ if( (pIn->flags & EP_xIsSelect)!=0 && !pParse->db->mallocFailed ){
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
return 1;
@@ -3325,6 +3403,7 @@ static void sqlite3ExprCodeIN(
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; ipLeft, i);
+ if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
@@ -3950,7 +4029,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
** Expr node to be passed into this function, it will be handled
** sanely and not crash. But keep the assert() to bring the problem
** to the attention of the developers. */
- assert( op==TK_NULL );
+ assert( op==TK_NULL || op==TK_ERROR || pParse->db->mallocFailed );
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
@@ -4016,8 +4095,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
- codeCompare(pParse, pLeft, pExpr->pRight, op,
- r1, r2, inReg, SQLITE_STOREP2 | p5,
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
+ codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
+ sqlite3VdbeCurrentAddr(v)+2, p5,
ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -4025,6 +4105,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
+ if( p5==SQLITE_NULLEQ ){
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
+ }
testcase( regFree1==0 );
testcase( regFree2==0 );
}
@@ -4287,7 +4372,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
- assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
+ assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT
+ || pExpr->pLeft->op==TK_ERROR );
if( pExpr->iTable!=0
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
){
@@ -5767,8 +5853,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
@@ -5777,8 +5862,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- pParse->pConstExpr =
- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
@@ -5850,7 +5934,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( ALWAYS(pSrcList!=0) ){
- struct SrcList_item *pItem = pSrcList->a;
+ SrcItem *pItem = pSrcList->a;
for(i=0; inSrc; i++, pItem++){
struct AggInfo_col *pCol;
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
@@ -5921,6 +6005,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; inFunc; i++, pItem++){
+ if( pItem->pFExpr==pExpr ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
diff --git a/src/fkey.c b/src/fkey.c
index 959e994d1..9f622f40c 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -1024,7 +1024,7 @@ void sqlite3FkCheck(
** child table as a SrcList for sqlite3WhereBegin() */
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
pItem->pTab->nTabRef++;
@@ -1112,7 +1112,9 @@ u32 sqlite3FkOldmask(
**
** For an UPDATE, this function returns 2 if:
**
-** * There are any FKs for which pTab is the child and the parent table, or
+** * There are any FKs for which pTab is the child and the parent table
+** and any FK processing at all is required (even of a different FK), or
+**
** * the UPDATE modifies one or more parent keys for which the action is
** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
**
@@ -1124,13 +1126,14 @@ int sqlite3FkRequired(
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
- int eRet = 0;
+ int eRet = 1; /* Value to return if bHaveFK is true */
+ int bHaveFK = 0; /* If FK processing is required */
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
- eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
+ bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
@@ -1138,9 +1141,9 @@ int sqlite3FkRequired(
/* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
- eRet = 1;
+ if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
+ bHaveFK = 1;
}
}
@@ -1148,12 +1151,12 @@ int sqlite3FkRequired(
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
if( p->aAction[1]!=OE_None ) return 2;
- eRet = 1;
+ bHaveFK = 1;
}
}
}
}
- return eRet;
+ return bHaveFK ? eRet : 0;
}
/*
@@ -1352,7 +1355,7 @@ static Trigger *fkActionTrigger(
switch( action ){
case OE_Restrict:
- pStep->op = TK_SELECT;
+ pStep->op = TK_SELECT;
break;
case OE_Cascade:
if( !pChanges ){
diff --git a/src/func.c b/src/func.c
index 5d00c94a9..dc19ec722 100644
--- a/src/func.c
+++ b/src/func.c
@@ -694,7 +694,8 @@ static int patternCompare(
/* Skip over multiple "*" characters in the pattern. If there
** are also "?" characters, skip those as well, but consume a
** single character of the input string for each "?" skipped */
- while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
+ while( (c=Utf8Read(zPattern)) == matchAll
+ || (c == matchOne && matchOne!=0) ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
return SQLITE_NOWILDCARDMATCH;
}
@@ -1315,10 +1316,10 @@ static void trimFunc(
){
const unsigned char *zIn; /* Input string */
const unsigned char *zCharSet; /* Set of characters to trim */
- int nIn; /* Number of bytes in input */
+ unsigned int nIn; /* Number of bytes in input */
int flags; /* 1: trimleft 2: trimright 3: trim */
int i; /* Loop counter */
- unsigned char *aLen = 0; /* Length of each character in zCharSet */
+ unsigned int *aLen = 0; /* Length of each character in zCharSet */
unsigned char **azChar = 0; /* Individual characters in zCharSet */
int nChar; /* Number of characters in zCharSet */
@@ -1327,13 +1328,13 @@ static void trimFunc(
}
zIn = sqlite3_value_text(argv[0]);
if( zIn==0 ) return;
- nIn = sqlite3_value_bytes(argv[0]);
+ nIn = (unsigned)sqlite3_value_bytes(argv[0]);
assert( zIn==sqlite3_value_text(argv[0]) );
if( argc==1 ){
- static const unsigned char lenOne[] = { 1 };
+ static const unsigned lenOne[] = { 1 };
static unsigned char * const azOne[] = { (u8*)" " };
nChar = 1;
- aLen = (u8*)lenOne;
+ aLen = (unsigned*)lenOne;
azChar = (unsigned char **)azOne;
zCharSet = 0;
}else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
@@ -1344,15 +1345,16 @@ static void trimFunc(
SQLITE_SKIP_UTF8(z);
}
if( nChar>0 ){
- azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
+ azChar = contextMalloc(context,
+ ((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
if( azChar==0 ){
return;
}
- aLen = (unsigned char*)&azChar[nChar];
+ aLen = (unsigned*)&azChar[nChar];
for(z=zCharSet, nChar=0; *z; nChar++){
azChar[nChar] = (unsigned char *)z;
SQLITE_SKIP_UTF8(z);
- aLen[nChar] = (u8)(z - azChar[nChar]);
+ aLen[nChar] = (unsigned)(z - azChar[nChar]);
}
}
}
@@ -1360,7 +1362,7 @@ static void trimFunc(
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
if( flags & 1 ){
while( nIn>0 ){
- int len = 0;
+ unsigned int len = 0;
for(i=0; i0 ){
- int len = 0;
+ unsigned int len = 0;
for(i=0; iop!=TK_FUNCTION || !pExpr->x.pList ){
+ assert( pExpr!=0 );
+ assert( pExpr->op==TK_FUNCTION );
+ if( !pExpr->x.pList ){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -1904,6 +1908,201 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
return 1;
}
+/* Mathematical Constants */
+#ifndef M_PI
+# define M_PI 3.141592653589793238462643383279502884
+#endif
+#ifndef M_LN10
+# define M_LN10 2.302585092994045684017991454684364208
+#endif
+#ifndef M_LN2
+# define M_LN2 0.693147180559945309417232121458176568
+#endif
+
+
+/* Extra math functions that require linking with -lm
+*/
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+/*
+** Implementation SQL functions:
+**
+** ceil(X)
+** ceiling(X)
+** floor(X)
+**
+** The sqlite3_user_data() pointer is a pointer to the libm implementation
+** of the underlying C function.
+*/
+static void ceilingFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==1 );
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER: {
+ sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
+ break;
+ }
+ case SQLITE_FLOAT: {
+ double (*x)(double) = (double(*)(double))sqlite3_user_data(context);
+ sqlite3_result_double(context, x(sqlite3_value_double(argv[0])));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+/*
+** On some systems, ceil() and floor() are intrinsic function. You are
+** unable to take a pointer to these functions. Hence, we here wrap them
+** in our own actual functions.
+*/
+static double xCeil(double x){ return ceil(x); }
+static double xFloor(double x){ return floor(x); }
+
+/*
+** Implementation of SQL functions:
+**
+** ln(X) - natural logarithm
+** log(X) - log X base 10
+** log10(X) - log X base 10
+** log(B,X) - log X base B
+*/
+static void logFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ double x, b, ans;
+ assert( argc==1 || argc==2 );
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ x = sqlite3_value_double(argv[0]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ if( argc==2 ){
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ b = log(x);
+ if( b<=0.0 ) return;
+ x = sqlite3_value_double(argv[1]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ ans = log(x)/b;
+ }else{
+ ans = log(x);
+ switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
+ case 1:
+ /* Convert from natural logarithm to log base 10 */
+ ans *= 1.0/M_LN10;
+ break;
+ case 2:
+ /* Convert from natural logarithm to log base 2 */
+ ans *= 1.0/M_LN2;
+ break;
+ default:
+ break;
+ }
+ }
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Functions to converts degrees to radians and radians to degrees.
+*/
+static double degToRad(double x){ return x*(M_PI/180.0); }
+static double radToDeg(double x){ return x*(180.0/M_PI); }
+
+/*
+** Implementation of 1-argument SQL math functions:
+**
+** exp(X) - Compute e to the X-th power
+*/
+static void math1Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0;
+ double v0, ans;
+ double (*x)(double);
+ assert( argc==1 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ x = (double(*)(double))sqlite3_user_data(context);
+ ans = x(v0);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void math2Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0, type1;
+ double v0, v1, ans;
+ double (*x)(double,double);
+ assert( argc==2 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ type1 = sqlite3_value_numeric_type(argv[1]);
+ if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ v1 = sqlite3_value_double(argv[1]);
+ x = (double(*)(double,double))sqlite3_user_data(context);
+ ans = x(v0, v1);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 0-argument pi() function.
+*/
+static void piFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==0 );
+ sqlite3_result_double(context, M_PI);
+}
+
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+
+/*
+** Implementation of sign(X) function.
+*/
+static void signFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int type0;
+ double x;
+ UNUSED_PARAMETER(argc);
+ assert( argc==1 );
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ x = sqlite3_value_double(argv[0]);
+ sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
+}
+
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -2022,6 +2221,43 @@ void sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ MFUNCTION(ceil, 1, xCeil, ceilingFunc ),
+ MFUNCTION(ceiling, 1, xCeil, ceilingFunc ),
+ MFUNCTION(floor, 1, xFloor, ceilingFunc ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(trunc, 1, trunc, ceilingFunc ),
+#endif
+ FUNCTION(ln, 1, 0, 0, logFunc ),
+ FUNCTION(log, 1, 1, 0, logFunc ),
+ FUNCTION(log10, 1, 1, 0, logFunc ),
+ FUNCTION(log2, 1, 2, 0, logFunc ),
+ FUNCTION(log, 2, 0, 0, logFunc ),
+ MFUNCTION(exp, 1, exp, math1Func ),
+ MFUNCTION(pow, 2, pow, math2Func ),
+ MFUNCTION(power, 2, pow, math2Func ),
+ MFUNCTION(mod, 2, fmod, math2Func ),
+ MFUNCTION(acos, 1, acos, math1Func ),
+ MFUNCTION(asin, 1, asin, math1Func ),
+ MFUNCTION(atan, 1, atan, math1Func ),
+ MFUNCTION(atan2, 2, atan2, math2Func ),
+ MFUNCTION(cos, 1, cos, math1Func ),
+ MFUNCTION(sin, 1, sin, math1Func ),
+ MFUNCTION(tan, 1, tan, math1Func ),
+ MFUNCTION(cosh, 1, cosh, math1Func ),
+ MFUNCTION(sinh, 1, sinh, math1Func ),
+ MFUNCTION(tanh, 1, tanh, math1Func ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(acosh, 1, acosh, math1Func ),
+ MFUNCTION(asinh, 1, asinh, math1Func ),
+ MFUNCTION(atanh, 1, atanh, math1Func ),
+#endif
+ MFUNCTION(sqrt, 1, sqrt, math1Func ),
+ MFUNCTION(radians, 1, degToRad, math1Func ),
+ MFUNCTION(degrees, 1, radToDeg, math1Func ),
+ FUNCTION(pi, 0, 0, 0, piFunc ),
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+ FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
};
diff --git a/src/global.c b/src/global.c
index 8ef5a8b2d..4648c26d9 100644
--- a/src/global.c
+++ b/src/global.c
@@ -37,7 +37,7 @@ const unsigned char sqlite3UpperToLower[] = {
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
+ 252,253,254,255,
#endif
#ifdef SQLITE_EBCDIC
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
@@ -57,7 +57,35 @@ const unsigned char sqlite3UpperToLower[] = {
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
+/* All of the upper-to-lower conversion data is above. The following
+** 18 integers are completely unrelated. They are appended to the
+** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
+** going on:
+**
+** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
+** by invoking sqlite3MemCompare(A,B) which compares values A and B and
+** returns negative, zero, or positive if A is less then, equal to, or
+** greater than B, respectively. Then the true false results is found by
+** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
+** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
+** is negative, zero, or positive, where opcode is the specific opcode.
+** The only works because the comparison opcodes are consecutive and in
+** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
+** ensure that is the case.
+**
+** These elements must be appended to another array. Otherwise the
+** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
+** be undefined behavior. That's goofy, but the C-standards people thought
+** it was a good idea, so here we are.
+*/
+/* NE EQ GT LE LT GE */
+ 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
+ 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
+ 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
};
+const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
+const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
+const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
/*
** The following 256 byte lookup table is used to support SQLites built-in
@@ -251,7 +279,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
@@ -301,9 +329,10 @@ int sqlite3PendingByte = 0x40000000;
#endif
/*
-** Flags for select tracing and the ".selecttrace" macro of the CLI
+** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
*/
-u32 sqlite3_unsupported_selecttrace = 0;
+u32 sqlite3SelectTrace = 0;
+u32 sqlite3WhereTrace = 0;
#include "opcodes.h"
/*
diff --git a/src/insert.c b/src/insert.c
index 393cd528f..1ed0b4315 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -358,7 +358,7 @@ static int autoIncBegin(
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
- || IsVirtual(pSeqTab)
+ || NEVER(IsVirtual(pSeqTab))
|| pSeqTab->nCol!=2
){
pParse->nErr++;
@@ -370,7 +370,9 @@ static int autoIncBegin(
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
- if( pInfo==0 ) return 0;
+ sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo);
+ testcase( pParse->earlyCleanup );
+ if( pParse->db->mallocFailed ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
pInfo->pTab = pTab;
@@ -815,7 +817,7 @@ void sqlite3Insert(
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
- pTabList, 0, pColumn->a[i].zName);
+ pTabList->a, pColumn->a[i].zName);
pParse->checkSchema = 1;
goto insert_cleanup;
}
@@ -928,19 +930,24 @@ void sqlite3Insert(
}
}
#endif
- }
- /* Make sure the number of columns in the source data matches the number
- ** of columns to be inserted into the table.
- */
- for(i=0; inCol; i++){
- if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
- }
- if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlite3ErrorMsg(pParse,
- "table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol-nHidden, nColumn);
- goto insert_cleanup;
+ /* Make sure the number of columns in the source data matches the number
+ ** of columns to be inserted into the table.
+ */
+ assert( TF_HasHidden==COLFLAG_HIDDEN );
+ assert( TF_HasGenerated==COLFLAG_GENERATED );
+ assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) );
+ if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){
+ for(i=0; inCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
+ }
+ }
+ if( nColumn!=(pTab->nCol-nHidden) ){
+ sqlite3ErrorMsg(pParse,
+ "table %S has %d columns but %d values were supplied",
+ pTabList->a, pTab->nCol-nHidden, nColumn);
+ goto insert_cleanup;
+ }
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
@@ -952,6 +959,7 @@ void sqlite3Insert(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
@@ -975,6 +983,7 @@ void sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
+ Upsert *pNx;
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
pTab->zName);
@@ -988,13 +997,19 @@ void sqlite3Insert(
goto insert_cleanup;
}
pTabList->a[0].iCursor = iDataCur;
- pUpsert->pUpsertSrc = pTabList;
- pUpsert->regData = regData;
- pUpsert->iDataCur = iDataCur;
- pUpsert->iIdxCur = iIdxCur;
- if( pUpsert->pUpsertTarget ){
- sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
- }
+ pNx = pUpsert;
+ do{
+ pNx->pUpsertSrc = pTabList;
+ pNx->regData = regData;
+ pNx->iDataCur = iDataCur;
+ pNx->iIdxCur = iIdxCur;
+ if( pNx->pUpsertTarget ){
+ if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+ goto insert_cleanup;
+ }
+ }
+ pNx = pNx->pNextUpsert;
+ }while( pNx!=0 );
}
#endif
@@ -1135,11 +1150,6 @@ void sqlite3Insert(
sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
}
- /* Cannot have triggers on a virtual table. If it were possible,
- ** this block would have to account for hidden column.
- */
- assert( !IsVirtual(pTab) );
-
/* Copy the new data already generated. */
assert( pTab->nNVCol>0 );
sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
@@ -1238,7 +1248,7 @@ void sqlite3Insert(
}else
#endif
{
- int isReplace; /* Set to true if constraints may cause a replace */
+ int isReplace = 0;/* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
@@ -1258,6 +1268,13 @@ void sqlite3Insert(
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ }else if( pParse->bReturning ){
+ /* If there is a RETURNING clause, populate the rowid register with
+ ** constant value -1, in case one or more of the returned expressions
+ ** refer to the "rowid" of the view. */
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
+#endif
}
/* Update the count of rows that are inserted
@@ -1294,7 +1311,9 @@ void sqlite3Insert(
sqlite3VdbeJumpHere(v, addrInsTop);
}
+#ifndef SQLITE_OMIT_XFER_OPT
insert_end:
+#endif /* SQLITE_OMIT_XFER_OPT */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
** autoincrement tables.
@@ -1309,7 +1328,7 @@ void sqlite3Insert(
** invoke the callback function.
*/
if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
}
@@ -1399,6 +1418,70 @@ int sqlite3ExprReferencesUpdatedColumn(
return w.eCode!=0;
}
+/*
+** The sqlite3GenerateConstraintChecks() routine usually wants to visit
+** the indexes of a table in the order provided in the Table->pIndex list.
+** However, sometimes (rarely - when there is an upsert) it wants to visit
+** the indexes in a different order. The following data structures accomplish
+** this.
+**
+** The IndexIterator object is used to walk through all of the indexes
+** of a table in either Index.pNext order, or in some other order established
+** by an array of IndexListTerm objects.
+*/
+typedef struct IndexListTerm IndexListTerm;
+typedef struct IndexIterator IndexIterator;
+struct IndexIterator {
+ int eType; /* 0 for Index.pNext list. 1 for an array of IndexListTerm */
+ int i; /* Index of the current item from the list */
+ union {
+ struct { /* Use this object for eType==0: A Index.pNext list */
+ Index *pIdx; /* The current Index */
+ } lx;
+ struct { /* Use this object for eType==1; Array of IndexListTerm */
+ int nIdx; /* Size of the array */
+ IndexListTerm *aIdx; /* Array of IndexListTerms */
+ } ax;
+ } u;
+};
+
+/* When IndexIterator.eType==1, then each index is an array of instances
+** of the following object
+*/
+struct IndexListTerm {
+ Index *p; /* The index */
+ int ix; /* Which entry in the original Table.pIndex list is this index*/
+};
+
+/* Return the first index on the list */
+static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){
+ assert( pIter->i==0 );
+ if( pIter->eType ){
+ *pIx = pIter->u.ax.aIdx[0].ix;
+ return pIter->u.ax.aIdx[0].p;
+ }else{
+ *pIx = 0;
+ return pIter->u.lx.pIdx;
+ }
+}
+
+/* Return the next index from the list. Return NULL when out of indexes */
+static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
+ if( pIter->eType ){
+ int i = ++pIter->i;
+ if( i>=pIter->u.ax.nIdx ){
+ *pIx = i;
+ return 0;
+ }
+ *pIx = pIter->u.ax.aIdx[i].ix;
+ return pIter->u.ax.aIdx[i].p;
+ }else{
+ ++(*pIx);
+ pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
+ return pIter->u.lx.pIdx;
+ }
+}
+
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
@@ -1507,7 +1590,7 @@ void sqlite3GenerateConstraintChecks(
){
Vdbe *v; /* VDBE under constrution */
Index *pIdx; /* Pointer to one of the indices */
- Index *pPk = 0; /* The PRIMARY KEY index */
+ Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */
sqlite3 *db; /* Database connection */
int i; /* loop counter */
int ix; /* Index loop counter */
@@ -1515,11 +1598,11 @@ void sqlite3GenerateConstraintChecks(
int onError; /* Conflict resolution strategy */
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 */
- u8 isUpdate; /* True if this is an UPDATE operation */
+ Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */
+ u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
- int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
+ int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
+ int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
/* Variables associated with retesting uniqueness constraints after
@@ -1529,6 +1612,7 @@ void sqlite3GenerateConstraintChecks(
int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
int nReplaceTrig = 0; /* Number of replace triggers coded */
+ IndexIterator sIdxIter; /* Index iterator */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -1726,19 +1810,63 @@ void sqlite3GenerateConstraintChecks(
** list of indexes attached to a table puts all OE_Replace indexes last
** in the list. See sqlite3CreateIndex() for where that happens.
*/
-
+ sIdxIter.eType = 0;
+ sIdxIter.i = 0;
+ sIdxIter.u.ax.aIdx = 0; /* Silence harmless compiler warning */
+ sIdxIter.u.lx.pIdx = pTab->pIndex;
if( pUpsert ){
if( pUpsert->pUpsertTarget==0 ){
- /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
- ** Make all unique constraint resolution be OE_Ignore */
- assert( pUpsert->pUpsertSet==0 );
- overrideError = OE_Ignore;
- pUpsert = 0;
- }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
- /* If the constraint-target uniqueness check must be run first.
- ** Jump to that uniqueness check now */
- upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
- VdbeComment((v, "UPSERT constraint goes first"));
+ /* There is just on ON CONFLICT clause and it has no constraint-target */
+ assert( pUpsert->pNextUpsert==0 );
+ if( pUpsert->isDoUpdate==0 ){
+ /* A single ON CONFLICT DO NOTHING clause, without a constraint-target.
+ ** Make all unique constraint resolution be OE_Ignore */
+ overrideError = OE_Ignore;
+ pUpsert = 0;
+ }else{
+ /* A single ON CONFLICT DO UPDATE. Make all resolutions OE_Update */
+ overrideError = OE_Update;
+ }
+ }else if( pTab->pIndex!=0 ){
+ /* Otherwise, we'll need to run the IndexListTerm array version of the
+ ** iterator to ensure that all of the ON CONFLICT conditions are
+ ** checked first and in order. */
+ int nIdx, jj;
+ u64 nByte;
+ Upsert *pTerm;
+ u8 *bUsed;
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
+ assert( aRegIdx[nIdx]>0 );
+ }
+ sIdxIter.eType = 1;
+ sIdxIter.u.ax.nIdx = nIdx;
+ nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx;
+ sIdxIter.u.ax.aIdx = sqlite3DbMallocZero(db, nByte);
+ if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */
+ bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx];
+ pUpsert->pToFree = sIdxIter.u.ax.aIdx;
+ for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){
+ if( pTerm->pUpsertTarget==0 ) break;
+ if( pTerm->pUpsertIdx==0 ) continue; /* Skip ON CONFLICT for the IPK */
+ jj = 0;
+ pIdx = pTab->pIndex;
+ while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){
+ pIdx = pIdx->pNext;
+ jj++;
+ }
+ if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */
+ bUsed[jj] = 1;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){
+ if( bUsed[jj] ) continue;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ assert( i==nIdx );
}
}
@@ -1801,11 +1929,20 @@ void sqlite3GenerateConstraintChecks(
}
/* figure out whether or not upsert applies in this case */
- if( pUpsert && pUpsert->pUpsertIdx==0 ){
- if( pUpsert->pUpsertSet==0 ){
- onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
- }else{
- onError = OE_Update; /* DO UPDATE */
+ if( pUpsert ){
+ pUpsertClause = sqlite3UpsertOfIndex(pUpsert,0);
+ if( pUpsertClause!=0 ){
+ if( pUpsertClause->isDoUpdate==0 ){
+ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
+ }else{
+ onError = OE_Update; /* DO UPDATE */
+ }
+ }
+ if( pUpsertClause!=pUpsert ){
+ /* The first ON CONFLICT clause has a conflict target other than
+ ** the IPK. We have to jump ahead to that first ON CONFLICT clause
+ ** and then come back here and deal with the IPK afterwards */
+ upsertIpkDelay = sqlite3VdbeAddOp0(v, OP_Goto);
}
}
@@ -1815,7 +1952,7 @@ void sqlite3GenerateConstraintChecks(
** the UNIQUE constraints have run.
*/
if( onError==OE_Replace /* IPK rule is REPLACE */
- && onError!=overrideError /* Rules for other contraints are different */
+ && onError!=overrideError /* Rules for other constraints are different */
&& pTab->pIndex /* There exist other constraints */
){
ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
@@ -1912,7 +2049,9 @@ void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( ipkTop ){
+ if( pUpsert && pUpsertClause!=pUpsert ){
+ upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
+ }else if( ipkTop ){
ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, ipkTop-1);
}
@@ -1925,7 +2064,10 @@ void sqlite3GenerateConstraintChecks(
** This loop also handles the case of the PRIMARY KEY index for a
** WITHOUT ROWID table.
*/
- for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
+ for(pIdx = indexIteratorFirst(&sIdxIter, &ix);
+ pIdx;
+ pIdx = indexIteratorNext(&sIdxIter, &ix)
+ ){
int regIdx; /* Range of registers hold conent for pIdx */
int regR; /* Range of registers holding conflicting PK */
int iThisCur; /* Cursor for this UNIQUE index */
@@ -1933,15 +2075,14 @@ void sqlite3GenerateConstraintChecks(
int addrConflictCk; /* First opcode in the conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
- if( pUpIdx==pIdx ){
- addrUniqueOk = upsertJump+1;
- upsertBypass = sqlite3VdbeGoto(v, 0);
- VdbeComment((v, "Skip upsert subroutine"));
- sqlite3VdbeJumpHere(v, upsertJump);
- }else{
- addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
+ if( pUpsert ){
+ pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx);
+ if( upsertIpkDelay && pUpsertClause==pUpsert ){
+ sqlite3VdbeJumpHere(v, upsertIpkDelay);
+ }
}
- if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
+ addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
+ if( bAffinityDone==0 ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
@@ -2012,8 +2153,8 @@ void sqlite3GenerateConstraintChecks(
}
/* Figure out if the upsert clause applies to this index */
- if( pUpIdx==pIdx ){
- if( pUpsert->pUpsertSet==0 ){
+ if( pUpsertClause ){
+ if( pUpsertClause->isDoUpdate==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
@@ -2051,7 +2192,7 @@ void sqlite3GenerateConstraintChecks(
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */
- regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
+ regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField);
if( isUpdate || onError==OE_Replace ){
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
@@ -2203,13 +2344,16 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
- if( pUpIdx==pIdx ){
- sqlite3VdbeGoto(v, upsertJump+1);
- sqlite3VdbeJumpHere(v, upsertBypass);
- }else{
- sqlite3VdbeResolveLabel(v, addrUniqueOk);
- }
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
+ if( pUpsertClause
+ && upsertIpkReturn
+ && sqlite3UpsertNextIsIPK(pUpsertClause)
+ ){
+ sqlite3VdbeGoto(v, upsertIpkDelay+1);
+ sqlite3VdbeJumpHere(v, upsertIpkReturn);
+ upsertIpkReturn = 0;
+ }
}
/* If the IPK constraint is a REPLACE, run it last */
@@ -2275,6 +2419,32 @@ void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
}
#endif
+/*
+** Table pTab is a WITHOUT ROWID table that is being written to. The cursor
+** number is iCur, and register regData contains the new record for the
+** PK index. This function adds code to invoke the pre-update hook,
+** if one is registered.
+*/
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+static void codeWithoutRowidPreupdate(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being updated */
+ int iCur, /* Cursor number for table */
+ int regData /* Data containing new record */
+){
+ Vdbe *v = pParse->pVdbe;
+ int r = sqlite3GetTempReg(pParse);
+ assert( !HasRowid(pTab) );
+ assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB );
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
+ sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE);
+ sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
+ sqlite3ReleaseTempReg(pParse, r);
+}
+#else
+# define codeWithoutRowidPreupdate(a,b,c,d)
+#endif
+
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
@@ -2323,17 +2493,9 @@ void sqlite3CompleteInsertion(
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( update_flags==0 ){
- int r = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
- sqlite3VdbeAddOp4(v, OP_Insert,
- iIdxCur+i, aRegIdx[i], r, (char*)pTab, P4_TABLE
- );
- sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
- sqlite3ReleaseTempReg(pParse, r);
+ codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]);
}
-#endif
}
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
@@ -2531,7 +2693,7 @@ static int xferOptimization(
ExprList *pEList; /* The result set of the SELECT */
Table *pSrc; /* The table in the FROM clause of SELECT */
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
- struct SrcList_item *pItem; /* An element of pSelect->pSrc */
+ SrcItem *pItem; /* An element of pSelect->pSrc */
int i; /* Loop counter */
int iDbSrc; /* The database of pSrc */
int iSrc, iDest; /* Cursors from source and destination */
@@ -2748,6 +2910,7 @@ static int xferOptimization(
iDest = pParse->nTab++;
regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
regData = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
@@ -2783,11 +2946,13 @@ static int xferOptimization(
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- sqlite3VdbeVerifyAbortable(v, onError);
- addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- VdbeCoverage(v);
- sqlite3RowidConstraint(pParse, onError, pDest);
- sqlite3VdbeJumpHere(v, addr2);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeVerifyAbortable(v, onError);
+ addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+ VdbeCoverage(v);
+ sqlite3RowidConstraint(pParse, onError, pDest);
+ sqlite3VdbeJumpHere(v, addr2);
+ }
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){
addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
@@ -2795,16 +2960,28 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
+
if( db->mDbFlags & DBFLAG_Vacuum ){
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
- insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
+ insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
}else{
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
+ }
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ insFlags &= ~OPFLAG_PREFORMAT;
+ }else
+#endif
+ {
+ sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
+ }
+ sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE);
}
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
- (char*)pDest, P4_TABLE);
sqlite3VdbeChangeP5(v, insFlags);
+
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -2846,13 +3023,22 @@ static int xferOptimization(
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
- idxInsFlags = OPFLAG_USESEEKRESULT;
+ idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
+ sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc);
}
}else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
idxInsFlags |= OPFLAG_NCHANGE;
}
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0
+ && !HasRowid(pDest)
+ && IsPrimaryKeyIndex(pDestIdx)
+ ){
+ codeWithoutRowidPreupdate(pParse, pDest, iDest, regData);
+ }
+ }
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
diff --git a/src/loadext.c b/src/loadext.c
index 60cffdaed..aeea837c9 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -515,7 +515,7 @@ static int sqlite3LoadExtension(
const char *zEntry;
char *zAltEntry = 0;
void **aHandle;
- u64 nMsg = 300 + sqlite3Strlen30(zFile);
+ u64 nMsg = strlen(zFile);
int ii;
int rc;
@@ -549,6 +549,12 @@ static int sqlite3LoadExtension(
zEntry = zProc ? zProc : "sqlite3_extension_init";
+ /* tag-20210611-1. Some dlopen() implementations will segfault if given
+ ** an oversize filename. Most filesystems have a pathname limit of 4K,
+ ** so limit the extension filename length to about twice that.
+ ** https://sqlite.org/forum/forumpost/08a0d6d9bf */
+ if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found;
+
handle = sqlite3OsDlOpen(pVfs, zFile);
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
for(ii=0; iiaExtension[db->nExtension++] = handle;
return SQLITE_OK;
+
+extension_not_found:
+ if( pzErrMsg ){
+ nMsg += 300;
+ *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
+ if( zErrmsg ){
+ assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */
+ sqlite3_snprintf((int)nMsg, zErrmsg,
+ "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile);
+ sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
+ }
+ }
+ return SQLITE_ERROR;
}
int sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
diff --git a/src/main.c b/src/main.c
index cc1464f13..a04a6bc0f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -305,7 +305,7 @@ int sqlite3_initialize(void){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlite3MemdbInit();
}
@@ -720,12 +720,12 @@ int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
break;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
@@ -1274,7 +1274,7 @@ int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
-** leaves the connection option if there are unfinalized prepared
+** leaves the connection open if there are unfinalized prepared
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
** version forces the connection to become a zombie if there are
** unclosed resources, and arranges for deallocation when the last
@@ -1884,6 +1884,10 @@ int sqlite3CreateFunc(
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
+ }else if( xSFunc==0 && xFinal==0 ){
+ /* Trying to delete a function that does not exist. This is a no-op.
+ ** https://sqlite.org/forum/forumpost/726219164b */
+ return SQLITE_OK;
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
@@ -2374,7 +2378,7 @@ int sqlite3_wal_checkpoint_v2(
return SQLITE_OK;
#else
int rc; /* Return code */
- int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
+ int iDb; /* Schema to checkpoint */
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
@@ -2397,6 +2401,8 @@ int sqlite3_wal_checkpoint_v2(
sqlite3_mutex_enter(db->mutex);
if( zDb && zDb[0] ){
iDb = sqlite3FindDbName(db, zDb);
+ }else{
+ iDb = SQLITE_MAX_DB; /* This means process all schemas */
}
if( iDb<0 ){
rc = SQLITE_ERROR;
@@ -2445,7 +2451,7 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
** associated with the specific b-tree being checkpointed is taken by
** this function while the checkpoint is running.
**
-** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
+** If iDb is passed SQLITE_MAX_DB then all attached databases are
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
@@ -2460,9 +2466,11 @@ int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
assert( sqlite3_mutex_held(db->mutex) );
assert( !pnLog || *pnLog==-1 );
assert( !pnCkpt || *pnCkpt==-1 );
+ testcase( iDb==SQLITE_MAX_ATTACHED ); /* See forum post a006d86f72 */
+ testcase( iDb==SQLITE_MAX_DB );
for(i=0; inDb && rc==SQLITE_OK; i++){
- if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
+ if( i==iDb || iDb==SQLITE_MAX_DB ){
rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
pnLog = 0;
pnCkpt = 0;
@@ -4080,7 +4088,7 @@ int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlite3 *db = va_arg(ap, sqlite3*);
- db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
+ db->dbOptFlags = va_arg(ap, u32);
break;
}
@@ -4255,7 +4263,56 @@ int sqlite3_test_control(int op, ...){
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
+ **
+ ** "ptr" is a pointer to a u32.
+ **
+ ** op==0 Store the current sqlite3SelectTrace in *ptr
+ ** op==1 Set sqlite3SelectTrace to the value *ptr
+ ** op==3 Store the current sqlite3WhereTrace in *ptr
+ ** op==3 Set sqlite3WhereTrace to the value *ptr
+ */
+ case SQLITE_TESTCTRL_TRACEFLAGS: {
+ int opTrace = va_arg(ap, int);
+ u32 *ptr = va_arg(ap, u32*);
+ switch( opTrace ){
+ case 0: *ptr = sqlite3SelectTrace; break;
+ case 1: sqlite3SelectTrace = *ptr; break;
+ case 2: *ptr = sqlite3WhereTrace; break;
+ case 3: sqlite3WhereTrace = *ptr; break;
+ }
+ break;
+ }
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
+ /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
+ **
+ ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
+ ** of the id-th tuning parameter to *piValue. If "id" is between -1
+ ** and -SQLITE_NTUNE, then write the current value of the (-id)-th
+ ** tuning parameter into *piValue.
+ **
+ ** Tuning parameters are for use during transient development builds,
+ ** to help find the best values for constants in the query planner.
+ ** Access tuning parameters using the Tuning(ID) macro. Set the
+ ** parameters in the CLI using ".testctrl tune ID VALUE".
+ **
+ ** Transient use only. Tuning parameters should not be used in
+ ** checked-in code.
+ */
+ case SQLITE_TESTCTRL_TUNE: {
+ int id = va_arg(ap, int);
+ int *piValue = va_arg(ap, int*);
+ if( id>0 && id<=SQLITE_NTUNE ){
+ Tuning(id) = *piValue;
+ }else if( id<0 && id>=-SQLITE_NTUNE ){
+ *piValue = Tuning(-id);
+ }else{
+ rc = SQLITE_NOTFOUND;
+ }
+ break;
+ }
+#endif
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
diff --git a/src/malloc.c b/src/malloc.c
index a0f7a739c..b8a88f128 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -161,7 +161,6 @@ int sqlite3MallocInit(void){
if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
- memset(&mem0, 0, sizeof(mem0));
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|| sqlite3GlobalConfig.nPage<=0 ){
diff --git a/src/memdb.c b/src/memdb.c
index a48980aa3..4e5751f93 100644
--- a/src/memdb.c
+++ b/src/memdb.c
@@ -17,31 +17,88 @@
** sqlite3_deserialize().
*/
#include "sqliteInt.h"
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
+typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
+/* Storage for a memdb file.
+**
+** An memdb object can be shared or separate. Shared memdb objects can be
+** used by more than one database connection. Mutexes are used by shared
+** memdb objects to coordinate access. Separate memdb objects are only
+** connected to a single database connection and do not require additional
+** mutexes.
+**
+** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
+** using "file:/name?vfs=memdb". The first character of the name must be
+** "/" or else the object will be a separate memdb object. All shared
+** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
+**
+** Separate memdb objects are created using a name that does not begin
+** with "/" or using sqlite3_deserialize().
+**
+** Access rules for shared MemStore objects:
+**
+** * .zFName is initialized when the object is created and afterwards
+** is unchanged until the object is destroyed. So it can be accessed
+** at any time as long as we know the object is not being destroyed,
+** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
+** .pMutex is held or the object is not part of memdb_g.apMemStore[].
+**
+** * Can .pMutex can only be changed while holding the
+** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
+** of memdb_g.apMemStore[].
+**
+** * Other fields can only be changed while holding the .pMutex mutex
+** or when the .nRef is less than zero and the object is not part of
+** memdb_g.apMemStore[].
+**
+** * The .aData pointer has the added requirement that it can can only
+** be changed (for resizing) when nMmap is zero.
+**
+*/
+struct MemStore {
sqlite3_int64 sz; /* Size of the file */
sqlite3_int64 szAlloc; /* Space allocated to aData */
sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
+ sqlite3_mutex *pMutex; /* Used by shared stores only */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
+ int nRdLock; /* Number of readers */
+ int nWrLock; /* Number of writers. (Always 0 or 1) */
+ int nRef; /* Number of users of this MemStore */
+ char *zFName; /* The filename for shared stores */
+};
+
+/* An open file */
+struct MemFile {
+ sqlite3_file base; /* IO methods */
+ MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
+/*
+** File-scope variables for holding the memdb files that are accessible
+** to multiple database connections in separate threads.
+**
+** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
+*/
+static struct MemFS {
+ int nMemStore; /* Number of shared MemStore objects */
+ MemStore **apMemStore; /* Array of all shared MemStore objects */
+} memdb_g;
+
/*
** Methods for MemFile
*/
@@ -95,7 +152,10 @@ static sqlite3_vfs memdb_vfs = {
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+ memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 0, /* xSetSystemCall */
+ 0, /* xGetSystemCall */
+ 0, /* xNextSystemCall */
};
static const sqlite3_io_methods memdb_io_methods = {
@@ -120,19 +180,67 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbUnfetch /* xUnfetch */
};
+/*
+** Enter/leave the mutex on a MemStore
+*/
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+static void memdbEnter(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+static void memdbLeave(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+#else
+static void memdbEnter(MemStore *p){
+ sqlite3_mutex_enter(p->pMutex);
+}
+static void memdbLeave(MemStore *p){
+ sqlite3_mutex_leave(p->pMutex);
+}
+#endif
+
/*
** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
-** in which case we own the pData pointer and need to free it.
+** Free the underlying MemStore object when its refcount drops to zero
+** or less.
*/
static int memdbClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
- sqlite3_free(p->aData);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ if( p->zFName ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; ALWAYS(inRef==1 ){
+ memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
+ if( memdb_g.nMemStore==0 ){
+ sqlite3_free(memdb_g.apMemStore);
+ memdb_g.apMemStore = 0;
+ }
+ }
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ memdbEnter(p);
+ }
+ p->nRef--;
+ if( p->nRef<=0 ){
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
+ memdbLeave(p);
+ sqlite3_mutex_free(p->pMutex);
+ sqlite3_free(p);
+ }else{
+ memdbLeave(p);
}
return SQLITE_OK;
}
@@ -146,20 +254,23 @@ static int memdbRead(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
-static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
+static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
@@ -170,7 +281,7 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlite3Realloc(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
p->szAlloc = newSz;
return SQLITE_OK;
@@ -185,19 +296,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ /* Can't happen: memdbLock() will return SQLITE_READONLY before
+ ** reaching this point */
+ memdbLeave(p);
+ return SQLITE_IOERR_WRITE;
+ }
if( iOfst+iAmt>p->sz ){
int rc;
if( iOfst+iAmt>p->szAlloc
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
+ memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -209,16 +328,24 @@ static int memdbWrite(
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ int rc = SQLITE_OK;
+ memdbEnter(p);
+ if( NEVER(size>p->sz) ){
+ rc = SQLITE_FULL;
+ }else{
+ p->sz = size;
+ }
+ memdbLeave(p);
+ return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
+ UNUSED_PARAMETER(pFile);
+ UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
@@ -226,8 +353,10 @@ static int memdbSync(sqlite3_file *pFile, int flags){
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
*pSize = p->sz;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -235,19 +364,48 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- if( eLock>SQLITE_LOCK_SHARED
- && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
- ){
- return SQLITE_READONLY;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock==pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+ if( eLock>SQLITE_LOCK_SHARED ){
+ if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
+ rc = SQLITE_READONLY;
+ }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
+ if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ }else if( eLock==SQLITE_LOCK_SHARED ){
+ if( pThis->eLock > SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }else if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ }else{
+ assert( eLock==SQLITE_LOCK_NONE );
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }
+ assert( p->nRdLock>0 );
+ p->nRdLock--;
}
- p->eLock = eLock;
- return SQLITE_OK;
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
}
-#if 0 /* Never used because memdbAccess() always returns false */
+#if 0
/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
+** This interface is only used for crash recovery, which does not
+** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
@@ -255,12 +413,14 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
}
#endif
+
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
+ memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
@@ -278,6 +438,7 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
+ memdbLeave(p);
return rc;
}
@@ -294,6 +455,7 @@ static int memdbSectorSize(sqlite3_file *pFile){
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
+ UNUSED_PARAMETER(pFile);
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
@@ -307,20 +469,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
+ memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ UNUSED_PARAMETER(iOfst);
+ UNUSED_PARAMETER(pPage);
+ memdbEnter(p);
p->nMmap--;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -330,20 +498,79 @@ static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
static int memdbOpen(
sqlite3_vfs *pVfs,
const char *zName,
- sqlite3_file *pFile,
+ sqlite3_file *pFd,
int flags,
int *pOutFlags
){
- MemFile *p = (MemFile*)pFile;
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ memset(pFile, 0, sizeof(*p));
+ szName = sqlite3Strlen30(zName);
+ if( szName>1 && zName[0]=='/' ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; izFName,zName)==0 ){
+ p = memdb_g.apMemStore[i];
+ break;
+ }
+ }
+ if( p==0 ){
+ MemStore **apNew;
+ p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ if( p==0 ){
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ if( apNew==0 ){
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew[memdb_g.nMemStore++] = p;
+ memdb_g.apMemStore = apNew;
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ p->zFName = (char*)&p[1];
+ memcpy(p->zFName, zName, szName+1);
+ p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( p->pMutex==0 ){
+ memdb_g.nMemStore--;
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ p->nRef = 1;
+ memdbEnter(p);
+ }else{
+ memdbEnter(p);
+ p->nRef++;
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ p = sqlite3Malloc( sizeof(*p) );
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
+ pFile->pStore = p;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
- pFile->pMethods = &memdb_io_methods;
- p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ pFd->pMethods = &memdb_io_methods;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -371,6 +598,9 @@ static int memdbAccess(
int flags,
int *pResOut
){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(zPath);
+ UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
@@ -386,6 +616,7 @@ static int memdbFullPathname(
int nOut,
char *zOut
){
+ UNUSED_PARAMETER(pVfs);
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
@@ -458,9 +689,14 @@ static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
+ MemStore *pStore;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ pStore = p->pStore;
+ memdbEnter(pStore);
+ if( pStore->zFName!=0 ) p = 0;
+ memdbLeave(pStore);
return p;
}
@@ -496,12 +732,14 @@ unsigned char *sqlite3_serialize(
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
- if( piSize ) *piSize = p->sz;
+ MemStore *pStore = p->pStore;
+ assert( pStore->pMutex==0 );
+ if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
+ pOut = pStore->aData;
}else{
- pOut = sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
+ pOut = sqlite3_malloc64( pStore->sz );
+ if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
@@ -595,15 +833,16 @@ int sqlite3_deserialize(
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
+ MemStore *pStore = p->pStore;
+ pStore->aData = pData;
pData = 0;
- p->sz = szDb;
- p->szAlloc = szBuf;
- p->szMax = szBuf;
- if( p->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
+ pStore->sz = szDb;
+ pStore->szAlloc = szBuf;
+ pStore->szMax = szBuf;
+ if( pStore->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
}
- p->mFlags = mFlags;
+ pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
@@ -622,7 +861,9 @@ int sqlite3_deserialize(
*/
int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
+ unsigned int sz;
+ if( NEVER(pLower==0) ) return SQLITE_ERROR;
+ sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
@@ -632,4 +873,4 @@ int sqlite3MemdbInit(void){
memdb_vfs.szOsFile = sz;
return sqlite3_vfs_register(&memdb_vfs, 0);
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
diff --git a/src/memjournal.c b/src/memjournal.c
index 4811f2d8d..598d5cc02 100644
--- a/src/memjournal.c
+++ b/src/memjournal.c
@@ -70,7 +70,6 @@ struct MemJournal {
int nChunkSize; /* In-memory chunk-size */
int nSpill; /* Bytes of data before flushing */
- int nSize; /* Bytes of data currently in memory */
FileChunk *pFirst; /* Head of in-memory chunk-list */
FilePoint endpoint; /* Pointer to the end of the file */
FilePoint readpoint; /* Pointer to the end of the last xRead() */
@@ -131,14 +130,13 @@ static int memjrnlRead(
/*
** Free the list of FileChunk structures headed at MemJournal.pFirst.
*/
-static void memjrnlFreeChunks(MemJournal *p){
+static void memjrnlFreeChunks(FileChunk *pFirst){
FileChunk *pIter;
FileChunk *pNext;
- for(pIter=p->pFirst; pIter; pIter=pNext){
+ for(pIter=pFirst; pIter; pIter=pNext){
pNext = pIter->pNext;
sqlite3_free(pIter);
}
- p->pFirst = 0;
}
/*
@@ -165,7 +163,7 @@ static int memjrnlCreateFile(MemJournal *p){
}
if( rc==SQLITE_OK ){
/* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(©);
+ memjrnlFreeChunks(copy.pFirst);
}
}
if( rc!=SQLITE_OK ){
@@ -248,7 +246,6 @@ static int memjrnlWrite(
nWrite -= iSpace;
p->endpoint.iOffset += iSpace;
}
- p->nSize = iAmt + iOfst;
}
}
@@ -256,19 +253,29 @@ static int memjrnlWrite(
}
/*
-** Truncate the file.
-**
-** If the journal file is already on disk, truncate it there. Or, if it
-** is still in main memory but is being truncated to zero bytes in size,
-** ignore
+** Truncate the in-memory file.
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
- if( ALWAYS(size==0) ){
- memjrnlFreeChunks(p);
- p->nSize = 0;
- p->endpoint.pChunk = 0;
- p->endpoint.iOffset = 0;
+ assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 );
+ if( sizeendpoint.iOffset ){
+ FileChunk *pIter = 0;
+ if( size==0 ){
+ memjrnlFreeChunks(p->pFirst);
+ p->pFirst = 0;
+ }else{
+ i64 iOff = p->nChunkSize;
+ for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){
+ iOff += p->nChunkSize;
+ }
+ if( ALWAYS(pIter) ){
+ memjrnlFreeChunks(pIter->pNext);
+ pIter->pNext = 0;
+ }
+ }
+
+ p->endpoint.pChunk = pIter;
+ p->endpoint.iOffset = size;
p->readpoint.pChunk = 0;
p->readpoint.iOffset = 0;
}
@@ -280,7 +287,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
*/
static int memjrnlClose(sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
- memjrnlFreeChunks(p);
+ memjrnlFreeChunks(p->pFirst);
return SQLITE_OK;
}
diff --git a/src/os.c b/src/os.c
index a1a276f43..f1798ff96 100644
--- a/src/os.c
+++ b/src/os.c
@@ -129,6 +129,8 @@ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_TEST
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
+ && op!=SQLITE_FCNTL_CKPT_DONE
+ && op!=SQLITE_FCNTL_CKPT_START
){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
@@ -139,7 +141,12 @@ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
** The core must call OsFileControl() though, not OsFileControlHint(),
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
** means the commit really has failed and an error should be returned
- ** to the user. */
+ ** to the user.
+ **
+ ** The CKPT_DONE and CKPT_START file-controls are write-only signals
+ ** to the cksumvfs. Their return code is meaningless and is ignored
+ ** by the SQLite core, so there is no point in simulating OOMs for them.
+ */
DO_OS_MALLOC_TEST(id);
}
#endif
@@ -222,7 +229,7 @@ int sqlite3OsOpen(
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
- return pVfs->xDelete(pVfs, zPath, dirSync);
+ return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
int sqlite3OsAccess(
sqlite3_vfs *pVfs,
@@ -245,6 +252,8 @@ int sqlite3OsFullPathname(
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+ assert( zPath!=0 );
+ assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
return pVfs->xDlOpen(pVfs, zPath);
}
void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
diff --git a/src/os.h b/src/os.h
index f841d6bab..1a8eff329 100644
--- a/src/os.h
+++ b/src/os.h
@@ -33,6 +33,12 @@
# define SET_FULLSYNC(x,y)
#endif
+/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
+*/
+#ifndef SQLITE_MAX_PATHLEN
+# define SQLITE_MAX_PATHLEN FILENAME_MAX
+#endif
+
/*
** The default size of a disk sector
*/
diff --git a/src/os_unix.c b/src/os_unix.c
index a688ed270..d45fdabab 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -3951,6 +3951,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
+static int unixFcntlExternalReader(unixFile*, int*);
/*
** Information and control of an open file handle.
@@ -4067,6 +4068,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+
+ case SQLITE_FCNTL_EXTERNAL_READER: {
+ return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+ }
}
return SQLITE_NOTFOUND;
}
@@ -4312,6 +4317,40 @@ struct unixShm {
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+/*
+** Use F_GETLK to check whether or not there are any readers with open
+** wal-mode transactions in other processes on database file pFile. If
+** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
+** such transactions, or 0 otherwise. If an error occurs, return an
+** SQLite error code. The final value of *piOut is undefined in this
+** case.
+*/
+static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
+ int rc = SQLITE_OK;
+ *piOut = 0;
+ if( pFile->pShm){
+ unixShmNode *pShmNode = pFile->pShm->pShmNode;
+ struct flock f;
+
+ memset(&f, 0, sizeof(f));
+ f.l_type = F_WRLCK;
+ f.l_whence = SEEK_SET;
+ f.l_start = UNIX_SHM_BASE + 3;
+ f.l_len = SQLITE_SHM_NLOCK - 3;
+
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+ if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
+ rc = SQLITE_IOERR_LOCK;
+ }else{
+ *piOut = (f.l_type!=F_UNLCK);
+ }
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
+ }
+
+ return rc;
+}
+
+
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
@@ -6361,7 +6400,8 @@ static int unixBackupDir(const char *z, int *pJ){
int j = *pJ;
int i;
if( j<=0 ) return 0;
- for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
+ for(i=j-1; i>0 && z[i-1]!='/'; i--){}
+ if( i==0 ) return 0;
if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
*pJ = i-1;
return 1;
@@ -8027,6 +8067,25 @@ int sqlite3_os_init(void){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+
+#ifndef SQLITE_OMIT_WAL
+ /* Validate lock assumptions */
+ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
+ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
+ /* Locks:
+ ** WRITE UNIX_SHM_BASE 120
+ ** CKPT UNIX_SHM_BASE+1 121
+ ** RECOVER UNIX_SHM_BASE+2 122
+ ** READ-0 UNIX_SHM_BASE+3 123
+ ** READ-1 UNIX_SHM_BASE+4 124
+ ** READ-2 UNIX_SHM_BASE+5 125
+ ** READ-3 UNIX_SHM_BASE+6 126
+ ** READ-4 UNIX_SHM_BASE+7 127
+ ** DMS UNIX_SHM_BASE+8 128
+ */
+ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
+#endif
+
return SQLITE_OK;
}
diff --git a/src/pager.c b/src/pager.c
index a5510e7eb..12a78cde8 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -435,6 +435,7 @@ struct PagerSavepoint {
Bitvec *pInSavepoint; /* Set of pages in this savepoint */
Pgno nOrig; /* Original number of pages in file */
Pgno iSubRec; /* Index of first record in sub-journal */
+ int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */
#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
#endif
@@ -1070,6 +1071,9 @@ static int subjRequiresPage(PgHdr *pPg){
for(i=0; inSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
+ for(i=i+1; inSavepoint; i++){
+ pPager->aSavepoint[i].bTruncateOnRelease = 0;
+ }
return 1;
}
}
@@ -3932,7 +3936,8 @@ static void assertTruncateConstraint(Pager *pPager){
** then continue writing to the database.
*/
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
- assert( pPager->dbSize>=nPage );
+ assert( pPager->dbSize>=nPage || CORRUPT_DB );
+ testcase( pPager->dbSizeeState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
@@ -4660,7 +4665,7 @@ int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
@@ -4864,7 +4869,7 @@ int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
@@ -5832,7 +5837,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory;
- if( ALWAYS(pPager->eState==PAGER_READER) ){
+ if( pPager->eState==PAGER_READER ){
assert( pPager->pInJournal==0 );
if( pagerUseWal(pPager) ){
@@ -6848,6 +6853,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
}
aNew[ii].iSubRec = pPager->nSubRec;
aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
+ aNew[ii].bTruncateOnRelease = 1;
if( !aNew[ii].pInSavepoint ){
return SQLITE_NOMEM_BKPT;
}
@@ -6929,13 +6935,15 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
- if( nNew==0 && isOpen(pPager->sjfd) ){
+ PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
+ if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3JournalIsInMemory(pPager->sjfd) ){
- rc = sqlite3OsTruncate(pPager->sjfd, 0);
+ i64 sz = (pPager->pageSize+4)*pRel->iSubRec;
+ rc = sqlite3OsTruncate(pPager->sjfd, sz);
assert( rc==SQLITE_OK );
}
- pPager->nSubRec = 0;
+ pPager->nSubRec = pRel->iSubRec;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
diff --git a/src/parse.y b/src/parse.y
index d3ec2b3da..359b02bc4 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -193,7 +193,7 @@ ifnotexists(A) ::= . {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
-temp(A) ::= TEMP. {A = 1;}
+temp(A) ::= TEMP. {A = pParse->db->init.busy==0;}
%endif SQLITE_OMIT_TEMPDB
temp(A) ::= . {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
@@ -250,6 +250,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
GENERATED ALWAYS
%endif
+ MATERIALIZED
REINDEX RENAME CTIME_KW IF
.
%wildcard ANY.
@@ -496,11 +497,21 @@ cmd ::= select(X). {
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
assert( p!=0 );
if( p->pPrior ){
- Select *pNext = 0, *pLoop;
- int mxSelect, cnt = 0;
- for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
+ Select *pNext = 0, *pLoop = p;
+ int mxSelect, cnt = 1;
+ while(1){
pLoop->pNext = pNext;
pLoop->selFlags |= SF_Compound;
+ pNext = pLoop;
+ pLoop = pLoop->pPrior;
+ if( pLoop==0 ) break;
+ cnt++;
+ if( pLoop->pOrderBy || pLoop->pLimit ){
+ sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
+ pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT",
+ sqlite3SelectOpName(pNext->op));
+ break;
+ }
}
if( (p->selFlags & SF_MultiValue)==0 &&
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
@@ -510,29 +521,25 @@ cmd ::= select(X). {
}
}
}
-}
-%ifndef SQLITE_OMIT_CTE
-select(A) ::= WITH wqlist(W) selectnowith(X). {
- Select *p = X;
- if( p ){
- p->pWith = W;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, W);
- }
- A = p;
-}
-select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
- Select *p = X;
- if( p ){
- p->pWith = W;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlite3WithDelete(pParse->db, W);
+ /* Attach a With object describing the WITH clause to a Select
+ ** object describing the query for which the WITH clause is a prefix.
+ */
+ static Select *attachWithToSelect(Parse *pParse, Select *pSelect, With *pWith){
+ if( pSelect ){
+ pSelect->pWith = pWith;
+ parserDoubleLinkSelect(pParse, pSelect);
+ }else{
+ sqlite3WithDelete(pParse->db, pWith);
+ }
+ return pSelect;
}
- A = p;
}
+
+%ifndef SQLITE_OMIT_CTE
+select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
+select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
+ {A = attachWithToSelect(pParse,X,W);}
%endif /* SQLITE_OMIT_CTE */
select(A) ::= selectnowith(X). {
Select *p = X;
@@ -699,8 +706,8 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
}else if( F->nSrc==1 ){
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U);
if( A ){
- struct SrcList_item *pNew = &A->a[A->nSrc-1];
- struct SrcList_item *pOld = F->a;
+ SrcItem *pNew = &A->a[A->nSrc-1];
+ SrcItem *pOld = F->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
@@ -868,7 +875,7 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
/////////////////////////// The DELETE statement /////////////////////////////
//
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
-cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W)
+cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W)
orderby_opt(O) limit_opt(L). {
sqlite3SrcListIndexedBy(pParse, X, &I);
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
@@ -881,7 +888,7 @@ cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W)
sqlite3DeleteFrom(pParse,X,W,O,L);
}
%else
-cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). {
+cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W). {
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3DeleteFrom(pParse,X,W,0,0);
}
@@ -889,15 +896,23 @@ cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). {
%type where_opt {Expr*}
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
+%type where_opt_ret {Expr*}
+%destructor where_opt_ret {sqlite3ExprDelete(pParse->db, $$);}
where_opt(A) ::= . {A = 0;}
where_opt(A) ::= WHERE expr(X). {A = X;}
+where_opt_ret(A) ::= . {A = 0;}
+where_opt_ret(A) ::= WHERE expr(X). {A = X;}
+where_opt_ret(A) ::= RETURNING selcollist(X).
+ {sqlite3AddReturning(pParse,X); A = 0;}
+where_opt_ret(A) ::= WHERE expr(X) RETURNING selcollist(Y).
+ {sqlite3AddReturning(pParse,Y); A = X;}
////////////////////////// The UPDATE command ////////////////////////////////
//
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
- where_opt(W) orderby_opt(O) limit_opt(L). {
+ where_opt_ret(W) orderby_opt(O) limit_opt(L). {
sqlite3SrcListIndexedBy(pParse, X, &I);
X = sqlite3SrcListAppendList(pParse, X, F);
sqlite3ExprListCheckLength(pParse,Y,"set list");
@@ -912,7 +927,7 @@ cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
}
%else
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
- where_opt(W). {
+ where_opt_ret(W). {
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
X = sqlite3SrcListAppendList(pParse, X, F);
@@ -946,7 +961,7 @@ cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S)
upsert(U). {
sqlite3Insert(pParse, X, S, F, R, U);
}
-cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES.
+cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES returning.
{
sqlite3Insert(pParse, X, 0, F, R, 0);
}
@@ -959,13 +974,19 @@ cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES.
// avoid unreachable code.
//%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
upsert(A) ::= . { A = 0; }
+upsert(A) ::= RETURNING selcollist(X). { A = 0; sqlite3AddReturning(pParse,X); }
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW)
- DO UPDATE SET setlist(Z) where_opt(W).
- { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W);}
-upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING.
- { A = sqlite3UpsertNew(pParse->db,T,TW,0,0); }
-upsert(A) ::= ON CONFLICT DO NOTHING.
- { A = sqlite3UpsertNew(pParse->db,0,0,0,0); }
+ DO UPDATE SET setlist(Z) where_opt(W) upsert(N).
+ { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W,N);}
+upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING upsert(N).
+ { A = sqlite3UpsertNew(pParse->db,T,TW,0,0,N); }
+upsert(A) ::= ON CONFLICT DO NOTHING returning.
+ { A = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
+upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W) returning.
+ { A = sqlite3UpsertNew(pParse->db,0,0,Z,W,0);}
+
+returning ::= RETURNING selcollist(X). {sqlite3AddReturning(pParse,X);}
+returning ::= .
%type insert_cmd {int}
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
@@ -1607,6 +1628,10 @@ cmd ::= ALTER TABLE add_column_fullname
Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &Y);
}
+cmd ::= ALTER TABLE fullname(X) DROP kwcolumn_opt nm(Y). {
+ sqlite3AlterDropColumn(pParse, X, &Y);
+}
+
add_column_fullname ::= fullname(X). {
disableLookaside(pParse);
sqlite3AlterBeginAddColumn(pParse, X);
@@ -1644,17 +1669,26 @@ anylist ::= anylist ANY.
//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
%type wqlist {With*}
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}
+%type wqitem {Cte*}
+// %destructor wqitem {sqlite3CteDelete(pParse->db, $$);} // not reachable
with ::= .
%ifndef SQLITE_OMIT_CTE
with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); }
with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
-wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
- A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/
+%type wqas {u8}
+wqas(A) ::= AS. {A = M10d_Any;}
+wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;}
+wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;}
+wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. {
+ A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/
+}
+wqlist(A) ::= wqitem(X). {
+ A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
}
-wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
- A = sqlite3WithAdd(pParse, A, &X, Y, Z);
+wqlist(A) ::= wqlist(A) COMMA wqitem(X). {
+ A = sqlite3WithAdd(pParse, A, X);
}
%endif SQLITE_OMIT_CTE
@@ -1767,7 +1801,11 @@ frame_exclude(A) ::= GROUP|TIES(X). {A = @X; /*A-overwrites-X*/}
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
filter_over(A) ::= filter_clause(F) over_clause(O). {
- O->pFilter = F;
+ if( O ){
+ O->pFilter = F;
+ }else{
+ sqlite3ExprDelete(pParse->db, F);
+ }
A = O;
}
filter_over(A) ::= over_clause(O). {
@@ -1817,6 +1855,7 @@ filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; }
IF_NULL_ROW /* the if-null-row operator */
ASTERISK /* The "*" in count(*) and similar */
SPAN /* The span operator */
+ ERROR /* An expression containing an error */
.
/* There must be no more than 255 tokens defined above. If this grammar
** is extended with new rules and tokens, they must either be so few in
diff --git a/src/pcache1.c b/src/pcache1.c
index ed762ebf7..3eae6b63c 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -461,6 +461,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
p->isAnchor = 0;
+ p->pLruPrev = 0; /* Initializing this saves a valgrind error */
}
(*pCache->pnPurgeable)++;
return p;
diff --git a/src/pragma.c b/src/pragma.c
index 7be0f7f25..84f29c2fd 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1969,7 +1969,7 @@ void sqlite3Pragma(
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
- int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
+ int iBt = (pId2->z?iDb:SQLITE_MAX_DB);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
if( sqlite3StrICmp(zRight, "full")==0 ){
diff --git a/src/prepare.c b/src/prepare.c
index 13fd1d33b..6dcb3842e 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -21,7 +21,7 @@
*/
static void corruptSchema(
InitData *pData, /* Initialization context */
- const char *zObj, /* Object being parsed at the point of error */
+ char **azObj, /* Type and name of object being parsed */
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
@@ -29,14 +29,18 @@ static void corruptSchema(
pData->rc = SQLITE_NOMEM_BKPT;
}else if( pData->pzErrMsg[0]!=0 ){
/* A error message has already been generated. Do not overwrite it */
- }else if( pData->mInitFlags & INITFLAG_AlterTable ){
- *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
+ }else if( pData->mInitFlags & (INITFLAG_AlterRename|INITFLAG_AlterDrop) ){
+ *pData->pzErrMsg = sqlite3MPrintf(db,
+ "error in %s %s after %s: %s", azObj[0], azObj[1],
+ (pData->mInitFlags & INITFLAG_AlterRename) ? "rename" : "drop column",
+ zExtra
+ );
pData->rc = SQLITE_ERROR;
}else if( db->flags & SQLITE_WriteSchema ){
pData->rc = SQLITE_CORRUPT_BKPT;
}else{
char *z;
- if( zObj==0 ) zObj = "?";
+ const char *zObj = azObj[1] ? azObj[1] : "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
*pData->pzErrMsg = z;
@@ -92,21 +96,28 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
db->mDbFlags |= DBFLAG_EncodingFixed;
+ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
pData->nInitRow++;
if( db->mallocFailed ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
return 1;
}
assert( iDb>=0 && iDbnDb );
- if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[3]==0 ){
- corruptSchema(pData, argv[1], 0);
- }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
+ corruptSchema(pData, argv, 0);
+ }else if( argv[4]
+ && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
+ && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
+ **
+ ** No other valid SQL statement, other than the variable CREATE statements,
+ ** can begin with the letters "C" and "R". Thus, it is not possible run
+ ** any other kind of statement while parsing the schema, even a corrupt
+ ** schema.
*/
int rc;
u8 saved_iDb = db->init.iDb;
@@ -119,7 +130,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|| (db->init.newTnum>pData->mxPage && pData->mxPage>0)
){
if( sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
db->init.orphanTrigger = 0;
@@ -138,13 +149,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
- corruptSchema(pData, argv[1], sqlite3_errmsg(db));
+ corruptSchema(pData, argv, sqlite3_errmsg(db));
}
}
}
sqlite3_finalize(pStmt);
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -155,7 +166,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0 ){
- corruptSchema(pData, argv[1], "orphan index");
+ corruptSchema(pData, argv, "orphan index");
}else
if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
@@ -163,7 +174,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|| sqlite3IndexHasDuplicateRootPage(pIndex)
){
if( sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
}
@@ -366,18 +377,22 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
}
#endif
}
+ assert( pDb == &(db->aDb[iDb]) );
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
- }
+ pDb = &db->aDb[iDb];
+ }else
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
- /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
- ** current sqlite3_prepare() operation will fail, but the following one
- ** will attempt to compile the supplied statement against whatever subset
- ** of the schema was loaded before the error occurred. The primary
- ** purpose of this is to allow access to the sqlite_schema table
- ** even when its contents have been corrupted.
+ /* Hack: If the SQLITE_NoSchemaError flag is set, then consider
+ ** the schema loaded, even if errors (other than OOM) occurred. In
+ ** this situation the current sqlite3_prepare() operation will fail,
+ ** but the following one will attempt to compile the supplied statement
+ ** against whatever subset of the schema was loaded before the error
+ ** occurred.
+ **
+ ** The primary purpose of this is to allow access to the sqlite_schema
+ ** table even when its contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
@@ -487,6 +502,7 @@ static void schemaIsValid(Parse *pParse){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
+ pParse->rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
@@ -543,28 +559,21 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
return i;
}
-/*
-** Deallocate a single AggInfo object
-*/
-static void agginfoFree(sqlite3 *db, AggInfo *p){
- sqlite3DbFree(db, p->aCol);
- sqlite3DbFree(db, p->aFunc);
- sqlite3DbFree(db, p);
-}
-
/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
sqlite3 *db = pParse->db;
- AggInfo *pThis = pParse->pAggList;
- while( pThis ){
- AggInfo *pNext = pThis->pNext;
- agginfoFree(db, pThis);
- pThis = pNext;
+ while( pParse->pCleanup ){
+ ParseCleanup *pCleanup = pParse->pCleanup;
+ pParse->pCleanup = pCleanup->pNext;
+ pCleanup->xCleanup(db, pCleanup->pPtr);
+ sqlite3DbFreeNN(db, pCleanup);
}
sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if( pParse->pConstExpr ){
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ }
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
@@ -573,6 +582,55 @@ void sqlite3ParserReset(Parse *pParse){
pParse->disableLookaside = 0;
}
+/*
+** Add a new cleanup operation to a Parser. The cleanup should happen when
+** the parser object is destroyed. But, beware: the cleanup might happen
+** immediately.
+**
+** Use this mechanism for uncommon cleanups. There is a higher setup
+** cost for this mechansim (an extra malloc), so it should not be used
+** for common cleanups that happen on most calls. But for less
+** common cleanups, we save a single NULL-pointer comparison in
+** sqlite3ParserReset(), which reduces the total CPU cycle count.
+**
+** If a memory allocation error occurs, then the cleanup happens immediately.
+** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
+** pParse->earlyCleanup flag is set in that case. Calling code show verify
+** that test cases exist for which this happens, to guard against possible
+** use-after-free errors following an OOM. The preferred way to do this is
+** to immediately follow the call to this routine with:
+**
+** testcase( pParse->earlyCleanup );
+**
+** This routine returns a copy of its pPtr input (the third parameter)
+** except if an early cleanup occurs, in which case it returns NULL. So
+** another way to check for early cleanup is to check the return value.
+** Or, stop using the pPtr parameter with this call and use only its
+** return value thereafter. Something like this:
+**
+** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj);
+*/
+void *sqlite3ParserAddCleanup(
+ Parse *pParse, /* Destroy when this Parser finishes */
+ void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
+ void *pPtr /* Pointer to object to be cleaned up */
+){
+ ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ if( pCleanup ){
+ pCleanup->pNext = pParse->pCleanup;
+ pParse->pCleanup = pCleanup;
+ pCleanup->pPtr = pPtr;
+ pCleanup->xCleanup = xCleanup;
+ }else{
+ xCleanup(pParse->db, pPtr);
+ pPtr = 0;
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ pParse->earlyCleanup = 1;
+#endif
+ }
+ return pPtr;
+}
+
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -671,12 +729,6 @@ static int sqlite3Prepare(
}
assert( 0==sParse.nQueryLoop );
- if( sParse.rc==SQLITE_DONE ){
- sParse.rc = SQLITE_OK;
- }
- if( sParse.checkSchema ){
- schemaIsValid(&sParse);
- }
if( pzTail ){
*pzTail = sParse.zTail;
}
@@ -686,21 +738,30 @@ static int sqlite3Prepare(
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
+ sParse.checkSchema = 0;
}
- rc = sParse.rc;
- if( rc!=SQLITE_OK ){
- if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
- assert(!(*ppStmt));
+ if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
+ if( sParse.checkSchema ){
+ schemaIsValid(&sParse);
+ }
+ if( sParse.pVdbe ){
+ sqlite3VdbeFinalize(sParse.pVdbe);
+ }
+ assert( 0==(*ppStmt) );
+ rc = sParse.rc;
+ if( zErrMsg ){
+ sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
+ }else{
+ sqlite3Error(db, rc);
+ }
}else{
+ assert( zErrMsg==0 );
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
+ rc = SQLITE_OK;
+ sqlite3ErrorClear(db);
}
- if( zErrMsg ){
- sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
- sqlite3DbFree(db, zErrMsg);
- }else{
- sqlite3Error(db, rc);
- }
/* Delete any TriggerPrg structures allocated while parsing this statement. */
while( sParse.pTriggerPrg ){
diff --git a/src/printf.c b/src/printf.c
index f78d3bbb1..f663e1b1e 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -29,7 +29,7 @@
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCLIST 12 /* a pointer to a SrcList */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
@@ -95,10 +95,16 @@ static const et_info fmtinfo[] = {
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'S', 0, 0, etSRCITEM, 0, 0 },
{ 'r', 10, 1, etORDINAL, 0, 0 },
};
+/* Notes:
+**
+** %S Takes a pointer to SrcItem. Shows name or database.name
+** %!S Like %S but prefer the zName over the zAlias
+*/
+
/* Floating point constants used for rounding */
static const double arRound[] = {
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
@@ -853,21 +859,24 @@ void sqlite3_str_vappendf(
length = width = 0;
break;
}
- case etSRCLIST: {
- SrcList *pSrc;
- int k;
- struct SrcList_item *pItem;
+ case etSRCITEM: {
+ SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pSrc = va_arg(ap, SrcList*);
- k = va_arg(ap, int);
- pItem = &pSrc->a[k];
+ pItem = va_arg(ap, SrcItem*);
assert( bArgList==0 );
- assert( k>=0 && knSrc );
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
- sqlite3_str_append(pAccum, ".", 1);
+ if( pItem->zAlias && !flag_altform2 ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( pItem->zName ){
+ if( pItem->zDatabase ){
+ sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ sqlite3_str_append(pAccum, ".", 1);
+ }
+ sqlite3_str_appendall(pAccum, pItem->zName);
+ }else if( pItem->zAlias ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( ALWAYS(pItem->pSelect) ){
+ sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
}
- sqlite3_str_appendall(pAccum, pItem->zName);
length = width = 0;
break;
}
@@ -921,7 +930,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- szNew += N + 1;
+ szNew += (sqlite3_int64)N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
** to avoid having to call this routine too often */
diff --git a/src/random.c b/src/random.c
index d4ae77c43..87f9e2cec 100644
--- a/src/random.c
+++ b/src/random.c
@@ -76,11 +76,16 @@ void sqlite3_randomness(int N, void *pBuf){
** number generator) not as an encryption device.
*/
if( !wsdPrng.isInit ){
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
int i;
char k[256];
wsdPrng.j = 0;
wsdPrng.i = 0;
- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
+ if( NEVER(pVfs==0) ){
+ memset(k, 0, sizeof(k));
+ }else{
+ sqlite3OsRandomness(pVfs, 256, k);
+ }
for(i=0; i<256; i++){
wsdPrng.s[i] = (u8)i;
}
diff --git a/src/resolve.c b/src/resolve.c
index b55bdc418..93e10b6e4 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -70,7 +70,6 @@ static void resolveAlias(
ExprList *pEList, /* A result set */
int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
Expr *pExpr, /* Transform this into an alias to the result set */
- const char *zType, /* "GROUP" or "ORDER" or "" */
int nSubquery /* Number of subqueries that the label is moving */
){
Expr *pOrig; /* The iCol-th column of the result set */
@@ -82,8 +81,11 @@ static void resolveAlias(
assert( pOrig!=0 );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
- if( pDup!=0 ){
- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ pDup = 0;
+ }else{
+ incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
@@ -104,15 +106,12 @@ static void resolveAlias(
pExpr->flags |= EP_MemToken;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( pExpr->y.pWin!=0 ){
+ if( ALWAYS(pExpr->y.pWin!=0) ){
pExpr->y.pWin->pOwner = pExpr;
- }else{
- assert( db->mallocFailed );
}
}
sqlite3DbFree(db, pDup);
}
- ExprSetProperty(pExpr, EP_Alias);
}
@@ -247,8 +246,8 @@ static int lookupName(
int cntTab = 0; /* Number of matching table names */
int nSubquery = 0; /* How many levels of subquery */
sqlite3 *db = pParse->db; /* The database connection */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ SrcItem *pItem; /* Use for looping over pSrcList items */
+ SrcItem *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
@@ -369,25 +368,33 @@ static int lookupName(
#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference. Or
- ** maybe it is an excluded.* from an upsert.
+ ** maybe it is an excluded.* from an upsert. Or maybe it is
+ ** a reference in the RETURNING clause to a table being modified.
*/
- if( zDb==0 && zTab!=0 && cntTab==0 ){
+ if( cnt==0 && zDb==0 ){
pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
- if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
+ if( pParse->bReturning ){
+ if( (pNC->ncFlags & NC_UBaseReg)!=0
+ && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
+ ){
+ pExpr->iTable = op!=TK_DELETE;
+ pTab = pParse->pTriggerTab;
+ }
+ }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
pTab = pParse->pTriggerTab;
- }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
+ }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
- if( (pNC->ncFlags & NC_UUpsert)!=0 ){
+ if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
pTab = pUpsert->pUpsertSrc->a[0].pTab;
@@ -415,6 +422,7 @@ static int lookupName(
}
if( iColnCol ){
cnt++;
+ pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
@@ -426,27 +434,32 @@ static int lookupName(
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
- ExprSetProperty(pExpr, EP_Alias);
}
}else
#endif /* SQLITE_OMIT_UPSERT */
{
-#ifndef SQLITE_OMIT_TRIGGER
- if( iCol<0 ){
- pExpr->affExpr = SQLITE_AFF_INTEGER;
- }else if( pExpr->iTable==0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<y.pTab = pTab;
- pExpr->iColumn = (i16)iCol;
- eNewExprOp = TK_TRIGGER;
+ if( pParse->bReturning ){
+ eNewExprOp = TK_REGISTER;
+ pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
+ sqlite3TableColumnToStorage(pTab, iCol) + 1;
+ }else{
+ pExpr->iColumn = (i16)iCol;
+ eNewExprOp = TK_TRIGGER;
+#ifndef SQLITE_OMIT_TRIGGER
+ if( iCol<0 ){
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
+ }else if( pExpr->iTable==0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<ncFlags & NC_UEList)!=0
- && cnt==0
+ if( cnt==0
+ && (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
@@ -516,7 +529,7 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "row value misused");
return WRC_Abort;
}
- resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
+ resolveAlias(pParse, pEList, j, pExpr, nSubquery);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@@ -595,7 +608,7 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
pParse->checkSchema = 1;
- pTopNC->nErr++;
+ pTopNC->nNcErr++;
}
/* If a column from a table in pSrcList is referenced, then record
@@ -618,18 +631,24 @@ static int lookupName(
/* Clean up and return
*/
- sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ }
pExpr->op = eNewExprOp;
ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
- if( !ExprHasProperty(pExpr, EP_Alias) ){
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pParse->db->xAuth
+ && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
+ ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
+#endif
/* Increment the nRef value on all name contexts from TopNC up to
** the point where the name matched. */
for(;;){
@@ -651,7 +670,7 @@ static int lookupName(
Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
- struct SrcList_item *pItem = &pSrc->a[iSrc];
+ SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab = p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
@@ -763,7 +782,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
@@ -774,6 +793,47 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
+ /* An optimization: Attempt to convert
+ **
+ ** "expr IS NOT NULL" --> "TRUE"
+ ** "expr IS NULL" --> "FALSE"
+ **
+ ** if we can prove that "expr" is never NULL. Call this the
+ ** "NOT NULL strength reduction optimization".
+ **
+ ** If this optimization occurs, also restore the NameContext ref-counts
+ ** to the state they where in before the "column" LHS expression was
+ ** resolved. This prevents "column" from being counted as having been
+ ** referenced, which might prevent a SELECT from being erroneously
+ ** marked as correlated.
+ */
+ case TK_NOTNULL:
+ case TK_ISNULL: {
+ int anRef[8];
+ NameContext *p;
+ int i;
+ for(i=0, p=pNC; p && ipNext, i++){
+ anRef[i] = p->nRef;
+ }
+ sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
+ if( pExpr->op==TK_NOTNULL ){
+ pExpr->u.zToken = "true";
+ ExprSetProperty(pExpr, EP_IsTrue);
+ }else{
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ }
+ pExpr->op = TK_TRUEFALSE;
+ for(i=0, p=pNC; p && ipNext, i++){
+ p->nRef = anRef[i];
+ }
+ sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ }
+ return WRC_Prune;
+ }
+
/* A column name: ID
** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
@@ -855,7 +915,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3ErrorMsg(pParse,
"second argument to likelihood() must be a "
"constant between 0.0 and 1.0");
- pNC->nErr++;
+ pNC->nNcErr++;
}
}else{
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
@@ -877,7 +937,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( auth==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
pDef->zName);
- pNC->nErr++;
+ pNC->nNcErr++;
}
pExpr->op = TK_NULL;
return WRC_Prune;
@@ -933,7 +993,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
- pNC->nErr++;
+ pNC->nNcErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
@@ -946,13 +1006,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zType = "aggregate";
}
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
- pNC->nErr++;
+ pNC->nNcErr++;
is_agg = 0;
}
#else
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
- pNC->nErr++;
+ pNC->nNcErr++;
is_agg = 0;
}
#endif
@@ -962,11 +1022,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
+ pNC->nNcErr++;
}else if( wrong_num_args ){
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
nId, zId);
- pNC->nErr++;
+ pNC->nNcErr++;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
@@ -974,7 +1034,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
"FILTER may not be used with non-aggregate %.*s()",
nId, zId
);
- pNC->nErr++;
+ pNC->nNcErr++;
}
#endif
if( is_agg ){
@@ -1001,6 +1061,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
+ if( pParse->db->mallocFailed ) break;
}
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
@@ -1075,7 +1136,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
+ if( ALWAYS(pRight) && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -1197,11 +1258,11 @@ static int resolveOrderByTermToExprList(
nc.pParse = pParse;
nc.pSrcList = pSelect->pSrc;
nc.uNC.pEList = pEList;
- nc.ncFlags = NC_AllowAgg|NC_UEList;
- nc.nErr = 0;
+ nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect;
+ nc.nNcErr = 0;
db = pParse->db;
savedSuppErr = db->suppressErr;
- if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
+ db->suppressErr = 1;
rc = sqlite3ResolveExprNames(&nc, pE);
db->suppressErr = savedSuppErr;
if( rc ) return 0;
@@ -1300,29 +1361,24 @@ static int resolveCompoundOrderBy(
** Once the comparisons are finished, the duplicate expression
** is deleted.
**
- ** Or, if this is running as part of an ALTER TABLE operation,
- ** resolve the symbols in the actual expression, not a duplicate.
- ** And, if one of the comparisons is successful, leave the expression
- ** as is instead of transforming it to an integer as in the usual
- ** case. This allows the code in alter.c to modify column
- ** refererences within the ORDER BY expression as required. */
- if( IN_RENAME_OBJECT ){
- pDup = pE;
- }else{
- pDup = sqlite3ExprDup(db, pE, 0);
- }
+ ** If this is running as part of an ALTER TABLE operation and
+ ** the symbols resolve successfully, also resolve the symbols in the
+ ** actual expression. This allows the code in alter.c to modify
+ ** column references within the ORDER BY expression as required. */
+ pDup = sqlite3ExprDup(db, pE, 0);
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+ if( IN_RENAME_OBJECT && iCol>0 ){
+ resolveOrderByTermToExprList(pParse, pSelect, pE);
+ }
}
- if( !IN_RENAME_OBJECT ){
- sqlite3ExprDelete(db, pDup);
- }
+ sqlite3ExprDelete(db, pDup);
}
}
if( iCol>0 ){
/* Convert the ORDER BY term into an integer column number iCol,
- ** taking care to preserve the COLLATE clause if it exists */
+ ** taking care to preserve the COLLATE clause if it exists. */
if( !IN_RENAME_OBJECT ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return 1;
@@ -1391,8 +1447,7 @@ int sqlite3ResolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
- resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
- zType,0);
+ resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
}
}
return 0;
@@ -1458,7 +1513,7 @@ static int resolveOrderGroupBy(
Parse *pParse; /* Parsing context */
int nResult; /* Number of terms in the result set */
- if( pOrderBy==0 ) return 0;
+ assert( pOrderBy!=0 );
nResult = pSelect->pEList->nExpr;
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){
@@ -1548,8 +1603,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
while( p ){
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
+ assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */
p->selFlags |= SF_Resolved;
+
/* Resolve the expressions in the LIMIT and OFFSET clauses. These
** are not allowed to refer to any names, so pass an empty NameContext.
*/
@@ -1577,27 +1634,26 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries
*/
for(i=0; ipSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
- NameContext *pNC; /* Used to iterate name contexts */
- int nRef = 0; /* Refcount for pOuterNC and outer contexts */
+ int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
- /* Count the total number of references to pOuterNC and all of its
- ** parent contexts. After resolving references to expressions in
- ** pItem->pSelect, check if this value has changed. If so, then
- ** SELECT statement pItem->pSelect must be correlated. Set the
- ** pItem->fg.isCorrelated flag if this is the case. */
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
-
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
- assert( pItem->fg.isCorrelated==0 && nRef<=0 );
- pItem->fg.isCorrelated = (nRef!=0);
+ /* If the number of references to the outer context changed when
+ ** expressions in the sub-select were resolved, the sub-select
+ ** is correlated. It is not required to check the refcount on any
+ ** but the innermost outer context object, as lookupName() increments
+ ** the refcount on all contexts between the current one and the
+ ** context containing the column when it resolves a name. */
+ if( pOuterNC ){
+ assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
+ pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
+ }
}
}
@@ -1624,13 +1680,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sNC.ncFlags &= ~NC_AllowAgg;
}
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return WRC_Abort;
- }
-
/* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
@@ -1639,15 +1688,21 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** Minor point: If this is the case, then the expression will be
** re-evaluated for each reference to it.
*/
- assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 );
+ assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
- if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ if( p->pHaving ){
+ if( !pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return WRC_Abort;
+ }
+ if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ }
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
/* Resolve names in table-valued-function arguments */
for(i=0; ipSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->fg.isTabFunc
&& sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
){
@@ -1655,6 +1710,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
*/
@@ -1682,7 +1750,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** is not detected until much later, and so we need to go ahead and
** resolve those symbols on the incorrect ORDER BY for consistency.
*/
- if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
+ if( p->pOrderBy!=0
+ && isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
){
return WRC_Abort;
@@ -1710,19 +1779,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( IN_RENAME_OBJECT ){
- Window *pWin;
- for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
- if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
- || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
- ){
- return WRC_Abort;
- }
- }
- }
-#endif
-
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
@@ -1806,7 +1862,7 @@ int sqlite3ResolveExprNames(
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
+ w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
@@ -1825,7 +1881,7 @@ int sqlite3ResolveExprNames(
testcase( pNC->ncFlags & NC_HasWin );
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
pNC->ncFlags |= savedHasAgg;
- return pNC->nErr>0 || w.pParse->nErr>0;
+ return pNC->nNcErr>0 || w.pParse->nErr>0;
}
/*
@@ -1870,7 +1926,7 @@ int sqlite3ResolveExprListNames(
savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
}
- if( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
+ if( w.pParse->nErr>0 ) return WRC_Abort;
}
pNC->ncFlags |= savedHasAgg;
return WRC_Continue;
diff --git a/src/select.c b/src/select.c
index b4f272679..7d8fd5939 100644
--- a/src/select.c
+++ b/src/select.c
@@ -85,12 +85,16 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlite3WindowListDelete(db, p->pWinDefn);
}
+ while( p->pWin ){
+ assert( p->pWin->ppThis==&p->pWin );
+ sqlite3WindowUnlinkFromSelect(p->pWin);
+ }
#endif
- if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -262,7 +266,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
** Return the index of a column in a table. Return -1 if the column
** is not contained in the table.
*/
-static int columnIndex(Table *pTab, const char *zCol){
+int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
u8 h = sqlite3StrIHash(zCol);
Column *pCol;
@@ -294,7 +298,7 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; ia[i].pTab, zCol);
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
if( iCol>=0
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
){
@@ -347,7 +351,7 @@ static void addWhereTerm(
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
- pEq->iRightJoinTable = (i16)pE2->iTable;
+ pEq->iRightJoinTable = pE2->iTable;
}
*ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
}
@@ -383,7 +387,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
- p->iRightJoinTable = (i16)iTable;
+ p->iRightJoinTable = iTable;
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; ix.pList->nExpr; i++){
@@ -407,6 +411,9 @@ static void unsetJoinExpr(Expr *p, int iTable){
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
+ if( p->op==TK_COLUMN && p->iTable==iTable ){
+ ExprClearProperty(p, EP_CanBeNull);
+ }
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; ix.pList->nExpr; i++){
@@ -435,8 +442,8 @@ static void unsetJoinExpr(Expr *p, int iTable){
static int sqliteProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; /* All tables in the FROM clause */
int i, j; /* Loop counters */
- struct SrcList_item *pLeft; /* Left table being joined */
- struct SrcList_item *pRight; /* Right table being joined */
+ SrcItem *pLeft; /* Left table being joined */
+ SrcItem *pRight; /* Right table being joined */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
@@ -504,7 +511,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iRightCol; /* Column number of matching column on the right */
zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
+ iRightCol = sqlite3ColumnIndex(pRightTab, zName);
if( iRightCol<0
|| !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
){
@@ -734,31 +741,155 @@ static void codeOffset(
}
/*
-** Add code that will check to make sure the N registers starting at iMem
-** form a distinct entry. iTab is a sorting index that holds previously
-** seen combinations of the N values. A new entry is made in iTab
-** if the current N values are new.
-**
-** A jump to addrRepeat is made and the N+1 values are popped from the
-** stack if the top N elements are not distinct.
+** Add code that will check to make sure the array of registers starting at
+** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
+** distinct aggregates ("SELECT count(DISTINCT ) ..."). Three strategies
+** are available. Which is used depends on the value of parameter eTnctType,
+** as follows:
+**
+** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
+** Build an ephemeral table that contains all entries seen before and
+** skip entries which have been seen before.
+**
+** Parameter iTab is the cursor number of an ephemeral table that must
+** be opened before the VM code generated by this routine is executed.
+** The ephemeral cursor table is queried for a record identical to the
+** record formed by the current array of registers. If one is found,
+** jump to VM address addrRepeat. Otherwise, insert a new record into
+** the ephemeral cursor and proceed.
+**
+** The returned value in this case is a copy of parameter iTab.
+**
+** WHERE_DISTINCT_ORDERED:
+** In this case rows are being delivered sorted order. The ephermal
+** table is not required. Instead, the current set of values
+** is compared against previous row. If they match, the new row
+** is not distinct and control jumps to VM address addrRepeat. Otherwise,
+** the VM program proceeds with processing the new row.
+**
+** The returned value in this case is the register number of the first
+** in an array of registers used to store the previous result row so that
+** it can be compared to the next. The caller must ensure that this
+** register is initialized to NULL. (The fixDistinctOpenEph() routine
+** will take care of this initialization.)
+**
+** WHERE_DISTINCT_UNIQUE:
+** In this case it has already been determined that the rows are distinct.
+** No special action is required. The return value is zero.
+**
+** Parameter pEList is the list of expressions used to generated the
+** contents of each row. It is used by this routine to determine (a)
+** how many elements there are in the array of registers and (b) the
+** collation sequences that should be used for the comparisons if
+** eTnctType is WHERE_DISTINCT_ORDERED.
*/
-static void codeDistinct(
+static int codeDistinct(
Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
- int N, /* Number of elements */
- int iMem /* First element */
+ ExprList *pEList, /* Expression for each element */
+ int regElem /* First element */
){
- Vdbe *v;
- int r1;
+ int iRet = 0;
+ int nResultCol = pEList->nExpr;
+ Vdbe *v = pParse->pVdbe;
- v = pParse->pVdbe;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlite3ReleaseTempReg(pParse, r1);
+ switch( eTnctType ){
+ case WHERE_DISTINCT_ORDERED: {
+ int i;
+ int iJump; /* Jump destination */
+ int regPrev; /* Previous row content */
+
+ /* Allocate space for the previous row */
+ iRet = regPrev = pParse->nMem+1;
+ pParse->nMem += nResultCol;
+
+ iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
+ for(i=0; ia[i].pExpr);
+ if( idb->mallocFailed );
+ sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1);
+ break;
+ }
+
+ case WHERE_DISTINCT_UNIQUE: {
+ /* nothing to do */
+ break;
+ }
+
+ default: {
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlite3ReleaseTempReg(pParse, r1);
+ iRet = iTab;
+ break;
+ }
+ }
+
+ return iRet;
+}
+
+/*
+** This routine runs after codeDistinct(). It makes necessary
+** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
+** routine made use of. This processing must be done separately since
+** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
+** laid down.
+**
+** WHERE_DISTINCT_NOOP:
+** WHERE_DISTINCT_UNORDERED:
+**
+** No adjustments necessary. This function is a no-op.
+**
+** WHERE_DISTINCT_UNIQUE:
+**
+** The ephemeral table is not needed. So change the
+** OP_OpenEphemeral opcode into an OP_Noop.
+**
+** WHERE_DISTINCT_ORDERED:
+**
+** The ephemeral table is not needed. But we do need register
+** iVal to be initialized to NULL. So change the OP_OpenEphemeral
+** into an OP_Null on the iVal register.
+*/
+static void fixDistinctOpenEph(
+ Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
+ int iVal, /* Value returned by codeDistinct() */
+ int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
+){
+ if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
+ Vdbe *v = pParse->pVdbe;
+ sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
+ if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
+ sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
+ }
+ if( eTnctType==WHERE_DISTINCT_ORDERED ){
+ /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
+ ** bit on the first register of the previous value. This will cause the
+ ** OP_Ne added in codeDistinct() to always fail on the first iteration of
+ ** the loop even if the first row is all NULLs. */
+ VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
+ pOp->opcode = OP_Null;
+ pOp->p1 = 1;
+ pOp->p2 = iVal;
+ }
+ }
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -1006,59 +1137,11 @@ static void selectInnerLoop(
** part of the result.
*/
if( hasDistinct ){
- switch( pDistinct->eTnctType ){
- case WHERE_DISTINCT_ORDERED: {
- VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
- int iJump; /* Jump destination */
- int regPrev; /* Previous row content */
-
- /* Allocate space for the previous row */
- regPrev = pParse->nMem+1;
- pParse->nMem += nResultCol;
-
- /* Change the OP_OpenEphemeral coded earlier to an OP_Null
- ** sets the MEM_Cleared bit on the first register of the
- ** previous value. This will cause the OP_Ne below to always
- ** fail on the first iteration of the loop even if the first
- ** row is all NULLs.
- */
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
- pOp->opcode = OP_Null;
- pOp->p1 = 1;
- pOp->p2 = regPrev;
- pOp = 0; /* Ensure pOp is not used after sqlite3VdbeAddOp() */
-
- iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
- for(i=0; ipEList->a[i].pExpr);
- if( idb->mallocFailed );
- sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
- break;
- }
-
- case WHERE_DISTINCT_UNIQUE: {
- sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- break;
- }
-
- default: {
- assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
- codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
- regResult);
- break;
- }
- }
+ int eType = pDistinct->eTnctType;
+ int iTab = pDistinct->tabTnct;
+ assert( nResultCol==p->pEList->nExpr );
+ iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
+ fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
@@ -1383,7 +1466,7 @@ KeyInfo *sqlite3KeyInfoFromExprList(
/*
** Name of the connection operator, used for error messages.
*/
-static const char *selectOpName(int id){
+const char *sqlite3SelectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
@@ -1724,7 +1807,13 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && iColpEList->nExpr ){
+ if( iColpEList->nExpr
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && iCol>=0
+#else
+ && ALWAYS(iCol>=0)
+#endif
+ ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
@@ -1866,7 +1955,7 @@ static void generateColumnTypes(
** then the result column name with the table name
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
-static void generateColumnNames(
+void sqlite3GenerateColumnNames(
Parse *pParse, /* Parser context */
Select *pSelect /* Generate column names for this SELECT statement */
){
@@ -1956,7 +2045,7 @@ static void generateColumnNames(
** and will break if those assumptions changes. Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
-** See Also: generateColumnNames()
+** See Also: sqlite3GenerateColumnNames()
*/
int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
@@ -1979,7 +2068,7 @@ int sqlite3ColumnsFromExprList(
nCol = pEList->nExpr;
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
testcase( aCol==0 );
- if( nCol>32767 ) nCol = 32767;
+ if( NEVER(nCol>32767) ) nCol = 32767;
}else{
nCol = 0;
aCol = 0;
@@ -2086,6 +2175,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){
const char *zType;
int n, m;
+ pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
zType = columnType(&sNC, p, 0, 0, 0);
/* pCol->szEst = ... // Column size est for SELECT tables never used */
@@ -2601,12 +2691,8 @@ static int multiSelect(
db = pParse->db;
pPrior = p->pPrior;
dest = *pDest;
- if( pPrior->pOrderBy || pPrior->pLimit ){
- sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
- pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
+ assert( pPrior->pOrderBy==0 );
+ assert( pPrior->pLimit==0 );
v = sqlite3GetVdbe(pParse);
assert( v!=0 ); /* The VDBE already created by calling function */
@@ -2657,13 +2743,14 @@ static int multiSelect(
switch( p->op ){
case TK_ALL: {
int addr = 0;
- int nLimit;
+ int nLimit = 0; /* Initialize to suppress harmless compiler warning */
assert( !pPrior->pLimit );
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlite3Select(pParse, pPrior, &dest);
- p->pLimit = 0;
+ pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
}
@@ -2679,13 +2766,14 @@ static int multiSelect(
}
}
ExplainQueryPlan((pParse, 1, "UNION ALL"));
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
rc = sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( pPrior->pLimit
- && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
+ if( p->pLimit
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -2731,6 +2819,7 @@ static int multiSelect(
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
@@ -2749,7 +2838,8 @@ static int multiSelect(
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
@@ -2810,6 +2900,7 @@ static int multiSelect(
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
@@ -2825,7 +2916,8 @@ static int multiSelect(
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -2934,7 +3026,8 @@ void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
+ " do not have the same number of result columns",
+ sqlite3SelectOpName(p->op));
}
}
@@ -3031,10 +3124,8 @@ static int generateOutputSubroutine(
** if it is the RHS of a row-value IN operator.
*/
case SRT_Mem: {
- if( pParse->nErr==0 ){
- testcase( pIn->nSdst>1 );
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
- }
+ testcase( pIn->nSdst>1 );
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
/* The LIMIT clause will jump out of the loop for us */
break;
}
@@ -3326,7 +3417,7 @@ static int multiSelectOrderBy(
sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
- ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
+ ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op)));
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
@@ -3460,6 +3551,9 @@ static int multiSelectOrderBy(
p->pPrior = pPrior;
pPrior->pNext = p;
+ sqlite3ExprListDelete(db, pPrior->pOrderBy);
+ pPrior->pOrderBy = 0;
+
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
ExplainQueryPlanPop(pParse);
@@ -3514,9 +3608,12 @@ static Expr *substExpr(
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
- }else{
+ }else
+#endif
+ {
Expr *pNew;
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
@@ -3536,10 +3633,14 @@ static Expr *substExpr(
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
- if( pNew && pSubst->isLeftJoin ){
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pNew);
+ return pExpr;
+ }
+ if( pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
+ if( ExprHasProperty(pExpr,EP_FromJoin) ){
sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
@@ -3547,15 +3648,13 @@ static Expr *substExpr(
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
- if( pExpr ){
- if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
- (pColl ? pColl->zName : "BINARY")
- );
- }
- ExprClearProperty(pExpr, EP_Collate);
+ if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ (pColl ? pColl->zName : "BINARY")
+ );
}
+ ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
@@ -3596,7 +3695,7 @@ static void substSelect(
int doPrior /* Do substitutes on p->pPrior too */
){
SrcList *pSrc;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
int i;
if( !p ) return;
do{
@@ -3626,7 +3725,7 @@ static void substSelect(
** pSrcItem->colUsed mask.
*/
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
pItem = pWalker->u.pSrcItem;
if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
@@ -3636,7 +3735,7 @@ static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
}
static void recomputeColumnsUsed(
Select *pSelect, /* The complete SELECT statement */
- struct SrcList_item *pSrcItem /* Which FROM clause item to recompute */
+ SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
if( NEVER(pSrcItem->pTab==0) ) return;
@@ -3649,6 +3748,92 @@ static void recomputeColumnsUsed(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
+** Assign new cursor numbers to each of the items in pSrc. For each
+** new cursor number assigned, set an entry in the aCsrMap[] array
+** to map the old cursor number to the new:
+**
+** aCsrMap[iOld] = iNew;
+**
+** The array is guaranteed by the caller to be large enough for all
+** existing cursor numbers in pSrc.
+**
+** If pSrc contains any sub-selects, call this routine recursively
+** on the FROM clause of each such sub-select, with iExcept set to -1.
+*/
+static void srclistRenumberCursors(
+ Parse *pParse, /* Parse context */
+ int *aCsrMap, /* Array to store cursor mappings in */
+ SrcList *pSrc, /* FROM clause to renumber */
+ int iExcept /* FROM clause item to skip */
+){
+ int i;
+ SrcItem *pItem;
+ for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){
+ if( i!=iExcept ){
+ Select *p;
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
+ aCsrMap[pItem->iCursor] = pParse->nTab++;
+ }
+ pItem->iCursor = aCsrMap[pItem->iCursor];
+ for(p=pItem->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
+ }
+ }
+}
+
+/*
+** Expression walker callback used by renumberCursors() to update
+** Expr objects to match newly assigned cursor numbers.
+*/
+static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
+ int *aCsrMap = pWalker->u.aiCol;
+ int op = pExpr->op;
+ if( (op==TK_COLUMN || op==TK_IF_NULL_ROW) && aCsrMap[pExpr->iTable] ){
+ pExpr->iTable = aCsrMap[pExpr->iTable];
+ }
+ if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
+ pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
+ }
+ return WRC_Continue;
+}
+
+/*
+** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
+** of the SELECT statement passed as the second argument, and to each
+** cursor in the FROM clause of any FROM clause sub-selects, recursively.
+** Except, do not assign a new cursor number to the iExcept'th element in
+** the FROM clause of (*p). Update all expressions and other references
+** to refer to the new cursor numbers.
+**
+** Argument aCsrMap is an array that may be used for temporary working
+** space. Two guarantees are made by the caller:
+**
+** * the array is larger than the largest cursor number used within the
+** select statement passed as an argument, and
+**
+** * the array entries for all cursor numbers that do *not* appear in
+** FROM clauses of the select statement as described above are
+** initialized to zero.
+*/
+static void renumberCursors(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Select to renumber cursors within */
+ int iExcept, /* FROM clause item to skip */
+ int *aCsrMap /* Working space */
+){
+ Walker w;
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
+ memset(&w, 0, sizeof(w));
+ w.u.aiCol = aCsrMap;
+ w.xExprCallback = renumberCursorsCb;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ sqlite3WalkSelect(&w, p);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
@@ -3743,9 +3928,9 @@ static void recomputeColumnsUsed(
** (17c) every term within the subquery compound must have a FROM clause
** (17d) the outer query may not be
** (17d1) aggregate, or
-** (17d2) DISTINCT, or
-** (17d3) a join.
-** (17e) the subquery may not contain window functions
+** (17d2) DISTINCT
+** (17e) the subquery may not contain window functions, and
+** (17f) the subquery must not be the RHS of a LEFT JOIN.
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -3761,8 +3946,8 @@ static void recomputeColumnsUsed(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER BY clause of the parent must be simple references to
-** columns of the sub-query.
+** ORDER BY clause of the parent must be copies of a term returned
+** by the parent query.
**
** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
@@ -3778,9 +3963,8 @@ static void recomputeColumnsUsed(
**
** (22) The subquery may not be a recursive CTE.
**
-** (**) Subsumed into restriction (17d3). Was: If the outer query is
-** a recursive CTE, then the sub-query may not be a compound query.
-** This restriction is because transforming the
+** (23) If the outer query is a recursive CTE, then the sub-query may not be
+** a compound query. This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
@@ -3822,9 +4006,10 @@ static int flattenSubquery(
int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
- struct SrcList_item *pSubitem; /* The subquery */
+ SrcItem *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
+ int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -3920,13 +4105,14 @@ static int flattenSubquery(
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
- if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0; /* (17d1), (17d2), or (17d3) */
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || isLeftJoin>0 ){
+ return 0; /* (17d1), (17d2), or (17f) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
+ assert( (pSub->selFlags & SF_Recursive)==0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
@@ -3947,15 +4133,15 @@ static int flattenSubquery(
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
- }
- /* Ex-restriction (23):
- ** The only way that the recursive part of a CTE can contain a compound
- ** subquery is for the subquery to be one term of a join. But if the
- ** subquery is a join, then the flattening has already been stopped by
- ** restriction (17d3)
- */
- assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
+ /* Restriction (23) */
+ if( (p->selFlags & SF_Recursive) ) return 0;
+
+ if( pSrc->nSrc>1 ){
+ if( pParse->nSelect>500 ) return 0;
+ aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
+ }
+ }
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -3967,6 +4153,17 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
+ /* Delete the transient structures associated with thesubquery */
+ pSub1 = pSubitem->pSelect;
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ pSubitem->pSelect = 0;
+ assert( pSubitem->pOn==0 );
+
/* If the sub-query is a compound SELECT statement, then (by restrictions
** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
@@ -4005,18 +4202,23 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
+ Table *pItemTab = pSubitem->pTab;
+ pSubitem->pTab = 0;
p->pOrderBy = 0;
- p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
p->op = TK_ALL;
+ pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
+ pNew->selId = ++pParse->nSelect;
+ if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
+ renumberCursors(pParse, pNew, iFrom, aCsrMap);
+ }
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
@@ -4024,24 +4226,13 @@ static int flattenSubquery(
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- if( db->mallocFailed ) return 1;
+ assert( pSubitem->pSelect==0 );
+ }
+ sqlite3DbFree(db, aCsrMap);
+ if( db->mallocFailed ){
+ pSubitem->pSelect = pSub1;
+ return 1;
}
-
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
- */
- pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
/* Defer deleting the Table object associated with the
** subquery until code generation is
@@ -4054,8 +4245,10 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
+ sqlite3ParserAddCleanup(pToplevel,
+ (void(*)(sqlite3*,void*))sqlite3DeleteTable,
+ pTabToDel);
+ testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
@@ -4075,6 +4268,7 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
+ pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
@@ -4083,16 +4277,10 @@ static int flattenSubquery(
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
- if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
- jointype = pSubitem->fg.jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
- if( pSrc==0 ) break;
- pParent->pSrc = pSrc;
+ if( pParent==p ){
+ jointype = pSubitem->fg.jointype; /* First time through the loop */
}
-
+
/* The subquery uses a single slot of the FROM clause of the outer
** query. If the subquery has more than one element in its FROM clause,
** then expand the outer query to make space for it to hold all elements
@@ -4210,7 +4398,7 @@ static int flattenSubquery(
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -4227,8 +4415,10 @@ static int flattenSubquery(
typedef struct WhereConst WhereConst;
struct WhereConst {
Parse *pParse; /* Parsing context */
+ u8 *pOomFault; /* Pointer to pParse->db->mallocFailed */
int nConst; /* Number for COLUMN=CONSTANT terms */
int nChng; /* Number of times a constant is propagated */
+ int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
};
@@ -4267,6 +4457,9 @@ static void constInsert(
return; /* Already present. Return without doing anything. */
}
}
+ if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ pConst->bHasAffBlob = 1;
+ }
pConst->nConst++;
pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
@@ -4287,7 +4480,7 @@ static void constInsert(
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
- if( pExpr==0 ) return;
+ if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
@@ -4308,37 +4501,83 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
}
/*
-** This is a Walker expression callback. pExpr is a candidate expression
-** to be replaced by a value. If pExpr is equivalent to one of the
-** columns named in pWalker->u.pConst, then overwrite it with its
-** corresponding value.
+** This is a helper function for Walker callback propagateConstantExprRewrite().
+**
+** Argument pExpr is a candidate expression to be replaced by a value. If
+** pExpr is equivalent to one of the columns named in pWalker->u.pConst,
+** then overwrite it with the corresponding value. Except, do not do so
+** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
+** is SQLITE_AFF_BLOB.
*/
-static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
+static int propagateConstantExprRewriteOne(
+ WhereConst *pConst,
+ Expr *pExpr,
+ int bIgnoreAffBlob
+){
int i;
- WhereConst *pConst;
+ if( pConst->pOomFault[0] ) return WRC_Prune;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
testcase( ExprHasProperty(pExpr, EP_FromJoin) );
return WRC_Continue;
}
- pConst = pWalker->u.pConst;
for(i=0; inConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
+ if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ break;
+ }
/* A match is found. Add the EP_FixedCol property */
pConst->nChng++;
ExprClearProperty(pExpr, EP_Leaf);
ExprSetProperty(pExpr, EP_FixedCol);
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0);
+ if( pConst->pParse->db->mallocFailed ) return WRC_Prune;
break;
}
return WRC_Prune;
}
+/*
+** This is a Walker expression callback. pExpr is a node from the WHERE
+** clause of a SELECT statement. This function examines pExpr to see if
+** any substitutions based on the contents of pWalker->u.pConst should
+** be made to pExpr or its immediate children.
+**
+** A substitution is made if:
+**
+** + pExpr is a column with an affinity other than BLOB that matches
+** one of the columns in pWalker->u.pConst, or
+**
+** + pExpr is a binary comparison operator (=, <=, >=, <, >) that
+** uses an affinity other than TEXT and one of its immediate
+** children is a column that matches one of the columns in
+** pWalker->u.pConst.
+*/
+static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
+ WhereConst *pConst = pWalker->u.pConst;
+ assert( TK_GT==TK_EQ+1 );
+ assert( TK_LE==TK_EQ+2 );
+ assert( TK_LT==TK_EQ+3 );
+ assert( TK_GE==TK_EQ+4 );
+ if( pConst->bHasAffBlob ){
+ if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE)
+ || pExpr->op==TK_IS
+ ){
+ propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0);
+ if( pConst->pOomFault[0] ) return WRC_Prune;
+ if( sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){
+ propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0);
+ }
+ }
+ }
+ return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob);
+}
+
/*
** The WHERE-clause constant propagation optimization.
**
@@ -4374,6 +4613,21 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
** routines know to generate the constant "123" instead of looking up the
** column value. Also, to avoid collation problems, this optimization is
** only attempted if the "a=123" term uses the default BINARY collation.
+**
+** 2021-05-25 forum post 6a06202608: Another troublesome case is...
+**
+** CREATE TABLE t1(x);
+** INSERT INTO t1 VALUES(10.0);
+** SELECT 1 FROM t1 WHERE x=10 AND x LIKE 10;
+**
+** The query should return no rows, because the t1.x value is '10.0' not '10'
+** and '10.0' is not LIKE '10'. But if we are not careful, the first WHERE
+** term "x=10" will cause the second WHERE term to become "10 LIKE 10",
+** resulting in a false positive. To avoid this, constant propagation for
+** columns with BLOB affinity is only allowed if the constant is used with
+** operators ==, <=, <, >=, >, or IS in a way that will cause the correct
+** type conversions to occur. See logic associated with the bHasAffBlob flag
+** for details.
*/
static int propagateConstants(
Parse *pParse, /* The parsing context */
@@ -4383,10 +4637,12 @@ static int propagateConstants(
Walker w;
int nChng = 0;
x.pParse = pParse;
+ x.pOomFault = &pParse->db->mallocFailed;
do{
x.nConst = 0;
x.nChng = 0;
x.apExpr = 0;
+ x.bHasAffBlob = 0;
findConstInWhere(&x, p->pWhere);
if( x.nConst ){
memset(&w, 0, sizeof(w));
@@ -4404,6 +4660,35 @@ static int propagateConstants(
return nChng;
}
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+# if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** This function is called to determine whether or not it is safe to
+** push WHERE clause expression pExpr down to FROM clause sub-query
+** pSubq, which contains at least one window function. Return 1
+** if it is safe and the expression should be pushed down, or 0
+** otherwise.
+**
+** It is only safe to push the expression down if it consists only
+** of constants and copies of expressions that appear in the PARTITION
+** BY clause of all window function used by the sub-query. It is safe
+** to filter out entire partitions, but not rows within partitions, as
+** this may change the results of the window functions.
+**
+** At the time this function is called it is guaranteed that
+**
+** * the sub-query uses only one distinct window frame, and
+** * that the window frame has a PARTITION BY clase.
+*/
+static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
+ assert( pSubq->pWin->pPartition );
+ assert( (pSubq->selFlags & SF_MultiPart)==0 );
+ assert( pSubq->pPrior==0 );
+ return sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition);
+}
+# endif /* SQLITE_OMIT_WINDOWFUNC */
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
@@ -4451,9 +4736,24 @@ static int propagateConstants(
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
-** (6) The inner query features one or more window-functions (since
-** changes to the WHERE clause of the inner query could change the
-** window over which window functions are calculated).
+** (6) Window functions make things tricky as changes to the WHERE clause
+** of the inner query could change the window over which window
+** functions are calculated. Therefore, do not attempt the optimization
+** if:
+**
+** (6a) The inner query uses multiple incompatible window partitions.
+**
+** (6b) The inner query is a compound and uses window-functions.
+**
+** (6c) The WHERE clause does not consist entirely of constants and
+** copies of expressions found in the PARTITION BY clause of
+** all window-functions used by the sub-query. It is safe to
+** filter out entire partitions, as this does not change the
+** window over which any window-function is calculated.
+**
+** (7) The inner query is a Common Table Expression (CTE) that should
+** be materialized. (This restriction is implemented in the calling
+** routine.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -4467,13 +4767,17 @@ static int pushDownWhereTerms(
){
Expr *pNew;
int nChng = 0;
- Select *pSel;
if( pWhere==0 ) return 0;
- if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+ if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
- for(pSel=pSubq; pSel; pSel=pSel->pPrior){
- if( pSel->pWin ) return 0; /* restriction (6) */
+ if( pSubq->pPrior ){
+ Select *pSel;
+ for(pSel=pSubq; pSel; pSel=pSel->pPrior){
+ if( pSel->pWin ) return 0; /* restriction (6b) */
+ }
+ }else{
+ if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
}
#endif
@@ -4509,6 +4813,7 @@ static int pushDownWhereTerms(
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
+ pSubq->selFlags |= SF_PushDown;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -4519,6 +4824,14 @@ static int pushDownWhereTerms(
x.isLeftJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
+ /* Restriction 6c has prevented push-down in this case */
+ sqlite3ExprDelete(pParse->db, pNew);
+ nChng--;
+ break;
+ }
+#endif
if( pSubq->selFlags & SF_Aggregate ){
pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
}else{
@@ -4557,7 +4870,11 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
assert( !IsWindowFunc(pFunc) );
- if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
+ if( pEList==0
+ || pEList->nExpr!=1
+ || ExprHasProperty(pFunc, EP_WinFunc)
+ || OptimizationDisabled(db, SQLITE_MinMaxOpt)
+ ){
return eRet;
}
zFunc = pFunc->u.zToken;
@@ -4620,24 +4937,26 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
-int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->fg.isIndexedBy ){
- Table *pTab = pFrom->pTab;
- char *zIndexedBy = pFrom->u1.zIndexedBy;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
- pParse->checkSchema = 1;
- return SQLITE_ERROR;
- }
- pFrom->pIBIndex = pIdx;
+int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
+ Table *pTab = pFrom->pTab;
+ char *zIndexedBy = pFrom->u1.zIndexedBy;
+ Index *pIdx;
+ assert( pTab!=0 );
+ assert( pFrom->fg.isIndexedBy!=0 );
+
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
+ pIdx=pIdx->pNext
+ );
+ if( !pIdx ){
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
+ pParse->checkSchema = 1;
+ return SQLITE_ERROR;
}
+ pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
+
/*
** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
@@ -4724,7 +5043,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** arguments. If it does, leave an error message in pParse and return
** non-zero, since pFrom is not allowed to be a table-valued function.
*/
-static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
+static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){
if( pFrom->fg.isTabFunc ){
sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
return 1;
@@ -4745,21 +5064,22 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
*/
static struct Cte *searchWith(
With *pWith, /* Current innermost WITH clause */
- struct SrcList_item *pItem, /* FROM clause element to resolve */
+ SrcItem *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
- const char *zName;
- if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
- With *p;
- for(p=pWith; p; p=p->pOuter){
- int i;
- for(i=0; inCte; i++){
- if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
- *ppContext = p;
- return &p->a[i];
- }
+ const char *zName = pItem->zName;
+ With *p;
+ assert( pItem->zDatabase==0 );
+ assert( zName!=0 );
+ for(p=pWith; p; p=p->pOuter){
+ int i;
+ for(i=0; inCte; i++){
+ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+ *ppContext = p;
+ return &p->a[i];
}
}
+ if( p->bView ) break;
}
return 0;
}
@@ -4769,52 +5089,83 @@ static struct Cte *searchWith(
**
** This routine pushes the WITH clause passed as the second argument
** onto the top of the stack. If argument bFree is true, then this
-** WITH clause will never be popped from the stack. In this case it
-** should be freed along with the Parse object. In other cases, when
+** WITH clause will never be popped from the stack but should instead
+** be freed along with the Parse object. In other cases, when
** bFree==0, the With object will be freed along with the SELECT
** statement with which it is associated.
+**
+** This routine returns a copy of pWith. Or, if bFree is true and
+** the pWith object is destroyed immediately due to an OOM condition,
+** then this routine return NULL.
+**
+** If bFree is true, do not continue to use the pWith pointer after
+** calling this routine, Instead, use only the return value.
*/
-void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
- assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
+With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
- assert( pParse->pWith!=pWith );
- pWith->pOuter = pParse->pWith;
- pParse->pWith = pWith;
- if( bFree ) pParse->pWithToFree = pWith;
+ if( bFree ){
+ pWith = (With*)sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3WithDelete,
+ pWith);
+ if( pWith==0 ) return 0;
+ }
+ if( pParse->nErr==0 ){
+ assert( pParse->pWith!=pWith );
+ pWith->pOuter = pParse->pWith;
+ pParse->pWith = pWith;
+ }
}
+ return pWith;
}
/*
** This function checks if argument pFrom refers to a CTE declared by
-** a WITH clause on the stack currently maintained by the parser. And,
-** if currently processing a CTE expression, if it is a recursive
-** reference to the current CTE.
-**
-** If pFrom falls into either of the two categories above, pFrom->pTab
-** and other fields are populated accordingly. The caller should check
-** (pFrom->pTab!=0) to determine whether or not a successful match
-** was found.
-**
-** Whether or not a match is found, SQLITE_OK is returned if no error
-** occurs. If an error does occur, an error message is stored in the
-** parser and some error code other than SQLITE_OK returned.
+** a WITH clause on the stack currently maintained by the parser (on the
+** pParse->pWith linked list). And if currently processing a CTE
+** CTE expression, through routine checks to see if the reference is
+** a recursive reference to the CTE.
+**
+** If pFrom matches a CTE according to either of these two above, pFrom->pTab
+** and other fields are populated accordingly.
+**
+** Return 0 if no match is found.
+** Return 1 if a match is found.
+** Return 2 if an error condition is detected.
*/
-static int withExpand(
- Walker *pWalker,
- struct SrcList_item *pFrom
+static int resolveFromTermToCte(
+ Parse *pParse, /* The parsing context */
+ Walker *pWalker, /* Current tree walker */
+ SrcItem *pFrom /* The FROM clause term to check */
){
- Parse *pParse = pWalker->pParse;
- sqlite3 *db = pParse->db;
- struct Cte *pCte; /* Matched CTE (or NULL if no match) */
- With *pWith; /* WITH clause that pCte belongs to */
+ Cte *pCte; /* Matched CTE (or NULL if no match) */
+ With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
+ if( pParse->pWith==0 ){
+ /* There are no WITH clauses in the stack. No match is possible */
+ return 0;
+ }
if( pParse->nErr ){
- return SQLITE_ERROR;
+ /* Prior errors might have left pParse->pWith in a goofy state, so
+ ** go no further. */
+ return 0;
+ }
+ if( pFrom->zDatabase!=0 ){
+ /* The FROM term contains a schema qualifier (ex: main.t1) and so
+ ** it cannot possibly be a CTE reference. */
+ return 0;
+ }
+ if( pFrom->fg.notCte ){
+ /* The FROM term is specifically excluded from matching a CTE.
+ ** (1) It is part of a trigger that used to have zDatabase but had
+ ** zDatabase removed by sqlite3FixTriggerStep().
+ ** (2) This is the first term in the FROM clause of an UPDATE.
+ */
+ return 0;
}
-
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
+ sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
@@ -4823,6 +5174,7 @@ static int withExpand(
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
int iRecTab = -1; /* Cursor for recursive table */
+ CteUse *pCteUse;
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -4830,21 +5182,40 @@ static int withExpand(
** In this case, proceed. */
if( pCte->zCteErr ){
sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
- return SQLITE_ERROR;
+ return 2;
}
- if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
+ if( cannotBeFunction(pParse, pFrom) ) return 2;
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
+ pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return 2;
+ pCteUse = pCte->pUse;
+ if( pCteUse==0 ){
+ pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0]));
+ if( pCteUse==0
+ || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0
+ ){
+ sqlite3DbFree(db, pTab);
+ return 2;
+ }
+ pCteUse->eM10d = pCte->eM10d;
+ }
+ pFrom->pTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ) return 2;
+ pFrom->pSelect->selFlags |= SF_CopyCte;
assert( pFrom->pSelect );
+ pFrom->fg.isCte = 1;
+ pFrom->u2.pCteUse = pCteUse;
+ pCteUse->nUse++;
+ if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
+ pCteUse->eM10d = M10d_Yes;
+ }
/* Check if this is a recursive CTE. */
pRecTerm = pSel = pFrom->pSelect;
@@ -4854,7 +5225,7 @@ static int withExpand(
SrcList *pSrc = pRecTerm->pSrc;
assert( pRecTerm->pPrior!=0 );
for(i=0; inSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
@@ -4866,7 +5237,7 @@ static int withExpand(
sqlite3ErrorMsg(pParse,
"multiple references to recursive table: %s", pCte->zName
);
- return SQLITE_ERROR;
+ return 2;
}
pRecTerm->selFlags |= SF_Recursive;
if( iRecTab<0 ) iRecTab = pParse->nTab++;
@@ -4881,16 +5252,24 @@ static int withExpand(
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
if( pSel->selFlags & SF_Recursive ){
+ int rc;
assert( pRecTerm!=0 );
assert( (pRecTerm->selFlags & SF_Recursive)==0 );
assert( pRecTerm->pNext!=0 );
assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
assert( pRecTerm->pWith==0 );
pRecTerm->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pRecTerm);
+ rc = sqlite3WalkSelect(pWalker, pRecTerm);
pRecTerm->pWith = 0;
+ if( rc ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}else{
- sqlite3WalkSelect(pWalker, pSel);
+ if( sqlite3WalkSelect(pWalker, pSel) ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}
pParse->pWith = pWith;
@@ -4902,7 +5281,7 @@ static int withExpand(
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
pParse->pWith = pSavedWith;
- return SQLITE_ERROR;
+ return 2;
}
pEList = pCte->pCols;
}
@@ -4918,9 +5297,9 @@ static int withExpand(
}
pCte->zCteErr = 0;
pParse->pWith = pSavedWith;
+ return 1; /* Success */
}
-
- return SQLITE_OK;
+ return 0; /* No match */
}
#endif
@@ -4933,7 +5312,7 @@ static int withExpand(
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements.
*/
-static void selectPopWith(Walker *pWalker, Select *p){
+void sqlite3SelectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
@@ -4943,8 +5322,6 @@ static void selectPopWith(Walker *pWalker, Select *p){
}
}
}
-#else
-#define selectPopWith 0
#endif
/*
@@ -4954,7 +5331,7 @@ static void selectPopWith(Walker *pWalker, Select *p){
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
-int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
+int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
Select *pSel = pFrom->pSelect;
Table *pTab;
@@ -4971,7 +5348,13 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral;
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ /* The usual case - do not allow ROWID on a subquery */
+ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
+#else
+ pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
+#endif
+
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
@@ -5002,10 +5385,10 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
*/
static int selectExpander(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- int i, j, k;
+ int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
sqlite3 *db = pParse->db;
Expr *pE, *pRight, *pExpr;
u16 selFlags = p->selFlags;
@@ -5025,6 +5408,15 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
+ if( pParse->pWith && (p->selFlags & SF_View) ){
+ if( p->pWith==0 ){
+ p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
+ if( p->pWith==0 ){
+ return WRC_Abort;
+ }
+ }
+ p->pWith->bView = 1;
+ }
sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
@@ -5041,10 +5433,6 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
if( pFrom->pTab ) continue;
assert( pFrom->fg.isRecursive==0 );
-#ifndef SQLITE_OMIT_CTE
- if( withExpand(pWalker, pFrom) ) return WRC_Abort;
- if( pFrom->pTab ) {} else
-#endif
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
Select *pSel = pFrom->pSelect;
@@ -5053,6 +5441,12 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->pTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
+#endif
+#ifndef SQLITE_OMIT_CTE
+ }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
+ if( rc>1 ) return WRC_Abort;
+ pTab = pFrom->pTab;
+ assert( pTab!=0 );
#endif
}else{
/* An ordinary table or view name in the FROM clause */
@@ -5075,11 +5469,15 @@ static int selectExpander(Walker *pWalker, Select *p){
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
- if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
+ if( pTab->pSelect
+ && (db->flags & SQLITE_EnableView)==0
+ && pTab->pSchema!=db->aDb[1].pSchema
+ ){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
+ assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
if( IsVirtual(pTab)
&& pFrom->fg.fromDDL
&& ALWAYS(pTab->pVTable!=0)
@@ -5101,7 +5499,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
/* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlite3IndexedByLookup(pParse, pFrom) ){
+ if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){
return WRC_Abort;
}
}
@@ -5320,7 +5718,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- w.xSelectCallback2 = selectPopWith;
+ w.xSelectCallback2 = sqlite3SelectPopWith;
w.eCode = 0;
sqlite3WalkSelect(&w, pSelect);
}
@@ -5344,7 +5742,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
assert( p->selFlags & SF_Resolved );
if( p->selFlags & SF_HasTypeInfo ) return;
@@ -5453,8 +5851,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO);
+ pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
+ ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
+ pFunc->pFunc->zName));
}
}
}
@@ -5486,7 +5886,12 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
-static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
+static void updateAccumulator(
+ Parse *pParse,
+ int regAcc,
+ AggInfo *pAggInfo,
+ int eDistinctType
+){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
@@ -5532,13 +5937,12 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
nArg = 0;
regAgg = 0;
}
- if( pF->iDistinct>=0 ){
+ if( pF->iDistinct>=0 && pList ){
if( addrNext==0 ){
addrNext = sqlite3VdbeMakeLabel(pParse);
}
- testcase( nArg==0 ); /* Error condition */
- testcase( nArg>1 ); /* Also an error */
- codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
+ pF->iDistinct = codeDistinct(pParse, eDistinctType,
+ pF->iDistinct, addrNext, pList, regAgg);
}
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl = 0;
@@ -5590,7 +5994,7 @@ static void explainSimpleCount(
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
- sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
+ sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
@@ -5656,7 +6060,7 @@ static void havingToWhere(Parse *pParse, Select *p){
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
#if SELECTTRACE_ENABLED
- if( sWalker.eCode && (sqlite3_unsupported_selecttrace & 0x100)!=0 ){
+ if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5668,11 +6072,13 @@ static void havingToWhere(Parse *pParse, Select *p){
** If it is, then return the SrcList_item for the prior view. If it is not,
** then return 0.
*/
-static struct SrcList_item *isSelfJoinView(
+static SrcItem *isSelfJoinView(
SrcList *pTabList, /* Search for self-joins in this FROM clause */
- struct SrcList_item *pThis /* Search for prior reference to this subquery */
+ SrcItem *pThis /* Search for prior reference to this subquery */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
+ assert( pThis->pSelect!=0 );
+ if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
for(pItem = pTabList->a; pItempSelect==0 ) continue;
@@ -5688,9 +6094,7 @@ static struct SrcList_item *isSelfJoinView(
** names in the same FROM clause. */
continue;
}
- if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1)
- || sqlite3ExprCompare(0, pThis->pSelect->pHaving, pS1->pHaving, -1)
- ){
+ if( pItem->pSelect->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -5700,6 +6104,15 @@ static struct SrcList_item *isSelfJoinView(
return 0;
}
+/*
+** Deallocate a single AggInfo object
+*/
+static void agginfoFree(sqlite3 *db, AggInfo *p){
+ sqlite3DbFree(db, p->aCol);
+ sqlite3DbFree(db, p->aFunc);
+ sqlite3DbFreeNN(db, p);
+}
+
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
/*
** Attempt to transform a query of the form
@@ -5778,7 +6191,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
p->selFlags &= ~SF_Aggregate;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5831,7 +6244,7 @@ int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -5845,8 +6258,19 @@ int sqlite3Select(
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
/* All of these destinations are also able to ignore the ORDER BY clause */
- sqlite3ExprListDelete(db, p->pOrderBy);
- p->pOrderBy = 0;
+ if( p->pOrderBy ){
+#if SELECTTRACE_ENABLED
+ SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n"));
+ if( sqlite3SelectTrace & 0x100 ){
+ sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
+ }
+#endif
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
+ p->pOrderBy);
+ testcase( pParse->earlyCleanup );
+ p->pOrderBy = 0;
+ }
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
@@ -5856,7 +6280,7 @@ int sqlite3Select(
}
assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x104 ){
+ if( sqlite3SelectTrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5867,9 +6291,9 @@ int sqlite3Select(
** In this case, it is an error if the target object (pSrc->a[0]) name
** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
if( p->selFlags & SF_UpdateFrom ){
- struct SrcList_item *p0 = &p->pSrc->a[0];
+ SrcItem *p0 = &p->pSrc->a[0];
for(i=1; ipSrc->nSrc; i++){
- struct SrcList_item *p1 = &p->pSrc->a[i];
+ SrcItem *p1 = &p->pSrc->a[i];
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
@@ -5881,17 +6305,16 @@ int sqlite3Select(
}
if( pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, p);
+ sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- rc = sqlite3WindowRewrite(pParse, p);
- if( rc ){
+ if( sqlite3WindowRewrite(pParse, p) ){
assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED
- if( p->pWin && (sqlite3_unsupported_selecttrace & 0x108)!=0 ){
+ if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5907,7 +6330,7 @@ int sqlite3Select(
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && inSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
@@ -5998,7 +6421,7 @@ int sqlite3Select(
rc = multiSelect(pParse, p, pDest);
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
- if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -6012,12 +6435,13 @@ int sqlite3Select(
** as the equivalent optimization will be handled by query planner in
** sqlite3WhereBegin().
*/
- if( pTabList->nSrc>1
+ if( p->pWhere!=0
+ && p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6041,7 +6465,8 @@ int sqlite3Select(
** (2) Generate code for all sub-queries
*/
for(i=0; inSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
+ SrcItem *pPrior;
SelectDest dest;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -6074,19 +6499,8 @@ int sqlite3Select(
pSub = pItem->pSelect;
if( pSub==0 ) continue;
- /* The code for a subquery should only be generated once, though it is
- ** technically harmless for it to be generated multiple times. The
- ** following assert() will detect if something changes to cause
- ** the same subquery to be coded multiple times, as a signal to the
- ** developers to try to optimize the situation.
- **
- ** Update 2019-07-24:
- ** See ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311cec40.
- ** The dbsqlfuzz fuzzer found a case where the same subquery gets
- ** coded twice. So this assert() now becomes a testcase(). It should
- ** be very rare, though.
- */
- testcase( pItem->addrFillSub!=0 );
+ /* The code for a subquery should only be generated once. */
+ assert( pItem->addrFillSub==0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -6101,16 +6515,18 @@ int sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
(pItem->fg.jointype & JT_OUTER)!=0)
){
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x100 ){
+ if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
@@ -6120,16 +6536,18 @@ int sqlite3Select(
/* Generate code to implement the subquery
**
- ** The subquery is implemented as a co-routine if the subquery is
- ** guaranteed to be the outer loop (so that it does not need to be
- ** computed more than once)
+ ** The subquery is implemented as a co-routine if:
+ ** (1) the subquery is guaranteed to be the outer loop (so that
+ ** it does not need to be computed more than once), and
+ ** (2) the subquery is not a CTE that should be materialized
**
- ** TODO: Are there other reasons beside (1) to use a co-routine
+ ** TODO: Are there other reasons beside (1) and (2) to use a co-routine
** implementation?
*/
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -6138,10 +6556,10 @@ int sqlite3Select(
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->zName));
+ VdbeComment((v, "%!S", pItem));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
- ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
+ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
@@ -6149,18 +6567,33 @@ int sqlite3Select(
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
+ }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
+ /* This is a CTE for which materialization code has already been
+ ** generated. Invoke the subroutine to compute the materialization,
+ ** the make the pItem->iCursor be a copy of the ephemerial table that
+ ** holds the result of the materialization. */
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
+ if( pItem->iCursor!=pCteUse->iCur ){
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur);
+ }
+ pSub->nSelectRow = pCteUse->nRowEst;
+ }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){
+ /* This view has already been materialized by a prior entry in
+ ** this same FROM clause. Reuse it. */
+ if( pPrior->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ }
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
+ pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
- /* Generate a subroutine that will fill an ephemeral table with
- ** the content of this subquery. pItem->addrFillSub will point
- ** to the address of the generated subroutine. pItem->regReturn
- ** is a register allocated to hold the subroutine return address
- */
+ /* Materialize the view. If the view is not correlated, generate a
+ ** subroutine to do the materialization so that subsequent uses of
+ ** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
int retAddr;
- struct SrcList_item *pPrior;
- testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
@@ -6169,26 +6602,26 @@ int sqlite3Select(
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
+ VdbeComment((v, "materialize %!S", pItem));
}else{
- VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
- }
- pPrior = isSelfJoinView(pTabList, pItem);
- if( pPrior ){
- sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- assert( pPrior->pSelect!=0 );
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
- }else{
- sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
- sqlite3Select(pParse, pSub, &dest);
+ VdbeNoopComment((v, "materialize %!S", pItem));
}
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
+ sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->zName));
+ VdbeComment((v, "end %!S", pItem));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
+ if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ pCteUse->addrM9e = pItem->addrFillSub;
+ pCteUse->regRtn = pItem->regReturn;
+ pCteUse->iCur = pItem->iCursor;
+ pCteUse->nRowEst = pSub->nSelectRow;
+ }
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
@@ -6205,7 +6638,7 @@ int sqlite3Select(
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6241,7 +6674,7 @@ int sqlite3Select(
assert( sDistinct.isTnct );
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6333,6 +6766,7 @@ int sqlite3Select(
sSort.pOrderBy = 0;
}
}
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -6371,6 +6805,7 @@ int sqlite3Select(
/* End the database scan loop.
*/
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
}
}else{
@@ -6441,11 +6876,14 @@ int sqlite3Select(
** SELECT statement.
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
- if( pAggInfo==0 ){
+ if( pAggInfo ){
+ sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlite3*,void*))agginfoFree, pAggInfo);
+ testcase( pParse->earlyCleanup );
+ }
+ if( db->mallocFailed ){
goto select_end;
}
- pAggInfo->pNext = pParse->pAggList;
- pParse->pAggList = pAggInfo;
pAggInfo->selId = p->selId;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
@@ -6489,10 +6927,14 @@ int sqlite3Select(
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
- if( sqlite3_unsupported_selecttrace & 0x400 ){
+ if( sqlite3SelectTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
+ if( minMaxFlag ){
+ sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
+ sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
+ }
for(ii=0; iinColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, pAggInfo->aCol[ii].iMem);
@@ -6520,6 +6962,20 @@ int sqlite3Select(
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
int regReset; /* Return address register for reset subroutine */
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist = WHERE_DISTINCT_NOOP;
+
+ if( pAggInfo->nFunc==1
+ && pAggInfo->aFunc[0].iDistinct>=0
+ && pAggInfo->aFunc[0].pFExpr->x.pList
+ ){
+ Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
+ pExpr = sqlite3ExprDup(db, pExpr, 0);
+ pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
+ pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
+ }
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
@@ -6556,10 +7012,15 @@ int sqlite3Select(
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
- WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
+ WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
);
- if( pWInfo==0 ) goto select_end;
+ if( pWInfo==0 ){
+ sqlite3ExprListDelete(db, pDistinct);
+ goto select_end;
+ }
+ eDist = sqlite3WhereIsDistinct(pWInfo);
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
@@ -6608,6 +7069,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nCol);
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlite3GetTempReg(pParse);
@@ -6675,19 +7137,21 @@ int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, iUseFlag, pAggInfo);
+ updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
/* End of the loop
*/
if( groupBySort ){
- sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
+ sqlite3ExprListDelete(db, pDistinct);
/* Output the final row of result
*/
@@ -6730,7 +7194,11 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
+ if( eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = &pAggInfo->aFunc[0];
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
@@ -6794,7 +7262,9 @@ int sqlite3Select(
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
- int addrSkip;
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -6818,6 +7288,9 @@ int sqlite3Select(
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
+ }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
+ pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
/* This case runs if the aggregate has no GROUP BY clause. The
@@ -6837,16 +7310,23 @@ int sqlite3Select(
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
- 0, minMaxFlag, 0);
+ pDistinct, minMaxFlag|distFlag, 0);
if( pWInfo==0 ){
goto select_end;
}
- updateAccumulator(pParse, regAcc, pAggInfo);
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
+ eDist = sqlite3WhereIsDistinct(pWInfo);
+ updateAccumulator(pParse, regAcc, pAggInfo, eDist);
+ if( eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = &pAggInfo->aFunc[0];
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
+
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
- addrSkip = sqlite3WhereOrderByLimitOptLabel(pWInfo);
- if( addrSkip!=sqlite3WhereContinueLabel(pWInfo) ){
- sqlite3VdbeGoto(v, addrSkip);
+ if( minMaxFlag ){
+ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo);
}
@@ -6886,20 +7366,20 @@ int sqlite3Select(
** successful coding of the SELECT.
*/
select_end:
+ assert( db->mallocFailed==0 || db->mallocFailed==1 );
+ pParse->nErr += db->mallocFailed;
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
for(i=0; inColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; inFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
@@ -6908,7 +7388,7 @@ int sqlite3Select(
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
- if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
diff --git a/src/shell.c.in b/src/shell.c.in
index 2d98d23c2..0f8de61a1 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -226,6 +226,7 @@ static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
+ if( clockVfs==0 ) return 0; /* Never actually happens */
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
@@ -1027,6 +1028,7 @@ INCLUDE ../ext/misc/uint.c
INCLUDE ../ext/misc/decimal.c
INCLUDE ../ext/misc/ieee754.c
INCLUDE ../ext/misc/series.c
+INCLUDE ../ext/misc/regexp.c
#ifdef SQLITE_HAVE_ZLIB
INCLUDE ../ext/misc/zipfile.c
INCLUDE ../ext/misc/sqlar.c
@@ -1085,12 +1087,12 @@ struct ShellState {
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
u8 autoEQPtest; /* autoEQP is in test mode */
u8 autoEQPtrace; /* autoEQP is in trace mode */
- u8 statsOn; /* True to display memory stats before each finalize */
u8 scanstatsOn; /* True to display scan stats before each finalize */
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
+ unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
@@ -2027,6 +2029,7 @@ static int shell_callback(
if( azArg==0 ) break;
for(i=0; iw ){
w = strlenChar(azArg[i]);
}
@@ -2591,7 +2594,7 @@ static int display_stats(
if( pArg==0 || pArg->out==0 ) return 0;
out = pArg->out;
- if( pArg->pStmt && (pArg->statsOn & 2) ){
+ if( pArg->pStmt && pArg->statsOn==2 ){
int nCol, i, x;
sqlite3_stmt *pStmt = pArg->pStmt;
char z[100];
@@ -2615,6 +2618,14 @@ static int display_stats(
}
}
+ if( pArg->statsOn==3 ){
+ if( pArg->pStmt ){
+ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
+ raw_printf(pArg->out, "VM-steps: %d\n", iCur);
+ }
+ return 0;
+ }
+
displayStatLine(pArg, "Memory Used:",
"%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
displayStatLine(pArg, "Number of Outstanding Allocations:",
@@ -2881,31 +2892,18 @@ static void explain_data_delete(ShellState *p){
/*
** Disable and restore .wheretrace and .selecttrace settings.
*/
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
-extern unsigned int sqlite3_unsupported_selecttrace;
-static int savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
-extern int sqlite3WhereTrace;
-static int savedWhereTrace;
-#endif
+static unsigned int savedSelectTrace;
+static unsigned int savedWhereTrace;
static void disable_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- savedSelectTrace = sqlite3_unsupported_selecttrace;
- sqlite3_unsupported_selecttrace = 0;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- savedWhereTrace = sqlite3WhereTrace;
- sqlite3WhereTrace = 0;
-#endif
+ unsigned int zero = 0;
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
}
static void restore_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- sqlite3_unsupported_selecttrace = savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- sqlite3WhereTrace = savedWhereTrace;
-#endif
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
}
/* Create the TEMP table used to store parameter bindings */
@@ -2919,7 +2917,7 @@ static void bind_table_init(ShellState *p){
sqlite3_exec(p->db,
"CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
" key TEXT PRIMARY KEY,\n"
- " value ANY\n"
+ " value\n"
") WITHOUT ROWID;",
0, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
@@ -3067,6 +3065,7 @@ static void exec_prepared_stmt_columnar(
if( rc!=SQLITE_ROW ) return;
nColumn = sqlite3_column_count(pStmt);
nAlloc = nColumn*4;
+ if( nAlloc<=0 ) nAlloc = 1;
azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
if( azData==0 ) shell_out_of_memory();
for(i=0; ip->actualWidth[j] ) p->actualWidth[j] = n;
}
if( seenInterrupt ) goto columnar_end;
+ if( nColumn==0 ) goto columnar_end;
switch( p->cMode ){
case MODE_Column: {
colSep = " ";
@@ -3878,7 +3878,7 @@ static const char *(azHelp[]) = {
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
- " http://sqlite.org/cli.html#sqlar_archive_support",
+ " http://sqlite.org/cli.html#sqlite_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
".auth ON|OFF Show authorizer callbacks",
@@ -3895,13 +3895,13 @@ static const char *(azHelp[]) = {
".databases List names and files of attached databases",
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
".dbinfo ?DB? Show status information about the database",
- ".dump ?TABLE? Render database content as SQL",
+ ".dump ?OBJECTS? Render database content as SQL",
" Options:",
" --data-only Output only INSERT statements",
" --newlines Allow unescaped newline characters in output",
" --nosys Omit system tables (ex: \"sqlite_stat1\")",
" --preserve-rowids Include ROWID values in the output",
- " TABLE is a LIKE pattern for the tables to dump",
+ " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
" Additional LIKE patterns can be given in subsequent arguments",
".echo on|off Turn command echo on or off",
".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
@@ -3980,8 +3980,8 @@ static const char *(azHelp[]) = {
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
" Options:",
" --append Use appendvfs to append database to the end of FILE",
-#ifdef SQLITE_ENABLE_DESERIALIZE
- " --deserialize Load into memory useing sqlite3_deserialize()",
+#ifndef SQLITE_OMIT_DESERIALIZE
+ " --deserialize Load into memory using sqlite3_deserialize()",
" --hexdb Load the output of \"dbtotxt\" as an in-memory db",
" --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
@@ -4060,7 +4060,11 @@ static const char *(azHelp[]) = {
".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
".show Show the current values for various settings",
- ".stats ?on|off? Show stats or turn stats on or off",
+ ".stats ?ARG? Show stats or turn stats on or off",
+ " off Turn off automatic stat display",
+ " on Turn on automatic stat display",
+ " stmt Show statement stats",
+ " vmstep Show the virtual machine step count only",
#ifndef SQLITE_NOHAVE_SYSTEM
".system CMD ARGS... Run CMD ARGS... in a system shell",
#endif
@@ -4298,7 +4302,7 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->zDbFilename. If p->zDbFilename
@@ -4387,7 +4391,7 @@ readHexDb_error:
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
/*
** Scalar function "shell_int32". The first argument to this function
@@ -4613,6 +4617,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_completion_init(p->db, 0, 0);
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
+ sqlite3_regexp_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
@@ -4648,7 +4653,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
@@ -5777,7 +5782,7 @@ static int lintFkeyIndexes(
" || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
", "
- " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
+ " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
" || group_concat('*=?', ' AND ') || ')'"
", "
" s.name || '(' || group_concat(f.[from], ', ') || ')'"
@@ -5797,7 +5802,7 @@ static int lintFkeyIndexes(
"GROUP BY s.name, f.id "
"ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
;
- const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
+ const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
for(i=2; inErr = 0;
if( zLike==0 ) zLike = sqlite3_mprintf("true");
zSql = sqlite3_mprintf(
- "SELECT name, type, sql FROM sqlite_schema "
+ "SELECT name, type, sql FROM sqlite_schema AS o "
"WHERE (%s) AND type=='table'"
" AND sql NOT NULL"
" ORDER BY tbl_name='sqlite_sequence', rowid",
@@ -7772,7 +7793,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zSql);
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_schema "
+ "SELECT sql FROM sqlite_schema AS o "
"WHERE (%s) AND sql NOT NULL"
" AND type IN ('index','trigger','view')",
zLike
@@ -7876,16 +7897,17 @@ static int do_meta_command(char *zLine, ShellState *p){
int ctrlCode; /* Integer code for that option */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
- { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
{ "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
- /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
- { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
- { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
- /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
- { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
+ { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
{ "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
{ "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
+ { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
+ /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
+ { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
{ "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
+ { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
+ { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
+ /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
};
int filectrl = -1;
int iCtrl = -1;
@@ -7972,6 +7994,7 @@ static int do_meta_command(char *zLine, ShellState *p){
isOk = 1;
break;
}
+ case SQLITE_FCNTL_DATA_VERSION:
case SQLITE_FCNTL_HAS_MOVED: {
int x;
if( nArg!=2 ) break;
@@ -8017,7 +8040,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
- char *zErrMsg = 0;
int doStats = 0;
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
@@ -8039,7 +8061,7 @@ static int do_meta_command(char *zLine, ShellState *p){
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
- callback, &data, &zErrMsg
+ callback, &data, 0
);
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt;
@@ -8055,12 +8077,12 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
- callback, &data, &zErrMsg);
+ callback, &data, 0);
data.cMode = data.mode = MODE_Insert;
data.zDestTable = "sqlite_stat1";
- shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
data.zDestTable = "sqlite_stat4";
- shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
+ shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}
}else
@@ -8680,9 +8702,9 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif /* SQLITE_DEBUG */
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
- char *zNewFilename; /* Name of the database file to open */
- int iName = 1; /* Index in azArg[] of the filename */
- int newFlag = 0; /* True to delete file before opening */
+ char *zNewFilename = 0; /* Name of the database file to open */
+ int iName = 1; /* Index in azArg[] of the filename */
+ int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */
session_close_all(p);
close_db(p->db);
@@ -8694,7 +8716,7 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openFlags = 0;
p->szMax = 0;
/* Check for command-line arguments */
- for(iName=1; iNameopenMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1szMax = integerValue(azArg[++iName]);
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
goto meta_command_exit;
+ }else if( zNewFilename ){
+ utf8_printf(stderr, "extra argument: \"%s\"\n", z);
+ rc = 1;
+ goto meta_command_exit;
+ }else{
+ zNewFilename = sqlite3_mprintf("%s", z);
}
}
/* If a filename is specified, try to open it first */
- zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
@@ -8746,7 +8773,7 @@ static int do_meta_command(char *zLine, ShellState *p){
&& (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
|| (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
){
- const char *zFile = 0;
+ char *zFile = 0;
int bTxtMode = 0;
int i;
int eMode = 0;
@@ -8776,17 +8803,22 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
- }else if( zFile==0 ){
- zFile = z;
+ }else if( zFile==0 && eMode!='e' && eMode!='x' ){
+ zFile = sqlite3_mprintf("%s", z);
+ if( zFile[0]=='|' ){
+ while( i+1out,"ERROR: extra parameter: \"%s\". Usage:\n",
azArg[i]);
showHelp(p->out, azArg[0]);
rc = 1;
+ sqlite3_free(zFile);
goto meta_command_exit;
}
}
- if( zFile==0 ) zFile = "stdout";
+ if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
if( bOnce ){
p->outCount = 2;
}else{
@@ -8809,7 +8841,8 @@ static int do_meta_command(char *zLine, ShellState *p){
newTempFile(p, "txt");
bTxtMode = 1;
}
- zFile = p->zTempFile;
+ sqlite3_free(zFile);
+ zFile = sqlite3_mprintf("%s", p->zTempFile);
}
#endif /* SQLITE_NOHAVE_SYSTEM */
if( zFile[0]=='|' ){
@@ -8841,6 +8874,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
+ sqlite3_free(zFile);
}else
if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
@@ -9024,6 +9058,11 @@ static int do_meta_command(char *zLine, ShellState *p){
goto meta_command_exit;
}
if( azArg[1][0]=='|' ){
+#ifdef SQLITE_OMIT_POPEN
+ raw_printf(stderr, "Error: pipes are not supported in this OS\n");
+ rc = 1;
+ p->out = stdout;
+#else
p->in = popen(azArg[1]+1, "r");
if( p->in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
@@ -9032,6 +9071,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = process_input(p);
pclose(p->in);
}
+#endif
}else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
@@ -9246,11 +9286,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
- sqlite3_unsupported_selecttrace = nArg>=2 ? (int)integerValue(azArg[1]) : 0xffff;
+ unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
}else
-#endif
#if defined(SQLITE_ENABLE_SESSION)
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
@@ -9731,6 +9770,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
static const char *azBool[] = { "off", "on", "trigger", "full"};
+ const char *zOut;
int i;
if( nArg!=1 ){
raw_printf(stderr, "Usage: .show\n");
@@ -9755,7 +9795,13 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(p->out,"%12.12s: ", "rowseparator");
output_c_string(p->out, p->rowSeparator);
raw_printf(p->out, "\n");
- utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
+ switch( p->statsOn ){
+ case 0: zOut = "off"; break;
+ default: zOut = "on"; break;
+ case 2: zOut = "stmt"; break;
+ case 3: zOut = "vmstep"; break;
+ }
+ utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
utf8_printf(p->out, "%12.12s: ", "width");
for (i=0;inWidth;i++) {
raw_printf(p->out, "%d ", p->colWidth[i]);
@@ -9767,11 +9813,17 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
if( nArg==2 ){
- p->statsOn = (u8)booleanValue(azArg[1]);
+ if( strcmp(azArg[1],"stmt")==0 ){
+ p->statsOn = 2;
+ }else if( strcmp(azArg[1],"vmstep")==0 ){
+ p->statsOn = 3;
+ }else{
+ p->statsOn = (u8)booleanValue(azArg[1]);
+ }
}else if( nArg==1 ){
display_stats(p->db, p, 0);
}else{
- raw_printf(stderr, "Usage: .stats ?on|off?\n");
+ raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
rc = 1;
}
}else
@@ -9923,6 +9975,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
+ { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
};
int testctrl = -1;
int iCtrl = -1;
@@ -9976,7 +10029,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){
- int opt = (int)strtol(azArg[2], 0, 0);
+ unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
isOk = 3;
}
@@ -10067,11 +10120,40 @@ static int do_meta_command(char *zLine, ShellState *p){
}
#ifdef YYCOVERAGE
- case SQLITE_TESTCTRL_PARSER_COVERAGE:
+ case SQLITE_TESTCTRL_PARSER_COVERAGE: {
if( nArg==2 ){
sqlite3_test_control(testctrl, p->out);
isOk = 3;
}
+ break;
+ }
+#endif
+#ifdef SQLITE_DEBUG
+ case SQLITE_TESTCTRL_TUNE: {
+ if( nArg==4 ){
+ int id = (int)integerValue(azArg[2]);
+ int val = (int)integerValue(azArg[3]);
+ sqlite3_test_control(testctrl, id, &val);
+ isOk = 3;
+ }else if( nArg==3 ){
+ int id = (int)integerValue(azArg[2]);
+ sqlite3_test_control(testctrl, -id, &rc2);
+ isOk = 1;
+ }else if( nArg==2 ){
+ int id = 1;
+ while(1){
+ int val = 0;
+ rc2 = sqlite3_test_control(testctrl, -id, &val);
+ if( rc2!=SQLITE_OK ) break;
+ if( id>1 ) utf8_printf(p->out, " ");
+ utf8_printf(p->out, "%d: %d", id, val);
+ id++;
+ }
+ if( id>1 ) utf8_printf(p->out, "\n");
+ isOk = 3;
+ }
+ break;
+ }
#endif
}
}
@@ -10305,11 +10387,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
- sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
+ unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
+ sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
}else
-#endif
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
int j;
@@ -10670,7 +10751,7 @@ static const char zOptions[] =
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -deserialize open the database using sqlite3_deserialize()\n"
#endif
" -echo print commands before execution\n"
@@ -10687,7 +10768,7 @@ static const char zOptions[] =
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
" -markdown set output mode to 'markdown'\n"
-#if defined(SQLITE_ENABLE_DESERIALIZE)
+#if !defined(SQLITE_OMIT_DESERIALIZE)
" -maxsize N maximum size for a --deserialize database\n"
#endif
" -memtrace trace all memory allocations and deallocations\n"
@@ -10798,7 +10879,8 @@ static char *cmdline_option_value(int argc, char **argv, int i){
}
#ifndef SQLITE_SHELL_IS_UTF8
-# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
+# if (defined(_WIN32) || defined(WIN32)) \
+ && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
# define SQLITE_SHELL_IS_UTF8 (0)
# else
# define SQLITE_SHELL_IS_UTF8 (1)
@@ -11016,7 +11098,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1
+**
+** [[SQLITE_FCNTL_EXTERNAL_READER]]
+** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
+** whether or not there is a database client in another process with a wal-mode
+** transaction open on the database or not. It is only available on unix.The
+** (void*) argument passed with this file-control should be a pointer to a
+** value of type (int). The integer value is set to 1 if the database is a wal
+** mode database and there exists at least one client in another process that
+** currently has an SQL transaction open on the database. It is set to 0 if
+** the database is not a wal-mode db, or if there is no such connection in any
+** other process. This opcode cannot be used to detect transactions opened
+** by clients within the current process, only within other processes.
+**
+**
+** [[SQLITE_FCNTL_CKSM_FILE]]
+** Used by the cksmvfs VFS module only.
+**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@@ -1167,6 +1184,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
+#define SQLITE_FCNTL_EXTERNAL_READER 40
+#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2115,7 +2134,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back.
+** which case the trigger setting is not reported back.
+**
+** Originally this option disabled all triggers. ^(However, since
+** SQLite version 3.35.0, TEMP triggers are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** triggers in the main database schema or in the schemas of ATTACH-ed
+** databases.)^
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
**
SQLITE_DBCONFIG_ENABLE_VIEW
@@ -2126,7 +2151,13 @@ struct sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the view setting is not reported back.
+** which case the view setting is not reported back.
+**
+** Originally this option disabled all views. ^(However, since
+** SQLite version 3.35.0, TEMP views are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** views in the main database schema or in the schemas of ATTACH-ed
+** databases.)^
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
**
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
@@ -3499,6 +3530,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** that uses dot-files in place of posix advisory locking.
** | file:data.db?mode=readonly |
** An error. "readonly" is not a valid option for the "mode" parameter.
+** Use "ro" instead: "file:data.db?mode=ro".
** |
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -4166,6 +4198,15 @@ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
+**
+** ^This routine returns false if there is any possibility that the
+** statement might change the database file. ^A false return does
+** not guarantee that the statement will change the database file.
+** ^For example, an UPDATE statement might have a WHERE clause that
+** makes it a no-op, but the sqlite3_stmt_readonly() result would still
+** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
+** read-only no-op if the table already exists, but
+** sqlite3_stmt_readonly() still returns false for such a statement.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -4335,18 +4376,22 @@ typedef struct sqlite3_context sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to the bind API fails,
-** except the destructor is not called if the third parameter is a NULL
-** pointer or the fourth parameter is negative.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlite3_bind_*() routine returns.
+** ^The fifth argument to the BLOB and string binding interfaces controls
+** or indicates the lifetime of the object referenced by the third parameter.
+** These three options exist:
+** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
+** with it may be passed. ^It is called to dispose of the BLOB or string even
+** if the call to the bind API fails, except the destructor is not called if
+** the third parameter is a NULL pointer or the fourth parameter is negative.
+** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
+** the application remains responsible for disposing of the object. ^In this
+** case, the object and the provided pointer to it must remain valid until
+** either the prepared statement is finalized or the same SQL parameter is
+** bound to something else, whichever occurs sooner.
+** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
+** object is to be copied prior to the return from sqlite3_bind_*(). ^The
+** object and pointer to it must remain valid until then. ^SQLite will then
+** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -5088,7 +5133,6 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
** index expressions, or the WHERE clause of partial indexes.
**
-**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of
@@ -5098,7 +5142,6 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** a database file to include invocations of the function with parameters
** chosen by the attacker, which the application will then execute when
** the database file is opened and read.
-**
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -7765,7 +7808,9 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
-#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_TUNE 32
+#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9517,6 +9562,15 @@ int sqlite3_db_cacheflush(sqlite3*);
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
+** When the [sqlite3_blob_write()] API is used to update a blob column,
+** the pre-update hook is invoked with SQLITE_DELETE. This is because the
+** in this case the new values are not available. In this case, when a
+** callback made with op==SQLITE_DELETE is actuall a write using the
+** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
+** the index of the column being written. In other cases, where the
+** pre-update hook is being invoked for some other reason, including a
+** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
+**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@@ -9537,6 +9591,7 @@ int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
int sqlite3_preupdate_count(sqlite3 *);
int sqlite3_preupdate_depth(sqlite3 *);
int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif
/*
@@ -9775,8 +9830,8 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */
@@ -9827,8 +9882,8 @@ unsigned char *sqlite3_serialize(
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 467062277..91af412bb 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -119,6 +119,18 @@
# define MSVC_VERSION 0
#endif
+/*
+** Some C99 functions in "math.h" are only present for MSVC when its version
+** is associated with Visual Studio 2013 or higher.
+*/
+#ifndef SQLITE_HAVE_C99_MATH_FUNCS
+# if MSVC_VERSION==0 || MSVC_VERSION>=1800
+# define SQLITE_HAVE_C99_MATH_FUNCS (1)
+# else
+# define SQLITE_HAVE_C99_MATH_FUNCS (0)
+# endif
+#endif
+
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
@@ -202,7 +214,8 @@
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
-#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
+#if GCC_VERSION>=4007000 || \
+ (__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
@@ -984,15 +997,14 @@ typedef INT16_TYPE LogEst;
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
-#else
-# define SELECTTRACE_ENABLED 0
+#if !defined(SQLITE_AMALGAMATION)
+extern u32 sqlite3SelectTrace;
#endif
-#if defined(SQLITE_ENABLE_SELECTTRACE)
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE))
# define SELECTTRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
- if(sqlite3_unsupported_selecttrace&(K)) \
+ if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
@@ -1000,6 +1012,19 @@ typedef INT16_TYPE LogEst;
# define SELECTTRACE_ENABLED 0
#endif
+/*
+** Macros for "wheretrace"
+*/
+extern u32 sqlite3WhereTrace;
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
+#else
+# define WHERETRACE(K,X)
+#endif
+
+
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@@ -1111,7 +1136,10 @@ typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
+typedef struct Cte Cte;
+typedef struct CteUse CteUse;
typedef struct Db Db;
+typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
@@ -1129,14 +1157,17 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
+typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
+typedef struct Returning Returning;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
typedef struct Table Table;
@@ -1450,6 +1481,11 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
#endif /* SQLITE_OMIT_DEPRECATED */
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
+/*
+** Maximum number of sqlite3.aDb[] entries. This is the number of attached
+** databases plus 2 for "main" and "temp".
+*/
+#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)
/*
** Each database connection is an instance of the following structure.
@@ -1470,7 +1506,7 @@ struct sqlite3 {
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */
- u16 dbOptFlags; /* Flags to enable/disable optimizations */
+ u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
@@ -1677,24 +1713,26 @@ struct sqlite3 {
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
-#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
-#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */
-#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
-#define SQLITE_Transitive 0x0080 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
-#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
-#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
- /* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
-#define SQLITE_PushDown 0x1000 /* The push-down optimization */
-#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
-#define SQLITE_SkipScan 0x4000 /* Skip-scans */
-#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
-#define SQLITE_AllOpts 0xffff /* All optimizations */
+#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
+#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
+#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
+#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
+#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
+#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
+#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
+#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
+#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
+#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
+#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
+#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
@@ -1850,6 +1888,9 @@ struct FuncDestructor {
** a single query. The iArg is ignored. The user-data is always set
** to a NULL pointer. The bNC parameter is not used.
**
+** MFUNCTION(zName, nArg, xPtr, xFunc)
+** For math-library functions. xPtr is an arbitrary pointer.
+**
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
** Used for "pure" date/time functions, this macro is like DFUNCTION
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
@@ -1885,6 +1926,9 @@ struct FuncDestructor {
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define MFUNCTION(zName, nArg, xPtr, xFunc) \
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
+ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
@@ -1979,7 +2023,12 @@ struct Column {
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
-/* Allowed values for Column.colFlags:
+/* Allowed values for Column.colFlags.
+**
+** Constraints:
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
@@ -2055,9 +2104,7 @@ struct CollSeq {
** operator is NULL. It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
-#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
-#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
@@ -2155,7 +2202,6 @@ struct Table {
#endif
Trigger *pTrigger; /* List of triggers stored in pSchema */
Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -2169,11 +2215,12 @@ struct Table {
**
** Constraints:
**
-** TF_HasVirtual == COLFLAG_Virtual
-** TF_HasStored == COLFLAG_Stored
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
+#define TF_HasHidden 0x0002 /* Has one or more hidden columns */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
@@ -2188,6 +2235,8 @@ struct Table {
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
+#define TF_Ephemeral 0x4000 /* An ephemeral table */
+#define TF_Eponymous 0x8000 /* An eponymous virtual table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2284,16 +2333,22 @@ struct FKey {
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
+** UPDATE applies to insert operations only and means that the insert
+** is omitted and the DO UPDATE clause of an upsert is run instead.
**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
+** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
+** key is set to NULL. SETDFLT means that the foreign key is set
+** to its default value. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
+** The OE_Default value is a place holder that means to use whatever
+** conflict resolution algorthm is required from context.
+**
** The following symbolic values are used to record which type
-** of action to take.
+** of conflict resolution action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
@@ -2547,10 +2602,10 @@ struct AggInfo {
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
+ int iDistAddr; /* Address of OP_OpenEphemeral */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
- AggInfo *pNext; /* Next in list of them all */
};
/*
@@ -2679,7 +2734,7 @@ struct Expr {
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
- i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
+ int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
@@ -2721,7 +2776,7 @@ struct Expr {
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
+ /* 0x400000 // Available */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
@@ -2820,6 +2875,7 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
+ int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
@@ -2869,6 +2925,46 @@ struct IdList {
int nId; /* Number of identifiers on the list */
};
+/*
+** The SrcItem object represents a single term in the FROM clause of a query.
+** The SrcList object is mostly an array of SrcItems.
+*/
+struct SrcItem {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pTab; /* An SQL table corresponding to zName */
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+ struct {
+ u8 jointype; /* Type of join between this table and the previous */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isTabFunc :1; /* True if table-valued-function syntax */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
+ unsigned isRecursive :1; /* True for recursive reference in WITH */
+ unsigned fromDDL :1; /* Comes from sqlite_schema */
+ unsigned isCte :1; /* This is a CTE */
+ unsigned notCte :1; /* This item may not match a CTE */
+ } fg;
+ int iCursor; /* The VDBE cursor number used to access this table */
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
+ Bitmask colUsed; /* Bit N (1<" clause */
+ ExprList *pFuncArg; /* Arguments to table-valued-function */
+ } u1;
+ union {
+ Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
+ CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */
+ } u2;
+};
+
/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
@@ -2891,36 +2987,7 @@ struct IdList {
struct SrcList {
int nSrc; /* Number of tables or subqueries in the FROM clause */
u32 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
- struct {
- u8 jointype; /* Type of join between this table and the previous */
- unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
- unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
- unsigned isTabFunc :1; /* True if table-valued-function syntax */
- unsigned isCorrelated :1; /* True if sub-query is correlated */
- unsigned viaCoroutine :1; /* Implemented as a co-routine */
- unsigned isRecursive :1; /* True for recursive reference in WITH */
- unsigned fromDDL :1; /* Comes from sqlite_schema */
- } fg;
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<" clause */
- ExprList *pFuncArg; /* Arguments to table-valued-function */
- } u1;
- Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
- } a[1]; /* One entry for each identifier on the list */
+ SrcItem a[1]; /* One entry for each identifier on the list */
};
/*
@@ -2954,7 +3021,7 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
- /* 0x0400 not currently used */
+#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
/* 0x1000 not currently used */
/* 0x2000 not currently used */
@@ -2996,10 +3063,11 @@ struct NameContext {
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
+ int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
- int nErr; /* Number of errors encountered while resolving names */
+ int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -3024,6 +3092,7 @@ struct NameContext {
#define NC_UEList 0x00080 /* True if uNC.pEList is used */
#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
#define NC_Complex 0x02000 /* True if a function or subquery seen */
#define NC_AllowWin 0x04000 /* Window functions are allowed here */
@@ -3031,6 +3100,7 @@ struct NameContext {
#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -3047,15 +3117,21 @@ struct NameContext {
** WHERE clause is omitted.
*/
struct Upsert {
- ExprList *pUpsertTarget; /* Optional description of conflicting index */
+ ExprList *pUpsertTarget; /* Optional description of conflict target */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
- /* The fields above comprise the parse tree for the upsert clause.
- ** The fields below are used to transfer information from the INSERT
- ** processing down into the UPDATE processing while generating code.
- ** Upsert owns the memory allocated above, but not the memory below. */
- Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
+ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
+ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ /* Above this point is the parse tree for the ON CONFLICT clauses.
+ ** The next group of fields stores intermediate data. */
+ void *pToFree; /* Free memory when deleting the Upsert object */
+ /* All fields above are owned by the Upsert object and must be freed
+ ** when the Upsert is destroyed. The fields below are used to transfer
+ ** information from the INSERT processing down into the UPDATE processing
+ ** while generating code. The fields below are owned by the INSERT
+ ** statement and will be freed by INSERT processing. */
+ Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
@@ -3135,6 +3211,9 @@ struct Select {
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
+#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
+#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -3305,6 +3384,17 @@ struct TriggerPrg {
# define DbMaskNonZero(M) (M)!=0
#endif
+/*
+** An instance of the ParseCleanup object specifies an operation that
+** should be performed after parsing to deallocation resources obtained
+** during the parse and which are no longer needed.
+*/
+struct ParseCleanup {
+ ParseCleanup *pNext; /* Next cleanup task */
+ void *pPtr; /* Pointer to object to deallocate */
+ void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
+};
+
/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
@@ -3336,6 +3426,9 @@ struct Parse {
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 disableVtab; /* Disable all virtual tables for this parse */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
+#endif
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -3363,12 +3456,15 @@ struct Parse {
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
Parse *pParentParse; /* Parent parser if this parser is nested */
- AggInfo *pAggList; /* List of all AggInfo objects */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
+ union {
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ Returning *pReturning; /* The RETURNING clause */
+ } u1;
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
+ u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
@@ -3414,10 +3510,9 @@ struct Parse {
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
- Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
- With *pWithToFree; /* Free this WITH object at the end of the parse */
+ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
@@ -3497,6 +3592,7 @@ struct AuthContext {
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
+#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -3518,6 +3614,7 @@ struct Trigger {
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF trigger,
the is stored here */
@@ -3576,14 +3673,15 @@ struct Trigger {
*
*/
struct TriggerStep {
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
+ ** or TK_RETURNING */
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE */
+ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
IdList *pIdList; /* Column names for INSERT */
Upsert *pUpsert; /* Upsert clauses on an INSERT */
char *zSpan; /* Original SQL text of this command */
@@ -3592,18 +3690,16 @@ struct TriggerStep {
};
/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
+** Information about a RETURNING clause
*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- Schema *pSchema; /* Fix items to this schema */
- u8 bTemp; /* True for TEMP schema entries */
- const char *zDb; /* Make sure all objects are contained in this database */
- const char *zType; /* Type of the container - used for error messages */
- const Token *pName; /* Name of the container - used for error messages */
+struct Returning {
+ Parse *pParse; /* The parse that includes the RETURNING clause */
+ ExprList *pReturnEL; /* List of expressions to return */
+ Trigger retTrig; /* The transient trigger that implements RETURNING */
+ TriggerStep retTStep; /* The trigger step */
+ int iRetCur; /* Transient table holding RETURNING results */
+ int nRetCol; /* Number of in pReturnEL after expansion */
+ int iRetReg; /* Register array for holding a row of RETURNING */
};
/*
@@ -3643,7 +3739,24 @@ typedef struct {
/*
** Allowed values for mInitFlags
*/
-#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */
+#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
+#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
+
+/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
+** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
+** parameters are for temporary use during development, to help find
+** optimial values for parameters in the query planner. The should not
+** be used on trunk check-ins. They are a temporary mechanism available
+** for transient development builds only.
+**
+** Tuning parameters are numbered starting with 1.
+*/
+#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */
+#ifdef SQLITE_DEBUG
+# define Tuning(X) (sqlite3Config.aTune[(X)-1])
+#else
+# define Tuning(X) 0
+#endif
/*
** Structure containing global configuration data for the SQLite library.
@@ -3699,7 +3812,7 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
@@ -3709,6 +3822,10 @@ struct Sqlite3Config {
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
+ /* vvvv--- must be last ---vvv */
+#ifdef SQLITE_DEBUG
+ sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
+#endif
};
/*
@@ -3755,10 +3872,26 @@ struct Walker {
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
struct Table *pTab; /* Table of generated column */
- struct SrcList_item *pSrcItem; /* A single FROM clause item */
+ SrcItem *pSrcItem; /* A single FROM clause item */
+ DbFixer *pFix;
} u;
};
+/*
+** The following structure contains information used by the sqliteFix...
+** routines as they walk the parse tree to make database references
+** explicit.
+*/
+struct DbFixer {
+ Parse *pParse; /* The parsing context. Error messages written here */
+ Walker w; /* Walker object */
+ Schema *pSchema; /* Fix items to this schema */
+ u8 bTemp; /* True for TEMP schema entries */
+ const char *zDb; /* Make sure all objects are contained in this database */
+ const char *zType; /* Type of the container - used for error messages */
+ const Token *pName; /* Name of the container - used for error messages */
+};
+
/* Forward declarations */
int sqlite3WalkExpr(Walker*, Expr*);
int sqlite3WalkExprList(Walker*, ExprList*);
@@ -3770,11 +3903,18 @@ int sqlite3SelectWalkNoop(Walker*, Select*);
int sqlite3SelectWalkFail(Walker*, Select*);
int sqlite3WalkerDepthIncrease(Walker*,Select*);
void sqlite3WalkerDepthDecrease(Walker*,Select*);
+void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
+#ifndef SQLITE_OMIT_CTE
+void sqlite3SelectPopWith(Walker*, Select*);
+#else
+# define sqlite3SelectPopWith 0
+#endif
+
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
@@ -3784,20 +3924,56 @@ void sqlite3SelectWalkAssert2(Walker*, Select*);
#define WRC_Abort 2 /* Abandon the tree walk */
/*
-** An instance of this structure represents a set of one or more CTEs
-** (common table expressions) created by a single WITH clause.
+** A single common table expression
+*/
+struct Cte {
+ char *zName; /* Name of this CTE */
+ ExprList *pCols; /* List of explicit column names, or NULL */
+ Select *pSelect; /* The definition of this CTE */
+ const char *zCteErr; /* Error message for circular references */
+ CteUse *pUse; /* Usage information for this CTE */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+/*
+** Allowed values for the materialized flag (eM10d):
+*/
+#define M10d_Yes 0 /* AS MATERIALIZED */
+#define M10d_Any 1 /* Not specified. Query planner's choice */
+#define M10d_No 2 /* AS NOT MATERIALIZED */
+
+/*
+** An instance of the With object represents a WITH clause containing
+** one or more CTEs (common table expressions).
*/
struct With {
- int nCte; /* Number of CTEs in the WITH clause */
- With *pOuter; /* Containing WITH clause, or NULL */
- struct Cte { /* For each CTE in the WITH clause.... */
- char *zName; /* Name of this CTE */
- ExprList *pCols; /* List of explicit column names, or NULL */
- Select *pSelect; /* The definition of this CTE */
- const char *zCteErr; /* Error message for circular references */
- } a[1];
+ int nCte; /* Number of CTEs in the WITH clause */
+ int bView; /* Belongs to the outermost Select of a view */
+ With *pOuter; /* Containing WITH clause, or NULL */
+ Cte a[1]; /* For each CTE in the WITH clause.... */
};
+/*
+** The Cte object is not guaranteed to persist for the entire duration
+** of code generation. (The query flattener or other parser tree
+** edits might delete it.) The following object records information
+** about each Common Table Expression that must be preserved for the
+** duration of the parse.
+**
+** The CteUse objects are freed using sqlite3ParserAddCleanup() rather
+** than sqlite3SelectDelete(), which is what enables them to persist
+** until the end of code generation.
+*/
+struct CteUse {
+ int nUse; /* Number of users of this CTE */
+ int addrM9e; /* Start of subroutine to compute materialization */
+ int regRtn; /* Return address register for addrM9e subroutine */
+ int iCur; /* Ephemeral table holding the materialization */
+ LogEst nRowEst; /* Estimated number of rows in the table */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -3875,7 +4051,6 @@ int sqlite3WindowCompare(Parse*, Window*, Window*, int);
void sqlite3WindowCodeInit(Parse*, Select*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
-int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
@@ -4144,6 +4319,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
+void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
@@ -4165,6 +4341,7 @@ void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
+void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -4192,6 +4369,7 @@ void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3AddGenerated(Parse*,Expr*,Token*);
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+void sqlite3AddReturning(Parse*,ExprList*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
#define sqlite3CodecQueryParameters(A,B,C) 0
@@ -4257,7 +4435,7 @@ SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, Expr*, IdList*);
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+int sqlite3IndexedByLookup(Parse *, SrcItem *);
void sqlite3SrcListShiftJoinType(SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(sqlite3*, IdList*);
@@ -4285,6 +4463,7 @@ LogEst sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
+void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
@@ -4318,7 +4497,7 @@ Table *sqlite3FindTable(sqlite3*,const char*, const char*);
#define LOCATE_VIEW 0x01
#define LOCATE_NOERR 0x02
Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
-Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
+Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
@@ -4398,6 +4577,7 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
+With *sqlite3WithDup(sqlite3 *db, With *p);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
@@ -4446,6 +4626,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+int sqlite3ColumnIndex(Table *pTab, const char *zCol);
void sqlite3SetJoinExpr(Expr*,int);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
@@ -4468,7 +4649,6 @@ void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite3FixSrcList(DbFixer*, SrcList*);
int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*);
-int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
void sqlite3Int64ToText(i64,char*);
@@ -4531,6 +4711,7 @@ int sqlite3Atoi64(const char*, i64*, int, u8);
int sqlite3DecOrHexToI64(const char*, i64*);
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
void sqlite3Error(sqlite3*,int);
+void sqlite3ErrorClear(sqlite3*);
void sqlite3SystemError(sqlite3*,int);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
@@ -4540,7 +4721,7 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrName(int);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int sqlite3MemdbInit(void);
#endif
@@ -4591,10 +4772,12 @@ void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];
+extern const unsigned char *sqlite3aLTb;
+extern const unsigned char *sqlite3aEQb;
+extern const unsigned char *sqlite3aGTb;
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
-extern u32 sqlite3_unsupported_selecttrace;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
@@ -4613,6 +4796,7 @@ void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+int sqlite3ExpandSubquery(Parse*, SrcItem*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchEName(
const struct ExprList_item*,
@@ -4630,6 +4814,7 @@ int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+void sqlite3AlterDropColumn(Parse*, SrcList*, Token*);
void *sqlite3RenameTokenMap(Parse*, void*, Token*);
void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
void sqlite3RenameExprUnmap(Parse*, Expr*);
@@ -4653,6 +4838,7 @@ void sqlite3KeyInfoUnref(KeyInfo*);
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+const char *sqlite3SelectOpName(int);
int sqlite3HasExplicitNulls(Parse*, ExprList*);
#ifdef SQLITE_DEBUG
@@ -4783,6 +4969,7 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
+void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
char *sqlite3Normalize(Vdbe*, const char*);
#endif
@@ -4797,23 +4984,32 @@ const char *sqlite3JournalModename(int);
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#endif
#ifndef SQLITE_OMIT_CTE
- With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+ Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
+ void sqlite3CteDelete(sqlite3*,Cte*);
+ With *sqlite3WithAdd(Parse*,With*,Cte*);
void sqlite3WithDelete(sqlite3*,With*);
- void sqlite3WithPush(Parse*, With*, u8);
+ With *sqlite3WithPush(Parse*, With*, u8);
#else
-#define sqlite3WithPush(x,y,z)
-#define sqlite3WithDelete(x,y)
+# define sqlite3CteNew(P,T,E,S) ((void*)0)
+# define sqlite3CteDelete(D,C)
+# define sqlite3CteWithAdd(P,W,C) ((void*)0)
+# define sqlite3WithDelete(x,y)
+# define sqlite3WithPush(x,y,z)
#endif
#ifndef SQLITE_OMIT_UPSERT
- Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
+ Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
void sqlite3UpsertDelete(sqlite3*,Upsert*);
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
+ Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
+ int sqlite3UpsertNextIsIPK(Upsert*);
#else
-#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
+#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
-#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
+#define sqlite3UpsertNextIsIPK(x) 0
#endif
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index d80c25251..2206bca32 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2600,7 +2600,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Reopen DATABASE (default "main") using the content in $VALUE
*/
case DB_DESERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
@@ -3167,7 +3167,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** Return a serialization of a database.
*/
case DB_SERIALIZE: {
-#ifndef SQLITE_ENABLE_DESERIALIZE
+#ifdef SQLITE_OMIT_DESERIALIZE
Tcl_AppendResult(interp, "MEMDB not available in this build",
(char*)0);
rc = TCL_ERROR;
diff --git a/src/test1.c b/src/test1.c
index 49461ea5f..7cb56d3be 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -3825,9 +3825,11 @@ static int SQLITE_TCLAPI test_bind_text(
){
sqlite3_stmt *pStmt;
int idx;
+ int trueLength = 0;
int bytes;
char *value;
int rc;
+ char *toFree = 0;
if( objc!=5 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -3837,13 +3839,23 @@ static int SQLITE_TCLAPI test_bind_text(
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
+ value = (char*)Tcl_GetByteArrayFromObj(objv[3], &trueLength);
if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
-
+ if( bytes<0 ){
+ toFree = malloc( trueLength + 1 );
+ if( toFree==0 ){
+ Tcl_AppendResult(interp, "out of memory", (void*)0);
+ return TCL_ERROR;
+ }
+ memcpy(toFree, value, trueLength);
+ toFree[trueLength] = 0;
+ value = toFree;
+ }
rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
+ free(toFree);
if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
if( rc!=SQLITE_OK ){
- Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+ Tcl_AppendResult(interp, sqlite3ErrName(rc), (void*)0);
return TCL_ERROR;
}
@@ -3869,7 +3881,9 @@ static int SQLITE_TCLAPI test_bind_text16(
int idx;
int bytes;
char *value;
+ char *toFree = 0;
int rc;
+ int trueLength = 0;
void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
Tcl_Obj *oStmt = objv[objc-4];
@@ -3885,10 +3899,20 @@ static int SQLITE_TCLAPI test_bind_text16(
if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
- value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
+ value = (char*)Tcl_GetByteArrayFromObj(oString, &trueLength);
if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
-
+ if( bytes<0 && xDel==SQLITE_TRANSIENT ){
+ toFree = malloc( trueLength + 3 );
+ if( toFree==0 ){
+ Tcl_AppendResult(interp, "out of memory", (void*)0);
+ return TCL_ERROR;
+ }
+ memcpy(toFree, value, trueLength);
+ memset(toFree+trueLength, 0, 3);
+ value = toFree;
+ }
rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
+ free(toFree);
if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
@@ -6490,6 +6514,42 @@ static int SQLITE_TCLAPI file_control_tempfilename(
return TCL_OK;
}
+/*
+** tclcmd: file_control_external_reader DB ?AUXDB?
+**
+** Return a string that is a temporary filename
+*/
+static int SQLITE_TCLAPI file_control_external_reader(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ const char *zName = "main";
+ int iRes = 0;
+ int rc = SQLITE_OK;
+
+ if( objc!=2 && objc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+ return TCL_ERROR;
+ }
+ if( objc==3 ){
+ zName = Tcl_GetString(objv[2]);
+ }
+ rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
+ if( rc!=SQLITE_OK ){
+ Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
+ return TCL_OK;
+}
+
/*
** tclcmd: sqlite3_vfs_list
@@ -6648,7 +6708,7 @@ static int SQLITE_TCLAPI prng_seed(
Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?");
return TCL_ERROR;
}
- if( Tcl_GetIntFromObj(interp,objv[0],&i) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp,objv[1],&i) ) return TCL_ERROR;
if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
return TCL_ERROR;
}
@@ -7494,6 +7554,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
Tcl_Obj *CONST objv[]
){
extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
+ extern int sqlite3_appendvfs_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -7523,6 +7584,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
} aExtension[] = {
{ "amatch", sqlite3_amatch_init },
+ { "appendvfs", sqlite3_appendvfs_init },
{ "carray", sqlite3_carray_init },
{ "closure", sqlite3_closure_init },
{ "csv", sqlite3_csv_init },
@@ -7571,7 +7633,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
}else{
rc = SQLITE_OK;
}
- if( rc!=SQLITE_OK || zErrMsg ){
+ if( (rc!=SQLITE_OK && rc!=SQLITE_OK_LOAD_PERMANENTLY) || zErrMsg ){
Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
(char*)0);
sqlite3_free(zErrMsg);
@@ -8426,6 +8488,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_vfsname", file_control_vfsname, 0 },
{ "file_control_reservebytes", file_control_reservebytes, 0 },
{ "file_control_tempfilename", file_control_tempfilename, 0 },
+ { "file_control_external_reader", file_control_external_reader, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
@@ -8512,7 +8575,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern LONG volatile sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG
- extern int sqlite3WhereTrace;
+ extern u32 sqlite3WhereTrace;
extern int sqlite3OSTrace;
extern int sqlite3WalTrace;
#endif
@@ -8520,9 +8583,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_FTS3
extern int sqlite3_fts3_enable_parentheses;
#endif
-#endif
-#if defined(SQLITE_ENABLE_SELECTTRACE)
- extern u32 sqlite3_unsupported_selecttrace;
#endif
for(i=0; idb, "function_that_does_not_exist_0982ma98",
+ SQLITE_ANY, 1, 0, 0, 0, 0);
sqlite3_free(p);
}
@@ -1376,6 +1380,7 @@ static int SQLITE_TCLAPI register_echo_module(
/* Virtual table module "echo" */
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(
db, "echo", &echoModule, (void*)pMod, moduleDestroy
);
@@ -1384,6 +1389,7 @@ static int SQLITE_TCLAPI register_echo_module(
if( rc==SQLITE_OK ){
pMod = sqlite3_malloc(sizeof(EchoModule));
pMod->interp = interp;
+ pMod->db = db;
rc = sqlite3_create_module_v2(db, "echo_v2",
&echoModuleV2, (void*)pMod, moduleDestroy
);
diff --git a/src/test_config.c b/src/test_config.c
index 362e92aa9..86e4df38f 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -65,6 +65,13 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
#endif
+#ifdef CONFIG_SLOWDOWN_FACTOR
+ Tcl_SetVar2(interp, "sqlite_options","configslower",
+ STRINGVALUE(CONFIG_SLOWDOWN_FACTOR),TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options","configslower","1.0",TCL_GLOBAL_ONLY);
+#endif
+
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
#else
@@ -148,12 +155,18 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ Tcl_SetVar2(interp, "sqlite_options", "mathlib", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "mathlib", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_ENABLE_MEMSYS3
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
#else
@@ -220,6 +233,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_ENABLE_GEOPOLY
+ Tcl_SetVar2(interp, "sqlite_options", "geopoly", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "geopoly", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_ENABLE_JSON1
Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
diff --git a/src/tokenize.c b/src/tokenize.c
index 70f0c6367..5d250e6f6 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -27,8 +27,8 @@
** all of them need to be used within the switch.
*/
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
-#define CC_ID 2 /* unicode characters usable in IDs */
+#define CC_KYWD0 1 /* First letter of a keyword */
+#define CC_KYWD 2 /* Alphabetics or '_'. Usable in a keyword */
#define CC_DIGIT 3 /* Digits */
#define CC_DOLLAR 4 /* '$' */
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
@@ -53,47 +53,49 @@
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
-#define CC_ILLEGAL 27 /* Illegal character */
-#define CC_NUL 28 /* 0x00 */
+#define CC_ID 27 /* unicode characters usable in IDs */
+#define CC_ILLEGAL 28 /* Illegal character */
+#define CC_NUL 29 /* 0x00 */
+#define CC_BOM 30 /* First byte of UTF8 BOM: 0xEF 0xBB 0xBF */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
+/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
-/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
+/* 8x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 9x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ax */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Cx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Dx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ex */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
+/* Fx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
-/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
-/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
-/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
-/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
-/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 4x */ 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
+/* 5x */ 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15, 4, 21, 18, 19, 28,
+/* 6x */ 11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22, 2, 13, 6,
+/* 7x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 8, 5, 5, 5, 8, 14, 8,
+/* 8x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* 9x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ax */ 28, 25, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Bx */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, 28,
+/* Cx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Dx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ex */ 28, 28, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 28, 28, 28, 28, 28, 28,
#endif
};
@@ -499,7 +501,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
- case CC_KYWD: {
+ case CC_KYWD0: {
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
@@ -529,10 +531,19 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
+ case CC_KYWD:
case CC_ID: {
i = 1;
break;
}
+ case CC_BOM: {
+ if( z[1]==0xbb && z[2]==0xbf ){
+ *tokenType = TK_SPACE;
+ return 3;
+ }
+ i = 1;
+ break;
+ }
case CC_NUL: {
*tokenType = TK_ILLEGAL;
return 0;
@@ -711,19 +722,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
if( !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
-
- if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DbFree(db, pParse->pVList);
- while( pParse->pAinc ){
- AutoincInfo *p = pParse->pAinc;
- pParse->pAinc = p->pNext;
- sqlite3DbFreeNN(db, p);
- }
- while( pParse->pZombieTab ){
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlite3DeleteTable(db, p);
- }
db->pParse = pParse->pParentParse;
pParse->pParentParse = 0;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
diff --git a/src/treeview.c b/src/treeview.c
index 187f1a07d..c737a1b98 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -111,7 +111,10 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
}
sqlite3_str_appendf(&x, ")");
}
- sqlite3_str_appendf(&x, " AS");
+ if( pCte->pUse ){
+ sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
+ pCte->pUse->nUse);
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, inCte-1);
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
@@ -127,29 +130,25 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
for(i=0; inSrc; i++){
- const struct SrcList_item *pItem = &pSrc->a[i];
+ const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d:*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
+ x.printfFlags |= SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
if( pItem->pTab ){
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
}
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
}
if( pItem->fg.fromDDL ){
sqlite3_str_appendf(&x, " DDL");
}
+ if( pItem->fg.isCte ){
+ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, inSrc-1);
if( pItem->pSelect ){
@@ -707,6 +706,14 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
+ case TK_ERROR: {
+ Expr tmp;
+ sqlite3TreeViewLine(pView, "ERROR");
+ tmp = *pExpr;
+ tmp.op = pExpr->op2;
+ sqlite3TreeViewExpr(pView, &tmp, 0);
+ break;
+ }
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
diff --git a/src/trigger.c b/src/trigger.c
index dd4ed8c2e..90e6ef4a7 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -48,28 +48,51 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
** pTab as well as the triggers lised in pTab->pTrigger.
*/
Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
- Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
- Trigger *pList = 0; /* List of triggers to return */
+ Schema *pTmpSchema; /* Schema of the pTab table */
+ Trigger *pList; /* List of triggers to return */
+ HashElem *p; /* Loop variable for TEMP triggers */
if( pParse->disableTriggers ){
return 0;
}
-
- if( pTmpSchema!=pTab->pSchema ){
- HashElem *p;
- assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
- for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
- Trigger *pTrig = (Trigger *)sqliteHashData(p);
- if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
- ){
- pTrig->pNext = (pList ? pList : pTab->pTrigger);
- pList = pTrig;
- }
+ pTmpSchema = pParse->db->aDb[1].pSchema;
+ p = sqliteHashFirst(&pTmpSchema->trigHash);
+ pList = pTab->pTrigger;
+ while( p ){
+ Trigger *pTrig = (Trigger *)sqliteHashData(p);
+ if( pTrig->pTabSchema==pTab->pSchema
+ && pTrig->table
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ && pTrig->pTabSchema!=pTmpSchema
+ ){
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }else if( pTrig->op==TK_RETURNING
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ && pParse->db->pVtabCtx==0
+#endif
+ ){
+ assert( pParse->bReturning );
+ assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ pTrig->table = pTab->zName;
+ pTrig->pTabSchema = pTab->pSchema;
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }
+ p = sqliteHashNext(p);
+ }
+#if 0
+ if( pList ){
+ Trigger *pX;
+ printf("Triggers for %s:", pTab->zName);
+ for(pX=pList; pX; pX=pX->pNext){
+ printf(" %s", pX->zName);
}
+ printf("\n");
+ fflush(stdout);
}
-
- return (pList ? pList : pTab->pTrigger);
+#endif
+ return pList;
}
/*
@@ -198,12 +221,12 @@ void sqlite3BeginTrigger(
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
- (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
+ (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
- " trigger on table: %S", pTableName, 0);
+ " trigger on table: %S", pTableName->a);
goto trigger_orphan_error;
}
@@ -345,7 +368,7 @@ void sqlite3FinishTrigger(
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
+ sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
}
if( db->init.busy ){
@@ -558,7 +581,7 @@ TriggerStep *sqlite3TriggerDeleteStep(
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
- if( pTrigger==0 ) return;
+ if( pTrigger==0 || pTrigger->bReturning ) return;
sqlite3DeleteTriggerStep(db, pTrigger->step_list);
sqlite3DbFree(db, pTrigger->zName);
sqlite3DbFree(db, pTrigger->table);
@@ -600,7 +623,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
}
if( !pTrigger ){
if( !noErr ){
- sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, zDb);
}
@@ -723,15 +746,53 @@ Trigger *sqlite3TriggersExist(
Trigger *pList = 0;
Trigger *p;
- if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
- pList = sqlite3TriggerList(pParse, pTab);
- }
- assert( pList==0 || IsVirtual(pTab)==0 );
- for(p=pList; p; p=p->pNext){
- if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
- mask |= p->tr_tm;
+ pList = sqlite3TriggerList(pParse, pTab);
+ assert( pList==0 || IsVirtual(pTab)==0
+ || (pList->bReturning && pList->pNext==0) );
+ if( pList!=0 ){
+ p = pList;
+ if( (pParse->db->flags & SQLITE_EnableTrigger)==0
+ && pTab->pTrigger!=0
+ ){
+ /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
+ ** only TEMP triggers are allowed. Truncate the pList so that it
+ ** includes only TEMP triggers */
+ if( pList==pTab->pTrigger ){
+ pList = 0;
+ goto exit_triggers_exist;
+ }
+ while( ALWAYS(p->pNext) && p->pNext!=pTab->pTrigger ) p = p->pNext;
+ p->pNext = 0;
+ p = pList;
}
+ do{
+ if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
+ mask |= p->tr_tm;
+ }else if( p->op==TK_RETURNING ){
+ /* The first time a RETURNING trigger is seen, the "op" value tells
+ ** us what time of trigger it should be. */
+ assert( sqlite3IsToplevel(pParse) );
+ p->op = op;
+ if( IsVirtual(pTab) ){
+ if( op!=TK_INSERT ){
+ sqlite3ErrorMsg(pParse,
+ "%s RETURNING is not available on virtual tables",
+ op==TK_DELETE ? "DELETE" : "UPDATE");
+ }
+ p->tr_tm = TRIGGER_BEFORE;
+ }else{
+ p->tr_tm = TRIGGER_AFTER;
+ }
+ mask |= p->tr_tm;
+ }else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE
+ && sqlite3IsToplevel(pParse) ){
+ /* Also fire a RETURNING trigger for an UPSERT */
+ mask |= p->tr_tm;
+ }
+ p = p->pNext;
+ }while( p );
}
+exit_triggers_exist:
if( pMask ){
*pMask = mask;
}
@@ -774,6 +835,137 @@ SrcList *sqlite3TriggerStepSrc(
return pSrc;
}
+/*
+** Return true if the pExpr term from the RETURNING clause argument
+** list is of the form "*". Raise an error if the terms if of the
+** form "table.*".
+*/
+static int isAsteriskTerm(
+ Parse *pParse, /* Parsing context */
+ Expr *pTerm /* A term in the RETURNING clause */
+){
+ assert( pTerm!=0 );
+ if( pTerm->op==TK_ASTERISK ) return 1;
+ if( pTerm->op!=TK_DOT ) return 0;
+ assert( pTerm->pRight!=0 );
+ assert( pTerm->pLeft!=0 );
+ if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
+ sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
+ return 1;
+}
+
+/* The input list pList is the list of result set terms from a RETURNING
+** clause. The table that we are returning from is pTab.
+**
+** This routine makes a copy of the pList, and at the same time expands
+** any "*" wildcards to be the complete set of columns from pTab.
+*/
+static ExprList *sqlite3ExpandReturning(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* The arguments to RETURNING */
+ Table *pTab /* The table being updated */
+){
+ ExprList *pNew = 0;
+ sqlite3 *db = pParse->db;
+ int i;
+
+ for(i=0; inExpr; i++){
+ Expr *pOldExpr = pList->a[i].pExpr;
+ if( NEVER(pOldExpr==0) ) continue;
+ if( isAsteriskTerm(pParse, pOldExpr) ){
+ int jj;
+ for(jj=0; jjnCol; jj++){
+ Expr *pNewExpr;
+ if( IsHiddenColumn(pTab->aCol+jj) ) continue;
+ pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
+ pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zName);
+ pItem->eEName = ENAME_NAME;
+ }
+ }
+ }else{
+ Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
+ pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
+ pItem->eEName = pList->a[i].eEName;
+ }
+ }
+ }
+ return pNew;
+}
+
+/*
+** Generate code for the RETURNING trigger. Unlike other triggers
+** that invoke a subprogram in the bytecode, the code for RETURNING
+** is generated in-line.
+*/
+static void codeReturningTrigger(
+ Parse *pParse, /* Parse context */
+ Trigger *pTrigger, /* The trigger step that defines the RETURNING */
+ Table *pTab, /* The table to code triggers from */
+ int regIn /* The first in an array of registers */
+){
+ Vdbe *v = pParse->pVdbe;
+ sqlite3 *db = pParse->db;
+ ExprList *pNew;
+ Returning *pReturning;
+ Select sSelect;
+ SrcList sFrom;
+
+ assert( v!=0 );
+ assert( pParse->bReturning );
+ pReturning = pParse->u1.pReturning;
+ assert( pTrigger == &(pReturning->retTrig) );
+ memset(&sSelect, 0, sizeof(sSelect));
+ memset(&sFrom, 0, sizeof(sFrom));
+ sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
+ sSelect.pSrc = &sFrom;
+ sFrom.nSrc = 1;
+ sFrom.a[0].pTab = pTab;
+ sqlite3SelectPrep(pParse, &sSelect, 0);
+ if( db->mallocFailed==0 && pParse->nErr==0 ){
+ sqlite3GenerateColumnNames(pParse, &sSelect);
+ }
+ sqlite3ExprListDelete(db, sSelect.pEList);
+ pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
+ if( pNew ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ if( pReturning->nRetCol==0 ){
+ pReturning->nRetCol = pNew->nExpr;
+ pReturning->iRetCur = pParse->nTab++;
+ }
+ sNC.pParse = pParse;
+ sNC.uNC.iBaseReg = regIn;
+ sNC.ncFlags = NC_UBaseReg;
+ pParse->eTriggerOp = pTrigger->op;
+ pParse->pTriggerTab = pTab;
+ if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
+ int i;
+ int nCol = pNew->nExpr;
+ int reg = pParse->nMem+1;
+ pParse->nMem += nCol+2;
+ pReturning->iRetReg = reg;
+ for(i=0; ia[i].pExpr;
+ sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
+ sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
+ }
+ sqlite3ExprListDelete(db, pNew);
+ pParse->eTriggerOp = 0;
+ pParse->pTriggerTab = 0;
+ }
+}
+
+
+
/*
** Generate VDBE code for the statements inside the body of a single
** trigger.
@@ -823,6 +1015,7 @@ static int codeTriggerProgram(
sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf, 0, 0, 0
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_INSERT: {
@@ -833,6 +1026,7 @@ static int codeTriggerProgram(
pParse->eOrconf,
sqlite3UpsertDup(db, pStep->pUpsert)
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_DELETE: {
@@ -840,6 +1034,7 @@ static int codeTriggerProgram(
sqlite3TriggerStepSrc(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
default: assert( pStep->op==TK_SELECT ); {
@@ -851,9 +1046,6 @@ static int codeTriggerProgram(
break;
}
}
- if( pStep->op!=TK_SELECT ){
- sqlite3VdbeAddOp0(v, OP_ResetCount);
- }
}
return 0;
@@ -969,8 +1161,8 @@ static TriggerPrg *codeRowTrigger(
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
+ if( db->mallocFailed==0
+ && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
){
iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
@@ -1000,7 +1192,6 @@ static TriggerPrg *codeRowTrigger(
sqlite3VdbeDelete(v);
}
- assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
@@ -1102,7 +1293,7 @@ void sqlite3CodeRowTriggerDirect(
** ... ...
** reg+N OLD.* value of right-most column of pTab
** reg+N+1 NEW.rowid
-** reg+N+2 OLD.* value of left-most column of pTab
+** reg+N+2 NEW.* value of left-most column of pTab
** ... ...
** reg+N+N+1 NEW.* value of right-most column of pTab
**
@@ -1147,12 +1338,20 @@ void sqlite3CodeRowTrigger(
assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
- /* Determine whether we should code this trigger */
- if( p->op==op
+ /* Determine whether we should code this trigger. One of two choices:
+ ** 1. The trigger is an exact match to the current DML statement
+ ** 2. This is a RETURNING trigger for INSERT but we are currently
+ ** doing the UPDATE part of an UPSERT.
+ */
+ if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE))
&& p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
- sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ if( !p->bReturning ){
+ sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ }else if( sqlite3IsToplevel(pParse) ){
+ codeReturningTrigger(pParse, p, pTab, reg);
+ }
}
}
}
@@ -1197,13 +1396,18 @@ u32 sqlite3TriggerColmask(
assert( isNew==1 || isNew==0 );
for(p=pTrigger; p; p=p->pNext){
- if( p->op==op && (tr_tm&p->tr_tm)
+ if( p->op==op
+ && (tr_tm&p->tr_tm)
&& checkColumnOverlap(p->pColumns,pChanges)
){
- TriggerPrg *pPrg;
- pPrg = getRowTrigger(pParse, p, pTab, orconf);
- if( pPrg ){
- mask |= pPrg->aColmask[isNew];
+ if( p->bReturning ){
+ mask = 0xffffffff;
+ }else{
+ TriggerPrg *pPrg;
+ pPrg = getRowTrigger(pParse, p, pTab, orconf);
+ if( pPrg ){
+ mask |= pPrg->aColmask[isNew];
+ }
}
}
}
diff --git a/src/update.c b/src/update.c
index f8cb2afed..132232724 100644
--- a/src/update.c
+++ b/src/update.c
@@ -220,6 +220,7 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ pSrc->a[0].fg.notCte = 1;
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -249,7 +250,8 @@ static void updateFromSelect(
}
#endif
}
- if( ALWAYS(pChanges) ){
+ assert( pChanges!=0 || pParse->db->mallocFailed );
+ if( pChanges ){
for(i=0; inExpr; i++){
pList = sqlite3ExprListAppend(pParse, pList,
sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
@@ -643,6 +645,7 @@ void sqlite3Update(
if( (db->flags&SQLITE_CountRows)!=0
&& !pParse->pTriggerTab
&& !pParse->nested
+ && !pParse->bReturning
&& pUpsert==0
){
regRowCount = ++pParse->nMem;
@@ -798,7 +801,12 @@ void sqlite3Update(
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
+ if( aiCurOnePass[0]!=iDataCur
+ && aiCurOnePass[1]!=iDataCur
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && !isView
+#endif
+ ){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
VdbeCoverage(v);
@@ -1106,7 +1114,7 @@ void sqlite3Update(
** that information.
*/
if( regRowCount ){
- sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
}
diff --git a/src/upsert.c b/src/upsert.c
index 9a33f75d0..982dc7dbc 100644
--- a/src/upsert.c
+++ b/src/upsert.c
@@ -18,15 +18,22 @@
/*
** Free a list of Upsert objects
*/
-void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
- if( p ){
+static void SQLITE_NOINLINE upsertDelete(sqlite3 *db, Upsert *p){
+ do{
+ Upsert *pNext = p->pNextUpsert;
sqlite3ExprListDelete(db, p->pUpsertTarget);
sqlite3ExprDelete(db, p->pUpsertTargetWhere);
sqlite3ExprListDelete(db, p->pUpsertSet);
sqlite3ExprDelete(db, p->pUpsertWhere);
+ sqlite3DbFree(db, p->pToFree);
sqlite3DbFree(db, p);
- }
+ p = pNext;
+ }while( p );
}
+void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
+ if( p ) upsertDelete(db, p);
+}
+
/*
** Duplicate an Upsert object.
@@ -37,7 +44,8 @@ Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
sqlite3ExprListDup(db, p->pUpsertTarget, 0),
sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
sqlite3ExprListDup(db, p->pUpsertSet, 0),
- sqlite3ExprDup(db, p->pUpsertWhere, 0)
+ sqlite3ExprDup(db, p->pUpsertWhere, 0),
+ sqlite3UpsertDup(db, p->pNextUpsert)
);
}
@@ -49,22 +57,25 @@ Upsert *sqlite3UpsertNew(
ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
Expr *pTargetWhere, /* Optional WHERE clause on the target */
ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */
- Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */
+ Expr *pWhere, /* WHERE clause for the ON CONFLICT UPDATE */
+ Upsert *pNext /* Next ON CONFLICT clause in the list */
){
Upsert *pNew;
- pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
+ pNew = sqlite3DbMallocZero(db, sizeof(Upsert));
if( pNew==0 ){
sqlite3ExprListDelete(db, pTarget);
sqlite3ExprDelete(db, pTargetWhere);
sqlite3ExprListDelete(db, pSet);
sqlite3ExprDelete(db, pWhere);
+ sqlite3UpsertDelete(db, pNext);
return 0;
}else{
pNew->pUpsertTarget = pTarget;
pNew->pUpsertTargetWhere = pTargetWhere;
pNew->pUpsertSet = pSet;
pNew->pUpsertWhere = pWhere;
- pNew->pUpsertIdx = 0;
+ pNew->isDoUpdate = pSet!=0;
+ pNew->pNextUpsert = pNext;
}
return pNew;
}
@@ -89,6 +100,7 @@ int sqlite3UpsertAnalyzeTarget(
Expr *pTerm; /* One term of the conflict-target clause */
NameContext sNC; /* Context for resolving symbolic names */
Expr sCol[2]; /* Index column converted into an Expr */
+ int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
assert( pTabList->a[0].pTab!=0 );
@@ -102,87 +114,131 @@ int sqlite3UpsertAnalyzeTarget(
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
- if( rc ) return rc;
- rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
- if( rc ) return rc;
-
- /* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
- pTarget = pUpsert->pUpsertTarget;
- iCursor = pTabList->a[0].iCursor;
- if( HasRowid(pTab)
- && pTarget->nExpr==1
- && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
- && pTerm->iColumn==XN_ROWID
- ){
- /* The conflict-target is the rowid of the primary table */
- assert( pUpsert->pUpsertIdx==0 );
- return SQLITE_OK;
- }
-
- /* Initialize sCol[0..1] to be an expression parse tree for a
- ** single column of an index. The sCol[0] node will be the TK_COLLATE
- ** operator and sCol[1] will be the TK_COLUMN operator. Code below
- ** will populate the specific collation and column number values
- ** prior to comparing against the conflict-target expression.
- */
- memset(sCol, 0, sizeof(sCol));
- sCol[0].op = TK_COLLATE;
- sCol[0].pLeft = &sCol[1];
- sCol[1].op = TK_COLUMN;
- sCol[1].iTable = pTabList->a[0].iCursor;
-
- /* Check for matches against other indexes */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int ii, jj, nn;
- if( !IsUniqueIndex(pIdx) ) continue;
- if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
- if( pIdx->pPartIdxWhere ){
- if( pUpsert->pUpsertTargetWhere==0 ) continue;
- if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
- pIdx->pPartIdxWhere, iCursor)!=0 ){
- continue;
- }
+ for(; pUpsert && pUpsert->pUpsertTarget;
+ pUpsert=pUpsert->pNextUpsert, nClause++){
+ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
+ if( rc ) return rc;
+ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
+ if( rc ) return rc;
+
+ /* Check to see if the conflict target matches the rowid. */
+ pTab = pTabList->a[0].pTab;
+ pTarget = pUpsert->pUpsertTarget;
+ iCursor = pTabList->a[0].iCursor;
+ if( HasRowid(pTab)
+ && pTarget->nExpr==1
+ && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
+ && pTerm->iColumn==XN_ROWID
+ ){
+ /* The conflict-target is the rowid of the primary table */
+ assert( pUpsert->pUpsertIdx==0 );
+ continue;
}
- nn = pIdx->nKeyCol;
- for(ii=0; iiazColl[ii];
- if( pIdx->aiColumn[ii]==XN_EXPR ){
- assert( pIdx->aColExpr!=0 );
- assert( pIdx->aColExpr->nExpr>ii );
- pExpr = pIdx->aColExpr->a[ii].pExpr;
- if( pExpr->op!=TK_COLLATE ){
- sCol[0].pLeft = pExpr;
- pExpr = &sCol[0];
+
+ /* Initialize sCol[0..1] to be an expression parse tree for a
+ ** single column of an index. The sCol[0] node will be the TK_COLLATE
+ ** operator and sCol[1] will be the TK_COLUMN operator. Code below
+ ** will populate the specific collation and column number values
+ ** prior to comparing against the conflict-target expression.
+ */
+ memset(sCol, 0, sizeof(sCol));
+ sCol[0].op = TK_COLLATE;
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].op = TK_COLUMN;
+ sCol[1].iTable = pTabList->a[0].iCursor;
+
+ /* Check for matches against other indexes */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int ii, jj, nn;
+ if( !IsUniqueIndex(pIdx) ) continue;
+ if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
+ if( pIdx->pPartIdxWhere ){
+ if( pUpsert->pUpsertTargetWhere==0 ) continue;
+ if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
+ pIdx->pPartIdxWhere, iCursor)!=0 ){
+ continue;
}
- }else{
- sCol[0].pLeft = &sCol[1];
- sCol[1].iColumn = pIdx->aiColumn[ii];
- pExpr = &sCol[0];
}
- for(jj=0; jja[jj].pExpr, pExpr,iCursor)<2 ){
- break; /* Column ii of the index matches column jj of target */
+ nn = pIdx->nKeyCol;
+ for(ii=0; iiazColl[ii];
+ if( pIdx->aiColumn[ii]==XN_EXPR ){
+ assert( pIdx->aColExpr!=0 );
+ assert( pIdx->aColExpr->nExpr>ii );
+ pExpr = pIdx->aColExpr->a[ii].pExpr;
+ if( pExpr->op!=TK_COLLATE ){
+ sCol[0].pLeft = pExpr;
+ pExpr = &sCol[0];
+ }
+ }else{
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].iColumn = pIdx->aiColumn[ii];
+ pExpr = &sCol[0];
+ }
+ for(jj=0; jja[jj].pExpr,pExpr,iCursor)<2 ){
+ break; /* Column ii of the index matches column jj of target */
+ }
+ }
+ if( jj>=nn ){
+ /* The target contains no match for column jj of the index */
+ break;
}
}
- if( jj>=nn ){
- /* The target contains no match for column jj of the index */
- break;
+ if( iipUpsertIdx = pIdx;
+ break;
}
- if( iipUpsertIdx==0 ){
+ char zWhich[16];
+ if( nClause==0 && pUpsert->pNextUpsert==0 ){
+ zWhich[0] = 0;
+ }else{
+ sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
+ }
+ sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
+ "PRIMARY KEY or UNIQUE constraint", zWhich);
+ return SQLITE_ERROR;
}
- pUpsert->pUpsertIdx = pIdx;
- return SQLITE_OK;
}
- sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
- "PRIMARY KEY or UNIQUE constraint");
- return SQLITE_ERROR;
+ return SQLITE_OK;
+}
+
+/*
+** Return true if pUpsert is the last ON CONFLICT clause with a
+** conflict target, or if pUpsert is followed by another ON CONFLICT
+** clause that targets the INTEGER PRIMARY KEY.
+*/
+int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
+ Upsert *pNext;
+ if( NEVER(pUpsert==0) ) return 0;
+ pNext = pUpsert->pNextUpsert;
+ if( pNext==0 ) return 1;
+ if( pNext->pUpsertTarget==0 ) return 1;
+ if( pNext->pUpsertIdx==0 ) return 1;
+ return 0;
+}
+
+/*
+** Given the list of ON CONFLICT clauses described by pUpsert, and
+** a particular index pIdx, return a pointer to the particular ON CONFLICT
+** clause that applies to the index. Or, if the index is not subject to
+** any ON CONFLICT clause, return NULL.
+*/
+Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
+ while(
+ pUpsert
+ && pUpsert->pUpsertTarget!=0
+ && pUpsert->pUpsertIdx!=pIdx
+ ){
+ pUpsert = pUpsert->pNextUpsert;
+ }
+ return pUpsert;
}
/*
@@ -206,11 +262,13 @@ void sqlite3UpsertDoUpdate(
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
+ Upsert *pTop = pUpsert;
assert( v!=0 );
assert( pUpsert!=0 );
- VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
iDataCur = pUpsert->iDataCur;
+ pUpsert = sqlite3UpsertOfIndex(pTop, pIdx);
+ VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlite3GetTempReg(pParse);
@@ -240,19 +298,17 @@ void sqlite3UpsertDoUpdate(
sqlite3VdbeJumpHere(v, i);
}
}
- /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
- ** we have to make a copy before passing it down into sqlite3Update() */
- pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
+ /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
+ ** So we have to make a copy before passing it down into sqlite3Update() */
+ pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; inCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
}
}
- sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
- pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
- pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */
- pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */
+ sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
+ sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
}
diff --git a/src/util.c b/src/util.c
index fb86d7d11..fc0c2042b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -114,6 +114,16 @@ void sqlite3Error(sqlite3 *db, int err_code){
if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
}
+/*
+** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state
+** and error message.
+*/
+void sqlite3ErrorClear(sqlite3 *db){
+ assert( db!=0 );
+ db->errCode = SQLITE_OK;
+ if( db->pErr ) sqlite3ValueSetNull(db->pErr);
+}
+
/*
** Load the sqlite3.iSysErrno field if that is an appropriate thing
** to do based on the SQLite error code in rc.
diff --git a/src/vdbe.c b/src/vdbe.c
index 1507fb318..4442f7d9f 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -272,26 +272,39 @@ static VdbeCursor *allocateCursor(
assert( iCur>=0 && iCurnCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
- /* Before calling sqlite3VdbeFreeCursor(), ensure the isEphemeral flag
- ** is clear. Otherwise, if this is an ephemeral cursor created by
- ** OP_OpenDup, the cursor will not be closed and will still be part
- ** of a BtShared.pCursor list. */
- if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0;
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
- if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+ /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
+ ** the pMem used to hold space for the cursor has enough storage available
+ ** in pMem->zMalloc. But for the special case of the aMem[] entries used
+ ** to hold cursors, it is faster to in-line the logic. */
+ assert( pMem->flags==MEM_Undefined );
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+ if( pMem->szMallocszMalloc>0 ){
+ sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ }
+ pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
+ if( pMem->zMalloc==0 ){
+ pMem->szMalloc = 0;
+ return 0;
}
+ pMem->szMalloc = nByte;
+ }
+
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+ pCx->eCurType = eCurType;
+ pCx->iDb = iDb;
+ pCx->nField = nField;
+ pCx->aOffset = &pCx->aType[nField];
+ if( eCurType==CURTYPE_BTREE ){
+ pCx->uc.pCursor = (BtCursor*)
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
@@ -438,7 +451,10 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
- ExpandBlob(pMem);
+ if( ExpandBlob(pMem) ){
+ pMem->u.i = 0;
+ return MEM_Int;
+ }
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
if( rc<=0 ){
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
@@ -576,6 +592,11 @@ static void registerTrace(int iReg, Mem *p){
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
+/**/ void sqlite3PrintMem(Mem *pMem){
+ memTracePrint(pMem);
+ printf("\n");
+ fflush(stdout);
+}
#endif
#ifdef SQLITE_DEBUG
@@ -685,7 +706,7 @@ int sqlite3VdbeExec(
#endif
/*** INSERT STACK UNION HERE ***/
- assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
sqlite3VdbeEnter(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
@@ -1445,6 +1466,26 @@ case OP_IntCopy: { /* out2 */
break;
}
+/* Opcode: ChngCntRow P1 P2 * * *
+** Synopsis: output=r[P1]
+**
+** Output value in register P1 as the chance count for a DML statement,
+** due to the "PRAGMA count_changes=ON" setting. Or, if there was a
+** foreign key error in the statement, trigger the error now.
+**
+** This opcode is a variant of OP_ResultRow that checks the foreign key
+** immediate constraint count and throws an error if the count is
+** non-zero. The P2 opcode must be 1.
+*/
+case OP_ChngCntRow: {
+ assert( pOp->p2==1 );
+ if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ /* Fall through to the next case, OP_ResultRow */
+ /* no break */ deliberate_fall_through
+}
+
/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
@@ -1458,37 +1499,9 @@ case OP_ResultRow: {
Mem *pMem;
int i;
assert( p->nResColumn==pOp->p2 );
- assert( pOp->p1>0 );
+ assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
- /* If this statement has violated immediate foreign key constraints, do
- ** not return the number of rows modified. And do not RELEASE the statement
- ** transaction. It needs to be rolled back. */
- if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
- assert( db->flags&SQLITE_CountRows );
- assert( p->usesStmtJournal );
- goto abort_due_to_error;
- }
-
- /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
- ** DML statements invoke this opcode to return the number of rows
- ** modified to the user. This is the only way that a VM that
- ** opens a statement transaction may invoke this opcode.
- **
- ** In case this is such a statement, close any statement transaction
- ** opened by this VM before returning control to the user. This is to
- ** ensure that statement-transactions are always nested, not overlapping.
- ** If the open statement-transaction is not closed here, then the user
- ** may step another VM that opens its own statement transaction. This
- ** may lead to overlapping statement transactions.
- **
- ** The statement transaction is never a top-level transaction. Hence
- ** the RELEASE call below can never fail.
- */
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
- assert( rc==SQLITE_OK );
-
/* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
@@ -1928,8 +1941,7 @@ case OP_Cast: { /* in1 */
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then
-** store the result of comparison in register P2.
+** jump to address P2.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
@@ -1955,9 +1967,8 @@ case OP_Cast: { /* in1 */
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 0 (false).
-** In other words, a prior r[P2] value will not be overwritten by 1 (true).
+** This opcode saves the result of comparison for use by the new
+** OP_Jump opcode.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
@@ -1965,17 +1976,12 @@ case OP_Cast: { /* in1 */
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Eq opcode for
** additional information.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 1 (true).
-** In other words, a prior r[P2] value will not be overwritten by 0 (false).
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
+ if( (flags1 & flags3 & MEM_Int)!=0 ){
+ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
+ /* Common case of comparison of two integers */
+ if( pIn3->u.i > pIn1->u.i ){
+ iCompare = +1;
+ if( sqlite3aGTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else if( pIn3->u.i < pIn1->u.i ){
+ iCompare = -1;
+ if( sqlite3aLTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else{
+ iCompare = 0;
+ if( sqlite3aEQb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }
+ VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ break;
+ }
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -2057,22 +2091,16 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = 1; /* Operands are not equal */
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(2,3);
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- goto jump_to_p2;
- }
+ iCompare = 1; /* Operands are not equal */
+ VdbeBranchTaken(2,3);
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ goto jump_to_p2;
}
break;
}
}else{
- /* Neither operand is NULL. Do a comparison. */
+ /* Neither operand is NULL and we couldn't do the special high-speed
+ ** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
@@ -2085,14 +2113,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
applyNumericAffinity(pIn3,0);
}
}
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
@@ -2115,7 +2135,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-compare_op:
+
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
@@ -2124,16 +2144,14 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** order: NE, EQ, GT, LE, LT, GE */
assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
- if( res<0 ){ /* ne, eq, gt, le, lt, ge */
- static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
- res2 = aLTb[pOp->opcode - OP_Ne];
+ if( res<0 ){
+ res2 = sqlite3aLTb[pOp->opcode];
}else if( res==0 ){
- static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
- res2 = aEQb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aEQb[pOp->opcode];
}else{
- static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
- res2 = aGTb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aGTb[pOp->opcode];
}
+ iCompare = res;
/* Undo any changes made by applyAffinity() to the input registers. */
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
@@ -2141,67 +2159,39 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = res;
- if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
- /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
- ** and prevents OP_Ne from overwriting NULL with 0. This flag
- ** is only used in contexts where either:
- ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
- ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
- ** Therefore it is not necessary to check the content of r[P2] for
- ** NULL. */
- assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
- assert( res2==0 || res2==1 );
- testcase( res2==0 && pOp->opcode==OP_Eq );
- testcase( res2==1 && pOp->opcode==OP_Eq );
- testcase( res2==0 && pOp->opcode==OP_Ne );
- testcase( res2==1 && pOp->opcode==OP_Ne );
- if( (pOp->opcode==OP_Eq)==res2 ) break;
- }
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = res2;
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
- if( res2 ){
- goto jump_to_p2;
- }
+ VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ if( res2 ){
+ goto jump_to_p2;
}
break;
}
-/* Opcode: ElseNotEq * P2 * * *
+/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
-** OP_Lt or OP_Gt. Furthermore, the prior OP_Lt or OP_Gt must have the
-** SQLITE_STOREP2 bit set in the P5 field.
+** OP_Lt or OP_Gt.
**
** If result of an OP_Eq comparison on the same two operands as the
-** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
-** jump to P2. If the result of an OP_Eq comparison on the two previous
-** operands would have been true (1), then fall through.
+** prior OP_Lt or OP_Gt would have been true, then jump to P2.
+** If the result of an OP_Eq comparison on the two previous
+** operands would have been false or NULL, then fall through.
*/
-case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
+case OP_ElseEq: { /* same as TK_ESCAPE, jump */
#ifdef SQLITE_DEBUG
/* Verify the preconditions of this opcode - that it follows an OP_Lt or
- ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
- ** OP_ReleaseReg opcodes */
+ ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
int iAddr;
for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
- assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
break;
}
#endif /* SQLITE_DEBUG */
- VdbeBranchTaken(iCompare!=0, 2);
- if( iCompare!=0 ) goto jump_to_p2;
+ VdbeBranchTaken(iCompare==0, 2);
+ if( iCompare==0 ) goto jump_to_p2;
break;
}
@@ -2512,6 +2502,24 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
break;
}
+/* Opcode: ZeroOrNull P1 P2 P3 * *
+** Synopsis: r[P2] = 0 OR NULL
+**
+** If all both registers P1 and P3 are NOT NULL, then store a zero in
+** register P2. If either registers P1 or P3 are NULL then put
+** a NULL in register P2.
+*/
+case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
+ if( (aMem[pOp->p1].flags & MEM_Null)!=0
+ || (aMem[pOp->p3].flags & MEM_Null)!=0
+ ){
+ sqlite3VdbeMemSetNull(aMem + pOp->p2);
+ }else{
+ sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
+ }
+ break;
+}
+
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
@@ -3881,7 +3889,7 @@ case OP_OpenDup: {
pOrig = p->apCsr[pOp->p2];
assert( pOrig );
- assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
+ assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
@@ -3891,7 +3899,10 @@ case OP_OpenDup: {
pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
- rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pCx->pBtx = pOrig->pBtx;
+ pCx->hasBeenDuped = 1;
+ pOrig->hasBeenDuped = 1;
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
@@ -3957,9 +3968,10 @@ case OP_OpenEphemeral: {
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
- if( pCx && pCx->pBtx ){
- /* If the ephermeral table is already open, erase all existing content
- ** so that the table is empty again, rather than creating a new table. */
+ if( pCx && !pCx->hasBeenDuped ){
+ /* If the ephermeral table is already open and has no duplicates from
+ ** OP_OpenDup, then erase all existing content so that the table is
+ ** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
@@ -3973,33 +3985,36 @@ case OP_OpenEphemeral: {
vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
- BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
+ BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pKeyInfo, pCx->uc.pCursor);
+ }
+ pCx->isTable = 0;
+ }else{
+ pCx->pgnoRoot = SCHEMA_ROOT;
+ rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
+ 0, pCx->uc.pCursor);
+ pCx->isTable = 1;
}
- pCx->isTable = 0;
- }else{
- pCx->pgnoRoot = SCHEMA_ROOT;
- rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
+ }
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ if( rc ){
+ sqlite3BtreeClose(pCx->pBtx);
}
}
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
}
if( rc ) goto abort_due_to_error;
pCx->nullRow = 1;
@@ -4433,13 +4448,13 @@ case OP_SeekGT: { /* jump, in3, group */
**
** There are three possible outcomes from this opcode:
**
-** - If after This.P1 steps, the cursor is still point to a place that
-** is earlier in the btree than the target row,
-** then fall through into the subsquence OP_SeekGE opcode.
+**
- If after This.P1 steps, the cursor is still pointing to a place that
+** is earlier in the btree than the target row, then fall through
+** into the subsquence OP_SeekGE opcode.
**
**
- If the cursor is successfully moved to the target row by 0 or more
** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
-** past the OP_IdxGT opcode that follows the OP_SeekGE.
+** past the OP_IdxGT or OP_IdxGE opcode that follows the OP_SeekGE.
**
**
- If the cursor ends up past the target row (indicating the the target
** row does not exist in the btree) then jump to SeekOP.P2.
@@ -4456,7 +4471,8 @@ case OP_SeekScan: {
/* pOp->p2 points to the first instruction past the OP_IdxGT that
** follows the OP_SeekGE. */
assert( pOp->p2>=(int)(pOp-aOp)+2 );
- assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT || aOp[pOp->p2-1].opcode==OP_IdxGE );
+ testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
@@ -4560,8 +4576,18 @@ case OP_SeekHit: {
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHitp2 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
+ }
+#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
+ }
+#endif
pC->seekHit = pOp->p3;
}
break;
@@ -4676,6 +4702,11 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit is %d\n", pC->seekHit);
+ }
+#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
@@ -4909,8 +4940,10 @@ case OP_NewRowid: { /* out2 */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
+#endif
v = 0;
res = 0;
@@ -5103,7 +5136,7 @@ case OP_Insert: {
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
+ sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
}
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
/* Prevent post-update hook from running in cases when it should not */
@@ -5126,7 +5159,8 @@ case OP_Insert: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
+ seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -5143,6 +5177,33 @@ case OP_Insert: {
break;
}
+/* Opcode: RowCell P1 P2 P3 * *
+**
+** P1 and P2 are both open cursors. Both must be opened on the same type
+** of table - intkey or index. This opcode is used as part of copying
+** the current row from P2 into P1. If the cursors are opened on intkey
+** tables, register P3 contains the rowid to use with the new record in
+** P1. If they are opened on index tables, P3 is not used.
+**
+** This opcode must be followed by either an Insert or InsertIdx opcode
+** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
+*/
+case OP_RowCell: {
+ VdbeCursor *pDest; /* Cursor to write to */
+ VdbeCursor *pSrc; /* Cursor to read from */
+ i64 iKey; /* Rowid value to insert with */
+ assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
+ assert( pOp[1].opcode==OP_Insert || pOp->p3==0 );
+ assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
+ assert( pOp[1].p5 & OPFLAG_PREFORMAT );
+ pDest = p->apCsr[pOp->p1];
+ pSrc = p->apCsr[pOp->p2];
+ iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
+ rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ break;
+};
+
/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
@@ -5235,7 +5296,7 @@ case OP_Delete: {
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
- pOp->p3
+ pOp->p3, -1
);
}
if( opflags & OPFLAG_ISNOOP ) break;
@@ -5798,7 +5859,7 @@ case OP_IdxInsert: { /* in2 */
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
- assert( pIn2->flags & MEM_Blob );
+ assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isTable==0 );
@@ -5809,7 +5870,7 @@ case OP_IdxInsert: { /* in2 */
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -5882,7 +5943,7 @@ case OP_IdxDelete: {
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
}else if( pOp->p5 ){
- rc = SQLITE_CORRUPT_INDEX;
+ rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
goto abort_due_to_error;
}
assert( pC->deferredMoveto==0 );
@@ -5961,6 +6022,8 @@ case OP_IdxRowid: { /* out2 */
pTabCur->deferredMoveto = 1;
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
pTabCur->aAltMap = pOp->p4.ai;
+ assert( !pC->isEphemeral );
+ assert( !pTabCur->isEphemeral );
pTabCur->pAltCursor = pC;
}else{
pOut = out2Prerelease(p, pOp);
@@ -6179,11 +6242,10 @@ case OP_Destroy: { /* out2 */
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
-** If the P3 value is non-zero, then the table referred to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
-** If P3 is greater than zero, then the value stored in register P3 is
-** also incremented by the number of rows in the table being cleared.
+** If the P3 value is non-zero, then the row change count is incremented
+** by the number of rows in the table being cleared. If P3 is greater
+** than zero, then the value stored in register P3 is also incremented
+** by the number of rows in the table being cleared.
**
** See also: Destroy
*/
@@ -6194,9 +6256,7 @@ case OP_Clear: {
nChange = 0;
assert( p->readOnly==0 );
assert( DbMaskTest(p->btreeMask, pOp->p2) );
- rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, (u32)pOp->p1, (pOp->p3 ? &nChange : 0)
- );
+ rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange);
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
@@ -6302,13 +6362,15 @@ case OP_ParseSchema: {
iDb = pOp->p1;
assert( iDb>=0 && iDbnDb );
- assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
+ assert( DbHasProperty(db, iDb, DB_SchemaLoaded)
+ || db->mallocFailed
+ || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) );
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
- rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
+ rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
p->expired = 0;
}else
@@ -7184,6 +7246,7 @@ case OP_JournalMode: { /* out2 */
pPager = sqlite3BtreePager(pBt);
eOld = sqlite3PagerGetJournalMode(pPager);
if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+ assert( sqlite3BtreeHoldsMutex(pBt) );
if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
#ifndef SQLITE_OMIT_WAL
diff --git a/src/vdbe.h b/src/vdbe.h
index 17f11fdd7..3257ff68a 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -223,7 +223,7 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#else
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
-void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 7d22cb809..b6e028880 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -86,6 +86,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
@@ -381,7 +382,7 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- u32 magic; /* Magic number for sanity checking */
+ u32 iVdbeMagic; /* Magic number defining state of the SQL statement */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
@@ -471,6 +472,7 @@ struct PreUpdate {
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
+ int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
@@ -514,7 +516,7 @@ int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
void sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
-int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
+int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
@@ -559,7 +561,8 @@ void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
+void sqlite3VdbePreUpdateHook(
+ Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
int sqlite3VdbeTransferError(Vdbe *p);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index a9cbf92fc..5de7c64c2 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -392,7 +392,7 @@ static int invokeValueDestructor(
}else{
xDel((void*)p);
}
- if( pCtx ) sqlite3_result_error_toobig(pCtx);
+ sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
void sqlite3_result_blob(
@@ -617,7 +617,7 @@ static int sqlite3Step(Vdbe *p){
int rc;
assert(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
@@ -1333,7 +1333,7 @@ static int vdbeUnbind(Vdbe *p, int i){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
@@ -1374,7 +1374,7 @@ static int bindText(
sqlite3_stmt *pStmt, /* The statement to bind against */
int i, /* Index of the parameter to bind */
const void *zData, /* Pointer to the data to be bound */
- int nData, /* Number of bytes of data to be bound */
+ i64 nData, /* Number of bytes of data to be bound */
void (*xDel)(void*), /* Destructor for the data */
u8 encoding /* Encoding for the data */
){
@@ -1426,11 +1426,7 @@ int sqlite3_bind_blob64(
void (*xDel)(void*)
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- return bindText(pStmt, i, zData, (int)nData, xDel, 0);
- }
+ return bindText(pStmt, i, zData, nData, xDel, 0);
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
@@ -1500,12 +1496,8 @@ int sqlite3_bind_text64(
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- return bindText(pStmt, i, zData, (int)nData, xDel, enc);
- }
+ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
+ return bindText(pStmt, i, zData, nData, xDel, enc);
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
@@ -1687,7 +1679,7 @@ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
*/
int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
- return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
+ return v!=0 && v->iVdbeMagic==VDBE_MAGIC_RUN && v->pc>=0;
}
/*
@@ -1905,6 +1897,17 @@ int sqlite3_preupdate_depth(sqlite3 *db){
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+/*
+** This function is designed to be called from within a pre-update callback
+** only.
+*/
+int sqlite3_preupdate_blobwrite(sqlite3 *db){
+ PreUpdate *p = db->pPreUpdate;
+ return (p ? p->iBlobWrite : -1);
+}
+#endif
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index dfd259d71..d22a6a559 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -35,7 +35,7 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
+ p->iVdbeMagic = VDBE_MAGIC_INIT;
p->pParse = pParse;
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
@@ -236,7 +236,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
VdbeOp *pOp;
i = p->nOp;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
@@ -471,9 +471,10 @@ void sqlite3VdbeExplainPop(Parse *pParse){
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
-void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(p, p5);
for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j);
sqlite3MayAbort(p->pParse);
}
@@ -565,7 +566,7 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
- assert( v->magic==VDBE_MAGIC_INIT );
+ assert( v->iVdbeMagic==VDBE_MAGIC_INIT );
assert( j<-p->nLabel );
assert( j>=0 );
#ifdef SQLITE_DEBUG
@@ -890,7 +891,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** Return the address of the next instruction to be inserted.
*/
int sqlite3VdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
return p->nOp;
}
@@ -975,7 +976,7 @@ VdbeOp *sqlite3VdbeAddOpList(
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
@@ -1299,7 +1300,7 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
sqlite3 *db;
assert( p!=0 );
db = p->db;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( p->aOp!=0 || db->mallocFailed );
if( db->mallocFailed ){
if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
@@ -1428,7 +1429,7 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
if( addr<0 ){
addr = p->nOp - 1;
}
@@ -1486,11 +1487,7 @@ char *sqlite3VdbeDisplayComment(
char c;
zSynopsis = zOpName += nOpName + 1;
if( strncmp(zSynopsis,"IF ",3)==0 ){
- if( pOp->p5 & SQLITE_STOREP2 ){
- sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
- }else{
- sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
- }
+ sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
zSynopsis = zAlt;
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
@@ -2113,7 +2110,7 @@ int sqlite3VdbeList(
Op *pOp; /* Current opcode */
assert( p->explain );
- assert( p->magic==VDBE_MAGIC_RUN );
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@@ -2293,14 +2290,14 @@ void sqlite3VdbeRewind(Vdbe *p){
int i;
#endif
assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT || p->iVdbeMagic==VDBE_MAGIC_RESET );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
- p->magic = VDBE_MAGIC_RUN;
+ p->iVdbeMagic = VDBE_MAGIC_RUN;
#ifdef SQLITE_DEBUG
for(i=0; inMem; i++){
@@ -2356,8 +2353,10 @@ void sqlite3VdbeMakeReady(
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( pParse==p->pParse );
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -2442,8 +2441,6 @@ void sqlite3VdbeMakeReady(
}
}
- p->pVList = pParse->pVList;
- pParse->pVList = 0;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
@@ -2471,20 +2468,15 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
return;
}
assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
+ assert( pCx->pBtx==0 || pCx->isEphemeral );
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->isEphemeral ){
- if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
- /* The pCx->pCursor will be close automatically, if it exists, by
- ** the call above. */
- }else{
- assert( pCx->uc.pCursor!=0 );
- sqlite3BtreeCloseCursor(pCx->uc.pCursor);
- }
+ assert( pCx->uc.pCursor!=0 );
+ sqlite3BtreeCloseCursor(pCx->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -3041,7 +3033,7 @@ int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
if( db->mallocFailed ){
@@ -3199,7 +3191,7 @@ int sqlite3VdbeHalt(Vdbe *p){
assert( db->nVdbeRead>=db->nVdbeWrite );
assert( db->nVdbeWrite>=0 );
}
- p->magic = VDBE_MAGIC_HALT;
+ p->iVdbeMagic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
@@ -3372,7 +3364,7 @@ int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->magic = VDBE_MAGIC_RESET;
+ p->iVdbeMagic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -3382,7 +3374,7 @@ int sqlite3VdbeReset(Vdbe *p){
*/
int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
- if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
+ if( p->iVdbeMagic==VDBE_MAGIC_RUN || p->iVdbeMagic==VDBE_MAGIC_HALT ){
rc = sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}
@@ -3443,7 +3435,7 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
- if( p->magic!=VDBE_MAGIC_INIT ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
@@ -3491,7 +3483,7 @@ void sqlite3VdbeDelete(Vdbe *p){
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
- p->magic = VDBE_MAGIC_DEAD;
+ p->iVdbeMagic = VDBE_MAGIC_DEAD;
p->db = 0;
sqlite3DbFreeNN(db, p);
}
@@ -3568,6 +3560,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){
assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
if( p->deferredMoveto ){
u32 iMap;
+ assert( !p->isEphemeral );
if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
*pp = p->pAltCursor;
*piCol = iMap - 1;
@@ -5196,7 +5189,8 @@ void sqlite3VdbePreUpdateHook(
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
- int iReg /* Register for new.* record */
+ int iReg, /* Register for new.* record */
+ int iBlobWrite
){
sqlite3 *db = v->db;
i64 iKey2;
@@ -5232,6 +5226,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
+ preupdate.iBlobWrite = iBlobWrite;
db->pPreUpdate = &preupdate;
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index d34e3cf9f..a4e79bf89 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -420,7 +420,7 @@ static int blobReadWrite(
sqlite3_int64 iKey;
iKey = sqlite3BtreeIntegerKey(p->pCsr);
sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
+ v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
#endif
@@ -491,6 +491,7 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
rc = SQLITE_ABORT;
}else{
char *zErr;
+ ((Vdbe*)p->pStmt)->rc = SQLITE_OK;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 384eacc01..dc177161b 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -75,7 +75,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
- || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
+ || (p->flags==MEM_Undefined
+ && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
+ || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@@ -239,7 +241,9 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
+ || (pMem->flags==MEM_Undefined
+ && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+ || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
@@ -1068,11 +1072,11 @@ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
+ i64 n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
- int nByte = n; /* New value for pMem->n */
+ i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
u16 flags = 0; /* New value for pMem->flags */
@@ -1094,7 +1098,7 @@ int sqlite3VdbeMemSetStr(
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
- nByte = 0x7fffffff & (int)strlen(z);
+ nByte = strlen(z);
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
}
@@ -1106,7 +1110,7 @@ int sqlite3VdbeMemSetStr(
** management (one of MEM_Dyn or MEM_Static).
*/
if( xDel==SQLITE_TRANSIENT ){
- u32 nAlloc = nByte;
+ i64 nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
@@ -1132,7 +1136,7 @@ int sqlite3VdbeMemSetStr(
}
}
- pMem->n = nByte;
+ pMem->n = (int)(nByte & 0x7fffffff);
pMem->flags = flags;
if( enc ){
pMem->enc = enc;
@@ -1152,7 +1156,7 @@ int sqlite3VdbeMemSetStr(
#endif
if( nByte>iLimit ){
- return SQLITE_TOOBIG;
+ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
}
return SQLITE_OK;
diff --git a/src/vdbesort.c b/src/vdbesort.c
index f61b8b732..397935aa8 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -1073,8 +1073,9 @@ static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){
fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
}
static void vdbeSorterRewindDebug(const char *zEvent){
- i64 t;
- sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
+ i64 t = 0;
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
+ if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t);
fprintf(stderr, "%lld:X %s\n", t, zEvent);
}
static void vdbeSorterPopulateDebug(
diff --git a/src/vdbetrace.c b/src/vdbetrace.c
index 32c66af22..1095e7f58 100644
--- a/src/vdbetrace.c
+++ b/src/vdbetrace.c
@@ -125,7 +125,7 @@ char *sqlite3VdbeExpandSql(
assert( idx>0 );
}
zRawSql += nToken;
- nextIndex = idx + 1;
+ nextIndex = MAX(idx + 1, nextIndex);
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
diff --git a/src/vtab.c b/src/vtab.c
index b2c01f2fa..c9dcadae4 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -489,7 +489,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp0(v, OP_Expire);
zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
@@ -660,6 +660,7 @@ static int vtabCallConstructor(
zType[i-1] = '\0';
}
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
+ pTab->tabFlags |= TF_HasHidden;
oooHidden = TF_OOOHidden;
}else{
pTab->tabFlags |= oooHidden;
@@ -828,7 +829,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Table *pNew = sParse.pNewTable;
Index *pIdx;
pTab->aCol = pNew->aCol;
- pTab->nCol = pNew->nCol;
+ pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
pNew->nCol = 0;
pNew->aCol = 0;
@@ -1220,6 +1221,7 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 );
pTab->iPKey = -1;
+ pTab->tabFlags |= TF_Eponymous;
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
diff --git a/src/wal.c b/src/wal.c
index ac0a03e93..c3f84dd2e 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -999,7 +999,6 @@ static void walCleanupHash(Wal *pWal){
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
- int rc; /* Return code form walHashGet() */
assert( pWal->writeLock );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
@@ -1014,8 +1013,8 @@ static void walCleanupHash(Wal *pWal){
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
- if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */
+ i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
+ if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
diff --git a/src/walker.c b/src/walker.c
index 7649036f5..8c0308473 100644
--- a/src/walker.c
+++ b/src/walker.c
@@ -22,7 +22,7 @@
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
-static int walkWindowList(Walker *pWalker, Window *pList){
+static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
Window *pWin;
for(pWin=pList; pWin; pWin=pWin->pNextWin){
int rc;
@@ -32,15 +32,11 @@ static int walkWindowList(Walker *pWalker, Window *pList){
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
-
- /* The next two are purely for calls to sqlite3RenameExprUnmap()
- ** within sqlite3WindowOffsetExpr(). Because of constraints imposed
- ** by sqlite3WindowOffsetExpr(), they can never fail. The results do
- ** not matter anyhow. */
rc = sqlite3WalkExpr(pWalker, pWin->pStart);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
+ if( bOneOnly ) break;
}
return WRC_Continue;
}
@@ -88,7 +84,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
+ if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort;
}
#endif
}
@@ -116,6 +112,16 @@ int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
return WRC_Continue;
}
+/*
+** This is a no-op callback for Walker->xSelectCallback2. If this
+** callback is set, then the Select->pWinDefn list is traversed.
+*/
+void sqlite3WalkWinDefnDummyCallback(Walker *pWalker, Select *p){
+ UNUSED_PARAMETER(pWalker);
+ UNUSED_PARAMETER(p);
+ /* No-op */
+}
+
/*
** Walk all expressions associated with SELECT statement p. Do
** not invoke the SELECT callback on p, but do (of course) invoke
@@ -129,13 +135,18 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
-#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
- {
- Parse *pParse = pWalker->pParse;
- if( pParse && IN_RENAME_OBJECT ){
+#if !defined(SQLITE_OMIT_WINDOWFUNC)
+ if( p->pWinDefn ){
+ Parse *pParse;
+ if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
+ || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
+#ifndef SQLITE_OMIT_CTE
+ || pWalker->xSelectCallback2==sqlite3SelectPopWith
+#endif
+ ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
- int rc = walkWindowList(pWalker, p->pWinDefn);
+ int rc = walkWindowList(pWalker, p->pWinDefn, 0);
return rc;
}
}
@@ -153,10 +164,10 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcList *pSrc;
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pSrc = p->pSrc;
- if( pSrc ){
+ if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
@@ -169,7 +180,7 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
}
}
return WRC_Continue;
-}
+}
/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
diff --git a/src/where.c b/src/where.c
index 2b97114e6..5315520db 100644
--- a/src/where.c
+++ b/src/where.c
@@ -37,12 +37,6 @@ struct HiddenIndexInfo {
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
-/* Test variable that can be set to enable WHERE tracing */
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlite3WhereTrace = 0;
-#endif
-
-
/*
** Return the estimated number of output rows from a WHERE clause
*/
@@ -105,6 +99,32 @@ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){
return pInner->addrNxt;
}
+/*
+** While generating code for the min/max optimization, after handling
+** the aggregate-step call to min() or max(), check to see if any
+** additional looping is required. If the output order is such that
+** we are certain that the correct answer has already been found, then
+** code an OP_Goto to by pass subsequent processing.
+**
+** Any extra OP_Goto that is coded here is an optimization. The
+** correct answer should be obtained regardless. This OP_Goto just
+** makes the answer appear faster.
+*/
+void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
+ WhereLevel *pInner;
+ int i;
+ if( !pWInfo->bOrderedInnerLoop ) return;
+ if( pWInfo->nOBSat==0 ) return;
+ for(i=pWInfo->nLevel-1; i>=0; i--){
+ pInner = &pWInfo->a[i];
+ if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
+ sqlite3VdbeGoto(v, pInner->addrNxt);
+ return;
+ }
+ }
+ sqlite3VdbeGoto(v, pWInfo->iBreak);
+}
+
/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
@@ -241,7 +261,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlite3ExprSkipCollateAndLikely(p->pRight);
- if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
+ return p;
+ }
return 0;
}
@@ -316,6 +338,18 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
pScan->pWC = pWC;
pScan->k = k+1;
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ int ii;
+ sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
+ pTerm, pScan->nEquiv);
+ for(ii=0; iinEquiv; ii++){
+ sqlite3DebugPrintf(" {%d:%d}",
+ pScan->aiCur[ii], pScan->aiColumn[ii]);
+ }
+ sqlite3DebugPrintf("\n");
+ }
+#endif
return pTerm;
}
}
@@ -472,7 +506,7 @@ static int findIndexCol(
for(i=0; inExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( ALWAYS(p!=0)
- && p->op==TK_COLUMN
+ && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -537,7 +571,8 @@ static int isDistinctRedundant(
for(i=0; inExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
- if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+ if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
+ if( p->iTable==iBase && p->iColumn<0 ) return 1;
}
/* Loop through all indices on the table, checking each to see if it makes
@@ -555,6 +590,7 @@ static int isDistinctRedundant(
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !IsUniqueIndex(pIdx) ) continue;
+ if( pIdx->pPartIdxWhere ) continue;
for(i=0; inKeyCol; i++){
if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
@@ -609,14 +645,14 @@ static void translateColumnToCopy(
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
- if( iAutoidxCur ){
- pOp->opcode = OP_Sequence;
- pOp->p1 = iAutoidxCur;
- }else{
+ pOp->opcode = OP_Sequence;
+ pOp->p1 = iAutoidxCur;
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
- pOp->p1 = 0;
pOp->p3 = 0;
}
+#endif
}
}
}
@@ -674,7 +710,7 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
*/
static int termCanDriveIndex(
WhereTerm *pTerm, /* WHERE clause term to check */
- struct SrcList_item *pSrc, /* Table we are trying to access */
+ SrcItem *pSrc, /* Table we are trying to access */
Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
@@ -708,7 +744,7 @@ static int termCanDriveIndex(
static void constructAutomaticIndex(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
+ SrcItem *pSrc, /* The FROM clause term to get the next index */
Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
@@ -732,7 +768,7 @@ static void constructAutomaticIndex(
u8 sentWarning = 0; /* True if a warnning has been issued */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
- struct SrcList_item *pTabItem; /* FROM clause term being indexed */
+ SrcItem *pTabItem; /* FROM clause term being indexed */
int addrCounter = 0; /* Address where integer counter is initialized */
int regBase; /* Array of registers where record is assembled */
@@ -781,7 +817,7 @@ static void constructAutomaticIndex(
}
}
}
- assert( nKeyCol>0 );
+ assert( nKeyCol>0 || pParse->db->mallocFailed );
pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
| WHERE_AUTO_INDEX;
@@ -916,7 +952,7 @@ static sqlite3_index_info *allocateIndexInfo(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause being analyzed */
Bitmask mUnusable, /* Ignore terms with these prereqs */
- struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */
+ SrcItem *pSrc, /* The FROM clause term that is the vtab */
ExprList *pOrderBy, /* The ORDER BY clause */
u16 *pmNoOmit /* Mask of terms not to omit */
){
@@ -1814,7 +1850,7 @@ void sqlite3WhereClausePrint(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;
+ SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
Table *pTab = pItem->pTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
@@ -1918,7 +1954,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
whereLoopClearUnion(db, pTo);
if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
- memset(&pTo->u, 0, sizeof(pTo->u));
+ memset(pTo, 0, WHERE_LOOP_XFER_SZ);
return SQLITE_NOMEM_BKPT;
}
memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
@@ -1961,6 +1997,17 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
sqlite3DbFreeNN(db, pWInfo);
}
+/* Undo all Expr node modifications
+*/
+static void whereUndoExprMods(WhereInfo *pWInfo){
+ while( pWInfo->pExprMods ){
+ WhereExprMod *p = pWInfo->pExprMods;
+ pWInfo->pExprMods = p->pNext;
+ memcpy(p->pExpr, &p->orig, sizeof(p->orig));
+ sqlite3DbFree(pWInfo->pParse->db, p);
+ }
+}
+
/*
** Return TRUE if all of the following are true:
**
@@ -2425,7 +2472,7 @@ static int whereRangeVectorLen(
*/
static int whereLoopAddBtreeIndex(
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
- struct SrcList_item *pSrc, /* FROM clause term being analyzed */
+ SrcItem *pSrc, /* FROM clause term being analyzed */
Index *pProbe, /* An index on pSrc */
LogEst nInMul /* log(Number of iterations due to IN) */
){
@@ -2466,6 +2513,8 @@ static int whereLoopAddBtreeIndex(
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEqnColumn );
+ assert( pNew->u.btree.nEqnKeyCol
+ || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
@@ -2548,7 +2597,7 @@ static int whereLoopAddBtreeIndex(
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
if( pProbe->hasStat1 && rLogSize>=10 ){
- LogEst M, logK, safetyMargin;
+ LogEst M, logK, x;
/* Let:
** N = the total number of rows in the table
** K = the number of entries on the RHS of the IN operator
@@ -2571,16 +2620,25 @@ static int whereLoopAddBtreeIndex(
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
- safetyMargin = 10; /* TUNING: extra weight for indexed IN */
- if( M + logK + safetyMargin < nIn + rLogSize ){
+ /* TUNING v----- 10 to bias toward indexed IN */
+ x = M + logK + 10 - (nIn + rLogSize);
+ if( x>=0 ){
WHERETRACE(0x40,
- ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
- saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d) "
+ "prefers indexed lookup\n",
+ saved_nEq, M, logK, nIn, rLogSize, x));
+ }else if( nInMul<2 && OptimizationEnabled(db, SQLITE_SeekScan) ){
+ WHERETRACE(0x40,
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
+ " nInMul=%d) prefers skip-scan\n",
+ saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
- ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
- saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
+ " nInMul=%d) prefers normal scan\n",
+ saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
+ continue;
}
}
pNew->wsFlags |= WHERE_COLUMN_IN;
@@ -2599,6 +2657,7 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
+ if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
}else if( eOp & WO_ISNULL ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
}else if( eOp & (WO_GT|WO_GE) ){
@@ -2611,7 +2670,7 @@ static int whereLoopAddBtreeIndex(
pBtm = pTerm;
pTop = 0;
if( pTerm->wtFlags & TERM_LIKEOPT ){
- /* Range contraints that come from the LIKE optimization are
+ /* Range constraints that come from the LIKE optimization are
** always used in pairs. */
pTop = &pTerm[1];
assert( (pTop-(pTerm->pWC->a))pWC->nTerm );
@@ -2660,7 +2719,7 @@ static int whereLoopAddBtreeIndex(
tRowcnt nOut = 0;
if( nInMul==0
&& pProbe->nSample
- && pNew->u.btree.nEq<=pProbe->nSampleCol
+ && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
&& OptimizationEnabled(db, SQLITE_Stat4)
){
@@ -2742,6 +2801,8 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEqnColumn
+ && (pNew->u.btree.nEqnKeyCol ||
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
@@ -2862,7 +2923,8 @@ static int whereUsablePartialIndex(
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
&& (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
- && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
}
@@ -2916,7 +2978,7 @@ static int whereLoopAddBtree(
LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */
i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */
SrcList *pTabList; /* The FROM clause */
- struct SrcList_item *pSrc; /* The FROM clause btree term to add */
+ SrcItem *pSrc; /* The FROM clause btree term to add */
WhereLoop *pNew; /* Template WhereLoop object */
int rc = SQLITE_OK; /* Return code */
int iSortIdx = 1; /* Index number */
@@ -2934,9 +2996,9 @@ static int whereLoopAddBtree(
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
- if( pSrc->pIBIndex ){
+ if( pSrc->fg.isIndexedBy ){
/* An INDEXED BY clause specifies a particular index to use */
- pProbe = pSrc->pIBIndex;
+ pProbe = pSrc->u2.pIBIndex;
}else if( !HasRowid(pTab) ){
pProbe = pTab->pIndex;
}else{
@@ -2972,7 +3034,7 @@ static int whereLoopAddBtree(
if( !pBuilder->pOrSet /* Not part of an OR optimization */
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
- && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
+ && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
@@ -3022,7 +3084,7 @@ static int whereLoopAddBtree(
/* Loop over all indices. If there was an INDEXED BY clause, then only
** consider index pProbe. */
for(; rc==SQLITE_OK && pProbe;
- pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
+ pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
){
int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0;
if( pProbe->pPartIdxWhere!=0
@@ -3197,7 +3259,7 @@ static int whereLoopAddVirtualOne(
int rc = SQLITE_OK;
WhereLoop *pNew = pBuilder->pNew;
Parse *pParse = pBuilder->pWInfo->pParse;
- struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
+ SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
int nConstraint = pIdxInfo->nConstraint;
assert( (mUsable & mPrereq)==mPrereq );
@@ -3389,7 +3451,7 @@ static int whereLoopAddVirtual(
WhereInfo *pWInfo; /* WHERE analysis context */
Parse *pParse; /* The parsing context */
WhereClause *pWC; /* The WHERE clause */
- struct SrcList_item *pSrc; /* The FROM clause term to search */
+ SrcItem *pSrc; /* The FROM clause term to search */
sqlite3_index_info *p; /* Object to pass to xBestIndex() */
int nConstraint; /* Number of constraints in p */
int bIn; /* True if plan uses IN(...) operator */
@@ -3517,7 +3579,7 @@ static int whereLoopAddOr(
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereOrSet sSum, sCur;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
@@ -3573,7 +3635,9 @@ static int whereLoopAddOr(
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
- assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0
+ || rc==SQLITE_NOMEM );
+ testcase( rc==SQLITE_NOMEM && sCur.n>0 );
testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
@@ -3633,8 +3697,8 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
- struct SrcList_item *pItem;
- struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel];
+ SrcItem *pItem;
+ SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
WhereLoop *pNew;
@@ -3657,7 +3721,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
- struct SrcList_item *p;
+ SrcItem *p;
for(p=&pItem[1]; pfg.jointype & (JT_LEFT|JT_CROSS)) ){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
@@ -3802,7 +3866,7 @@ static i8 wherePathSatisfiesOrderBy(
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( NEVER(pOBExpr==0) ) continue;
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, eqOpMask, 0);
@@ -3842,6 +3906,10 @@ static i8 wherePathSatisfiesOrderBy(
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
+ /* All relevant terms of the index must also be non-NULL in order
+ ** for isOrderDistinct to be true. So the isOrderDistint value
+ ** computed here might be a false positive. Corrections will be
+ ** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
@@ -3909,15 +3977,19 @@ static i8 wherePathSatisfiesOrderBy(
}
/* An unconstrained column that might be NULL means that this
- ** WhereLoop is not well-ordered
+ ** WhereLoop is not well-ordered. tag-20210426-1
*/
- if( isOrderDistinct
- && iColumn>=0
- && j>=pLoop->u.btree.nEq
- && pIndex->pTable->aCol[iColumn].notNull==0
- ){
- isOrderDistinct = 0;
- }
+ if( isOrderDistinct ){
+ if( iColumn>=0
+ && j>=pLoop->u.btree.nEq
+ && pIndex->pTable->aCol[iColumn].notNull==0
+ ){
+ isOrderDistinct = 0;
+ }
+ if( iColumn==XN_EXPR ){
+ isOrderDistinct = 0;
+ }
+ }
/* Find the ORDER BY term that corresponds to the j-th column
** of the index and mark that ORDER BY term off
@@ -3931,7 +4003,7 @@ static i8 wherePathSatisfiesOrderBy(
if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
@@ -4100,7 +4172,7 @@ static LogEst whereSortingCost(
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
- if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
+ if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -4512,7 +4584,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
*/
static int whereShortCut(WhereLoopBuilder *pBuilder){
WhereInfo *pWInfo;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
WhereClause *pWC;
WhereTerm *pTerm;
WhereLoop *pLoop;
@@ -4971,7 +5043,7 @@ WhereInfo *sqlite3WhereBegin(
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
pWInfo->revMask = ALLBITS;
}
- if( pParse->nErr || NEVER(db->mallocFailed) ){
+ if( pParse->nErr || db->mallocFailed ){
goto whereBeginError;
}
#ifdef WHERETRACE_ENABLED
@@ -5032,7 +5104,8 @@ WhereInfo *sqlite3WhereBegin(
*/
notReady = ~(Bitmask)0;
if( pWInfo->nLevel>=2
- && pResultSet!=0 /* guarantees condition (1) above */
+ && pResultSet!=0 /* these two combine to guarantee */
+ && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
int i;
@@ -5042,7 +5115,7 @@ WhereInfo *sqlite3WhereBegin(
}
for(i=pWInfo->nLevel-1; i>=1; i--){
WhereTerm *pTerm, *pEnd;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
@@ -5132,7 +5205,7 @@ WhereInfo *sqlite3WhereBegin(
for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom];
pTab = pTabItem->pTab;
@@ -5291,6 +5364,8 @@ WhereInfo *sqlite3WhereBegin(
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
+ testcase( pWInfo->pExprMods!=0 );
+ whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
}
@@ -5387,6 +5462,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+ assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
+ || pParse->db->mallocFailed );
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
@@ -5411,6 +5488,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
+ /* Retarget the OP_IsNull against the left operand of IN so
+ ** it jumps past the OP_IfNoHope. This is because the
+ ** OP_IsNull also bypasses the OP_Affinity opcode that is
+ ** required by OP_IfNoHope. */
+ sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
@@ -5469,7 +5551,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
int k, last;
VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
- struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
@@ -5545,7 +5627,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
- assert( pOpp1!=pLevel->iTabCur ){
/* no-op */
@@ -5590,16 +5672,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
- /* Undo all Expr node modifications */
- while( pWInfo->pExprMods ){
- WhereExprMod *p = pWInfo->pExprMods;
- pWInfo->pExprMods = p->pNext;
- memcpy(p->pExpr, &p->orig, sizeof(p->orig));
- sqlite3DbFree(db, p);
- }
-
/* Final cleanup
*/
+ if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
return;
diff --git a/src/whereInt.h b/src/whereInt.h
index 6c969af9c..c5dd83cc8 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -17,19 +17,6 @@
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H
-/*
-** Trace output macros
-*/
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ extern int sqlite3WhereTrace;
-#endif
-#if defined(SQLITE_DEBUG) \
- && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
-# define WHERETRACE_ENABLED 1
-#else
-# define WHERETRACE(K,X)
-#endif
/* Forward references
*/
@@ -283,11 +270,7 @@ struct WhereTerm {
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT4
-# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
-#else
-# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
-#endif
+#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x0400 /* The original LIKE operator */
@@ -310,8 +293,8 @@ struct WhereScan {
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
- unsigned char nEquiv; /* Number of entries in aEquiv[] */
- unsigned char iEquiv; /* Next unused slot in aEquiv[] */
+ unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
+ unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */
int aiCur[11]; /* Cursors in the equivalence class */
@@ -557,7 +540,7 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
-void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
+void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
@@ -620,5 +603,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
+#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
#endif /* !defined(SQLITE_WHEREINT_H) */
diff --git a/src/wherecode.c b/src/wherecode.c
index 4afe0ac9c..84fa1a141 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -129,7 +129,7 @@ int sqlite3WhereExplainOneScan(
if( sqlite3ParseToplevel(pParse)->explain==2 )
#endif
{
- struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
@@ -148,16 +148,8 @@ int sqlite3WhereExplainOneScan(
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
- if( pItem->pSelect ){
- sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId);
- }else{
- sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
- }
-
- if( pItem->zAlias ){
- sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
- }
+ str.printfFlags = SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
@@ -305,6 +297,12 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
}else{
pTerm->wtFlags |= TERM_CODED;
}
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x20000 ){
+ sqlite3DebugPrintf("DISABLE-");
+ sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
+ }
+#endif
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
@@ -622,7 +620,22 @@ static int codeEqualityTerm(
sqlite3DbFree(pParse->db, aiMap);
#endif
}
- disableTerm(pLevel, pTerm);
+
+ /* As an optimization, try to disable the WHERE clause term that is
+ ** driving the index as it will always be true. The correct answer is
+ ** obtained regardless, but we might get the answer with fewer CPU cycles
+ ** by omitting the term.
+ **
+ ** But do not disable the term unless we are certain that the term is
+ ** not a transitive constraint. For an example of where that does not
+ ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
+ */
+ if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
+ || (pTerm->eOperator & WO_EQUIV)==0
+ ){
+ disableTerm(pLevel, pTerm);
+ }
+
return iReg;
}
@@ -708,6 +721,7 @@ static int codeAllEqualityTerms(
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1);
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
@@ -742,7 +756,7 @@ static int codeAllEqualityTerms(
sqlite3ReleaseTempReg(pParse, regBase);
regBase = r1;
}else{
- sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
+ sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
}
}
if( pTerm->eOperator & WO_IN ){
@@ -759,7 +773,7 @@ static int codeAllEqualityTerms(
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
- if( zAff ){
+ if( pParse->db->mallocFailed==0 && pParse->nErr==0 ){
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
@@ -922,7 +936,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
- struct SrcList_item *pTabItem, /* FROM clause item */
+ SrcItem *pTabItem, /* FROM clause item */
WhereInfo *pWInfo, /* The where clause */
WhereLevel *pLevel, /* Which loop to provide hints for */
WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
@@ -1108,7 +1122,7 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
}
}
}else{
- assert( nReg==1 );
+ assert( nReg==1 || pParse->nErr );
sqlite3ExprCode(pParse, p, iReg);
}
}
@@ -1297,7 +1311,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
sqlite3 *db; /* Database connection */
- struct SrcList_item *pTabItem; /* FROM clause term being coded */
+ SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
@@ -1735,14 +1749,18 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( (nEqnKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nKeyCol==nEq)
- ){
+ if( (nEqnColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
}
+ if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
+ /* In case OP_SeekScan is used, ensure that the index cursor does not
+ ** point to a valid row for the first iteration of this loop. */
+ sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+ }
+
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
@@ -2079,7 +2097,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
*/
if( pWInfo->nLevel>1 ){
int nNotReady; /* The number of notReady tables */
- struct SrcList_item *origSrc; /* Original list of tables */
+ SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
pOrTab = sqlite3StackAllocRaw(db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
@@ -2152,7 +2170,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlite3PExpr() false, and this
- ** prevents sqlite3PExpr() from implementing AND short-circuit
+ ** prevents sqlite3PExpr() from applying the AND short-circuit
** optimization, which we do not want here. */
pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
}
@@ -2168,10 +2186,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
+ Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pOrExpr, EP_FromJoin)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
+ pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDelete);
+ continue;
+ }
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -2286,6 +2310,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
+ sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
@@ -2450,6 +2475,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
+ pAlt->wtFlags |= TERM_CODED;
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
diff --git a/src/whereexpr.c b/src/whereexpr.c
index a77eb3610..31f2ea438 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -511,6 +511,7 @@ static void whereCombineDisjuncts(
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
+ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
@@ -871,7 +872,7 @@ static void exprAnalyzeOrTerm(
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
- /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
+ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlite3ExprListDelete(db, pList);
@@ -995,6 +996,7 @@ static int exprMightBeIndexed(
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
pExpr = pExpr->x.pList->a[0].pExpr;
+
}
if( pExpr->op==TK_COLUMN ){
@@ -1007,6 +1009,7 @@ static int exprMightBeIndexed(
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
+
/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
@@ -1105,6 +1108,7 @@ static void exprAnalyze(
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
+ && !ExprHasProperty(pRight, EP_FixedCol)
){
WhereTerm *pNew;
Expr *pDup;
@@ -1140,6 +1144,12 @@ static void exprAnalyze(
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
+ }else if( op==TK_ISNULL && 0==sqlite3ExprCanBeNull(pLeft) ){
+ pExpr->op = TK_TRUEFALSE;
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ pTerm->prereqAll = 0;
+ pTerm->eOperator = 0;
}
}
@@ -1191,6 +1201,42 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+ /* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
+ ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
+ ** virtual term of that form.
+ **
+ ** The virtual term must be tagged with TERM_VNULL.
+ */
+ else if( pExpr->op==TK_NOTNULL ){
+ if( pExpr->pLeft->op==TK_COLUMN
+ && pExpr->pLeft->iColumn>=0
+ && !ExprHasProperty(pExpr, EP_FromJoin)
+ ){
+ Expr *pNewExpr;
+ Expr *pLeft = pExpr->pLeft;
+ int idxNew;
+ WhereTerm *pNewTerm;
+
+ pNewExpr = sqlite3PExpr(pParse, TK_GT,
+ sqlite3ExprDup(db, pLeft, 0),
+ sqlite3ExprAlloc(db, TK_NULL, 0, 0));
+
+ idxNew = whereClauseInsert(pWC, pNewExpr,
+ TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
+ if( idxNew ){
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = 0;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_GT;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+ }
+
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
/* Add constraints to reduce the search space on a LIKE or GLOB
@@ -1206,7 +1252,8 @@ static void exprAnalyze(
** bound is made all lowercase so that the bounds also work when comparing
** BLOBs.
*/
- if( pWC->op==TK_AND
+ else if( pExpr->op==TK_FUNCTION
+ && pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){
Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -1276,52 +1323,6 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Add a WO_AUX auxiliary term to the constraint set if the
- ** current expression is of the form "column OP expr" where OP
- ** is an operator that gets passed into virtual tables but which is
- ** not normally optimized for ordinary tables. In other words, OP
- ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
- ** This information is used by the xBestIndex methods of
- ** virtual tables. The native query optimizer does not attempt
- ** to do anything with MATCH functions.
- */
- if( pWC->op==TK_AND ){
- Expr *pRight = 0, *pLeft = 0;
- int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
- while( res-- > 0 ){
- int idxNew;
- WhereTerm *pNewTerm;
- Bitmask prereqColumn, prereqExpr;
-
- prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
- prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
- if( (prereqExpr & prereqColumn)==0 ){
- Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
- 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 );
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_AUX;
- pNewTerm->eMatchOp = eOp2;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
- }
- SWAP(Expr*, pLeft, pRight);
- }
- }
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
** new terms for each component comparison - "a = ?" and "b = ?". The
** new terms completely replace the original vector comparison, which is
@@ -1329,12 +1330,12 @@ static void exprAnalyze(
**
** This is only required if at least one side of the comparison operation
** is not a sub-select. */
- if( pWC->op==TK_AND
- && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
- && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
- && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
- && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
- || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
+ && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
+ && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
+ && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
+ || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ && pWC->op==TK_AND
){
int i;
for(i=0; iop==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
+ else if( pExpr->op==TK_IN
+ && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
+ && pWC->op==TK_AND
){
int i;
for(i=0; ipLeft); i++){
@@ -1379,44 +1382,51 @@ static void exprAnalyze(
}
}
-#ifdef SQLITE_ENABLE_STAT4
- /* When sqlite_stat4 histogram data is available an operator of the
- ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
- ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
- ** virtual term of that form.
- **
- ** Note that the virtual term must be tagged with TERM_VNULL.
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_AUX auxiliary term to the constraint set if the
+ ** current expression is of the form "column OP expr" where OP
+ ** is an operator that gets passed into virtual tables but which is
+ ** not normally optimized for ordinary tables. In other words, OP
+ ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
*/
- if( pExpr->op==TK_NOTNULL
- && pExpr->pLeft->op==TK_COLUMN
- && pExpr->pLeft->iColumn>=0
- && !ExprHasProperty(pExpr, EP_FromJoin)
- && OptimizationEnabled(db, SQLITE_Stat4)
- ){
- Expr *pNewExpr;
- Expr *pLeft = pExpr->pLeft;
- int idxNew;
- WhereTerm *pNewTerm;
-
- pNewExpr = sqlite3PExpr(pParse, TK_GT,
- sqlite3ExprDup(db, pLeft, 0),
- sqlite3ExprAlloc(db, TK_NULL, 0, 0));
-
- idxNew = whereClauseInsert(pWC, pNewExpr,
- TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
- if( idxNew ){
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = 0;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_GT;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
+ else if( pWC->op==TK_AND ){
+ Expr *pRight = 0, *pLeft = 0;
+ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
+ while( res-- > 0 ){
+ int idxNew;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
+ prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ 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 );
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_AUX;
+ pNewTerm->eMatchOp = eOp2;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ SWAP(Expr*, pLeft, pRight);
}
}
-#endif /* SQLITE_ENABLE_STAT4 */
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@@ -1576,7 +1586,7 @@ void sqlite3WhereExprAnalyze(
*/
void sqlite3WhereTabFuncArgs(
Parse *pParse, /* Parsing context */
- struct SrcList_item *pItem, /* The FROM clause term to process */
+ SrcItem *pItem, /* The FROM clause term to process */
WhereClause *pWC /* Xfer function arguments to here */
){
Table *pTab;
diff --git a/src/window.c b/src/window.c
index 88ff7d314..2afa7c12c 100644
--- a/src/window.c
+++ b/src/window.c
@@ -788,6 +788,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
case TK_AGG_FUNCTION:
case TK_COLUMN: {
int iCol = -1;
+ if( pParse->db->mallocFailed ) return WRC_Abort;
if( p->pSub ){
int i;
for(i=0; ipSub->nExpr; i++){
@@ -897,9 +898,14 @@ static ExprList *exprListAppendList(
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; inExpr; i++){
- Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
+ sqlite3 *db = pParse->db;
+ Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
- if( bIntToNull && pDup ){
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ break;
+ }
+ if( bIntToNull ){
int iDummy;
Expr *pSub;
for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
@@ -935,6 +941,14 @@ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
+static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
+ sqlite3ErrorMsg(pWalker->pParse,
+ "misuse of aggregate: %s()", pExpr->u.zToken);
+ }
+ return WRC_Continue;
+}
+
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
@@ -944,7 +958,7 @@ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
*/
int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
- if( p->pWin && p->pPrior==0 && (p->selFlags & SF_WinRewrite)==0 ){
+ if( p->pWin && p->pPrior==0 && ALWAYS((p->selFlags & SF_WinRewrite)==0) ){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -968,6 +982,11 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
+ if( (p->selFlags & SF_Aggregate)==0 ){
+ w.xExprCallback = disallowAggregatesInOrderByCb;
+ w.xSelectCallback = 0;
+ sqlite3WalkExprList(&w, p->pOrderBy);
+ }
p->pSrc = 0;
p->pWhere = 0;
@@ -1304,15 +1323,19 @@ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
void sqlite3WindowLink(Select *pSel, Window *pWin){
- if( pSel!=0
- && (0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0))
- ){
- pWin->pNextWin = pSel->pWin;
- if( pSel->pWin ){
- pSel->pWin->ppThis = &pWin->pNextWin;
+ if( pSel ){
+ if( 0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){
+ pWin->pNextWin = pSel->pWin;
+ if( pSel->pWin ){
+ pSel->pWin->ppThis = &pWin->pNextWin;
+ }
+ pSel->pWin = pWin;
+ pWin->ppThis = &pSel->pWin;
+ }else{
+ if( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){
+ pSel->selFlags |= SF_MultiPart;
+ }
}
- pSel->pWin = pWin;
- pWin->ppThis = &pSel->pWin;
}
}
@@ -1465,6 +1488,7 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
VdbeCoverageIf(v, eCond==2);
}
sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
@@ -1559,6 +1583,7 @@ struct WindowCodeArg {
int regGosub; /* Register used with OP_Gosub(addrGosub) */
int regArg; /* First in array of accumulator registers */
int eDelete; /* See above */
+ int regRowid;
WindowCsrAndReg start;
WindowCsrAndReg current;
@@ -1675,15 +1700,15 @@ static void windowAggStep(
}
if( pWin->bExprArgs ){
- int iStart = sqlite3VdbeCurrentAddr(v);
- VdbeOp *pOp, *pEnd;
+ int iOp = sqlite3VdbeCurrentAddr(v);
+ int iEnd;
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
- pEnd = sqlite3VdbeGetOp(v, -1);
- for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
+ for(iEnd=sqlite3VdbeCurrentAddr(v); iOpopcode==OP_Column && pOp->p1==pWin->iEphCsr ){
pOp->p1 = csr;
}
@@ -2042,7 +2067,7 @@ static void windowIfNewPeer(
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
-** a numeric type (real or integer), then the result of the addition addition
+** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
@@ -2061,6 +2086,12 @@ static void windowCodeRangeTest(
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
+ int addrDone = sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */
+ CollSeq *pColl;
+
+ /* Read the peer-value from each cursor into a register */
+ windowReadPeerValues(p, csr1, reg1);
+ windowReadPeerValues(p, csr2, reg2);
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
@@ -2073,34 +2104,11 @@ static void windowCodeRangeTest(
arith = OP_Subtract;
}
- /* Read the peer-value from each cursor into a register */
- windowReadPeerValues(p, csr1, reg1);
- windowReadPeerValues(p, csr2, reg2);
-
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
- /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
- ** This block adds (or subtracts for DESC) the numeric value in regVal
- ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
- ** then leave reg1 as it is. In pseudo-code, this is implemented as:
- **
- ** if( reg1>='' ) goto addrGe;
- ** reg1 = reg1 +/- regVal
- ** addrGe:
- **
- ** Since all strings and blobs are greater-than-or-equal-to an empty string,
- ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
- ** then the arithmetic is performed, but since adding or subtracting from
- ** NULL is always NULL anyway, this case is handled as required too. */
- sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
- addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
- sqlite3VdbeJumpHere(v, addrGe);
-
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
@@ -2137,21 +2145,46 @@ static void windowCodeRangeTest(
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
- sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
if( op==OP_Gt || op==OP_Ge ){
- sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
+ sqlite3VdbeChangeP2(v, -1, addrDone);
}
}
+ /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
+ ** This block adds (or subtracts for DESC) the numeric value in regVal
+ ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
+ ** then leave reg1 as it is. In pseudo-code, this is implemented as:
+ **
+ ** if( reg1>='' ) goto addrGe;
+ ** reg1 = reg1 +/- regVal
+ ** addrGe:
+ **
+ ** Since all strings and blobs are greater-than-or-equal-to an empty string,
+ ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
+ ** then the arithmetic is performed, but since adding or subtracting from
+ ** NULL is always NULL anyway, this case is handled as required too. */
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
+ addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
+ VdbeCoverage(v);
+ if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
+ sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ }
+ sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
+ sqlite3VdbeJumpHere(v, addrGe);
+
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
+ sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ sqlite3VdbeResolveLabel(v, addrDone);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
@@ -2227,16 +2260,24 @@ static int windowCodeOp(
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
- ** temporary table. It otherwise might, if (a>b). */
+ ** temporary table. It otherwise might, if (a>b). Also ensure that,
+ ** if the input cursor is still finding new rows, that the end
+ ** cursor does not go past it to EOF. */
if( pMWin->eStart==pMWin->eEnd && regCountdown
- && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
+ && pMWin->eFrmType==TK_RANGE
){
int regRowid1 = sqlite3GetTempReg(pParse);
int regRowid2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
- sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
- sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
- VdbeCoverage(v);
+ if( op==WINDOW_AGGINVERSE ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
+ sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
+ VdbeCoverage(v);
+ }else if( p->regRowid ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
+ sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
+ VdbeCoverageNeverNull(v);
+ }
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
@@ -2733,7 +2774,6 @@ void sqlite3WindowCodeStep(
int addrEmpty; /* Address of OP_Rewind in flush: */
int regNew; /* Array of registers holding new input row */
int regRecord; /* regNew array in record form */
- int regRowid; /* Rowid for regRecord in eph table */
int regNewPeer = 0; /* Peer values for new row (part of regNew) */
int regPeer = 0; /* Peer values for current row */
int regFlushPart = 0; /* Register for "Gosub flush_partition" */
@@ -2805,7 +2845,7 @@ void sqlite3WindowCodeStep(
regNew = pParse->nMem+1;
pParse->nMem += nInput;
regRecord = ++pParse->nMem;
- regRowid = ++pParse->nMem;
+ s.regRowid = ++pParse->nMem;
/* If the window frame contains an " PRECEDING" or " FOLLOWING"
** clause, allocate registers to store the results of evaluating each
@@ -2861,9 +2901,9 @@ void sqlite3WindowCodeStep(
}
/* Insert the new row into the ephemeral table */
- sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
- addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
+ addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
VdbeCoverageNeverNull(v);
/* This block is run for the first row of each partition */
@@ -2981,6 +3021,7 @@ void sqlite3WindowCodeStep(
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
+ s.regRowid = 0;
addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
VdbeCoverage(v);
if( pMWin->eEnd==TK_PRECEDING ){
diff --git a/test/alter.test b/test/alter.test
index 43d2a6d5a..634e318e3 100644
--- a/test/alter.test
+++ b/test/alter.test
@@ -903,4 +903,16 @@ ifcapable rtree {
} {1 1.0 2.0 3 1.5 3.5}
}
+# 2021-03-08 dbsqlfuzz 3f0a7245b69cd08617d7d7781ebaedb0fe765a93
+reset_db
+do_catchsql_test alter-18.1 {
+ CREATE TABLE t1(a,b,c);
+ CREATE TABLE log(a INTEGER PRIMARY KEY,b,c);
+ CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO logx(a,b,c) VALUES(new.a,new.b,new.c)
+ ON CONFLICT(a) DO UPDATE SET c=excluded.c, b=new.b;
+ END;
+ ALTER TABLE log RENAME COLUMN a TO x;
+} {1 {error in trigger tr1: no such table: main.logx}}
+
finish_test
diff --git a/test/alter4.test b/test/alter4.test
index 3aca7df33..c63ba6b07 100644
--- a/test/alter4.test
+++ b/test/alter4.test
@@ -318,16 +318,16 @@ ifcapable trigger&&tempdb {
END;
INSERT INTO t1 VALUES(1, 2);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2}
+ } {a 1 2 b 1 2}
do_test alter4-6.2 {
execsql {
ALTER TABLE t1 ADD COLUMN c DEFAULT 'c';
INSERT INTO t1(a, b) VALUES(3, 4);
- SELECT * FROM log;
+ SELECT * FROM log ORDER BY trig, a, b;
}
- } {b 1 2 a 1 2 b 3 4 a 3 4}
+ } {a 1 2 a 3 4 b 1 2 b 3 4}
}
# Ticket #1183 - Make sure adding columns to large tables does not cause
diff --git a/test/alterauth2.test b/test/alterauth2.test
index bd589cda1..27ded1c3e 100644
--- a/test/alterauth2.test
+++ b/test/alterauth2.test
@@ -82,6 +82,7 @@ do_auth_test 1.2 {
{SQLITE_ALTER_TABLE main t2 {} {}}
{SQLITE_FUNCTION {} like {} {}}
{SQLITE_FUNCTION {} sqlite_rename_column {} {}}
+ {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
{SQLITE_READ sqlite_master name main {}}
{SQLITE_READ sqlite_master sql main {}}
@@ -95,4 +96,23 @@ do_auth_test 1.2 {
{SQLITE_UPDATE sqlite_temp_master sql temp {}}
}
+do_auth_test 1.3 {
+ ALTER TABLE t2 DROP COLUMN c;
+} {
+ {SQLITE_FUNCTION {} like {} {}}
+ {SQLITE_FUNCTION {} sqlite_drop_column {} {}}
+ {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
+ {SQLITE_FUNCTION {} sqlite_rename_test {} {}}
+ {SQLITE_READ sqlite_master name main {}}
+ {SQLITE_READ sqlite_master sql main {}}
+ {SQLITE_READ sqlite_master tbl_name main {}}
+ {SQLITE_READ sqlite_master type main {}}
+ {SQLITE_READ sqlite_temp_master name temp {}}
+ {SQLITE_READ sqlite_temp_master sql temp {}}
+ {SQLITE_READ sqlite_temp_master type temp {}}
+ {SQLITE_SELECT {} {} {} {}}
+ {SQLITE_UPDATE sqlite_master sql main {}}
+ {SQLITE_UPDATE sqlite_temp_master sql temp {}}
+}
+
finish_test
diff --git a/test/altercol.test b/test/altercol.test
index 1479b3a7d..d0c5c40ea 100644
--- a/test/altercol.test
+++ b/test/altercol.test
@@ -13,8 +13,6 @@
# file format change that may be used in the future to implement
# "ALTER TABLE ... RENAME COLUMN ... TO".
#
-# $Id: alter4.test,v 1.1 2009/02/02 18:03:22 drh Exp $
-#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -569,7 +567,7 @@ do_execsql_test 13.1.6 {
do_catchsql_test 13.1.7 {
ALTER TABLE x1 RENAME COLUMN t TO ttt;
-} {1 {database disk image is malformed}}
+} {1 {error in index x1i: }}
do_execsql_test 13.1.8 {
DELETE FROM sqlite_master WHERE name = 'x1i';
@@ -804,6 +802,62 @@ do_execsql_test 20.110 {
SELECT sql FROM sqlite_master WHERE name='t1';
} {{CREATE TABLE t1(xx UNIQUE,yy UNIQUE,zz UNIQUE,UNIQUE(xx),PRIMARY KEY(yy),UNIQUE(zz))}}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 21.0 {
+ CREATE TABLE t1(a, b, c NOT NULL);
+ CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.c IS NOT NULL BEGIN
+ SELECT c NOT NULL FROM t1;
+ END;
+}
+
+do_execsql_test 21.1 {
+ ALTER TABLE t1 RENAME c TO d;
+}
+
+do_execsql_test 21.2 {
+ SELECT sql FROM sqlite_schema WHERE name IS 'tr1'
+} {{CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.d IS NOT NULL BEGIN
+ SELECT d NOT NULL FROM t1;
+ END}
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 22.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(c, othername, extra AS (c + 1));
+ ALTER TABLE t1 RENAME a to othername;
+ SELECT sql FROM sqlite_schema;
+} {
+ {CREATE TABLE t1(othername, b)}
+ {CREATE TABLE t2(c, othername, extra AS (c + 1))}
+}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 22.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX x1 on t1("c"=b);
+ INSERT INTO t1 VALUES('a', 'a');
+ INSERT INTO t1 VALUES('b', 'b');
+ INSERT INTO t1 VALUES('c', 'c');
+ ALTER TABLE t1 RENAME COLUMN a TO "c";
+ PRAGMA integrity_check;
+} {ok}
+
+reset_db
+do_execsql_test 23.0 {
+ CREATE TABLE t1('a'"b",c);
+ CREATE INDEX i1 ON t1('a');
+ INSERT INTO t1 VALUES(1,2), (3,4);
+ ALTER TABLE t1 RENAME COLUMN a TO x;
+ PRAGMA integrity_check;
+ SELECT sql FROM sqlite_schema WHERE name='t1';
+
+} {ok {CREATE TABLE t1("x" "b",c)}}
finish_test
diff --git a/test/altercorrupt.test b/test/altercorrupt.test
new file mode 100644
index 000000000..5c50fa4a4
--- /dev/null
+++ b/test/altercorrupt.test
@@ -0,0 +1,175 @@
+# 2019-01-11
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix altercorrupt
+
+database_may_be_corrupt
+
+#--------------------------------------------------------------------------
+reset_db
+do_test 1.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 24576 pagesize 4096 filename crash-685346d89b5e5f.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 06 .....@ ........
+| 32: 00 00 63 00 00 05 f0 00 00 00 00 04 10 00 00 04 ..c.............
+| 48: 00 00 00 00 00 00 0f f0 00 00 00 01 00 00 00 00 ................
+| 64: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 96: 00 00 00 00 0d 0f f8 00 05 0e cf 00 0f 79 0f d3 .............y..
+| 112: 0f 2e 0e f3 0e cf 00 00 00 00 00 00 00 00 00 00 ................
+| 3776: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
+| 3792: 05 06 17 11 11 01 31 74 61 62 6c 65 74 34 74 34 ......1tablet4t4
+| 3808: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 34 .CREATE TABLE t4
+| 3824: 28 7a 29 39 04 06 17 11 11 01 5f 74 61 62 6c 65 (z)9......_table
+| 3840: 74 33 74 33 05 43 52 45 41 54 45 20 54 41 42 4c t3t3.CREATE TABL
+| 3856: 45 20 74 33 28 78 20 49 4e 54 45 47 45 52 20 50 E t3(x INTEGER P
+| 3872: 52 49 4d 41 52 59 20 4b 45 59 2c 20 79 29 49 03 RIMARY KEY, y)I.
+| 3888: 06 17 11 11 01 7f 74 61 62 6c 65 74 32 74 32 04 ......tablet2t2.
+| 3904: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 28 CREATE TABLE t2(
+| 3920: 61 2c 62 2c 63 20 50 52 49 4d 41 52 59 20 4b 45 a,b,c PRIMARY KE
+| 3936: 59 2c 20 64 2c 20 65 2c 20 66 29 20 57 49 54 48 Y, d, e, f) WITH
+| 3952: 4f 55 54 20 52 4f 57 49 44 58 03 07 17 11 11 01 OUT ROWIDX......
+| 3968: 81 1b 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 ..tablet1t1.CREA
+| 3984: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 2c TE TABLE t1(a,b,
+| 4000: 63 20 41 53 20 28 2d 62 29 20 56 49 52 54 55 41 c AS (-b) VIRTUA
+| 4016: 4c 2c 64 20 43 48 45 43 4b 28 64 3e 35 29 2c 65 L,d CHECK(d>5),e
+| 4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b UNIQUE, f AS (+
+| 4048: 62 29 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b))#...7...index
+| 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex
+| 4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00 _t1_1t1.........
+| page 2 offset 4096
+| 0: 0d 00 00 00 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5 ................
+| 16: 0f ca 0f 8f 0f b4 0f a9 0f 9e 0f 93 00 00 00 00 ................
+| 3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09 ...........dn...
+| 4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 01 01 01 ......Zm........
+| 4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09 .Pl.........Fk..
+| 4032: 06 05 01 01 01 01 06 3c 6a 0c 09 05 05 01 01 01 .......5),e
+| 4032: 20 55 4e 49 51 55 45 2c 20 66 20 41 53 20 28 2b UNIQUE, f AS (+
+| 4048: 62 29 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b))#...7...index
+| 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex
+| 4080: 5f 74 31 5f 31 84 31 03 01 00 00 08 00 00 00 00 _t1_1.1.........
+| page 2 offset 4096
+| 0: 0d 00 00 00 0a 0f 93 00 0f f6 0f eb 0f e0 0f d5 ................
+| 16: 0f ca 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3984: 00 00 00 09 0a 05 01 01 01 01 0a 64 6e 14 09 09 ...........dn...
+| 4000: 05 01 01 01 01 09 5a 6d 12 09 08 05 01 00 f1 01 ......Zm........
+| 4016: 08 50 6c 10 09 07 05 01 01 01 01 07 46 6b 0e 09 .Pl.........Fk..
+| 4032: 06 05 01 00 f1 01 06 3c 6a 0c 09 05 05 01 01 01 .......10));
+ CREATE TABLE t13(a, b, c CHECK(c>10));
+}
+do_catchsql_test 3.1 {
+ ALTER TABLE t12 DROP COLUMN c;
+} {1 {error in table t12 after drop column: no such column: c}}
+
+do_catchsql_test 3.2 {
+ ALTER TABLE t13 DROP COLUMN c;
+} {0 {}}
+
+#-------------------------------------------------------------------------
+# Test that generated columns can be dropped. And that other columns from
+# tables that contain generated columns can be dropped.
+#
+foreach {tn wo vs} {
+ 1 "" ""
+ 2 "" VIRTUAL
+ 3 "" STORED
+ 4 "WITHOUT ROWID" STORED
+ 5 "WITHOUT ROWID" VIRTUAL
+} {
+ reset_db
+
+ do_execsql_test 4.$tn.0 "
+ CREATE TABLE 'my table'(a, b PRIMARY KEY, c AS (a+b) $vs, d) $wo
+ "
+ do_execsql_test 4.$tn.1 {
+ INSERT INTO "my table"(a, b, d) VALUES(1, 2, 'hello');
+ INSERT INTO "my table"(a, b, d) VALUES(3, 4, 'world');
+
+ SELECT * FROM "my table"
+ } {
+ 1 2 3 hello
+ 3 4 7 world
+ }
+
+ do_execsql_test 4.$tn.2 {
+ ALTER TABLE "my table" DROP COLUMN c;
+ }
+ do_execsql_test 4.$tn.3 {
+ SELECT * FROM "my table"
+ } {
+ 1 2 hello
+ 3 4 world
+ }
+
+ do_execsql_test 4.$tn.4 "
+ CREATE TABLE x1(a, b, c PRIMARY KEY, d AS (b+c) $vs, e) $wo
+ "
+ do_execsql_test 4.$tn.5 {
+ INSERT INTO x1(a, b, c, e) VALUES(1, 2, 3, 4);
+ INSERT INTO x1(a, b, c, e) VALUES(5, 6, 7, 8);
+ INSERT INTO x1(a, b, c, e) VALUES(9, 10, 11, 12);
+ SELECT * FROM x1;
+ } {
+ 1 2 3 5 4
+ 5 6 7 13 8
+ 9 10 11 21 12
+ }
+
+ do_execsql_test 4.$tn.6 {
+ ALTER TABLE x1 DROP COLUMN a
+ }
+ do_execsql_test 4.$tn.7 {
+ SELECT * FROM x1
+ } {
+ 2 3 5 4
+ 6 7 13 8
+ 10 11 21 12
+ }
+ do_execsql_test 4.$tn.8 {
+ ALTER TABLE x1 DROP COLUMN e
+ }
+ do_execsql_test 4.$tn.9 {
+ SELECT * FROM x1
+ } {
+ 2 3 5
+ 6 7 13
+ 10 11 21
+ }
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 5.0 {
+ CREATE TABLE p1(a PRIMARY KEY, b UNIQUE);
+ CREATE TABLE c1(x, y, z REFERENCES p1(c));
+ CREATE TABLE c2(x, y, z, w REFERENCES p1(b));
+}
+do_execsql_test 5.1 {
+ ALTER TABLE c1 DROP COLUMN z;
+ ALTER TABLE c2 DROP COLUMN z;
+ SELECT sql FROM sqlite_schema WHERE name IN ('c1', 'c2');
+} {
+ {CREATE TABLE c1(x, y)}
+ {CREATE TABLE c2(x, y, w REFERENCES p1(b))}
+}
+
+do_execsql_test 5.2.1 {
+ CREATE VIEW v1 AS SELECT d, e FROM p1
+}
+do_catchsql_test 5.2.2 {
+ ALTER TABLE c1 DROP COLUMN x
+} {1 {error in view v1: no such column: d}}
+do_execsql_test 5.3.1 {
+ DROP VIEW v1;
+ CREATE VIEW v1 AS SELECT x, y FROM c1;
+}
+do_catchsql_test 5.3.2 {
+ ALTER TABLE c1 DROP COLUMN x
+} {1 {error in view v1 after drop column: no such column: x}}
+
+do_execsql_test 5.4.1 {
+ CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
+ INSERT INTO p1 VALUES(new.y, new.xyz);
+ END;
+}
+do_catchsql_test 5.4.2 {
+ ALTER TABLE c1 DROP COLUMN y
+} {1 {error in trigger tr: no such column: new.xyz}}
+do_execsql_test 5.5.1 {
+ DROP TRIGGER tr;
+ CREATE TRIGGER tr AFTER INSERT ON c1 BEGIN
+ INSERT INTO p1 VALUES(new.y, new.z);
+ END;
+}
+do_catchsql_test 5.5.2 {
+ ALTER TABLE c1 DROP COLUMN y
+} {1 {error in trigger tr: no such column: new.z}}
+
+# 2021-03-06 dbsqlfuzz crash-419aa525df93db6e463772c686ac6da27b46da9e
+reset_db
+do_catchsql_test 6.0 {
+ CREATE TABLE t1(a,b,c);
+ CREATE TABLE t2(x,y,z);
+ PRAGMA writable_schema=ON;
+ UPDATE sqlite_schema SET sql='CREATE INDEX t1b ON t1(b)' WHERE name='t2';
+ PRAGMA writable_schema=OFF;
+ ALTER TABLE t2 DROP COLUMN z;
+} {1 {database disk image is malformed}}
+reset_db
+do_catchsql_test 6.1 {
+ CREATE TABLE t1(a,b,c);
+ CREATE TABLE t2(x,y,z);
+ PRAGMA writable_schema=ON;
+ UPDATE sqlite_schema SET sql='CREATE VIEW t2(x,y,z) AS SELECT b,a,c FROM t1'
+ WHERE name='t2';
+ PRAGMA writable_schema=OFF;
+ ALTER TABLE t2 DROP COLUMN z;
+} {1 {database disk image is malformed}}
+
+# 2021-04-06 dbsqlfuzz crash-331c5c29bb76257b198f1318eef3288f9624c8ce
+reset_db
+do_execsql_test 7.0 {
+ CREATE TABLE t1(a, b, c, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID;
+ INSERT INTO t1 VALUES(1, 2, 3);
+ INSERT INTO t1 VALUES(4, 5, 6);
+}
+do_execsql_test 7.1 {
+ ALTER TABLE t1 DROP COLUMN c;
+}
+do_execsql_test 7.2 {
+ SELECT sql FROM sqlite_schema;
+} {{CREATE TABLE t1(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID}}
+do_execsql_test 7.3 {
+ SELECT * FROM t1;
+} {1 2 4 5}
+
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = 'CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b)'
+}
+db close
+sqlite3 db test.db
+do_execsql_test 8.1 {
+ ALTER TABLE t1 DROP COLUMN b;
+}
+do_execsql_test 8.2 {
+ SELECT sql FROM sqlite_schema;
+} {{CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT)}}
+
+#-------------------------------------------------------------------------
+
+foreach {tn wo} {
+ 1 {}
+ 2 {WITHOUT ROWID}
+} {
+ reset_db
+ do_execsql_test 9.$tn.0 "
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) $wo;
+ "
+ do_execsql_test 9.$tn.1 {
+ WITH s(i) AS (
+ SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
+ )
+ INSERT INTO t1(a, b, c) SELECT i, 123, 456 FROM s;
+ }
+ do_execsql_test 9.$tn.2 {
+ ALTER TABLE t1 DROP COLUMN b;
+ }
+
+ do_execsql_test 9.$tn.3 {
+ SELECT count(*), c FROM t1 GROUP BY c;
+ } {50000 456}
+}
+
+
+
+finish_test
diff --git a/test/alterdropcol2.test b/test/alterdropcol2.test
new file mode 100644
index 000000000..d60e7db44
--- /dev/null
+++ b/test/alterdropcol2.test
@@ -0,0 +1,222 @@
+# 2021 February 19
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix alterdropcol2
+
+# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
+ifcapable !altertable {
+ finish_test
+ return
+}
+
+# EVIDENCE-OF: R-58318-35349 The DROP COLUMN syntax is used to remove an
+# existing column from a table.
+do_execsql_test 1.0 {
+ CREATE TABLE t1(c, b, a, PRIMARY KEY(b, a)) WITHOUT ROWID;
+ INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
+}
+do_execsql_test 1.1 {
+ ALTER TABLE t1 DROP c;
+}
+
+# EVIDENCE-OF: The DROP COLUMN command removes the named column from the table,
+# and also rewrites the entire table to purge the data associated with that
+# column.
+do_execsql_test 1.2.1 {
+ SELECT * FROM t1;
+} {2 3 5 6}
+
+do_execsql_test 1.2.2 {
+ SELECT sql FROM sqlite_schema;
+} {
+ {CREATE TABLE t1(b, a, PRIMARY KEY(b, a)) WITHOUT ROWID}
+}
+
+proc do_atdc_error_test {tn schema atdc error} {
+ reset_db
+ execsql $schema
+ uplevel [list do_catchsql_test $tn $atdc [list 1 [string trim $error]]]
+}
+
+#-------------------------------------------------------------------------
+# Test cases 2.* attempt to verify the following:
+#
+# EVIDENCE-OF: R-24098-10282 The DROP COLUMN command only works if the column
+# is not referenced by any other parts of the schema and is not a PRIMARY KEY
+# and does not have a UNIQUE constraint.
+#
+
+# EVIDENCE-OF: R-52436-31752 The column is a PRIMARY KEY or part of one.
+#
+do_atdc_error_test 2.1.1 {
+ CREATE TABLE x1(a PRIMARY KEY, b, c);
+} {
+ ALTER TABLE x1 DROP COLUMN a
+} {
+ cannot drop PRIMARY KEY column: "a"
+}
+do_atdc_error_test 2.1.2 {
+ CREATE TABLE x1(a,b,c,d,e, PRIMARY KEY(b,c,d));
+} {
+ ALTER TABLE x1 DROP COLUMN c
+} {
+ cannot drop PRIMARY KEY column: "c"
+}
+
+# EVIDENCE-OF: R-43412-16016 The column has a UNIQUE constraint.
+#
+do_atdc_error_test 2.2.1 {
+ CREATE TABLE x1(a PRIMARY KEY, b, c UNIQUE);
+} {
+ ALTER TABLE x1 DROP COLUMN c
+} {
+ cannot drop UNIQUE column: "c"
+}
+do_atdc_error_test 2.2.2 {
+ CREATE TABLE x1(a PRIMARY KEY, b, c, UNIQUE(b, c));
+} {
+ ALTER TABLE x1 DROP COLUMN c
+} {
+ error in table x1 after drop column: no such column: c
+}
+
+# EVIDENCE-OF: R-46731-08965 The column is indexed.
+#
+do_atdc_error_test 2.3.1 {
+ CREATE TABLE 'one two'('x y', 'z 1', 'a b');
+ CREATE INDEX idx ON 'one two'('z 1');
+} {
+ ALTER TABLE 'one two' DROP COLUMN 'z 1'
+} {
+ error in index idx after drop column: no such column: z 1
+}
+do_atdc_error_test 2.3.2 {
+ CREATE TABLE x1(a, b, c);
+ CREATE INDEX idx ON x1(a);
+} {
+ ALTER TABLE x1 DROP COLUMN a;
+} {
+ error in index idx after drop column: no such column: a
+}
+
+# EVIDENCE-OF: R-46731-08965 The column is indexed.
+#
+do_atdc_error_test 2.4.1 {
+ CREATE TABLE x1234(a, b, c PRIMARY KEY) WITHOUT ROWID;
+ CREATE INDEX i1 ON x1234(b) WHERE ((a+5) % 10)==0;
+} {
+ ALTER TABLE x1234 DROP a
+} {
+ error in index i1 after drop column: no such column: a
+}
+
+# EVIDENCE-OF: R-47838-03249 The column is named in a table or column
+# CHECK constraint not associated with the column being dropped.
+#
+do_atdc_error_test 2.5.1 {
+ CREATE TABLE x1234(a, b, c PRIMARY KEY, CHECK(((a+5)%10)!=0)) WITHOUT ROWID;
+} {
+ ALTER TABLE x1234 DROP a
+} {
+ error in table x1234 after drop column: no such column: a
+}
+
+# EVIDENCE-OF: R-55640-01652 The column is used in a foreign key constraint.
+#
+do_atdc_error_test 2.6.1 {
+ CREATE TABLE p1(x, y UNIQUE);
+ CREATE TABLE c1(u, v, FOREIGN KEY (v) REFERENCES p1(y))
+} {
+ ALTER TABLE c1 DROP v
+} {
+ error in table c1 after drop column: unknown column "v" in foreign key definition
+}
+
+# EVIDENCE-OF: R-20795-39479 The column is used in the expression of a
+# generated column.
+do_atdc_error_test 2.7.1 {
+ CREATE TABLE c1(u, v, w AS (u+v));
+} {
+ ALTER TABLE c1 DROP v
+} {
+ error in table c1 after drop column: no such column: v
+}
+do_atdc_error_test 2.7.2 {
+ CREATE TABLE c1(u, v, w AS (u+v) STORED);
+} {
+ ALTER TABLE c1 DROP u
+} {
+ error in table c1 after drop column: no such column: u
+}
+
+# EVIDENCE-OF: R-01515-49025 The column appears in a trigger or view.
+#
+do_atdc_error_test 2.8.1 {
+ CREATE TABLE log(l);
+ CREATE TABLE c1(u, v, w);
+ CREATE TRIGGER tr1 AFTER INSERT ON c1 BEGIN
+ INSERT INTO log VALUES(new.w);
+ END;
+} {
+ ALTER TABLE c1 DROP w
+} {
+ error in trigger tr1 after drop column: no such column: new.w
+}
+do_atdc_error_test 2.8.2 {
+ CREATE TABLE c1(u, v, w);
+ CREATE VIEW v1 AS SELECT u, v, w FROM c1;
+} {
+ ALTER TABLE c1 DROP w
+} {
+ error in view v1 after drop column: no such column: w
+}
+do_atdc_error_test 2.8.3 {
+ CREATE TABLE c1(u, v, w);
+ CREATE VIEW v1 AS SELECT * FROM c1 WHERE w IS NOT NULL;
+} {
+ ALTER TABLE c1 DROP w
+} {
+ error in view v1 after drop column: no such column: w
+}
+
+#-------------------------------------------------------------------------
+# Verify that a column that is part of a CHECK constraint may be dropped
+# if the CHECK constraint was specified as part of the column definition.
+#
+
+# STALE-EVIDENCE: R-60924-11170 However, the column being deleted can be used in a
+# column CHECK constraint because the column CHECK constraint is dropped
+# together with the column itself.
+do_execsql_test 3.0 {
+ CREATE TABLE yyy(q, w, e CHECK (e > 0), r);
+ INSERT INTO yyy VALUES(1,1,1,1), (2,2,2,2);
+
+ CREATE TABLE zzz(q, w, e, r, CHECK (e > 0));
+ INSERT INTO zzz VALUES(1,1,1,1), (2,2,2,2);
+}
+do_catchsql_test 3.1.1 {
+ INSERT INTO yyy VALUES(0,0,0,0);
+} {1 {CHECK constraint failed: e > 0}}
+do_catchsql_test 3.1.2 {
+ INSERT INTO yyy VALUES(0,0,0,0);
+} {1 {CHECK constraint failed: e > 0}}
+
+do_execsql_test 3.2.1 {
+ ALTER TABLE yyy DROP e;
+}
+do_catchsql_test 3.2.2 {
+ ALTER TABLE zzz DROP e;
+} {1 {error in table zzz after drop column: no such column: e}}
+
+finish_test
diff --git a/test/alterlegacy.test b/test/alterlegacy.test
index 47d8bcfba..dfa171646 100644
--- a/test/alterlegacy.test
+++ b/test/alterlegacy.test
@@ -40,7 +40,7 @@ do_execsql_test 1.1 {
# slightly different - it rejects the change and rolls back the transaction.
do_catchsql_test 1.2 {
ALTER TABLE t1 RENAME TO t1new;
-} {1 {no such column: t1.a}}
+} {1 {error in table t1new after rename: no such column: t1.a}}
do_execsql_test 1.3 {
CREATE TABLE t3(c, d);
@@ -59,7 +59,7 @@ do_execsql_test 1.4 {
do_catchsql_test 1.3 {
ALTER TABLE t2 RENAME TO t2new;
-} {1 {no such column: t2.b}}
+} {1 {error in index t2expr after rename: no such column: t2.b}}
do_execsql_test 1.4 {
SELECT sql FROM sqlite_master
} {
diff --git a/test/altermalloc2.test b/test/altermalloc2.test
index 610b3f6bf..3d22ad945 100644
--- a/test/altermalloc2.test
+++ b/test/altermalloc2.test
@@ -98,4 +98,25 @@ do_faultsim_test 4 -faults oom-* -prep {
faultsim_test_result {0 {}}
}
+reset_db
+do_execsql_test 5.0 {
+ CREATE TABLE rr(a, b);
+ CREATE VIEW vv AS SELECT * FROM (
+ WITH abc(d, e) AS (SELECT * FROM rr)
+ SELECT * FROM abc
+ );
+} {}
+
+faultsim_save_and_close
+do_faultsim_test 5 -faults oom-* -prep {
+ faultsim_restore_and_reopen
+ execsql { SELECT * FROM sqlite_master }
+} -body {
+ execsql {
+ ALTER TABLE rr RENAME TO c;
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
finish_test
diff --git a/test/altermalloc3.test b/test/altermalloc3.test
new file mode 100644
index 000000000..5e4e75149
--- /dev/null
+++ b/test/altermalloc3.test
@@ -0,0 +1,47 @@
+# 2021 February 18
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/malloc_common.tcl
+set testprefix altermalloc3
+
+# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
+ifcapable !altertable {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE x1(
+ one, two, three, PRIMARY KEY(one),
+ CHECK (three!="xyz"), CHECK (two!="one")
+ ) WITHOUT ROWID;
+ CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
+ CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
+ END;
+ CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
+ INSERT INTO t1 VALUES(1, 2, 3, 4);
+}
+faultsim_save_and_close
+
+do_faultsim_test 1 -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql { ALTER TABLE t1 DROP COLUMN c }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+
+finish_test
diff --git a/test/alterqf.test b/test/alterqf.test
new file mode 100644
index 000000000..ce00f3b59
--- /dev/null
+++ b/test/alterqf.test
@@ -0,0 +1,111 @@
+# 2021 March 16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. This
+# script focuses on testing internal function sqlite_rename_quotefix().
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix alterqf
+
+sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a, b, c);
+}
+
+foreach {tn before after} {
+ 1 {CREATE VIEW v1 AS SELECT "a", "b", "notacolumn!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'notacolumn!', "c" FROM t1}
+
+ 2 {CREATE VIEW v1 AS SELECT "a", "b", "not'a'column!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'not''a''column!', "c" FROM t1}
+
+ 3 {CREATE VIEW v1 AS SELECT "a", "b", "not""a""column!", "c" FROM t1}
+ {CREATE VIEW v1 AS SELECT "a", "b", 'not"a"column!', "c" FROM t1}
+
+ 4 {CREATE VIEW v1 AS SELECT "val", count("b") FROM t1 GROUP BY "abc"}
+ {CREATE VIEW v1 AS SELECT 'val', count("b") FROM t1 GROUP BY 'abc'}
+
+ 5 {CREATE TABLE xyz(a CHECK (a!="str"), b AS (a||"str"))}
+ {CREATE TABLE xyz(a CHECK (a!='str'), b AS (a||'str'))}
+
+ 6 {CREATE INDEX i1 ON t1(a || "str", "b", "val")}
+ {CREATE INDEX i1 ON t1(a || 'str', "b", 'val')}
+
+ 7 {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT "abcd"; END}
+ {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 'abcd'; END}
+
+ 8 {CREATE VIEW v1 AS SELECT "string"'alias' FROM t1}
+ {CREATE VIEW v1 AS SELECT 'string' 'alias' FROM t1}
+
+ 9 {CREATE INDEX i1 ON t1(a) WHERE "b"="bb"}
+ {CREATE INDEX i1 ON t1(a) WHERE "b"='bb'}
+
+ 10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))}
+ {CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))}
+
+ 11 {
+ CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
+ SELECT max("str", new."a") FROM t1
+ WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
+ UPDATE t1 SET c= b + "str";
+ DELETE FROM t1 WHERE EXISTS (
+ SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
+ );
+ END;
+ } {
+ CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
+ SELECT max('str', new."a") FROM t1
+ WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
+ UPDATE t1 SET c= b + 'str';
+ DELETE FROM t1 WHERE EXISTS (
+ SELECT 1 FROM t1 AS o WHERE o."a" = 'o.a' AND t1.b IN('t1.b')
+ );
+ END;
+ }
+
+} {
+ do_execsql_test 1.$tn {
+ SELECT sqlite_rename_quotefix('main', $before)
+ } [list $after]
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.0 {
+ CREATE TABLE x1(
+ one, two, three, PRIMARY KEY(one),
+ CHECK (three!="xyz"), CHECK (two!="one")
+ ) WITHOUT ROWID;
+ CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
+ CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
+ END;
+}
+
+do_execsql_test 2.1 {
+ ALTER TABLE x1 RENAME two TO 'four';
+ SELECT sql FROM sqlite_schema;
+ SELECT sql FROM sqlite_temp_schema;
+} {{CREATE TABLE x1(
+ one, "four", three, PRIMARY KEY(one),
+ CHECK (three!='xyz'), CHECK ("four"!="one")
+ ) WITHOUT ROWID}
+ {CREATE INDEX x1i ON x1(one+"four"+'four') WHERE 'five'}
+ {CREATE TRIGGER AFTER INSERT ON x1 BEGIN
+ UPDATE x1 SET "four"=new.three || 'new' WHERE one=new.one||'';
+ END}
+}
+
+
+finish_test
diff --git a/test/altertab.test b/test/altertab.test
index 4e6d98c93..079a382d8 100644
--- a/test/altertab.test
+++ b/test/altertab.test
@@ -711,5 +711,261 @@ do_execsql_test 23.4 {
{CREATE VIEW v1 AS SELECT * FROM "idx2" WHERE y='abc'}
}
-finish_test
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 24.1.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TRIGGER AFTER INSERT ON t1 BEGIN
+ INSERT INTO nosuchtable VALUES(new.a) ON CONFLICT(a) DO NOTHING;
+ END;
+}
+do_catchsql_test 24.1.1 {
+ ALTER TABLE t1 RENAME TO t2;
+} {1 {error in trigger AFTER: no such table: main.nosuchtable}}
+
+reset_db
+do_execsql_test 24.2.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TRIGGER AFTER INSERT ON t1 BEGIN
+ INSERT INTO v1 VALUES(new.a) ON CONFLICT(a) DO NOTHING;
+ END;
+ CREATE VIEW v1 AS SELECT * FROM nosuchtable;
+}
+do_catchsql_test 24.2.1 {
+ ALTER TABLE t1 RENAME TO t2;
+} {1 {error in trigger AFTER: no such table: main.nosuchtable}}
+
+#--------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 25.1 {
+ CREATE TABLE xx(x);
+ CREATE VIEW v3(b) AS WITH b AS (SELECT b FROM (SELECT * FROM t2)) VALUES(1);
+}
+
+ifcapable json1&&vtab {
+ do_catchsql_test 25.2 {
+ ALTER TABLE json_each RENAME TO t4;
+ } {1 {table json_each may not be altered}}
+}
+
+# 2021-05-01 dbsqlfuzz bc17a306a09329bba0ecc61547077f6178bcf321
+# Remove a NEVER() inserted on 2019-12-09 that is reachable after all.
+#
+reset_db
+do_execsql_test 26.1 {
+ CREATE TABLE t1(k,v);
+ CREATE TABLE t2_a(k,v);
+ CREATE VIEW t2 AS SELECT * FROM t2_a;
+ CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
+ UPDATE t1
+ SET (k,v)=((WITH cte1(a) AS (SELECT 1 FROM t2) SELECT t2.k FROM t2, cte1),1);
+ END;
+ ALTER TABLE t1 RENAME TO t1x;
+ INSERT INTO t2_a VALUES(2,3);
+ INSERT INTO t1x VALUES(98,99);
+ SELECT * FROM t1x;
+} {2 1}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 27.1 {
+
+ create table t_sa (
+ c_muyat INTEGER NOT NULL,
+ c_d4u TEXT
+ );
+
+ create table t2 ( abc );
+
+ CREATE TRIGGER trig AFTER DELETE ON t_sa
+ BEGIN
+ DELETE FROM t_sa WHERE (
+ SELECT 123 FROM t2
+ WINDOW oamat7fzf AS ( PARTITION BY t_sa.c_d4u )
+ );
+ END;
+}
+
+do_execsql_test 27.2 {
+ alter table t_sa rename column c_muyat to c_dg;
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 29.1 {
+ CREATE TABLE t1(a, b, c);
+ INSERT INTO t1 VALUES('a', 'b', 'c');
+
+ CREATE VIEW v0 AS
+ WITH p AS ( SELECT 1 FROM t1 ),
+ g AS ( SELECT 1 FROM p, t1 )
+ SELECT 1 FROM g;
+}
+
+do_execsql_test 29.2 {
+ SELECT * FROM v0
+} 1
+
+do_execsql_test 29.2 {
+ ALTER TABLE t1 RENAME TO t2
+}
+do_execsql_test 29.3 {
+ SELECT sql FROM sqlite_schema WHERE name='v0'
+} {{CREATE VIEW v0 AS
+ WITH p AS ( SELECT 1 FROM "t2" ),
+ g AS ( SELECT 1 FROM p, "t2" )
+ SELECT 1 FROM g}}
+
+do_execsql_test 29.4 {
+ CREATE VIEW v2 AS
+ WITH p AS ( SELECT 1 FROM t2 ),
+ g AS ( SELECT 1 FROM (
+ WITH i AS (SELECT 1 FROM p, t2)
+ SELECT * FROM i
+ )
+ )
+ SELECT 1 FROM g;
+}
+
+do_execsql_test 29.4 {
+ SELECT * FROM v2;
+} 1
+
+do_execsql_test 29.5 {
+ ALTER TABLE t2 RENAME TO t3;
+}
+
+do_execsql_test 29.5 {
+ SELECT sql FROM sqlite_schema WHERE name='v2'
+} {{CREATE VIEW v2 AS
+ WITH p AS ( SELECT 1 FROM "t3" ),
+ g AS ( SELECT 1 FROM (
+ WITH i AS (SELECT 1 FROM p, "t3")
+ SELECT * FROM i
+ )
+ )
+ SELECT 1 FROM g}}
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 28.1 {
+ CREATE TABLE t1(a);
+ CREATE TABLE t2(b,c);
+ CREATE TABLE t4(b,c);
+ INSERT INTO t2 VALUES(1,2),(1,3),(2,5);
+ INSERT INTO t4 VALUES(1,2),(1,3),(2,5);
+
+ CREATE VIEW v3 AS
+ WITH RECURSIVE t3(x,y,z) AS (
+ SELECT b,c,NULL FROM t4
+ UNION
+ SELECT x,y,NULL FROM t3, t2
+ )
+ SELECT * FROM t3 AS xyz;
+}
+
+do_execsql_test 28.2 {
+ SELECT * FROM v3
+} {
+ 1 2 {} 1 3 {} 2 5 {}
+}
+
+do_execsql_test 28.3 {
+ ALTER TABLE t1 RENAME a TO a2; -- fails in v3
+}
+
+do_execsql_test 28.4 {
+ ALTER TABLE t2 RENAME TO t5;
+}
+
+do_execsql_test 28.5 {
+ SELECT sql FROM sqlite_schema WHERE name='v3'
+} {{CREATE VIEW v3 AS
+ WITH RECURSIVE t3(x,y,z) AS (
+ SELECT b,c,NULL FROM t4
+ UNION
+ SELECT x,y,NULL FROM t3, "t5"
+ )
+ SELECT * FROM t3 AS xyz}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 30.0 {
+ CREATE TABLE t1(a,b,c,d,e,f);
+ CREATE TABLE t2(a,b,c);
+ CREATE INDEX t1abc ON t1(a,b,c+d+e);
+ CREATE VIEW v1(x,y) AS
+ SELECT t1.b,t2.b FROM t1,t2 WHERE t1.a=t2.a
+ GROUP BY 1 HAVING t2.c NOT NULL LIMIT 10;
+ CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN 'no' NOT NULL BEGIN
+ INSERT INTO t2(a,a,b,c) VALUES(new.b,new.a,new.c-7);
+ WITH c1(x) AS (
+ VALUES(0)
+ UNION ALL
+ SELECT current_time+x FROM c1 WHERE x
+ UNION ALL
+ SELECT 1+x FROM c1 WHERE x<1
+ ), c2(x) AS (VALUES(0),(1))
+ SELECT * FROM c1 AS x1, c2 AS x2, (
+ SELECT x+1 FROM c1 WHERE x IS NOT TRUE
+ UNION ALL
+ SELECT 1+x FROM c1 WHERE 1200 AND x<300
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
-} {SCAN TABLE t1}
+} {SCAN t1}
# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
# the use of bound parameters by STAT4
@@ -137,27 +137,27 @@ unset -nocomplain l
unset -nocomplain u
do_eqp_test analyze3-1.1.3.100 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
set l 200
set u 300
do_eqp_test analyze3-1.1.3.101 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
set l 0
set u 1100
do_eqp_test analyze3-1.1.3.102 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SCAN TABLE t1}
+} {SCAN t1}
db cache flush
sqlite3_db_config db ENABLE_QPSG 1
do_eqp_test analyze3-1.1.3.103 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x)}
+} {SEARCH t1 USING INDEX i1 (x>? AND x)}
db cache flush
sqlite3_db_config db ENABLE_QPSG 0
do_eqp_test analyze3-1.1.3.104 {
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
-} {SCAN TABLE t1}
+} {SCAN t1}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -207,10 +207,10 @@ do_execsql_test analyze3-2.1.x {
} {200 990}
do_eqp_test analyze3-1.2.2 {
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
-} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x)}
+} {SEARCH t2 USING INDEX i2 (x>? AND x)}
do_eqp_test analyze3-1.2.3 {
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
-} {SCAN TABLE t2}
+} {SCAN t2}
do_test analyze3-1.2.4 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
@@ -259,10 +259,10 @@ do_execsql_test analyze3-1.3.x {
} {99 1000}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
-} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x)}
+} {SEARCH t3 USING INDEX i3 (x>? AND x)}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
-} {SCAN TABLE t3}
+} {SCAN t3}
do_test analyze3-1.3.4 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
@@ -314,10 +314,10 @@ do_test analyze3-2.1 {
} {}
do_eqp_test analyze3-2.2 {
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
-} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b)}
+} {SEARCH t1 USING INDEX i1 (b>? AND b)}
do_eqp_test analyze3-2.3 {
SELECT count(a) FROM t1 WHERE b LIKE '%a'
-} {SCAN TABLE t1}
+} {SCAN t1}
# Return the first argument if like_match_blobs is true (the default)
# or the second argument if not
@@ -704,11 +704,11 @@ do_test analyze3-6.1 {
do_eqp_test analyze3-6-3 {
SELECT * FROM t1 WHERE a = 5 AND c = 13;
-} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
+} {SEARCH t1 USING INDEX i2 (c=?)}
do_eqp_test analyze3-6-2 {
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
-} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
+} {SEARCH t1 USING INDEX i2 (c=?)}
#-----------------------------------------------------------------------------
# 2015-04-20.
diff --git a/test/analyze4.test b/test/analyze4.test
index 9fc98aa8f..e3b0d23f6 100644
--- a/test/analyze4.test
+++ b/test/analyze4.test
@@ -38,7 +38,7 @@ do_test analyze4-1.0 {
# Should choose the t1a index since it is more specific than t1b.
db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
# Verify that the t1b index shows that it does not narrow down the
# search any at all.
diff --git a/test/analyze6.test b/test/analyze6.test
index b6353f266..807fec132 100644
--- a/test/analyze6.test
+++ b/test/analyze6.test
@@ -61,7 +61,7 @@ do_test analyze6-1.0 {
#
do_test analyze6-1.1 {
eqp {SELECT count(*) FROM ev, cat WHERE x=y}
-} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
+} {/*SCAN cat USING COVERING INDEX catx*SEARCH ev USING COVERING INDEX evy (y=?)*/}
# The same plan is chosen regardless of the order of the tables in the
# FROM clause.
@@ -70,8 +70,8 @@ do_eqp_test analyze6-1.2 {
SELECT count(*) FROM cat, ev WHERE x=y
} {
QUERY PLAN
- |--SCAN TABLE cat USING COVERING INDEX catx
- `--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
+ |--SCAN cat USING COVERING INDEX catx
+ `--SEARCH ev USING COVERING INDEX evy (y=?)
}
@@ -86,26 +86,26 @@ do_test analyze6-2.1 {
ANALYZE;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.2 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.3 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.4 {
execsql {
INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
ANALYZE t201;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.5 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.6 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.7 {
execsql {
INSERT INTO t201 VALUES(4,5,7);
@@ -115,12 +115,12 @@ do_test analyze6-2.7 {
ANALYZE t201;
}
eqp {SELECT * FROM t201 WHERE z=5}
-} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
+} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.8 {
eqp {SELECT * FROM t201 WHERE y=5}
-} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
+} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.9 {
eqp {SELECT * FROM t201 WHERE x=5}
-} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
+} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
finish_test
diff --git a/test/analyze7.test b/test/analyze7.test
index b3dba0256..53a80f641 100644
--- a/test/analyze7.test
+++ b/test/analyze7.test
@@ -37,13 +37,13 @@ do_test analyze7-1.0 {
WHERE value BETWEEN 1 AND 256;
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-1.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-1.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
# Run an analyze on one of the three indices. Verify that this
# effects the row-count estimate on the one query that uses that
@@ -53,20 +53,20 @@ do_test analyze7-2.0 {
execsql {ANALYZE t1a;}
db cache flush
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
# Verify that since the query planner now things that t1a is more
# selective than t1b, it prefers to use t1a.
#
do_test analyze7-2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
# Run an analysis on another of the three indices. Verify that this
# new analysis works and does not disrupt the previous analysis.
@@ -75,40 +75,40 @@ do_test analyze7-3.0 {
execsql {ANALYZE t1cd;}
db cache flush;
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-3.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.2.1 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
ifcapable stat4 {
# If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
# row count for (c=2) than it does for (c=?).
do_test analyze7-3.2.2 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+ } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
} else {
# If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
# same as that for (c=?).
do_test analyze7-3.2.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
- } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
+ } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
}
do_test analyze7-3.3 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
ifcapable {!stat4} {
do_test analyze7-3.4 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
- } {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+ } {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.5 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
- } {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+ } {/*SEARCH t1 USING INDEX t1a (a=?)*/}
}
do_test analyze7-3.6 {
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
-} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
+} {/*SEARCH t1 USING INDEX t1cd (c=? AND d=?)*/}
finish_test
diff --git a/test/analyze8.test b/test/analyze8.test
index 7c61652e5..69605fd6f 100644
--- a/test/analyze8.test
+++ b/test/analyze8.test
@@ -61,25 +61,25 @@ do_test 1.0 {
#
do_test 1.1 {
eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.2 {
eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.3 {
eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.4 {
eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
+} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.5 {
eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.6 {
eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 2.1 {
eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b)*/}
+} {/*SEARCH t1 USING INDEX t1b (b>? AND b)*/}
# There are many more values of c between 0 and 100000 than there are
# between 800000 and 900000. So t1c is more selective for the latter
@@ -99,17 +99,17 @@ do_execsql_test 3.0 {
} {50 376 32}
do_test 3.1 {
eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
-} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b)*/}
+} {/*SEARCH t1 USING INDEX t1b (b>? AND b)*/}
do_test 3.2 {
eqp {SELECT * FROM t1
WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
-} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c)*/}
+} {/*SEARCH t1 USING INDEX t1c (c>? AND c)*/}
do_test 3.3 {
eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
-} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
+} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 3.4 {
eqp {SELECT * FROM t1
WHERE a=100 AND c BETWEEN 800000 AND 900000}
-} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c)*/}
+} {/*SEARCH t1 USING INDEX t1c (c>? AND c)*/}
finish_test
diff --git a/test/analyze9.test b/test/analyze9.test
index 75a02653d..a7f9b5dea 100644
--- a/test/analyze9.test
+++ b/test/analyze9.test
@@ -578,16 +578,16 @@ do_test 13.1 {
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<12
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
-} {/SEARCH TABLE t1 USING INDEX i2/}
+} {/SEARCH t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
-} {/SEARCH TABLE t1 USING INDEX i2/}
+} {/SEARCH t1 USING INDEX i2/}
#-------------------------------------------------------------------------
# Check also that affinities are taken into account when using stat4 data
@@ -609,10 +609,10 @@ do_test 14.1 {
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='ott' AND b<10 AND c=1
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
-} {/SEARCH TABLE t1 USING INDEX i1/}
+} {/SEARCH t1 USING INDEX i1/}
#-------------------------------------------------------------------------
# By default, 16 non-periodic samples are collected for the stat4 table.
@@ -1056,11 +1056,11 @@ do_eqp_test 23.1 {
-- Formerly used index i41. But i41 is not a covering index whereas
-- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
-- PRIMARY KEY is preferred.
-} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a)}
+} {SEARCH t4 USING PRIMARY KEY (c=? AND b=? AND a)}
do_eqp_test 23.2 {
SELECT * FROM t4 WHERE
(e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
-} {SEARCH TABLE t4 USING INDEX i42 (f)}
+} {SEARCH t4 USING INDEX i42 (f)}
do_execsql_test 24.0 {
CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
@@ -1106,25 +1106,25 @@ ifcapable stat4&&cte {
# Term (b) is estimated at 25%. Better than (a<30) but not as
# good as (a<20).
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b } \
- {SEARCH TABLE t6 USING INDEX bb (b)}
+ {SEARCH t6 USING INDEX bb (b)}
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b } \
- {SEARCH TABLE t6 USING INDEX aa (a)}
+ {SEARCH t6 USING INDEX aa (a)}
# Term (b BETWEEN ? AND ?) is estimated at 1/64.
do_eqp_test 25.3.1 {
SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ?
- } {SEARCH TABLE t6 USING INDEX bb (b>? AND b)}
+ } {SEARCH t6 USING INDEX bb (b>? AND b)}
# Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
# 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
# (a<20) but not as good as (a<10).
do_eqp_test 25.4.1 {
SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
- } {SEARCH TABLE t6 USING INDEX aa (a)}
+ } {SEARCH t6 USING INDEX aa (a)}
do_eqp_test 25.4.2 {
SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
- } {SEARCH TABLE t6 USING INDEX bb (b>? AND b)}
+ } {SEARCH t6 USING INDEX bb (b>? AND b)}
}
#-------------------------------------------------------------------------
@@ -1180,7 +1180,7 @@ do_execsql_test 26.1.3 {
#
do_eqp_test 26.1.4 {
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
-} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
+} {SEARCH t1 USING INDEX t1z (z=?)}
# This test - 26.2.* - tests that another manifestation of the same problem
@@ -1229,7 +1229,7 @@ do_execsql_test 26.2.1 {
do_eqp_test 26.2.2 {
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
-} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
+} {SEARCH t1 USING INDEX i1 (x=? AND y>?)}
finish_test
diff --git a/test/analyzeC.test b/test/analyzeC.test
index 2a0a89781..2f43d57a1 100644
--- a/test/analyzeC.test
+++ b/test/analyzeC.test
@@ -50,7 +50,7 @@ do_execsql_test 1.2 {
do_execsql_test 1.3 {
EXPLAIN QUERY PLAN
SELECT c FROM t1 ORDER BY a;
-} {/.*SCAN TABLE t1 USING INDEX t1a.*/}
+} {/.*SCAN t1 USING INDEX t1a.*/}
do_execsql_test 1.3x {
EXPLAIN QUERY PLAN
SELECT c FROM t1 ORDER BY a;
diff --git a/test/analyzeD.test b/test/analyzeD.test
index 9c7ed7586..7a51785a1 100644
--- a/test/analyzeD.test
+++ b/test/analyzeD.test
@@ -63,7 +63,7 @@ do_test 1.1 {
#
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
do_test 1.3 {
execsql { DELETE FROM sqlite_stat1 }
@@ -78,7 +78,7 @@ do_test 1.3 {
#
do_eqp_test 1.4 {
SELECT * FROM t1 WHERE a=3001 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
+} {SEARCH t1 USING INDEX t1_ab (a=?)}
do_test 1.5 {
execsql {
@@ -89,7 +89,7 @@ do_test 1.5 {
do_eqp_test 1.6 {
SELECT * FROM t1 WHERE a=13 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
do_test 1.7 {
execsql { DELETE FROM sqlite_stat1 }
@@ -102,6 +102,6 @@ do_test 1.7 {
# gets this right, even without stat1 data.
do_eqp_test 1.8 {
SELECT * FROM t1 WHERE a=13 AND c=150;
-} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
+} {SEARCH t1 USING INDEX t1_c (c=?)}
finish_test
diff --git a/test/analyzeE.test b/test/analyzeE.test
index 66db1e122..733b79367 100644
--- a/test/analyzeE.test
+++ b/test/analyzeE.test
@@ -36,47 +36,47 @@ do_execsql_test analyzeE-1.0 {
do_execsql_test analyzeE-1.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-1.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-1.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Verify that everything works the same on a DESCENDING index.
#
@@ -88,47 +88,47 @@ do_execsql_test analyzeE-2.0 {
do_execsql_test analyzeE-2.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-2.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100
-} {/SEARCH TABLE t1 USING INDEX t1a/}
+} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Now do a range query on the second term of an ASCENDING index
# where the first term is constrained by equality.
@@ -145,47 +145,47 @@ do_execsql_test analyzeE-3.0 {
do_execsql_test analyzeE-3.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-3.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-3.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
# Repeat the 3.x tests using a DESCENDING index
#
@@ -197,46 +197,46 @@ do_execsql_test analyzeE-4.0 {
do_execsql_test analyzeE-4.1 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-4.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.3 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.4 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.5 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.6 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.7 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>2500 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.8 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1900 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.9 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a>1100 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
do_execsql_test analyzeE-4.10 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1100 AND c=123
-} {/SEARCH TABLE t1 USING INDEX t1ca/}
+} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.11 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a<1900 AND c=123
-} {/SCAN TABLE t1/}
+} {/SCAN t1/}
finish_test
diff --git a/test/analyzeF.test b/test/analyzeF.test
index 143cecdf5..00107993e 100644
--- a/test/analyzeF.test
+++ b/test/analyzeF.test
@@ -62,7 +62,7 @@ foreach {tn where idx} {
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
} {
- set res "SEARCH TABLE t1 USING INDEX $idx"
+ set res "SEARCH t1 USING INDEX $idx"
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
}
@@ -92,7 +92,7 @@ foreach {tn where idx} {
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
} {
- set res "SEARCH TABLE t1 USING INDEX $idx"
+ set res "SEARCH t1 USING INDEX $idx"
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
}
diff --git a/test/analyzeG.test b/test/analyzeG.test
index eb1853b1d..ca65bc3b9 100644
--- a/test/analyzeG.test
+++ b/test/analyzeG.test
@@ -20,16 +20,6 @@ ifcapable !stat4 {
}
set testprefix analyzeG
-proc do_scan_order_test {tn sql expect} {
- uplevel [list do_test $tn [subst -nocommands {
- set res ""
- db eval "explain query plan $sql" {
- lappend res [set detail]
- }
- set res
- }] [list {*}$expect]]
-}
-
#-------------------------------------------------------------------------
# Test cases 1.* seek to verify that even if an index is not used, its
# stat4 data may be used by the planner to estimate the number of
@@ -54,15 +44,17 @@ do_execsql_test 1.0 {
# know this, so it has no preference as to which order the tables are
# scanned in. In practice this means that tables are scanned in the order
# they are specified in in the FROM clause.
-do_scan_order_test 1.1.1 {
+do_eqp_test 1.1.1 {
SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
- {SCAN TABLE t1} {SCAN TABLE t2}
+
}
-do_scan_order_test 1.1.2 {
+do_eqp_test 1.1.2 {
SELECT * FROM t2, t1 WHERE a=44 AND b=44
} {
- {SCAN TABLE t2} {SCAN TABLE t1}
+ QUERY PLAN
+ |--SCAN t2
+ `--SCAN t1
}
do_execsql_test 1.2 {
@@ -73,15 +65,19 @@ do_execsql_test 1.2 {
# Now, with the ANALYZE data, the planner knows that (b=44) matches a
# large number of rows. So it elects to scan table "t1" first, regardless
# of the order in which the tables are specified in the FROM clause.
-do_scan_order_test 1.3.1 {
+do_eqp_test 1.3.1 {
SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
- {SCAN TABLE t1} {SCAN TABLE t2}
+ QUERY PLAN
+ |--SCAN t1
+ `--SCAN t2
}
-do_scan_order_test 1.3.2 {
+do_eqp_test 1.3.2 {
SELECT * FROM t2, t1 WHERE a=44 AND b=44
} {
- {SCAN TABLE t1} {SCAN TABLE t2}
+ QUERY PLAN
+ |--SCAN t1
+ `--SCAN t2
}
diff --git a/test/attach.test b/test/attach.test
index 1e1d426a4..557201d65 100644
--- a/test/attach.test
+++ b/test/attach.test
@@ -910,4 +910,19 @@ do_execsql_test attach-12.1 {
PRAGMA integrity_check;
} {ok}
+# 2021-03-10 Forum post https://sqlite.org/forum/forumpost/a006d86f72
+#
+reset_db
+do_test attach-13.1 {
+ sqlite3 db :memory:
+ db eval {CREATE TABLE base(x);}
+ for {set i 0} {$i<$SQLITE_MAX_ATTACHED} {incr i} {
+ db eval "ATTACH ':memory:' AS a$i"
+ }
+ set m "a[expr {$SQLITE_MAX_ATTACHED-1}]"
+ db eval "CREATE TABLE $m.t1(a INTEGER PRIMARY KEY, b);"
+ db eval "CREATE TABLE $m.t2(a INTEGER PRIMARY KEY, b);"
+ db eval {SELECT a FROM t1 WHERE b IN (SELECT a FROM t2);}
+} {}
+
finish_test
diff --git a/test/attach4.test b/test/attach4.test
index 87911814a..9d54e7df5 100644
--- a/test/attach4.test
+++ b/test/attach4.test
@@ -135,4 +135,3 @@ do_execsql_test 2.2 {
}
finish_test
-
diff --git a/test/auth.test b/test/auth.test
index cc48fdb9a..d8f23a15e 100644
--- a/test/auth.test
+++ b/test/auth.test
@@ -1391,9 +1391,23 @@ do_test auth-1.205 {
}
catchsql {DROP INDEX i2}
} {1 {not authorized}}
-do_test auth-1.206 {
+do_test auth-1.205a {
set ::authargs
} {i2 t2 main {}}
+db eval {
+ ATTACH ':memory:' as di205;
+ CREATE TABLE di205.t1(x);
+ CREATE INDEX di205.t1x ON t1(x);
+}
+do_catchsql_test auth-1.205b {
+ DROP INDEX di205.t1x;
+} {1 {not authorized}}
+db eval {
+ DETACH di205;
+}
+do_test auth-1.206 {
+ set ::authargs
+} {t1x t1 di205 {}}
do_test auth-1.207 {
execsql {SELECT name FROM sqlite_master}
} {t2 i2}
diff --git a/test/autoindex1.test b/test/autoindex1.test
index b08f8cfeb..6b437f186 100644
--- a/test/autoindex1.test
+++ b/test/autoindex1.test
@@ -183,18 +183,18 @@ do_eqp_test autoindex1-500.1 {
WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
} {
QUERY PLAN
- |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
`--LIST SUBQUERY xxxxxx
- `--SCAN TABLE t502
+ `--SCAN t502
}
do_eqp_test autoindex1-501 {
SELECT b FROM t501
WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
QUERY PLAN
- |--SCAN TABLE t501
+ |--SCAN t501
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
+ `--SEARCH t502 USING AUTOMATIC COVERING INDEX (y=?)
}
do_eqp_test autoindex1-502 {
SELECT b FROM t501
@@ -202,9 +202,9 @@ do_eqp_test autoindex1-502 {
AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
QUERY PLAN
- |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SCAN TABLE t502
+ `--SCAN t502
}
# The following code checks a performance regression reported on the
@@ -277,13 +277,13 @@ do_eqp_test autoindex1-600a {
ORDER BY x.registering_flock;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE sheep AS s
- | |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date)
+ |--MATERIALIZE y
+ | |--SCAN s
+ | |--SEARCH prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date)
| `--CORRELATED SCALAR SUBQUERY xxxxxx
- | `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date)
- |--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
- `--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
+ | `--SEARCH later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date)
+ |--SCAN x USING INDEX sheep_reg_flock_index
+ `--SEARCH y USING AUTOMATIC COVERING INDEX (sheep_no=?)
}
@@ -294,7 +294,7 @@ do_eqp_test autoindex1-700a {
SELECT a FROM t5 WHERE b=10 ORDER BY c;
} {
QUERY PLAN
- |--SCAN TABLE t5
+ |--SCAN t5
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -413,7 +413,7 @@ do_execsql_test autoindex1-800 {
JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id)
JOIN accounts ON (raw_contacts.account_id=accounts._id)
WHERE mimetype_id=10 AND data14 IS NOT NULL;
-} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
+} {/SEARCH data .*SEARCH raw_contacts/}
do_execsql_test autoindex1-801 {
EXPLAIN QUERY PLAN
SELECT * FROM
@@ -421,7 +421,7 @@ do_execsql_test autoindex1-801 {
JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id)
JOIN accounts ON (raw_contacts.account_id=accounts._id)
WHERE mimetypes._id=10 AND data14 IS NOT NULL;
-} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
+} {/SEARCH data .*SEARCH raw_contacts/}
# Another test case from an important user of SQLite. The key feature of
# this test is that the "aggindex" subquery should make use of an
diff --git a/test/autoindex3.test b/test/autoindex3.test
index 9dcf2491f..824a82973 100644
--- a/test/autoindex3.test
+++ b/test/autoindex3.test
@@ -74,8 +74,8 @@ do_execsql_test 210 {
# At one point, SQLite was using the inferior plan:
#
-# 0|0|1|SEARCH TABLE v USING INDEX ve (e>?)
-# 0|1|0|SEARCH TABLE u USING COVERING INDEX uab (ANY(a) AND b=?)
+# 0|0|1|SEARCH v USING INDEX ve (e>?)
+# 0|1|0|SEARCH u USING COVERING INDEX uab (ANY(a) AND b=?)
#
# on the basis that the real index "uab" must be better than the automatic
# index. This is not right - a skip-scan is not necessarily better than an
@@ -85,8 +85,8 @@ do_eqp_test 220 {
select count(*) from u, v where u.b = v.b and v.e > 34;
} {
QUERY PLAN
- |--SEARCH TABLE v USING INDEX ve (e>?)
- `--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
+ |--SEARCH v USING INDEX ve (e>?)
+ `--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
}
diff --git a/test/autoindex5.test b/test/autoindex5.test
index 94e220328..36695d7f7 100644
--- a/test/autoindex5.test
+++ b/test/autoindex5.test
@@ -102,7 +102,7 @@ do_eqp_test autoindex5-1.1 {
AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
-} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
+} {SEARCH debian_cve USING AUTOMATIC COVERING INDEX (bug_name=?)}
#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
@@ -123,7 +123,7 @@ do_execsql_test 2.1 {
SELECT sum(z) FROM vvv WHERE x='aaa'
) FROM one;
} {8.0}
-do_execsql_test 2.2 {
+do_catchsql_test 2.2 {
DROP TABLE t1;
CREATE TABLE t1(aaa);
INSERT INTO t1(aaa) VALUES(9);
@@ -136,7 +136,7 @@ do_execsql_test 2.2 {
) WHERE bbb = 1
)
);
-} {9}
+} {1 {no such column: rowid}}
# Ticket https://www.sqlite.org/src/info/787fa716be3a7f65
# Segfault due to multiple uses of the same subquery where the
diff --git a/test/avfs.test b/test/avfs.test
new file mode 100644
index 000000000..2ebd608ba
--- /dev/null
+++ b/test/avfs.test
@@ -0,0 +1,395 @@
+# 2021-03-06
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements tests for the appendvfs extension.
+#
+# Tests performed:
+# avfs-1.0. Test that an appendvfs DB can be added to an empty (ZLF) file.
+# avfs-1.1. Test that the DB can be read with correct content upon reopen.
+# avfs-1.2. Test that an appendvfs DB can be added to a simple text file.
+# avfs-1.3. Test that the DB can be read with correct content upon reopen.
+# avfs-1.4. Test that appended DB is aligned to default page boundary.
+# avfs-2.1. Test that the simple text file retains its initial text.
+# avfs-3.1. Test that the appendvfs can grow and shrink, remaining intact.
+# avfs-3.2. Test that appendvfs is intact after grow/shrink/close/reopen.
+# avfs-3.3. Test that appendvfs can grow by many pages and be written.
+# avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
+# avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
+# avfs-4.1. Test shell's ability to append to a non-appendvfs file.
+# avfs-4.2. Test shell's ability to append to empty or nonexistent file.
+# avfs-4.3. Test shell's ability to reopen and alter an appendvfs file.
+# avfs-5.1. Test appendvfs refusal to open too-tiny DB appended onto ZLF.
+# avfs-5.2. Test appendvfs refusal to open too-tiny DB appended on other.
+# ...
+# (more to come)
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set ::testprefix avfs
+
+# Do not attempt this test if SQLITE_OMIT_VIRTUALTABLE is defined.
+#
+ifcapable !vtab {
+ finish_test
+ return
+}
+
+set CLI [test_find_cli]
+db close
+# forcedelete test.db
+
+load_static_extension db appendvfs
+
+set ::fa avfs.adb
+set ::fza avfs.sdb
+forcedelete $::fa $::fza
+set ::result {}
+
+proc shellDoesAr {} {
+ set shdo "sh_app1.sql"
+ forcedelete $shdo
+ set fd [open $shdo w]
+ puts $fd ".help\n.q"
+ close $fd
+ set res [catchcmd "-batch -cmd \".read $shdo\""]
+ return [regexp {^.archive} [lindex $res 1]]
+}
+
+set ::vf "&vfs=apndvfs"
+
+# Return file offset of appendvfs portion of a file, or {} if none such.
+proc fosAvfs {fname} {
+ if {[file size $fname] < 25} {
+ return {}
+ }
+ if {[catch {set fd [open $fname rb]}]} {
+ return {}
+ }
+ seek $fd -25 end
+ set am [read $fd 17]
+ set ao [read $fd 8]
+ close $fd
+ if {$am ne "Start-Of-SQLite3-"} {
+ return {}
+ }
+ binary scan $ao "W" rvo
+ return $rvo
+}
+
+do_test 1.0 {
+ set results {}
+ set out [open $::fza wb]
+ close $out
+ sqlite3 adb "file:$::fza?mode=rwc$::vf" -uri 1
+ adb eval {
+ PRAGMA page_size=1024;
+ PRAGMA cache_size=10;
+ CREATE TABLE t1(a TEXT);
+ INSERT INTO t1 VALUES ('dog'),('cat');
+ SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
+ } { lappend results $pets }
+ adb close
+ lappend results [fosAvfs $fza]
+ set ::result [join $results " | "]
+} {cat,dog | 0}
+
+do_test 1.1 {
+ set results {}
+ sqlite3 adb "file:$::fza?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
+ } { lappend results $pets }
+ adb close
+ set ::result [join $results " | "]
+} {dog,cat}
+
+do_test 1.2 {
+ set results {}
+ set out [open $::fa wb]
+ set ::tlo { "Just some text," "and more text," "ending at 3 lines." }
+ puts $out [join $::tlo "\n"]
+ close $out
+ set adbSz [file size $::fa]
+ sqlite3 adb "file:$::fa?mode=rwc$::vf" -uri 1
+ adb eval {
+ PRAGMA auto_vacuum = 0;
+ PRAGMA page_size=512;
+ PRAGMA cache_size=0;
+ CREATE TABLE t1(a TEXT);
+ INSERT INTO t1 VALUES ('dog'),('cat'),('pig');
+ SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a);
+ } { lappend results $pets }
+ adb close
+ set adaSz [file size $::fa]
+ lappend results "Bytes before/after $adbSz/$adaSz"
+ set ::result [join $results " | "]
+} {cat,dog,pig | Bytes before/after 50/5145}
+
+do_test 1.3 {
+ set results {}
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT group_concat(a) as pets FROM (SELECT a FROM t1 ORDER BY a DESC);
+ } { lappend results $pets }
+ adb close
+ set ::result [join $results " | "]
+} {pig,dog,cat}
+
+do_test 1.4 {
+ set ::result [fosAvfs $fa]
+} {4096}
+
+do_test 2.1 {
+ set in [open $::fa r]
+ set tli {}
+ for {set i [llength $::tlo]} {$i > 0} {incr i -1} {
+ lappend tli [gets $in]
+ }
+ close $in
+ if { [join $tli ":"] ne [join $::tlo ":"] } {
+ set ::result "Appendee changed."
+ } else {
+ set ::result "Appendee intact."
+ }
+} {Appendee intact.}
+
+# Set of repeatable random integers for a couple tests.
+set ::nrint 50000
+proc rint {v} {
+ return [::tcl::mathfunc::int [expr $v * 100000]]
+}
+array set ::randints [list 0 [rint [::tcl::mathfunc::srand 0]]]
+for {set i 1} {$i < $::nrint} {incr i} {
+ set ::randints($i) [rint [::tcl::mathfunc::rand]]
+}
+
+do_test 3.1 {
+ set results {}
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ DROP TABLE t1;
+ PRAGMA cache_size=10;
+ CREATE TABLE ri (i INTEGER);
+ BEGIN;
+ }
+ for {set i 0} {$i < $::nrint} {incr i} {
+ set r $::randints($i)
+ set s $::randints([incr i])
+ set t $::randints([incr i])
+ set u $::randints([incr i])
+ set v $::randints([incr i])
+ adb eval {
+ INSERT INTO ri VALUES ($r),($s),($t),($u),($v)
+ }
+ }
+ adb eval {
+ COMMIT;
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ set adbSz [file size $::fa]
+ set qr {}
+ adb eval {
+ SELECT count(*) as ic FROM ri;
+ DELETE FROM ri WHERE (i % 50) <> 25;
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ VACUUM;
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ SELECT count(*) as ic FROM ri;
+ } { lappend qr $ic }
+ adb close
+ set adaSz [file size $::fa]
+ set adba [expr ($adbSz + 0.1)/$adaSz]
+ # lappend results $adba
+ set results [concat $results [lrange $qr 0 2]]
+ lappend results [expr {$adba > 10.0}]
+ set ::result [join $results " | "]
+} "ok | $::nrint | ok | ok | 1"
+
+do_test 3.2 {
+ set results {}
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ adb close
+ set ::result [join $results " | "]
+} {ok}
+
+# avfs-3.3. Test that appendvfs can grow by many pages and be written.
+do_test 3.3 {
+ set results {}
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ set npages 300
+ adb eval { BEGIN }
+ while {$npages > 0} {
+ adb eval { INSERT INTO ri VALUES (randomblob(1500)) }
+ incr npages -1
+ }
+ adb eval { COMMIT }
+ adb eval {
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ adb close
+ set adaSzr [expr [file size $::fa] / 300.0 / 1500 ]
+ set okSzr [expr $adaSzr > 1.0 && $adaSzr < 1.3 ]
+ lappend results $okSzr
+ set ::result [join $results " | "]
+} {ok | 1}
+
+# avfs-3.4. Test that grown appendvfs can be reopened and appear intact.
+do_test 3.4 {
+ set results {}
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ adb close
+ set ::result $ic
+} {ok}
+
+# avfs-3.5. Test that much grown appendvfs can shrink and reopen intact.
+do_test 3.5 {
+ set results {}
+ set adbsz [file size $::fa]
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ DELETE FROM ri WHERE rowid % 8 <> 0;
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ VACUUM;
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ adb close
+ set adasz [file size $::fa]
+ lappend results [expr {$adbsz/$adasz > 5}]
+ sqlite3 adb "file:$::fa?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT integrity_check as ic FROM pragma_integrity_check();
+ } { lappend results $ic }
+ adb close
+ set ::result [join $results " | "]
+} {ok | ok | 1 | ok}
+
+set ::cliDoesAr [shellDoesAr]
+
+do_test 4.1 {
+ set shdo "sh_app1.sql"
+ set shod "sh_app1.adb"
+ forcedelete $shdo $shod
+ set ofd [open $shdo w]
+ if {$::cliDoesAr} {
+ puts $ofd ".ar -c"
+ } else {
+ puts $ofd "pragma page_size=512;"
+ puts $ofd "create table sqlar (a);"
+ }
+ puts $ofd ".tables"
+ puts $ofd ".q"
+ close $ofd
+ set ofd [open $shod wb]
+ puts $ofd "Some text."
+ close $ofd
+ set res [catchcmd "-append -batch -init $shdo $shod" ""]
+ lappend res [fosAvfs $shod]
+ forcedelete $shdo $shod
+ set ::result [join $res " | "]
+} {0 | sqlar | 4096}
+
+do_test 4.2 {
+ set shdo "sh_app1.sql"
+ set shod "sh_app1.adb"
+ forcedelete $shdo $shod
+ set ofd [open $shdo w]
+ if {$::cliDoesAr} {
+ puts $ofd ".ar -c"
+ } else {
+ puts $ofd "pragma page_size=512;"
+ puts $ofd "create table sqlar (a);"
+ }
+ puts $ofd ".tables"
+ puts $ofd ".q"
+ close $ofd
+ set ofd [open $shod wb]
+ close $ofd
+ set res [catchcmd "-append -batch -init $shdo $shod" ""]
+ lappend res [fosAvfs $shod]
+ forcedelete $shdo ; # Leave $shod for next test.
+ set ::result [join $res " | "]
+} {0 | sqlar | 0}
+
+do_test 4.3 {
+ set shdo "sh_app1.sql"
+ set shod "sh_app1.adb" ; # Same as test 4.2, reusing ADB.
+ forcedelete $shdo
+ set ofd [open $shdo w]
+ if {$::cliDoesAr} {
+ puts $ofd ".ar -u $shdo"
+ puts $ofd "select count(*) from sqlar where name = '$shdo';"
+ } else {
+ puts $ofd "insert into sqlar values (1);"
+ puts $ofd "select count(*) from sqlar;"
+ }
+ puts $ofd ".q"
+ close $ofd
+ set res [catchcmd "-append -batch -init $shdo $shod" ""]
+ sqlite3 adb "file:$shod?mode=rw$::vf" -uri 1
+ adb eval {
+ SELECT count(*) as n FROM sqlar
+ } { lappend res $n }
+ adb close
+ forcedelete $shdo $shod;
+ set ::result [join $res " | "]
+} {0 | 1 | 1}
+
+do_test 5.1 {
+ set fake "faketiny.sdb"
+ forcedelete $fake
+ set ofd [open $fake wb]
+ puts -nonewline $ofd "SQLite format 3"
+ puts -nonewline $ofd [binary format "c" 0]
+ puts -nonewline $ofd "Start-Of-SQLite3-"
+ puts -nonewline $ofd [binary format "W" 0]
+ close $ofd
+ if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
+ set res "Open failed."
+ } else {
+ adb close
+ set res "Opened when should not."
+ }
+ forcedelete $fake
+ set ::result $res
+} {Open failed.}
+
+do_test 5.2 {
+ set fake "faketiny.sdb"
+ forcedelete $fake
+ set ofd [open $fake wb]
+ set fakeAppendee "Dog ate my homework.\n"
+ puts -nonewline $ofd $fakeAppendee
+ puts -nonewline $ofd "SQLite format 3"
+ puts -nonewline $ofd [binary format "c" 0]
+ puts -nonewline $ofd "Start-Of-SQLite3-"
+ puts -nonewline $ofd [binary format "W" [string length $fakeAppendee]]
+ close $ofd
+ if {[catch {sqlite3 adb "file:$fake?mode=rw$::vf" -uri 1}]} {
+ set res "Open failed."
+ } else {
+ adb close
+ set res "Opened when should not."
+ }
+ forcedelete $fake
+ set ::result $res
+} {Open failed.}
+
+forcedelete $::fa $::fza
+
+unset -nocomplain ::fa ::fza ::tlo ::result ::randints ::nrint ::cliDoesAr
+
+finish_test
diff --git a/test/backup2.test b/test/backup2.test
index b58c6a3cd..1822e2dbf 100644
--- a/test/backup2.test
+++ b/test/backup2.test
@@ -144,7 +144,7 @@ do_test backup2-9 {
if {$tcl_platform(platform)=="windows"} {
set msg {cannot open source database: unable to open database file}
} elseif {[string match *BSD $tcl_platform(os)]} {
- set msg {restore failed: file is not a database}
+ set msg {}
} else {
set msg {cannot open source database: disk I/O error}
}
@@ -152,7 +152,8 @@ do_test backup2-10 {
forcedelete bu3.db
file mkdir bu3.db
set rc [catch {db restore temp bu3.db} res]
- lappend rc $res
+ if {[string match *BSD $tcl_platform(os)]} { set res "" }
+ list $rc $res
} [list 1 $msg]
# Try to restore from something that is not a database file.
diff --git a/test/bestindex1.test b/test/bestindex1.test
index b97af1114..0d6946994 100644
--- a/test/bestindex1.test
+++ b/test/bestindex1.test
@@ -51,11 +51,11 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM x1 WHERE a = 'abc'
-} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
+} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}
do_eqp_test 1.2 {
SELECT * FROM x1 WHERE a IN ('abc', 'def');
-} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
+} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}
#-------------------------------------------------------------------------
#
@@ -141,17 +141,17 @@ foreach {tn mode} {
set plan(use) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
`--USE TEMP B-TREE FOR ORDER BY
}
set plan(omit) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
`--USE TEMP B-TREE FOR ORDER BY
}
set plan(use2) {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/bestindex2.test b/test/bestindex2.test
index c17665f6f..81ed9ebf6 100644
--- a/test/bestindex2.test
+++ b/test/bestindex2.test
@@ -89,40 +89,40 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a='abc'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a='abc' AND b='def'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a='abc' AND a='def'
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
do_eqp_test 1.4 {
SELECT * FROM t1,t2 WHERE c=a
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- `--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ `--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
}
do_eqp_test 1.5 {
SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
do_eqp_test 1.6 {
SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
} {
QUERY PLAN
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
do_execsql_test 1.7.1 {
@@ -133,10 +133,10 @@ do_eqp_test 1.7.2 {
WHERE t1.a = t2.c AND t1.b = t3.e
} {
QUERY PLAN
- |--SCAN TABLE x1
- |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
- |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
- `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
+ |--SCAN x1
+ |--SCAN t1 VIRTUAL TABLE INDEX 0:
+ |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
+ `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}
finish_test
diff --git a/test/bestindex3.test b/test/bestindex3.test
index 80038e285..1ee3975f8 100644
--- a/test/bestindex3.test
+++ b/test/bestindex3.test
@@ -79,11 +79,11 @@ do_execsql_test 1.0 {
do_eqp_test 1.1 {
SELECT * FROM t1 WHERE a LIKE 'abc';
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
do_eqp_test 1.2 {
SELECT * FROM t1 WHERE a = 'abc';
-} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
+} {SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?}
do_eqp_test 1.3 {
SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
@@ -91,9 +91,9 @@ do_eqp_test 1.3 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
+ | `--SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?
`--INDEX 2
- `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
+ `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}
do_eqp_test 1.4 {
@@ -102,9 +102,9 @@ do_eqp_test 1.4 {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
+ | `--SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?
`--INDEX 2
- `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
+ `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}
do_execsql_test 1.5 {
@@ -155,9 +155,9 @@ ifcapable !icu {
QUERY PLAN
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t2 USING INDEX t2x (x>? AND x)
+ | `--SEARCH t2 USING INDEX t2x (x>? AND x)
`--INDEX 2
- `--SEARCH TABLE t2 USING INDEX t2y (y=?)
+ `--SEARCH t2 USING INDEX t2y (y=?)
}]
}
diff --git a/test/bestindex4.test b/test/bestindex4.test
index e395012c4..f90bf41e9 100644
--- a/test/bestindex4.test
+++ b/test/bestindex4.test
@@ -159,16 +159,16 @@ do_eqp_test 2.1 {
SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
QUERY PLAN
- |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
+ |--SCAN x1 VIRTUAL TABLE INDEX 0:
+ `--SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
}
do_eqp_test 2.2 {
SELECT * FROM t1, x1(t1.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
- `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555:
+ |--SCAN t1
+ `--SCAN x1 VIRTUAL TABLE INDEX 555:
}
diff --git a/test/bestindex7.test b/test/bestindex7.test
index aa1d70b86..f8d42b2b0 100644
--- a/test/bestindex7.test
+++ b/test/bestindex7.test
@@ -76,4 +76,3 @@ do_execsql_test 1.11 { select * from vt1 WHERE a IN (0, NULL) } {0}
do_execsql_test 1.12 { select * from vt1 WHERE a IN (NULL) } {}
finish_test
-
diff --git a/test/between.test b/test/between.test
index e2b25ca3c..16c3913d1 100644
--- a/test/between.test
+++ b/test/between.test
@@ -58,10 +58,10 @@ proc queryplan {sql} {
set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
# puts eqp=$eqp
foreach {a b c x} $eqp {
- if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
- $x all as tab idx]} {
+ if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
+ $x all ss as tab idx]} {
lappend data $tab $idx
- } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
+ } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
lappend data $tab *
}
}
diff --git a/test/bigmmap.test b/test/bigmmap.test
index 62e035b05..7802fd58e 100644
--- a/test/bigmmap.test
+++ b/test/bigmmap.test
@@ -94,9 +94,9 @@ for {set i 0} {$i < 9} {incr i} {
ORDER BY b, c;
" [string map {"\n " "\n"} "
QUERY PLAN
- |--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
+ |--SCAN o USING COVERING INDEX sqlite_autoindex_t${t}_1
`--CORRELATED SCALAR SUBQUERY xxxxxx
- `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH i USING INTEGER PRIMARY KEY (rowid=?)
"]
}
}
diff --git a/test/busy2.test b/test/busy2.test
index db8ca0e38..61fb8496a 100644
--- a/test/busy2.test
+++ b/test/busy2.test
@@ -168,4 +168,3 @@ do_multiclient_test tn {
}
finish_test
-
diff --git a/test/columncount.test b/test/columncount.test
new file mode 100644
index 000000000..669a35a72
--- /dev/null
+++ b/test/columncount.test
@@ -0,0 +1,56 @@
+# 2021 February 15
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the sqlite3_column_count() API.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix columncount
+
+proc do_ccsql_test {tn sql res} {
+
+ uplevel [list do_test $tn [subst -nocommands {
+ set stmt [sqlite3_prepare_v2 db {$sql} -1 dummy]
+ set res [sqlite3_column_count [set stmt]]
+ while {[sqlite3_step [set stmt]]=="SQLITE_ROW"} {
+ for {set i 0} {[set i] < [sqlite3_data_count [set stmt]]} {incr i} {
+ lappend res [sqlite3_column_text [set stmt] [set i]]
+ }
+ }
+
+ set rc [sqlite3_finalize [set stmt]]
+ if {[set rc]!="SQLITE_OK"} {
+ error [sqlite3_errmsg db]
+ }
+
+ set res
+ }] [list {*}$res]]
+
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(x, y, z);
+ INSERT INTO t1 VALUES('a', 'b', 'c');
+}
+
+do_ccsql_test 1.1 { SELECT * FROM t1 } {3 a b c}
+do_ccsql_test 1.2 { CREATE TABLE t2(a, b) } {0}
+
+do_ccsql_test 1.3 { ALTER TABLE t2 RENAME TO t3 } {0}
+do_ccsql_test 1.4 { ALTER TABLE t3 RENAME b TO ccc } {0}
+do_ccsql_test 1.5 { ALTER TABLE t3 ADD COLUMN d } {0}
+
+do_ccsql_test 1.6 { DROP TABLE t3 } {0}
+
+
+
+finish_test
diff --git a/test/corrupt4.test b/test/corrupt4.test
index 55969c6a8..5b0965a83 100644
--- a/test/corrupt4.test
+++ b/test/corrupt4.test
@@ -13,10 +13,10 @@
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
-# $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix corrupt4
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
@@ -79,4 +79,71 @@ do_test corrupt4-1.4 {
}
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+
+reset_db
+do_execsql_test 2.0 {
+ PRAGMA page_size = 512;
+ CREATE TABLE t1(a, b, c);
+}
+
+# Create a database with a schema so large that the root of the
+# sqlite_schema table is the grandparent of its leaves.
+#
+set nView 1000
+do_test 2.1 {
+ execsql BEGIN
+ for {set ii 0} {$ii<$nView} {incr ii} {
+ execsql " CREATE VIEW v$ii AS SELECT a, b, c FROM t1 "
+ }
+ execsql COMMIT
+} {}
+db close
+
+proc get2byte {fd offset} {
+ seek $fd $offset
+ set bin [read $fd 2]
+ binary scan $bin S val
+ set val
+}
+proc get4byte {fd offset} {
+ seek $fd $offset
+ set bin [read $fd 4]
+ binary scan $bin I val
+ set val
+}
+proc put4byte {fd offset val} {
+ seek $fd $offset
+ set bin [binary format I $val]
+ puts -nonewline $fd $bin
+}
+
+# Page 1 is now the grandparent of its leaves. Corrupt the database by setting
+# the second rightmost child page number of page 1 to 1.
+#
+set fd [open test.db r+]
+fconfigure $fd -encoding binary -translation binary
+set nChild [get2byte $fd 103]
+set offChild [get2byte $fd [expr 100+12+($nChild-2)*2]]
+set pgnoChild [get4byte $fd $offChild]
+put4byte $fd $offChild 1
+close $fd
+
+if {![info exists ::G(perm:presql)]} {
+ sqlite3 db test.db
+
+ do_catchsql_test 2.2 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM sqlite_schema;
+ } {1 {database disk image is malformed}}
+
+ do_test 2.3 {
+ list [catch {
+ for {set ii $nView} {$ii<$nView*2} {incr ii} {
+ execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
+ }
+ } msg] $msg
+ } {1 {database disk image is malformed}}
+}
+
finish_test
diff --git a/test/corruptL.test b/test/corruptL.test
index 9af9fd2cf..5ade7010d 100644
--- a/test/corruptL.test
+++ b/test/corruptL.test
@@ -1337,5 +1337,93 @@ if {[wal_is_capable]} {
} {}
}
+#-------------------------------------------------------------------------
+reset_db
+do_test 18.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 12288 pagesize 4096 filename crash-40d5739835cbdb.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
+| 96: 00 00 00 00 0d 00 00 00 02 0f 4e 00 0f a2 0f 4e ..........N....N
+| 3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 52 02 ..............R.
+| 3920: 07 17 11 11 01 81 0f 74 61 62 6c 65 74 32 74 32 .......tablet2t2
+| 3936: 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32 .CREATE TABLE t2
+| 3952: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 45 47 45 (a INT, b INTEGE
+| 3968: 52 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 61 R, PRIMARY KEY(a
+| 3984: 2c 62 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 ,b)) WITHOUT ROW
+| 4000: 49 44 5c 01 07 16 11 11 01 81 23 74 61 62 6c 65 ID........#table
+| 4016: 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c t1t1.CREATE TABL
+| 4032: 45 20 74 31 28 61 20 49 4e 54 20 50 52 49 4d 41 E t1(a INT PRIMA
+| 4048: 52 59 20 4b 45 59 2c 20 62 20 54 45 58 54 2c 20 RY KEY, b TEXT,
+| 4064: 63 20 54 45 58 54 2c 20 64 20 49 4e 54 45 47 45 c TEXT, d INTEGE
+| 4080: 52 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 R) WITHOUT ROWID
+| page 2 offset 4096
+| 0: 0a 00 00 00 06 0f a7 00 0f f4 0f e5 0f d5 0f c5 ................
+| 16: 0f b6 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 4000: 00 00 00 00 00 00 00 0f 05 01 15 13 01 06 65 7f ..............e.
+| 4016: 25 6e 73 69 78 06 0e 05 01 13 15 03 b5 6f 64 64 %nsix........odd
+| 4032: 66 69 76 65 05 0f 05 01 15 15 01 04 65 76 65 61 five........evea
+| 4048: e6 6f 75 82 04 0f 05 01 13 17 01 03 6f 64 64 74 .ou.........oddt
+| 4064: 68 72 61 15 03 0e 05 01 15 12 01 02 64 76 64 6e hra.........dvdn
+| 4080: 74 77 6f 02 00 00 00 00 00 00 00 00 00 00 00 00 two.............
+| page 3 offset 8192
+| 2816: 00 00 00 00 00 00 00 00 00 00 00 06 03 02 01 00 ................
+| 2832: c8 07 06 03 02 01 00 c7 11 06 03 02 01 02 a6 52 ...............R
+| 2848: 06 d5 02 01 10 c5 1b 06 03 02 00 ef c4 53 06 03 .............S..
+| 2864: 02 01 00 c3 22 06 04 02 01 00 c2 26 06 03 02 01 ...........&....
+| 2880: 00 c2 1e 02 b3 02 01 00 c0 3a 06 03 3c 01 00 bf .........:..<...
+| 2896: 2c 06 03 02 01 00 be 27 00 83 02 01 01 bd 15 06 ,......'........
+| 2912: 03 02 01 00 bc 21 06 03 02 01 00 bb 54 16 13 02 .....!......T...
+| 2928: 01 09 9a 0a 06 03 02 01 00 b9 53 06 03 02 01 00 ..........S.....
+| 2944: b8 52 06 13 02 01 00 b7 1e 06 03 02 01 00 b6 34 .R.............4
+| 2960: 06 13 02 01 00 b5 3a 05 f3 12 01 00 b4 45 05 03 ......:......E..
+| 2976: 02 00 00 b4 6f 06 03 02 01 00 b2 03 06 03 02 01 ....o...........
+| 2992: 00 b1 63 06 03 02 01 00 b0 24 06 03 02 01 00 9f ..c......$......
+| 3008: ac 06 03 02 01 00 a2 2f 07 03 02 01 01 ad 21 06 ......./......!.
+| 3024: 03 02 01 fb cd 5b 06 c0 01 f1 00 ab 23 06 03 02 .....[......#...
+| 3040: 01 00 aa 5b 06 03 02 01 00 a3 ce 06 02 03 01 00 ...[............
+| 3056: a8 0e 06 03 02 01 00 a7 0c 06 02 f1 01 00 a6 0d ................
+| 3072: 06 03 02 01 00 95 25 06 03 02 01 00 a4 17 06 03 ......%.........
+| 3088: 02 01 00 a3 09 06 03 02 01 00 a2 51 06 03 02 02 ...........Q....
+| 3104: 00 a1 40 06 01 e2 00 00 a0 4b 06 13 02 00 00 9e ..@......K......
+| 3120: 5d 06 03 02 01 10 9e 81 06 03 02 01 00 9d 42 06 ].............B.
+| 3136: 03 69 01 00 9c 48 06 03 02 01 00 9b 48 06 03 01 .i...H......H...
+| 3152: 01 00 9a 09 06 03 02 01 00 99 2f 06 03 02 01 00 ........../.....
+| 3168: 98 3a 06 03 02 01 00 97 24 06 03 02 01 00 96 4a .:......$......J
+| 3184: 06 03 02 11 00 f9 50 02 93 02 01 00 94 2f 06 03 ......P....../..
+| 3200: 02 11 04 93 1a 06 03 01 04 e0 92 1a 06 03 02 01 ................
+| 3216: 00 91 27 06 03 02 01 00 90 23 06 03 02 01 00 8f ..'......#......
+| 3232: 3b 06 03 02 01 00 8e 46 06 16 02 01 00 8d 1d 07 ;......F........
+| 3248: 23 12 01 00 8c 5a 06 03 02 01 00 8a 39 06 03 02 #....Z......9...
+| 3264: 00 ff 84 b5 06 03 02 01 00 89 07 06 03 02 11 00 ................
+| 3280: 88 02 06 03 02 01 00 87 19 06 03 02 01 00 86 4d ...............M
+| 3296: 06 13 12 00 00 85 4b 06 03 02 01 00 84 37 06 13 ......K......7..
+| 3312: 02 01 00 83 2c 06 03 02 01 00 81 60 06 13 02 11 ....,......`....
+| 3328: 00 81 3b 06 03 02 01 0a b0 5a 06 03 01 01 7f 22 ..;......Z......
+| 3344: 05 03 01 01 7e 21 05 03 01 01 7d 0b 15 03 01 02 ....~!..........
+| 3360: 7b 08 05 03 06 91 7b 22 05 03 01 01 7a 58 05 03 ............zX..
+| 3376: 01 01 7a 4f 05 03 01 01 78 49 05 03 01 01 77 16 ..zO....xI....w.
+| 3392: 05 03 01 01 76 5f 05 03 01 01 75 0f 05 03 01 01 ....v_....u.....
+| 3408: 74 2f 05 03 01 01 3f 1f 05 03 01 02 72 14 05 03 t/....?.....r...
+| 3424: 00 f1 71 08 05 03 01 01 70 0c 05 03 01 47 7f 29 ..q.....p....G.)
+| 3440: 05 03 01 01 6e 57 05 03 01 01 6d 33 05 13 00 f1 ....nW....m3....
+| 3456: 6c 0b 05 03 01 01 6b 49 05 03 01 01 69 05 05 03 l.....kI....i...
+| 3472: 01 02 ed 23 00 00 01 00 00 00 00 00 00 00 00 00 ...#............
+| end crash-40d5739835cbdb.db
+}]} {}
+
+ifcapable json1 {
+do_catchsql_test 18.1 {
+ SELECT
+ json_group_array(c) OVER win4
+ FROM t1
+ WINDOW win4 AS (
+ ORDER BY a COLLATE nocase RANGE BETWEEN 1.0 PRECEDING AND CURRENT ROW
+ )
+} {1 {JSON cannot hold BLOB values}}
+} ;# ifcapable json1
finish_test
diff --git a/test/corruptN.test b/test/corruptN.test
new file mode 100644
index 000000000..8600e438d
--- /dev/null
+++ b/test/corruptN.test
@@ -0,0 +1,228 @@
+# 2020-12-16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix corruptN
+
+# These tests deal with corrupt database files
+#
+database_may_be_corrupt
+
+reset_db
+do_test 1.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 4096 pagesize 512 filename sql024239.txt.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 02 00 01 01 00 40 20 20 00 00 00 0c 00 00 00 07 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04 ................
+| 48: 00 00 00 00 89 00 00 04 00 10 00 01 0a 00 00 01 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c ................
+| 96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0 ..,P............
+| 112: 01 56 01 86 01 2a 01 06 00 00 00 00 00 00 00 00 .V...*..........
+| 256: 00 00 00 00 00 00 22 07 06 17 11 11 01 31 74 61 .............1ta
+| 272: 62 6c 65 74 34 74 34 07 43 52 45 41 54 45 20 54 blet4t4.CREATE T
+| 288: 41 42 4c 45 20 74 34 28 78 29 2a 06 06 17 13 11 ABLE t4(x)*.....
+| 304: 01 3f 69 6e 64 65 78 74 33 78 74 33 05 43 52 45 .?indext3xt3.CRE
+| 320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e ATE INDEX t3x ON
+| 336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e t3(x).......Ein
+| 352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45 dext2cdt2.CREATE
+| 368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74 INDEX t2cd ON t
+| 384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61 2(c,d)(......=ta
+| 400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54 blet3t3.CREATE T
+| 416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29 ABLE t3(c,x,e,f)
+| 432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74 (......=tablet2t
+| 448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 2.CREATE TABLE t
+| 464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11 2(c,d,e,f)$.....
+| 480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .5tablet1t1.CREA
+| 496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29 TE TABLE t1(a,b)
+| page 2 offset 512
+| 0: 0d 00 00 00 04 01 41 00 01 fa 01 f3 01 de 01 cf ......A.........
+| 160: 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 .. .............
+| 448: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d ................
+| 464: 04 03 17 17 73 65 76 65 6e 65 69 67 68 74 13 03 ....seveneight..
+| 480: 03 07 07 40 14 00 00 00 00 00 00 40 18 00 00 00 ...@.......@....
+| 496: 00 00 00 05 02 03 01 01 03 04 04 01 03 09 01 02 ................
+| page 3 offset 1024
+| 0: 0d 00 00 00 08 01 54 00 01 f7 01 ec 01 c5 01 aa ......T.........
+| 16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 112: 00 00 dd 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 336: 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68 74 ...........eight
+| 352: 65 69 67 68 74 73 65 76 65 6e 73 65 76 65 6e 25 eightsevenseven%
+| 368: 07 05 07 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 432: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
+| 480: 00 00 0f 04 17 17 01 65 69 67 68 74 65 69 67 68 .......eighteigh
+| 496: 74 08 15 04 07 07 01 40 18 00 00 00 00 00 00 40 t......@.......@
+| page 4 offset 1536
+| 0: 18 00 00 00 00 00 00 07 07 04 01 01 01 04 04 06 ................
+| 16: 07 04 01 01 01 02 02 05 0f 04 17 17 01 73 6d 76 .............smv
+| 32: 65 6e 65 69 67 68 74 04 15 04 07 07 01 40 14 00 eneight......@..
+| page 5 offset 2048
+| 0: 0a 00 00 00 08 01 96 00 01 fa 01 c4 01 f2 01 bc ................
+| 16: 01 dc 01 e1 01 96 01 cc 00 00 00 00 00 00 00 00 ................
+| 160: 00 00 00 00 00 00 32 00 00 00 00 00 00 00 00 00 ......2.........
+| 368: 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 400: 00 00 00 00 00 00 0f 04 17 17 01 85 69 67 68 74 ............ight
+| 416: 65 69 67 68 74 08 15 04 07 07 01 40 18 00 00 00 eight......@....
+| 432: 00 00 00 40 18 00 00 00 00 00 00 07 07 04 01 01 ...@............
+| 448: 01 04 04 06 07 04 01 01 01 02 02 05 0f 04 17 17 ................
+| 464: 01 73 6d 76 65 6e 65 69 67 68 74 04 15 04 07 07 .smveneight.....
+| 480: 01 40 14 00 00 00 00 00 00 40 18 00 00 00 00 00 .@.......@......
+| 496: 00 03 07 04 01 01 01 03 04 02 05 04 03 01 09 02 ................
+| page 6 offset 2560
+| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 16: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 ................
+| 304: 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 00 ...&............
+| page 7 offset 3072
+| 0: 0d 00 00 00 08 01 c2 00 01 fb 01 f6 01 f1 01 ec ................
+| 16: 01 e0 01 d4 01 cb 01 c2 00 00 00 00 00 00 00 00 ................
+| 128: 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 04 ............. ..
+| 384: 00 00 00 00 00 00 00 00 00 07 08 02 17 65 69 fc .............ei.
+| 400: 68 74 07 07 02 17 65 69 67 68 74 0a fb fd f8 bf ht....eight.....
+| 416: e7 ff ff ff 00 00 00 0a 05 02 07 40 18 00 00 00 ...........@....
+| 432: 00 00 00 03 04 02 01 04 03 03 02 01 04 03 02 01 ................
+| 448: ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 ................
+| end sql024239.txt.db
+}]} {}
+
+do_catchsql_test 1.1 {
+ VACUUM;
+} {1 {database disk image is malformed}}
+
+# 2021-04-05 dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618
+do_test 2.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 16384 pagesize 4096 filename c-b92b.txt.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 96: 00 00 00 00 0d 0f f8 00 04 0f 12 00 0f 91 0f d3 ................
+| 112: 0f 67 0f 12 00 00 00 00 00 00 00 00 00 00 00 00 .g..............
+| 3856: 00 00 53 04 07 1b 13 11 08 81 0d 74 72 69 67 67 ..S........trigg
+| 3872: 65 72 74 72 30 74 31 43 52 45 41 54 45 20 54 52 ertr0t1CREATE TR
+| 3888: 49 47 47 45 52 20 74 72 30 20 44 45 4c 45 54 45 IGGER tr0 DELETE
+| 3904: 20 4f 4e 20 74 31 20 42 45 47 49 4e 0a 20 20 55 ON t1 BEGIN. U
+| 3920: 50 44 41 54 45 20 74 31 20 53 45 54 20 62 20 3d PDATE t1 SET b =
+| 3936: 20 61 3b 0a 45 4e 44 28 03 06 17 11 11 01 3d 69 a;.END(......=i
+| 3952: 6e 64 65 78 69 30 74 31 04 43 52 45 41 54 45 20 ndexi0t1.CREATE
+| 3968: 49 4e 44 45 58 20 69 30 20 4f 4e 20 74 31 28 62 INDEX i0 ON t1(b
+| 3984: 29 40 01 06 17 11 11 01 6d 74 61 62 6c 65 74 31 )@......mtablet1
+| 4000: 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 t1.CREATE TABLE
+| 4016: 74 31 28 61 20 55 4e 49 51 55 45 20 4f 4e 20 43 t1(a UNIQUE ON C
+| 4032: 4f 4e 46 4c 49 43 54 20 52 45 50 4c 41 43 45 2c ONFLICT REPLACE,
+| 4048: 20 62 29 23 02 06 17 37 11 01 00 69 6e 64 65 78 b)#...7...index
+| 4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78 sqlite_autoindex
+| 4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00 _t1_1t1.........
+| page 2 offset 4096
+| 0: 0d 00 00 00 02 0f 00 00 00 00 00 00 00 00 00 00 ................
+| 4080: 00 00 05 02 03 01 01 09 0d 05 01 03 01 01 04 0c ................
+| page 3 offset 8192
+| 0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00 ................
+| 4080: 00 00 00 00 00 05 03 01 01 09 02 04 03 01 09 04 ................
+| page 4 offset 12288
+| 0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00 ................
+| 4080: 00 00 00 00 00 05 03 01 01 0d 02 04 03 00 00 00 ................
+| end c-b92b.txt.db
+}]} {}
+
+prng_seed 0 db
+do_catchsql_test 2.1 {
+SELECT count(*) FROM sqlite_schema;
+WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
+INSERT INTO t1(a) SELECT randomblob(null) FROM c;
+} {1 {database disk image is malformed}}
+
+reset_db
+if {![info exists ::G(perm:presql)]} {
+ do_execsql_test 3.0 {
+ CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = 'CREATE TABLE sqlite_sequence(name-seq)'
+ WHERE name = 'sqlite_sequence';
+ }
+ db close
+ sqlite3 db test.db
+ do_catchsql_test 3.1 {
+ PRAGMA writable_schema = 1;
+ INSERT INTO t1(y) VALUES('abc');
+ } {1 {database disk image is malformed}}
+ reset_db
+
+ do_execsql_test 4.1 {
+ CREATE TABLE x1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE);
+ INSERT INTO x1 VALUES(1, 1, 2);
+ INSERT INTO x1 VALUES(2, 2, 3);
+ INSERT INTO x1 VALUES(3, 3, 4);
+ INSERT INTO x1 VALUES(4, 5, 6);
+ PRAGMA writable_schema = 1;
+
+ UPDATE sqlite_schema SET rootpage = (
+ SELECT rootpage FROM sqlite_schema WHERE name = 'sqlite_autoindex_x1_2'
+ ) WHERE name = 'sqlite_autoindex_x1_1';
+ }
+
+ db close
+ sqlite3 db test.db
+ breakpoint
+ do_catchsql_test 4.2 {
+ PRAGMA writable_schema = 1;
+ REPLACE INTO x1 VALUES(5, 2, 3);
+ } {1 {database disk image is malformed}}
+
+}
+
+#-------------------------------------------------------------------------
+
+reset_db
+
+ifcapable json1&&vtab {
+ db func strreplace strreplace
+ proc strreplace {orig a b} {
+ string map [list $a $b] $orig
+ }
+
+ do_execsql_test 5.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1b ON t1(b);
+
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema
+ SET sql = strreplace(sql, 't1', 'json_each')
+ WHERE type='index';
+ }
+
+ # Do not run this tests if there is any presql (SQL run from within
+ # the [sqlite3] command) configured. In this case the schema is parsed
+ # before the "PRAGMA writable_schema" command is executed and the
+ # script throws and exception.
+ if {[info exists ::G(perm:presql)]==0 || $::G(perm:presql)==""} {
+ db close
+ sqlite3 db test.db
+
+ do_execsql_test 5.1 {
+ PRAGMA writable_schema = 1;
+ SELECT * FROM t1
+ }
+ }
+}; # ifcapable json1&&vtab
+
+
+finish_test
diff --git a/test/cost.test b/test/cost.test
index 592973ab5..5684177a1 100644
--- a/test/cost.test
+++ b/test/cost.test
@@ -25,8 +25,8 @@ do_eqp_test 1.2 {
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
} {
QUERY PLAN
- |--SCAN TABLE t3 USING COVERING INDEX i3
- `--SEARCH TABLE t4 USING INDEX i4 (c=?)
+ |--SCAN t3 USING COVERING INDEX i3
+ `--SEARCH t4 USING INDEX i4 (c=?)
}
@@ -39,7 +39,7 @@ do_execsql_test 2.1 {
# if the index is a non-covering index.
do_eqp_test 2.2 {
SELECT * FROM t1 ORDER BY a;
-} {SCAN TABLE t1 USING INDEX i1}
+} {SCAN t1 USING INDEX i1}
do_execsql_test 3.1 {
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
@@ -59,11 +59,11 @@ do_eqp_test 3.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t5 USING INDEX t5b (b=?)
+ | | `--SEARCH t5 USING INDEX t5b (b=?)
| |--INDEX 2
- | | `--SEARCH TABLE t5 USING INDEX t5c (c=?)
+ | | `--SEARCH t5 USING INDEX t5c (c=?)
| `--INDEX 3
- | `--SEARCH TABLE t5 USING INDEX t5d (d=?)
+ | `--SEARCH t5 USING INDEX t5d (d=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -83,11 +83,11 @@ do_execsql_test 4.1 {
}
do_eqp_test 4.2 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
-} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test 4.3 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
-} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b)}
+} {SEARCH t1 USING INDEX i2 (b>? AND b)}
#-------------------------------------------------------------------------
@@ -102,7 +102,7 @@ do_eqp_test 5.2 {
SELECT * FROM t2 ORDER BY x, y;
} {
QUERY PLAN
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
@@ -110,7 +110,7 @@ do_eqp_test 5.3 {
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
} {
QUERY PLAN
- |--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x)
+ |--SEARCH t2 USING INDEX t2i1 (x>? AND x)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -128,9 +128,9 @@ do_eqp_test 6.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b)
+ | | `--SEARCH t3 USING INDEX t3i1 (b>? AND b)
| `--INDEX 2
- | `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
+ | `--SEARCH t3 USING INDEX t3i2 (c=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -155,9 +155,9 @@ do_eqp_test 7.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t1 USING INDEX t1b (b>? AND b)
+ | | `--SEARCH t1 USING INDEX t1b (b>? AND b)
| `--INDEX 2
- | `--SEARCH TABLE t1 USING INDEX t1b (b=?)
+ | `--SEARCH t1 USING INDEX t1b (b=?)
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -166,11 +166,11 @@ do_eqp_test 7.3 {
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
-} {SCAN TABLE t1}
+} {SCAN t1}
do_eqp_test 7.4 {
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
-} {SCAN TABLE t1}
+} {SCAN t1}
#-------------------------------------------------------------------------
#
@@ -202,9 +202,9 @@ do_eqp_test 8.2 {
AND unlikely(album.aid=track.aid);
} {
QUERY PLAN
- |--SCAN TABLE track
- |--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
- |--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN track
+ |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR DISTINCT
}
@@ -271,19 +271,19 @@ ifcapable stat4 {
do_eqp_test 10.3 {
SELECT rowid FROM t6 WHERE a=0 AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
+ } {SEARCH t6 USING INDEX t6i2 (c=?)}
do_eqp_test 10.4 {
SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
+ } {SEARCH t6 USING INDEX t6i2 (c=?)}
do_eqp_test 10.5 {
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
+ } {SEARCH t6 USING INDEX t6i1 (a=?)}
do_eqp_test 10.6 {
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
- } {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
+ } {SEARCH t6 USING INDEX t6i1 (a=? AND b=?)}
}
finish_test
diff --git a/test/count.test b/test/count.test
index 250eb669b..9769b765f 100644
--- a/test/count.test
+++ b/test/count.test
@@ -212,25 +212,25 @@ do_eqp_test count-7.2 {
SELECT count(1) FROM t1;
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX t1b
+ `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.3 {
SELECT count(1) FROM t1 NOT INDEXED
} {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
do_eqp_test count-7.3 {
SELECT count(*) FROM t1;
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX t1b
+ `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.4 {
SELECT count(*) FROM t1 NOT INDEXED
} {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
diff --git a/test/coveridxscan.test b/test/coveridxscan.test
index cc9864439..c87227cab 100644
--- a/test/coveridxscan.test
+++ b/test/coveridxscan.test
@@ -109,11 +109,11 @@ do_execsql_test 5.1.0 "
do_eqp_test 5.1.1 {
SELECT * FROM t1 ORDER BY c1, c2;
-} {SCAN TABLE t1 USING COVERING INDEX i1}
+} {SCAN t1 USING COVERING INDEX i1}
do_eqp_test 5.1.2 {
SELECT * FROM t2 ORDER BY c1, c2;
-} {SCAN TABLE t2 USING COVERING INDEX i2}
+} {SCAN t2 USING COVERING INDEX i2}
finish_test
diff --git a/test/crash5.test b/test/crash5.test
index b80b15137..fc078b350 100644
--- a/test/crash5.test
+++ b/test/crash5.test
@@ -21,7 +21,7 @@ source $testdir/tester.tcl
# Only run these tests if memory debugging is turned on.
#
ifcapable !crashtest||!memorymanage {
- puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..."
+ puts "Skipping crash5 tests: not compiled with -DSQLITE_ENABLE_MEMORY_MANAGEMENT..."
finish_test
return
}
@@ -29,7 +29,7 @@ ifcapable !crashtest||!memorymanage {
db close
for {set ii 0} {$ii < 10} {incr ii} {
- for {set jj 50} {$jj < 100} {incr jj} {
+ for {set jj 1} {$jj < 100} {incr jj} {
# Set up the database so that it is an auto-vacuum database
# containing a single table (root page 3) with a single row.
@@ -47,6 +47,20 @@ for {set ii 0} {$ii < 10} {incr ii} {
do_test crash5-$ii.$jj.1 {
crashsql -delay 1 -file test.db-journal -seed $ii -tclbody [join [list \
[list set iFail $jj] {
+ proc get_pwd {} {
+ if {$::tcl_platform(platform) eq "windows"} {
+ if {[info exists ::env(ComSpec)]} {
+ set comSpec $::env(ComSpec)
+ } else {
+ # NOTE: Hard-code the typical default value.
+ set comSpec {C:\Windows\system32\cmd.exe}
+ }
+ return [string map [list \\ /] \
+ [string trim [exec -- $comSpec /c echo %CD%]]]
+ } else {
+ return [pwd]
+ }
+ }
sqlite3_crashparams 0 [file join [get_pwd] test.db-journal]
# Begin a transaction and evaluate a "CREATE INDEX" statement
@@ -61,36 +75,39 @@ for {set ii 0} {$ii < 10} {incr ii} {
#
db eval BEGIN
sqlite3_memdebug_fail $iFail -repeat 0
- catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg
- # puts "$n $msg ac=[sqlite3_get_autocommit db]"
+ set rc [catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg]
+# puts "$msg ac=[sqlite3_get_autocommit db] iFail=$iFail"
+# puts "fail=[sqlite3_memdebug_fail -1]"
- # If the transaction is still active (it may not be if the malloc()
- # failure occurred in the OS layer), write to the database. Make sure
- # page 4 is among those written.
- #
- if {![sqlite3_get_autocommit db]} {
- db eval {
- DELETE FROM t1; -- This will put page 4 on the free list.
- INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
- INSERT INTO t1 SELECT * FROM t1; -- 2
- INSERT INTO t1 SELECT * FROM t1; -- 4
- INSERT INTO t1 SELECT * FROM t1; -- 8
- INSERT INTO t1 SELECT * FROM t1; -- 16
- INSERT INTO t1 SELECT * FROM t1; -- 32
- INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48
+ if {$rc} {
+ # If the transaction is still active (it may not be if the malloc()
+ # failure occurred in the OS layer), write to the database. Make sure
+ # page 4 is among those written.
+ #
+ if {![sqlite3_get_autocommit db]} {
+ db eval {
+ DELETE FROM t1; -- This will put page 4 on the free list.
+ INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
+ INSERT INTO t1 SELECT * FROM t1; -- 2
+ INSERT INTO t1 SELECT * FROM t1; -- 4
+ INSERT INTO t1 SELECT * FROM t1; -- 8
+ INSERT INTO t1 SELECT * FROM t1; -- 16
+ INSERT INTO t1 SELECT * FROM t1; -- 32
+ INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48
+ }
}
+
+ # If the right malloc() failed during the 'CREATE INDEX' above and
+ # the transaction was not rolled back, then the sqlite cache now
+ # has a dirty page 4 that it incorrectly believes is already safely
+ # in the synced part of the journal file. When
+ # sqlite3_release_memory() is called sqlite tries to free memory
+ # by writing page 4 out to the db file. If it crashes later on,
+ # before syncing the journal... Corruption!
+ #
+ sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
+ sqlite3_release_memory 8092
}
-
- # If the right malloc() failed during the 'CREATE INDEX' above and
- # the transaction was not rolled back, then the sqlite cache now
- # has a dirty page 4 that it incorrectly believes is already safely
- # in the synced part of the journal file. When
- # sqlite3_release_memory() is called sqlite tries to free memory
- # by writing page 4 out to the db file. If it crashes later on,
- # before syncing the journal... Corruption!
- #
- sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
- sqlite3_release_memory 8092
}]] {}
expr 1
} {1}
diff --git a/test/date2.test b/test/date2.test
index 30a475737..a16e25c44 100644
--- a/test/date2.test
+++ b/test/date2.test
@@ -38,6 +38,13 @@ do_catchsql_test date2-130 {
INSERT INTO t1(x,y) VALUES('2017-08-01','two');
} {1 {CHECK constraint failed: date(x) BETWEEN '2017-07-01' AND '2017-07-31'}}
+# 2021-03-16 Forum post https://sqlite.org/forum/forumpost/464afd4086
+do_catchsql_test date2-140 {
+ DROP TABLE t1;
+ CREATE TABLE t1(x, y, z AS (date()));
+ INSERT INTO t1(x,y) VALUES(1,2);
+} {1 {non-deterministic use of date() in a generated column}}
+
do_execsql_test date2-200 {
CREATE TABLE t2(x,y);
INSERT INTO t2(x,y) VALUES(1, '2017-07-20'), (2, 'xyzzy');
diff --git a/test/dbfuzz2.c b/test/dbfuzz2.c
index e35162937..f0062915d 100644
--- a/test/dbfuzz2.c
+++ b/test/dbfuzz2.c
@@ -31,8 +31,7 @@
**
** mkdir dir
** cp dbfuzz2-seed*.db dir
-** clang-6.0 -I. -g -O1 -fsanitize=fuzzer \
-** -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \
+** clang-6.0 -I. -g -O1 -fsanitize=fuzzer -DTHREADSAFE=0 \
** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
** ./a.out dir
*/
@@ -287,10 +286,6 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
sqlite3MemTraceActivate(stdout);
continue;
}
- if( strcmp(z,"mem")==0 ){
- bVdbeDebug = 1;
- continue;
- }
if( strcmp(z,"max-db-size")==0 ){
if( i+1==argc ){
fprintf(stderr, "missing argument to %s\n", argv[i]);
@@ -299,6 +294,18 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
szMax = strtol(argv[++i], 0, 0);
continue;
}
+ if( strcmp(z, "lookaside")==0 ){
+ int sz, nSlot;
+ if( i+2>=argc ){
+ fprintf(stderr,
+ "--lookaside requires two arguments: slot-size num-slots\n");
+ exit(1);
+ }
+ sz = atoi(argv[++i]);
+ nSlot = atoi(argv[++i]);
+ sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, nSlot);
+ continue;
+ }
#ifndef _WIN32
if( strcmp(z,"max-stack")==0
|| strcmp(z,"max-data")==0
diff --git a/test/delete.test b/test/delete.test
index a448e52dd..c15ac53c6 100644
--- a/test/delete.test
+++ b/test/delete.test
@@ -100,7 +100,7 @@ do_test delete-5.2.1 {
} {200}
do_test delete-5.2.2 {
execsql {DELETE FROM table1}
-} {200}
+} {202}
do_test delete-5.2.3 {
execsql {BEGIN TRANSACTION}
for {set i 1} {$i<=200} {incr i} {
diff --git a/test/delete4.test b/test/delete4.test
index f64778a16..8d6a1b8c7 100644
--- a/test/delete4.test
+++ b/test/delete4.test
@@ -59,14 +59,22 @@ do_execsql_test 2.3 {
#-------------------------------------------------------------------------
#
reset_db
-do_execsql_test 3.1 {
+do_execsql_test 3.0.1 {
CREATE TABLE t1(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(2, 4);
INSERT INTO t1 VALUES(1, 5);
DELETE FROM t1 WHERE a=1;
+ SELECT printf('(%d)',changes());
SELECT * FROM t1;
-} {2 4}
+} {(2) 2 4}
+do_execsql_test 3.0.2 {
+ WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
+ INSERT INTO t1(a,b) SELECT x, x+1 FROM c;
+ SELECT printf('(%d)',changes());
+ DELETE FROM t1;
+ SELECT printf('(%d)',changes());
+} {(100) (101)}
#-------------------------------------------------------------------------
# DELETE statement that uses the OR optimization
diff --git a/test/distinct.test b/test/distinct.test
index f6f3c6cdc..a3cb1afc8 100644
--- a/test/distinct.test
+++ b/test/distinct.test
@@ -30,12 +30,11 @@ proc is_distinct_noop {sql} {
set program1 [list]
set program2 [list]
db eval "EXPLAIN $sql1" {
- if {$opcode != "Noop"} { lappend program1 $opcode }
+ if {$opcode != "Noop" && $opcode != "Explain"} { lappend program1 $opcode }
}
db eval "EXPLAIN $sql2" {
- if {$opcode != "Noop"} { lappend program2 $opcode }
+ if {$opcode != "Noop" && $opcode != "Explain"} { lappend program2 $opcode }
}
-
return [expr {$program1==$program2}]
}
@@ -128,7 +127,6 @@ foreach {tn noop sql} {
21 0 "SELECT DISTINCT c2 FROM t3"
22 0 "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
- 23 1 "SELECT DISTINCT rowid FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
24 0 "SELECT DISTINCT rowid/2 FROM t1"
25 1 "SELECT DISTINCT rowid/2, rowid FROM t1"
@@ -294,4 +292,13 @@ do_execsql_test 7.1 {
WHERE (t1.a=t3.a) AND (SELECT count(*) FROM t2 AS y WHERE t4.x!='abc')=t1.a
} {2 2 2}
+# 2021-04-06 forum post https://sqlite.org/forum/forumpost/66954e9ece
+reset_db
+do_execsql_test 8.0 {
+ CREATE TABLE person ( pid INT) ;
+ CREATE UNIQUE INDEX idx ON person ( pid ) WHERE pid == 1;
+ INSERT INTO person VALUES (1), (10), (10);
+ SELECT DISTINCT pid FROM person where pid = 10;
+} {10}
+
finish_test
diff --git a/test/distinctagg.test b/test/distinctagg.test
index 9b5dc2167..a34312ef9 100644
--- a/test/distinctagg.test
+++ b/test/distinctagg.test
@@ -16,6 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+set testprefix distinctagg
do_test distinctagg-1.1 {
execsql {
@@ -31,7 +32,7 @@ do_test distinctagg-1.1 {
} {1 2 3 3}
do_test distinctagg-1.2 {
execsql {
- SELECT b, count(distinct c) FROM t1 GROUP BY b ORDER BY b
+ SELECT b, count(distinct c) FROM t1 GROUP BY b
}
} {2 1 3 2}
do_test distinctagg-1.3 {
@@ -59,4 +60,158 @@ do_test distinctagg-2.2 {
}
} {1 {DISTINCT aggregates must have exactly one argument}}
+#--------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a, b, c);
+ CREATE TABLE t2(d, e, f);
+
+ INSERT INTO t1 VALUES (1, 1, 1);
+ INSERT INTO t1 VALUES (2, 2, 2);
+ INSERT INTO t1 VALUES (3, 3, 3);
+ INSERT INTO t1 VALUES (4, 1, 4);
+ INSERT INTO t1 VALUES (5, 2, 1);
+ INSERT INTO t1 VALUES (5, 3, 2);
+ INSERT INTO t1 VALUES (4, 1, 3);
+ INSERT INTO t1 VALUES (3, 2, 4);
+ INSERT INTO t1 VALUES (2, 3, 1);
+ INSERT INTO t1 VALUES (1, 1, 2);
+
+ INSERT INTO t2 VALUES('a', 'a', 'a');
+ INSERT INTO t2 VALUES('b', 'b', 'b');
+ INSERT INTO t2 VALUES('c', 'c', 'c');
+
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1bc ON t1(b, c);
+}
+
+foreach {tn use_eph sql res} {
+ 1 0 "SELECT count(DISTINCT a) FROM t1" 5
+ 2 0 "SELECT count(DISTINCT b) FROM t1" 3
+ 3 1 "SELECT count(DISTINCT c) FROM t1" 4
+ 4 0 "SELECT count(DISTINCT c) FROM t1 WHERE b=3" 3
+ 5 0 "SELECT count(DISTINCT rowid) FROM t1" 10
+ 6 0 "SELECT count(DISTINCT a) FROM t1, t2" 5
+ 7 0 "SELECT count(DISTINCT a) FROM t2, t1" 5
+ 8 1 "SELECT count(DISTINCT a+b) FROM t1, t2, t2, t2" 6
+ 9 0 "SELECT count(DISTINCT c) FROM t1 WHERE c=2" 1
+ 10 1 "SELECT count(DISTINCT t1.rowid) FROM t1, t2" 10
+} {
+ do_test 3.$tn.1 {
+ set prg [db eval "EXPLAIN $sql"]
+ set idx [lsearch $prg OpenEphemeral]
+ expr {$idx>=0}
+ } $use_eph
+
+ do_execsql_test 3.$tn.2 $sql $res
+}
+
+do_execsql_test 3.10 {
+ SELECT a, count(DISTINCT b) FROM t1 GROUP BY a;
+} {
+ 1 1 2 2 3 2 4 1 5 2
+}
+
+#--------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE t1(a, b, c);
+ CREATE INDEX t1a ON t1(a);
+ CREATE INDEX t1bc ON t1(b, c);
+
+ INSERT INTO t1 VALUES(1, 'A', 1);
+ INSERT INTO t1 VALUES(1, 'A', 1);
+ INSERT INTO t1 VALUES(2, 'A', 2);
+ INSERT INTO t1 VALUES(2, 'A', 2);
+ INSERT INTO t1 VALUES(1, 'B', 1);
+ INSERT INTO t1 VALUES(2, 'B', 2);
+ INSERT INTO t1 VALUES(3, 'B', 3);
+ INSERT INTO t1 VALUES(NULL, 'B', NULL);
+ INSERT INTO t1 VALUES(NULL, 'C', NULL);
+ INSERT INTO t1 VALUES('d', 'D', 'd');
+
+ CREATE TABLE t2(d, e, f);
+ CREATE INDEX t2def ON t2(d, e, f);
+
+ INSERT INTO t2 VALUES(1, 1, 'a');
+ INSERT INTO t2 VALUES(1, 1, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'a');
+ INSERT INTO t2 VALUES(1, 2, 'b');
+ INSERT INTO t2 VALUES(1, 3, 'b');
+ INSERT INTO t2 VALUES(1, 3, 'a');
+ INSERT INTO t2 VALUES(1, 3, 'b');
+ INSERT INTO t2 VALUES(2, 3, 'x');
+ INSERT INTO t2 VALUES(2, 3, 'y');
+ INSERT INTO t2 VALUES(2, 3, 'z');
+
+ CREATE TABLE t3(x, y, z);
+ INSERT INTO t3 VALUES(1,1,1);
+ INSERT INTO t3 VALUES(2,2,2);
+}
+
+foreach {tn use_eph sql res} {
+ 1 0 "SELECT count(DISTINCT c) FROM t1 GROUP BY b" {2 3 0 1}
+ 2 1 "SELECT count(DISTINCT a) FROM t1 GROUP BY b" {2 3 0 1}
+ 3 1 "SELECT count(DISTINCT a) FROM t1 GROUP BY b+c" {0 1 1 1 1}
+
+ 4 0 "SELECT count(DISTINCT f) FROM t2 GROUP BY d, e" {1 2 2 3}
+ 5 1 "SELECT count(DISTINCT f) FROM t2 GROUP BY d" {2 3}
+ 6 0 "SELECT count(DISTINCT f) FROM t2 WHERE d IS 1 GROUP BY e" {1 2 2}
+} {
+ do_test 4.$tn.1 {
+ set prg [db eval "EXPLAIN $sql"]
+ set idx [lsearch $prg OpenEphemeral]
+ expr {$idx>=0}
+ } $use_eph
+
+ do_execsql_test 4.$tn.2 $sql $res
+}
+
+
+set t3root [db one {SELECT rootpage FROM sqlite_schema WHERE name='t3'}]
+foreach {tn use_t3 sql res} {
+ 1 1 "SELECT count(*) FROM t3" 2
+ 2 0 "SELECT count(*) FROM t1" 10
+ 2 1 "SELECT count(DISTINCT a) FROM t1, t3" 4
+ 3 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3" 4
+ 4 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 4
+ 5 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
+ 6 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 ON (t3.x=0)" 4
+ 7 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3" 2
+ 8 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 1
+ 9 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
+ 10 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 ON (t3.x=0)" 0
+
+} {
+ do_test 5.$tn.1 {
+ set bUse 0
+ db eval "EXPLAIN $sql" a {
+ if {$a(opcode)=="OpenRead" && $a(p2)==$t3root} {set bUse 1}
+ }
+ set bUse
+ } $use_t3
+
+ do_execsql_test 5.$tn.2 $sql $res
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 6.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(c, d);
+ INSERT INTO t1 VALUES(123,456);
+ INSERT INTO t2 VALUES(123,456);
+}
+do_execsql_test 6.1 {
+ SELECT count(DISTINCT c) FROM t1 LEFT JOIN t2;
+} {1}
+
+do_execsql_test 7.0 {
+ CREATE TABLE v1 ( v2 UNIQUE, v3 AS( TYPEOF ( NULL ) ) UNIQUE );
+ SELECT COUNT ( DISTINCT TRUE ) FROM v1 GROUP BY likelihood ( v3 , 0.100000 );
+}
+
+
finish_test
+
diff --git a/test/e_createtable.test b/test/e_createtable.test
index e83e5cca1..c2cd1bc2c 100644
--- a/test/e_createtable.test
+++ b/test/e_createtable.test
@@ -1393,13 +1393,13 @@ do_execsql_test 4.10.0 {
}
do_createtable_tests 4.10 {
1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5"
- {/*SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
+ {/*SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
2 "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
- {/*SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1*/}
+ {/*SCAN t2 USING INDEX sqlite_autoindex_t2_1*/}
3 "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
- {/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
+ {/*SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
}
# EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
diff --git a/test/e_fkey.test b/test/e_fkey.test
index c5ac5fde3..e5eb0d49c 100644
--- a/test/e_fkey.test
+++ b/test/e_fkey.test
@@ -992,15 +992,15 @@ do_detail_test e_fkey-25.2 {
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
} {
- {SCAN TABLE artist}
- {SCAN TABLE track}
+ {SCAN artist}
+ {SCAN track}
}
do_detail_test e_fkey-25.3 {
PRAGMA foreign_keys = ON;
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
} {
- {SCAN TABLE artist}
- {SCAN TABLE track}
+ {SCAN artist}
+ {SCAN track}
}
do_test e_fkey-25.4 {
execsql {
@@ -1117,15 +1117,15 @@ do_test e_fkey-27.2 {
do_detail_test e_fkey-27.3 {
EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
} {
- {SCAN TABLE artist}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
+ {SCAN artist}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}
do_detail_test e_fkey-27.4 {
EXPLAIN QUERY PLAN DELETE FROM artist
} {
- {SCAN TABLE artist}
- {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
+ {SCAN artist}
+ {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}
###########################################################################
@@ -2055,9 +2055,9 @@ do_test e_fkey-44.5 {
#-------------------------------------------------------------------------
# Test SET DEFAULT actions.
#
-# EVIDENCE-OF: R-43054-54832 The "SET DEFAULT" actions are similar to
+# EVIDENCE-OF: R-55814-22637 The "SET DEFAULT" actions are similar to
# "SET NULL", except that each of the child key columns is set to
-# contain the columns default value instead of NULL.
+# contain the column's default value instead of NULL.
#
drop_all_tables
do_test e_fkey-45.1 {
diff --git a/test/e_select.test b/test/e_select.test
index c2fdc9ad9..a4e74d30e 100644
--- a/test/e_select.test
+++ b/test/e_select.test
@@ -1004,12 +1004,13 @@ do_execsql_test e_select-4.9.0 {
INSERT INTO b3 VALUES('dEF', 'dEF');
} {}
-# EVIDENCE-OF: R-07284-35990 If the SELECT statement is an aggregate
+# EVIDENCE-OF: R-40855-36147 If the SELECT statement is an aggregate
# query with a GROUP BY clause, then each of the expressions specified
# as part of the GROUP BY clause is evaluated for each row of the
-# dataset. Each row is then assigned to a "group" based on the results;
-# rows for which the results of evaluating the GROUP BY expressions are
-# the same get assigned to the same group.
+# dataset according to the processing rules stated below for ORDER BY
+# expressions. Each row is then assigned to a "group" based on the
+# results; rows for which the results of evaluating the GROUP BY
+# expressions are the same get assigned to the same group.
#
# These tests also show that the following is not untrue:
#
diff --git a/test/eqp.test b/test/eqp.test
index f931f8f34..19d6ea91a 100644
--- a/test/eqp.test
+++ b/test/eqp.test
@@ -46,111 +46,131 @@ do_eqp_test 1.2 {
QUERY PLAN
|--MULTI-INDEX OR
| |--INDEX 1
- | | `--SEARCH TABLE t1 USING INDEX i1 (a=?)
+ | | `--SEARCH t1 USING INDEX i1 (a=?)
| `--INDEX 2
- | `--SEARCH TABLE t1 USING INDEX i2 (b=?)
- `--SCAN TABLE t2
+ | `--SEARCH t1 USING INDEX i2 (b=?)
+ `--SCAN t2
}
do_eqp_test 1.3 {
SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
} {
QUERY PLAN
- |--SCAN TABLE t2
+ |--SCAN t2
`--MULTI-INDEX OR
|--INDEX 1
- | `--SEARCH TABLE t1 USING INDEX i1 (a=?)
+ | `--SEARCH t1 USING INDEX i1 (a=?)
`--INDEX 2
- `--SEARCH TABLE t1 USING INDEX i2 (b=?)
+ `--SEARCH t1 USING INDEX i2 (b=?)
}
do_eqp_test 1.3 {
SELECT a FROM t1 ORDER BY a
} {
QUERY PLAN
- `--SCAN TABLE t1 USING COVERING INDEX i1
+ `--SCAN t1 USING COVERING INDEX i1
}
do_eqp_test 1.4 {
SELECT a FROM t1 ORDER BY +a
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
+ |--SCAN t1 USING COVERING INDEX i1
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 1.5 {
SELECT a FROM t1 WHERE a=4
} {
QUERY PLAN
- `--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)
+ `--SEARCH t1 USING COVERING INDEX i1 (a=?)
}
do_eqp_test 1.6 {
SELECT DISTINCT count(*) FROM t3 GROUP BY a;
} {
QUERY PLAN
- |--SCAN TABLE t3
+ |--SCAN t3
|--USE TEMP B-TREE FOR GROUP BY
`--USE TEMP B-TREE FOR DISTINCT
}
-do_eqp_test 1.7 {
+do_eqp_test 1.7.1 {
SELECT * FROM t3 JOIN (SELECT 1)
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE SUBQUERY xxxxxx
| `--SCAN CONSTANT ROW
|--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ `--SCAN t3
}
+do_eqp_test 1.7.2 {
+ SELECT * FROM t3 JOIN (SELECT 1) AS v1
+} {
+ QUERY PLAN
+ |--MATERIALIZE v1
+ | `--SCAN CONSTANT ROW
+ |--SCAN v1
+ `--SCAN t3
+}
+do_eqp_test 1.7.3 {
+ SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy
+} {
+ QUERY PLAN
+ |--MATERIALIZE yy
+ | `--SCAN CONSTANT ROW
+ |--SCAN yy
+ `--SCAN xx
+}
+
+
do_eqp_test 1.8 {
SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE SUBQUERY xxxxxx
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--UNION USING TEMP B-TREE
| `--SCAN CONSTANT ROW
|--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ `--SCAN t3
}
do_eqp_test 1.9 {
- SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--EXCEPT USING TEMP B-TREE
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
do_eqp_test 1.10 {
- SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--INTERSECT USING TEMP B-TREE
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
do_eqp_test 1.11 {
- SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
+ SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) abc
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
+ |--MATERIALIZE abc
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SCAN CONSTANT ROW
| `--UNION ALL
- | `--SCAN TABLE t3
- |--SCAN SUBQUERY xxxxxx
- `--SCAN TABLE t3
+ | `--SCAN t3
+ |--SCAN abc
+ `--SCAN t3
}
#-------------------------------------------------------------------------
@@ -166,57 +186,57 @@ do_execsql_test 2.1 {
det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
|--USE TEMP B-TREE FOR GROUP BY
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
QUERY PLAN
- |--SCAN TABLE t2 USING COVERING INDEX t2i1
+ |--SCAN t2 USING COVERING INDEX t2i1
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.3 "SELECT DISTINCT * FROM t1" {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
QUERY PLAN
- |--SCAN TABLE t1
- |--SCAN TABLE t2
+ |--SCAN t1
+ |--SCAN t2
`--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
QUERY PLAN
- |--SCAN TABLE t1
- |--SCAN TABLE t2
+ |--SCAN t1
+ |--SCAN t2
|--USE TEMP B-TREE FOR DISTINCT
`--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
QUERY PLAN
- |--SCAN TABLE t2 USING COVERING INDEX t2i1
- `--SCAN TABLE t1
+ |--SCAN t2 USING COVERING INDEX t2i1
+ `--SCAN t1
}
det 2.3.1 "SELECT max(x) FROM t2" {
QUERY PLAN
- `--SEARCH TABLE t2 USING COVERING INDEX t2i1
+ `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.2 "SELECT min(x) FROM t2" {
QUERY PLAN
- `--SEARCH TABLE t2 USING COVERING INDEX t2i1
+ `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.3 "SELECT min(x), max(x) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}
@@ -228,42 +248,42 @@ do_eqp_test 3.1.1 {
SELECT (SELECT x FROM t1 AS sub) FROM t1;
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t1 AS sub
+ `--SCAN sub
}
do_eqp_test 3.1.2 {
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t1 AS sub
+ `--SCAN sub
}
do_eqp_test 3.1.3 {
SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- |--SCAN TABLE t1 AS sub
+ |--SCAN sub
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 3.1.4 {
SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
det 3.2.1 {
SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
} {
QUERY PLAN
- |--CO-ROUTINE xxxxxx
- | |--SCAN TABLE t1
+ |--CO-ROUTINE SUBQUERY xxxxxx
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
|--SCAN SUBQUERY xxxxxx
`--USE TEMP B-TREE FOR ORDER BY
@@ -275,13 +295,13 @@ det 3.2.2 {
ORDER BY x2.y LIMIT 5
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE t1
+ |--MATERIALIZE x1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
- |--MATERIALIZE xxxxxx
- | `--SCAN TABLE t2 USING INDEX t2i1
- |--SCAN SUBQUERY xxxxxx AS x1
- |--SCAN SUBQUERY xxxxxx AS x2
+ |--MATERIALIZE x2
+ | `--SCAN t2 USING INDEX t2i1
+ |--SCAN x1
+ |--SCAN x2
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -289,25 +309,25 @@ det 3.3.1 {
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--LIST SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 3.3.2 {
SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--CORRELATED LIST SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 3.3.3 {
SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
QUERY PLAN
- |--SCAN TABLE t1
+ |--SCAN t1
`--CORRELATED SCALAR SUBQUERY xxxxxx
- `--SCAN TABLE t2
+ `--SCAN t2
}
#-------------------------------------------------------------------------
@@ -319,9 +339,9 @@ do_eqp_test 4.1.1 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
`--UNION ALL
- `--SCAN TABLE t2
+ `--SCAN t2
}
do_eqp_test 4.1.2 {
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
@@ -329,10 +349,10 @@ do_eqp_test 4.1.2 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.3 {
@@ -341,10 +361,10 @@ do_eqp_test 4.1.3 {
QUERY PLAN
`--MERGE (UNION)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.4 {
@@ -353,10 +373,10 @@ do_eqp_test 4.1.4 {
QUERY PLAN
`--MERGE (INTERSECT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.5 {
@@ -365,10 +385,10 @@ do_eqp_test 4.1.5 {
QUERY PLAN
`--MERGE (EXCEPT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2
+ |--SCAN t2
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -378,10 +398,10 @@ do_eqp_test 4.2.2 {
QUERY PLAN
`--MERGE (UNION ALL)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- `--SCAN TABLE t2 USING INDEX t2i1
+ `--SCAN t2 USING INDEX t2i1
}
do_eqp_test 4.2.3 {
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
@@ -389,10 +409,10 @@ do_eqp_test 4.2.3 {
QUERY PLAN
`--MERGE (UNION)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.4 {
@@ -401,10 +421,10 @@ do_eqp_test 4.2.4 {
QUERY PLAN
`--MERGE (INTERSECT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.5 {
@@ -413,10 +433,10 @@ do_eqp_test 4.2.5 {
QUERY PLAN
`--MERGE (EXCEPT)
|--LEFT
- | |--SCAN TABLE t1
+ | |--SCAN t1
| `--USE TEMP B-TREE FOR ORDER BY
`--RIGHT
- |--SCAN TABLE t2 USING INDEX t2i1
+ |--SCAN t2 USING INDEX t2i1
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
@@ -426,9 +446,9 @@ do_eqp_test 4.3.1 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
`--UNION USING TEMP B-TREE
- `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ `--SCAN t2 USING COVERING INDEX t2i1
}
do_eqp_test 4.3.2 {
@@ -437,11 +457,11 @@ do_eqp_test 4.3.2 {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
- | `--SCAN TABLE t1
+ | `--SCAN t1
|--UNION USING TEMP B-TREE
- | `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ | `--SCAN t2 USING COVERING INDEX t2i1
`--UNION USING TEMP B-TREE
- `--SCAN TABLE t1
+ `--SCAN t1
}
do_eqp_test 4.3.3 {
SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
@@ -451,12 +471,12 @@ do_eqp_test 4.3.3 {
|--LEFT
| `--MERGE (UNION)
| |--LEFT
- | | |--SCAN TABLE t1
+ | | |--SCAN t1
| | `--USE TEMP B-TREE FOR ORDER BY
| `--RIGHT
- | `--SCAN TABLE t2 USING COVERING INDEX t2i1
+ | `--SCAN t2 USING COVERING INDEX t2i1
`--RIGHT
- |--SCAN TABLE t1
+ |--SCAN t1
`--USE TEMP B-TREE FOR ORDER BY
}
@@ -469,145 +489,145 @@ drop_all_tables
# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
# FROM t1 WHERE a=1;
-# 0|0|0|SCAN TABLE t1
+# 0|0|0|SCAN t1
#
do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SCAN TABLE t1}
+ 0 0 0 {SCAN t1}
}
# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
-# 0|0|0|SEARCH TABLE t1 USING INDEX i1
+# 0|0|0|SEARCH t1 USING INDEX i1
#
do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
+ 0 0 0 {SEARCH t1 USING INDEX i1 (a=?)}
}
# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
#
do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
}
# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
-# 0|1|1|SCAN TABLE t2
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
+# 0|1|1|SCAN t2
#
do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
- 0 1 1 {SCAN TABLE t2}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
+ 0 1 1 {SCAN t2}
}
# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
-# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
-# 0|1|0|SCAN TABLE t2
+# 0|0|1|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
+# 0|1|0|SCAN t2
#
det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
- 0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
- 0 1 0 {SCAN TABLE t2}
+ 0 0 1 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
+ 0 1 0 {SCAN t2}
}
# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
-# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
-# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
+# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
+# 0|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
- 0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
- 0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
+ 0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
+ 0 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}
# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
# SELECT c, d FROM t2 ORDER BY c;
-# 0|0|0|SCAN TABLE t2
+# 0|0|0|SCAN t2
# 0|0|0|USE TEMP B-TREE FOR ORDER BY
#
det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
- 0 0 0 {SCAN TABLE t2}
+ 0 0 0 {SCAN t2}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
-# 0|0|0|SCAN TABLE t2 USING INDEX i4
+# 0|0|0|SCAN t2 USING INDEX i4
#
do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
- 0 0 0 {SCAN TABLE t2 USING INDEX i4}
+ 0 0 0 {SCAN t2 USING INDEX i4}
}
# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
-# 0|0|0|SCAN TABLE t2
+# 0|0|0|SCAN t2
# 0|0|0|EXECUTE SCALAR SUBQUERY 1
-# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
+# 1|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
-# 2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
+# 2|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
det 5.9 {
SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
} {
- 0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
+ 0 0 0 {SCAN t2 USING COVERING INDEX i4}
0 0 0 {EXECUTE SCALAR SUBQUERY 1}
- 1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
+ 1 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
- 2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
+ 2 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}
# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
-# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
+# 1|0|0|SCAN t1 USING COVERING INDEX i2
# 0|0|0|SCAN SUBQUERY 1
# 0|0|0|USE TEMP B-TREE FOR GROUP BY
#
det 5.10 {
SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
} {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i2}
0 0 0 {SCAN SUBQUERY 1}
0 0 0 {USE TEMP B-TREE FOR GROUP BY}
}
# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
-# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
-# 0|1|1|SCAN TABLE t1
+# 0|0|0|SEARCH t2 USING INDEX i4 (c=?)
+# 0|1|1|SCAN t1
#
det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
- 0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
- 0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
+ 0 0 0 {SEARCH t2 USING INDEX i4 (c=?)}
+ 0 1 1 {SCAN t1 USING COVERING INDEX i2}
}
# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 UNION SELECT c FROM t2;
-# 1|0|0|SCAN TABLE t1
-# 2|0|0|SCAN TABLE t2
+# 1|0|0|SCAN t1
+# 2|0|0|SCAN t2
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
#
det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
- 2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i2}
+ 2 0 0 {SCAN t2 USING COVERING INDEX i4}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
}
# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
-# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
-# 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
+# 1|0|0|SCAN t1 USING COVERING INDEX i2
+# 2|0|0|SCAN t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
#
det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
- 1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
- 2 0 0 {SCAN TABLE t2}
+ 1 0 0 {SCAN t1 USING COVERING INDEX i1}
+ 2 0 0 {SCAN t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}
@@ -647,8 +667,8 @@ if {![nonzero_reserved_bytes]} {
do_peqp_test 6.1 {
SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
} [string trimleft {
-1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
-2 0 0 SCAN TABLE t2
+1 0 0 SCAN t1 USING COVERING INDEX i2
+2 0 0 SCAN t2
2 0 0 USE TEMP B-TREE FOR ORDER BY
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
}]
@@ -669,12 +689,12 @@ do_execsql_test 7.0 {
det 7.1 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 7.2 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX i1
+ `--SCAN t2 USING COVERING INDEX i1
}
do_execsql_test 7.3 {
@@ -693,12 +713,12 @@ sqlite3 db test.db
det 7.4 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 7.5 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2 USING COVERING INDEX i1
+ `--SCAN t2 USING COVERING INDEX i1
}
#-------------------------------------------------------------------------
@@ -714,37 +734,37 @@ do_execsql_test 8.0 {
det 8.1.1 "SELECT * FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
QUERY PLAN
- `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
+ `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
det 8.1.3 "SELECT count(*) FROM t2" {
QUERY PLAN
- `--SCAN TABLE t2
+ `--SCAN t2
}
det 8.2.1 "SELECT * FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (b=?)
+ `--SEARCH t1 USING PRIMARY KEY (b=?)
}
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
QUERY PLAN
- `--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)
+ `--SEARCH t1 USING PRIMARY KEY (b=? AND c=?)
}
det 8.2.4 "SELECT count(*) FROM t1" {
QUERY PLAN
- `--SCAN TABLE t1
+ `--SCAN t1
}
# 2018-08-16: While working on Fossil I discovered that EXPLAIN QUERY PLAN
@@ -814,16 +834,16 @@ do_eqp_test 9.1 {
ORDER BY 1;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | |--SCAN TABLE forumpost AS x USING INDEX forumthread
+ |--MATERIALIZE thread
+ | |--SCAN x USING INDEX forumthread
| |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
| |--CORRELATED SCALAR SUBQUERY xxxxxx
- | | |--SEARCH TABLE forumpost USING COVERING INDEX forumthread (froot=?)
+ | | |--SEARCH forumpost USING COVERING INDEX forumthread (froot=?)
| | `--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
| `--USE TEMP B-TREE FOR ORDER BY
- |--SCAN SUBQUERY xxxxxx
- |--SEARCH TABLE blob USING INTEGER PRIMARY KEY (rowid=?)
- |--SEARCH TABLE event USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN thread
+ |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)
+ |--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)
`--USE TEMP B-TREE FOR ORDER BY
}
diff --git a/test/exprfault.test b/test/exprfault.test
new file mode 100644
index 000000000..9e5977e1d
--- /dev/null
+++ b/test/exprfault.test
@@ -0,0 +1,35 @@
+# 2021 April 17
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix exprfault
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a);
+ CREATE TABLE t2(d);
+}
+faultsim_save_and_close
+
+do_faultsim_test 1.1 -faults oom* -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql {
+ SELECT a = ( SELECT d FROM (SELECT d FROM t2) ) FROM t1
+ }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+
+finish_test
diff --git a/test/external_reader.test b/test/external_reader.test
new file mode 100644
index 000000000..5d293981c
--- /dev/null
+++ b/test/external_reader.test
@@ -0,0 +1,74 @@
+# 2021 April 2
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix external_reader
+
+ifcapable !wal {
+ finish_test
+ return
+}
+if {$::tcl_platform(platform)!="unix"} {
+ finish_test
+ return
+}
+
+do_multiclient_test tn {
+
+ set bExternal 1
+ if {[info commands db3]!=""} { set bExternal 0 }
+
+ do_test 1.$tn.0 {
+ sql1 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES(1, 2);
+ }
+ } {wal}
+
+ do_test 1.$tn.1 {
+ sql2 { SELECT * FROM t1 }
+ } {1 2}
+
+ do_test 1.$tn.2 {
+ code1 {
+ file_control_external_reader db
+ }
+ } {0}
+
+ do_test 1.$tn.3 {
+ sql2 {
+ BEGIN;
+ SELECT * FROM t1;
+ }
+ } {1 2}
+
+ do_test 1.$tn.4 {
+ code1 {
+ file_control_external_reader db
+ }
+ } $bExternal
+
+ do_test 1.$tn.5 {
+ sql2 { COMMIT }
+ } {}
+
+ do_test 1.$tn.6 {
+ code1 { file_control_external_reader db }
+ } 0
+
+}
+
+
+finish_test
diff --git a/test/fts3aux1.test b/test/fts3aux1.test
index c7e1ac1a5..1524d6d30 100644
--- a/test/fts3aux1.test
+++ b/test/fts3aux1.test
@@ -105,10 +105,10 @@ db func rec rec
#
do_execsql_test 2.1.1.1 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 1:*/}
do_execsql_test 2.1.1.2 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
# Now show that using "term='braid'" means the virtual table returns
# only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
@@ -154,24 +154,24 @@ do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}
do_execsql_test 2.2.1.1 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 2:*/}
do_execsql_test 2.2.1.2 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_execsql_test 2.2.1.3 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 4:*/}
do_execsql_test 2.2.1.4 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_execsql_test 2.2.1.5 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 6:*/}
do_execsql_test 2.2.1.6 {
EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
-} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
+} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}
do_test 2.2.2.1 {
set cnt 0
@@ -335,7 +335,7 @@ foreach {tn sort orderby} {
9 1 "ORDER BY occurrences DESC"
} {
- set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
+ set res {SCAN terms VIRTUAL TABLE INDEX 0:}
if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} }
set res "/*$res*/"
@@ -413,8 +413,8 @@ do_plansql_test 4.2 {
SELECT y FROM x2, terms WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE x2
- `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
+ |--SCAN x2
+ `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
a b c d e f g h i j k l
}
@@ -423,8 +423,8 @@ do_plansql_test 4.3 {
SELECT y FROM terms, x2 WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE x2
- `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
+ |--SCAN x2
+ `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
a b c d e f g h i j k l
}
@@ -433,8 +433,8 @@ do_plansql_test 4.4 {
SELECT y FROM x3, terms WHERE y = term AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
+ |--SCAN terms VIRTUAL TABLE INDEX 0:
+ `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
a b c d e f g h i j k l
}
@@ -443,8 +443,8 @@ do_plansql_test 4.5 {
SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
} {
QUERY PLAN
- |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
- `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
+ |--SCAN terms VIRTUAL TABLE INDEX 0:
+ `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
a k l
}
diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test
index bddcc9f5d..044fd4e64 100644
--- a/test/fts3corrupt4.test
+++ b/test/fts3corrupt4.test
@@ -6298,4 +6298,514 @@ do_catchsql_test 47.3 {
SELECT matchinfo(t1) FROM t1 WHERE t1 MATCH '"json1 enable"';
} {1 {database disk image is malformed}}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_test 48.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 20480 pagesize 4096 filename sql038051.txt.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
+| 96: 00 00 00 00 0d 0e fc 00 05 0e 13 00 0f ca 0f 6c ...............l
+| 112: 0f 04 0e 13 0e c9 00 00 00 00 00 00 00 00 00 00 ................
+| 3600: 00 00 00 81 33 04 07 17 1f 1f 01 82 35 74 61 62 ....3.......5tab
+| 3616: 6c 65 78 31 5f 73 65 67 64 69 72 78 31 5f 73 65 lex1_segdirx1_se
+| 3632: 67 64 69 72 04 43 52 45 41 54 45 20 54 41 42 4c gdir.CREATE TABL
+| 3648: 45 20 27 78 31 5f 73 65 67 64 69 72 27 28 6c 65 E 'x1_segdir'(le
+| 3664: 76 65 6c 20 49 4e 54 45 47 45 52 2c 69 64 78 20 vel INTEGER,idx
+| 3680: 49 4e 54 45 47 45 52 2c 73 74 61 72 74 5f 62 6c INTEGER,start_bl
+| 3696: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c 65 61 76 ock INTEGER,leav
+| 3712: 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20 49 4e 54 es_end_block INT
+| 3728: 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63 6b 20 49 EGER,end_block I
+| 3744: 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42 4c 4f 42 NTEGER,root BLOB
+| 3760: 2c 50 52 49 4d 41 52 59 20 4b 45 59 28 6c 65 76 ,PRIMARY KEY(lev
+| 3776: 65 6c 2c 20 69 64 78 29 29 31 05 06 17 45 1f 01 el, idx))1...E..
+| 3792: 00 69 6e 64 65 78 73 71 6c 69 74 65 5f 61 75 74 .indexsqlite_aut
+| 3808: 6f 69 6e 64 65 78 5f 78 31 5f 73 65 67 64 69 72 oindex_x1_segdir
+| 3824: 5f 31 78 31 5f 73 65 67 64 69 72 05 00 00 00 08 _1x1_segdir.....
+| 3840: 00 00 00 00 66 03 07 17 23 23 01 81 13 74 61 62 ....f...##...tab
+| 3856: 6c 65 78 31 5f 73 65 67 6d 65 6e 74 73 78 31 5f lex1_segmentsx1_
+| 3872: 73 65 67 6d 65 6e 74 73 03 43 52 45 41 54 45 20 segments.CREATE
+| 3888: 54 41 42 4c 45 20 27 78 31 5f 73 65 67 6d 65 6e TABLE 'x1_segmen
+| 3904: 74 73 27 28 62 6c 6f 63 6b 69 64 20 49 4e 54 45 ts'(blockid INTE
+| 3920: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 3936: 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c 02 07 17 block BLOB)....
+| 3952: 21 21 01 81 03 74 61 62 6c 65 78 31 5f 63 6f 6e !!...tablex1_con
+| 3968: 74 65 6e 74 78 31 5f 63 6f 6e 74 65 6e 74 02 43 tentx1_content.C
+| 3984: 52 45 41 54 45 20 54 41 42 4c 45 20 27 78 31 5f REATE TABLE 'x1_
+| 4000: 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69 64 20 49 content'(docid I
+| 4016: 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b NTEGER PRIMARY K
+| 4032: 45 59 2c 20 27 63 30 78 27 29 34 01 06 17 11 11 EY, 'c0x')4.....
+| 4048: 08 57 74 61 62 6c 65 78 31 78 31 43 52 45 41 54 .Wtablex1x1CREAT
+| 4064: 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 E VIRTUAL TABLE
+| 4080: 78 31 20 55 53 49 4e 47 20 66 74 73 33 28 78 29 x1 USING fts3(x)
+| page 2 offset 4096
+| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3920: 00 00 00 2e 04 03 00 63 62 72 61 69 6e 73 74 65 .......cbrainste
+| 3936: 6d 20 62 72 61 69 6e 73 74 65 6d 73 20 62 72 61 m brainstems bra
+| 3952: 69 6e 73 74 6f 72 6d 20 62 72 61 69 6e 73 74 6f instorm brainsto
+| 3968: 72 6d 73 2b 03 03 00 5d 62 72 61 69 6e 20 62 72 rms+...]brain br
+| 3984: 61 69 6e 63 68 69 6c 64 20 62 72 61 69 6e 65 64 ainchild brained
+| 4000: 20 62 72 61 69 6e 69 6e 67 20 62 72 61 69 6e 73 braining brains
+| 4016: 26 02 03 00 53 62 72 61 67 73 20 62 72 61 69 64 &...Sbrags braid
+| 4032: 20 62 72 61 69 64 65 64 20 62 72 61 69 64 69 6e braided braidin
+| 4048: 67 20 62 72 61 69 64 73 26 01 03 00 53 62 72 61 g braids&...Sbra
+| 4064: 65 73 20 62 72 61 67 20 62 72 61 67 67 65 64 20 es brag bragged
+| 4080: 62 72 61 c3 67 65 72 20 62 72 61 67 67 69 6e 67 bra.ger bragging
+| page 3 offset 8192
+| 0: 0d 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 ................
+| page 4 offset 12288
+| 0: 0d 00 00 00 04 0f 20 00 0f c8 0f 90 0f 54 0f 20 ...... ......T.
+| 3872: 32 04 07 08 01 08 08 15 58 03 30 20 33 38 00 09 2.......X.0 38..
+| 3888: 62 72 61 69 6e 73 74 65 6d 03 04 02 00 09 01 73 brainstem......s
+| 3904: 03 04 03 00 07 03 6f 72 6d 03 04 04 00 0a 01 73 ......orm......s
+| 3920: 03 04 05 00 3a 03 07 08 01 08 08 15 68 02 30 20 ....:.......h.0
+| 3936: 34 36 00 05 62 72 61 69 6e 03 03 02 00 05 05 63 46..brain......c
+| 3952: 68 69 6c 64 03 03 03 00 05 02 65 64 03 03 04 00 hild......ed....
+| 3968: 05 03 69 6e 67 03 03 05 00 05 01 73 03 03 06 00 ..ing......s....
+| 3984: 36 02 07 08 09 08 08 15 62 30 20 34 33 00 05 62 6.......b0 43..b
+| 4000: 72 61 67 73 03 02 02 00 03 02 69 64 03 02 03 00 rags......id....
+| 4016: 05 02 65 64 03 02 04 00 05 03 69 6e 67 03 02 05 ..ed......ing...
+| 4032: 00 05 01 73 03 02 06 00 36 01 07 08 08 08 08 15 ...s....6.......
+| 4048: 62 30 20 34 33 00 05 62 72 61 65 73 03 01 02 00 b0 43..braes....
+| 4064: 03 01 68 03 01 03 00 04 03 67 65 74 03 01 04 00 ..h......get....
+| 4080: 06 01 72 03 01 05 00 05 03 69 6e 67 03 01 06 00 ..r......ing....
+| page 5 offset 16384
+| 0: 0a 00 00 00 04 0f e7 00 0f fb 0f f5 0f ee 0f e7 ................
+| 4064: 00 00 00 00 00 00 00 06 04 08 01 01 03 04 06 04 ................
+| 4080: 08 01 01 02 03 05 04 08 09 01 02 04 04 08 08 09 ................
+| end sql038051.txt.db
+}]} {}
+
+do_catchsql_test 48.1 {
+ INSERT INTO x1(x1) VALUES('nodesize=24'),('merge=3,4');
+ INSERT INTO x1(x1) VALUES( 'merge=3,4' ),('merge=3,4');
+} {1 {database disk image is malformed}}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_test 49.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 28672 pagesize 4096 filename crash-58821b8eae6883.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
+| 96: 00 00 00 00 0d 0e ef 00 07 0d 4d 00 0f bd 0f 5f ..........M...._
+| 112: 0e f7 0e 06 0e bc 0d a4 0d 4d 00 00 00 00 00 00 .........M......
+| 3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 55 07 07 .............U..
+| 3408: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 73 74 ......tablet1_st
+| 3424: 61 74 74 31 5f 73 74 61 74 07 43 52 45 41 54 45 att1_stat.CREATE
+| 3440: 20 54 41 42 4c 45 20 27 74 31 5f 73 74 61 74 27 TABLE 't1_stat'
+| 3456: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
+| 3472: 41 52 59 20 4b 45 59 2c 20 76 61 6c 75 65 20 42 ARY KEY, value B
+| 3488: 4c 4f 42 29 60 06 07 17 21 21 01 81 0b 74 61 62 LOB)`...!!...tab
+| 3504: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
+| 3520: 6f 63 73 69 7a 65 06 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
+| 3536: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
+| 3552: 28 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50 (docid INTEGER P
+| 3568: 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 69 7a 65 RIMARY KEY, size
+| 3584: 20 42 4c 4f 42 29 81 33 04 07 17 1f 1f 01 82 35 BLOB).3.......5
+| 3600: 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72 74 31 tablet1_segdirt1
+| 3616: 5f 73 65 67 64 69 72 04 43 52 45 41 54 45 20 54 _segdir.CREATE T
+| 3632: 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69 72 27 ABLE 't1_segdir'
+| 3648: 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52 2c 69 (level INTEGER,i
+| 3664: 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61 72 74 dx INTEGER,start
+| 3680: 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c _block INTEGER,l
+| 3696: 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20 eaves_end_block
+| 3712: 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63 INTEGER,end_bloc
+| 3728: 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42 k INTEGER,root B
+| 3744: 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45 59 28 LOB,PRIMARY KEY(
+| 3760: 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 05 06 17 level, idx))1...
+| 3776: 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74 65 5f E...indexsqlite_
+| 3792: 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73 65 67 autoindex_t1_seg
+| 3808: 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72 05 00 dir_1t1_segdir..
+| 3824: 00 00 08 00 00 00 00 66 03 07 17 23 23 01 81 13 .......f...##...
+| 3840: 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e 74 73 tablet1_segments
+| 3856: 74 31 5f 73 65 67 6d 65 6e 74 73 03 43 52 45 41 t1_segments.CREA
+| 3872: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 TE TABLE 't1_seg
+| 3888: 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64 20 49 ments'(blockid I
+| 3904: 4e 54 45 47 45 52 20 f9 52 49 4d 41 52 59 20 4b NTEGER .RIMARY K
+| 3920: 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c EY, block BLOB).
+| 3936: 02 07 17 21 21 01 81 03 74 61 62 6c 65 74 31 5f ...!!...tablet1_
+| 3952: 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 65 6e contentt1_conten
+| 3968: 74 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
+| 3984: 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69 t1_content'(doci
+| 4000: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
+| 4016: 59 20 4b 45 59 2c 20 27 63 30 61 27 29 41 01 06 Y KEY, 'c0a')A..
+| 4032: 17 11 11 08 71 74 61 62 6c 65 74 31 74 31 43 52 ....qtablet1t1CR
+| 4048: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
+| 4064: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 34 LE t1 USING fts4
+| 4080: 28 61 2c 70 72 65 66 69 78 3d 27 32 2c 32 27 29 (a,prefix='2,2')
+| page 2 offset 4096
+| 0: 0d 00 00 00 08 0e 1f 00 0f c4 0f 7c 0f 34 0f 07 ...........|.4..
+| 16: 0e c3 0e 97 0e 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 ...............B
+| 3616: 08 04 00 81 09 73 75 6e 74 20 69 6e 20 63 75 6c .....sunt in cul
+| 3632: 70 61 20 71 75 69 20 6f 66 66 69 63 69 61 20 64 pa qui officia d
+| 3648: 65 73 65 72 75 6e 74 20 6d 6f 6c 6c 69 74 20 61 eserunt mollit a
+| 3664: 6e 69 6d 20 69 64 20 65 73 74 20 6c 61 62 6f 72 nim id est labor
+| 3680: 75 6d 2e 32 07 03 00 6b 45 78 63 65 70 74 65 75 um.2...kExcepteu
+| 3696: 72 20 73 69 6e 74 20 6f 63 63 61 65 63 61 74 20 r sint occaecat
+| 3712: 63 75 70 69 64 61 74 61 74 20 6e 6f 6e 20 70 72 cupidatat non pr
+| 3728: 6f 69 64 65 6e 74 2c 2a 06 03 00 5b 63 69 6c 6c oident,*...[cill
+| 3744: 75 6d 20 64 6f 6c 6f 72 65 20 65 75 20 66 75 67 um dolore eu fug
+| 3760: 69 61 74 20 6e 75 6c 6c 61 20 70 61 72 69 61 74 iat nulla pariat
+| 3776: 75 72 2e 42 05 04 00 81 09 44 75 69 73 20 61 75 ur.B.....Duis au
+| 3792: 74 65 20 69 72 75 72 65 20 64 6f 6c 6f 72 20 69 te irure dolor i
+| 3808: 6e 20 72 65 70 72 65 68 65 6e 64 65 72 69 74 20 n reprehenderit
+| 3824: 69 6e 20 76 6f 6c 75 70 74 61 74 65 20 76 65 6c in voluptate vel
+| 3840: 69 74 20 65 73 73 65 2b 04 03 00 5d 6e 69 73 69 it esse+...]nisi
+| 3856: 20 75 74 20 61 6c 69 71 75 69 70 20 65 78 20 65 ut aliquip ex e
+| 3872: 61 20 63 6f 6d 6d 6f 64 6f 20 63 6f 6e 73 65 71 a commodo conseq
+| 3888: 75 61 74 2e 46 03 04 00 81 11 55 74 20 65 6e 69 uat.F.....Ut eni
+| 3904: 6d 20 61 64 20 6d 69 6e 69 6d 20 76 65 6e 69 61 m ad minim venia
+| 3920: 6d 2c 20 71 75 69 73 20 6e 6f 73 74 72 75 64 20 m, quis nostrud
+| 3936: 65 78 65 72 63 69 74 61 74 69 6f 6e 20 75 6c 6c exercitation ull
+| 3952: 61 6d 63 6f 20 6c 61 62 6f 72 69 73 46 02 04 00 amco laborisF...
+| 3968: 81 11 73 65 64 20 64 6f 20 65 69 75 73 6d 6f 64 ..sed do eiusmod
+| 3984: 20 74 65 6d 70 6f 72 20 69 6e 63 69 64 69 64 75 tempor incididu
+| 4000: 6e 74 20 75 74 20 6c 61 62 6f 72 65 20 65 74 20 nt ut labore et
+| 4016: 64 6f 6c 6f 72 65 20 6d 61 67 6e 61 20 61 6c 69 dolore magna ali
+| 4032: 71 75 61 2e 3a 01 03 00 7b 4c 6f 72 65 6d 20 69 qua.:....Lorem i
+| 4048: 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61 psum dolor sit a
+| 4064: 6d 65 74 2c 20 63 6f 6e 73 65 63 74 65 74 75 72 met, consectetur
+| 4080: 20 61 64 69 70 69 73 63 69 6e 67 20 65 00 01 00 adipiscing e...
+| page 4 offset 12288
+| 0: 0d 00 00 00 03 0a a6 00 0d 57 0c 4a 0a a6 00 00 .........W.J....
+| 2720: 00 00 00 00 00 00 83 21 03 08 02 08 08 08 17 86 .......!........
+| 2736: 30 08 00 30 20 34 30 32 00 02 61 64 06 01 08 00 0..0 402..ad....
+| 2752: 02 04 00 01 01 6c 06 02 0c 00 02 04 00 01 01 6d .....l.........m
+| 2768: 03 01 06 00 01 01 6e 03 08 09 00 01 01 75 03 05 ......n......u..
+| 2784: 03 00 00 02 63 69 03 06 02 00 01 01 6f 07 01 07 ....ci......o...
+| 2800: 00 03 07 03 00 01 01 75 06 07 05 00 01 04 00 00 .......u........
+| 2816: 02 64 65 03 08 07 00 01 01 6f 0d 01 04 00 01 03 .de......o......
+| 2832: 09 00 03 05 00 01 03 00 01 01 75 03 05 02 00 00 ..........u.....
+| 2848: 02 65 61 03 04 06 00 01 01 69 03 02 04 00 01 01 .ea......i......
+| 2864: 6c 03 01 09 00 01 01 6e 03 03 03 00 01 01 73 06 l......n......s.
+| 2880: 05 0b 00 03 0b 00 01 01 74 03 02 09 00 01 01 75 ........t......u
+| 2896: 03 06 04 00 01 01 78 09 03 09 00 01 05 00 03 02 ......x.........
+| 2912: 00 00 02 66 75 03 06 05 00 00 02 69 64 03 08 0a ...fu......id...
+| 2928: 00 01 01 6e 0a 02 06 00 03 06 04 00 03 03 00 01 ...n............
+| 2944: 01 70 03 01 03 00 01 01 72 03 05 04 00 00 02 6c .p......r......l
+| 2960: 61 09 02 08 00 01 0b 00 05 0c 00 01 01 6f 03 01 a............o..
+| 2976: 02 00 00 02 6d 61 03 02 0b 00 01 01 69 03 03 05 ....ma......i...
+| 2992: 00 01 01 6f 03 08 08 00 00 02 6e 69 03 04 02 00 ...o......ni....
+| 3008: 01 01 6f 06 03 08 00 04 06 00 01 01 75 03 06 06 ..o.........u...
+| 3024: 00 00 02 6f 63 03 07 04 00 01 01 66 03 08 06 00 ...oc......f....
+| 3040: 00 02 70 61 03 06 07 00 01 01 72 03 07 07 00 00 ..pa......r.....
+| 3056: 02 71 75 06 03 07 00 05 05 00 00 02 72 65 03 05 .qu.........re..
+| 3072: 07 00 00 02 73 65 03 02 02 00 01 01 69 06 01 05 ....se......i...
+| 3088: 00 06 03 00 01 01 75 03 08 02 00 00 02 74 65 03 ......u......te.
+| 3104: 02 05 00 00 02 75 6c 03 03 0a 00 01 01 74 09 02 .....ul......t..
+| 3120: 07 00 01 02 00 01 03 00 00 02 76 65 06 03 06 00 ..........ve....
+| 3136: 02 0a 00 01 01 6f 03 05 09 00 82 0a 02 08 02 08 .....o..........
+| 3152: 08 08 17 84 02 04 00 30 20 32 35 31 00 01 61 13 .......0 251..a.
+| 3168: 01 06 04 00 01 0c 00 01 04 00 01 04 00 01 03 00 ................
+| 3184: 03 09 00 00 01 63 10 01 07 00 03 07 03 00 02 02 .....c..........
+| 3200: 00 01 05 00 01 04 00 00 01 64 11 01 04 00 01 03 .........d......
+| 3216: 09 00 03 02 05 00 01 03 00 02 07 00 00 01 65 1b ..............e.
+| 3232: 01 09 00 01 04 07 00 01 03 08 00 01 05 03 00 01 ................
+| 3248: 0b 00 01 04 00 01 02 00 01 0b 00 00 01 66 03 06 .............f..
+| 3264: 05 00 00 01 69 0f 01 03 00 01 06 00 03 04 04 04 ....i...........
+| 3280: 00 03 03 09 00 00 01 6c 0c 01 02 00 01 08 00 01 .......l........
+| 3296: 0b 00 05 0c 00 00 01 6d 09 02 0b 00 01 05 00 05 .......m........
+| 3312: 08 00 00 01 6e 0c 03 08 00 01 02 00 02 06 00 01 ....n...........
+| 3328: 06 00 00 01 6f 06 07 04 00 01 06 00 00 01 70 06 ....o.........p.
+| 3344: 06 07 00 01 07 00 00 01 71 06 03 07 00 05 05 00 ........q.......
+| 3360: 00 01 72 03 05 07 00 00 01 73 0c 01 05 00 01 02 ..r......s......
+| 3376: 00 05 03 00 01 02 00 00 01 74 03 02 05 00 00 01 .........t......
+| 3392: 75 0a 02 07 00 01 02 0a 00 01 03 00 00 01 76 07 u.............v.
+| 3408: 03 06 00 02 09 03 00 85 26 01 08 08 08 08 08 17 ........&.......
+| 3424: 8a 3e 30 20 36 36 35 00 02 61 65 03 03 04 00 02 .>0 665..ae.....
+| 3440: 08 69 70 69 73 63 69 6e 67 03 01 08 00 01 05 6c .ipiscing......l
+| 3456: 69 71 75 61 03 02 0c 00 05 02 69 70 03 04 04 00 iqua......ip....
+| 3472: 01 03 6d 65 74 03 01 06 00 01 03 6e 69 6d 03 08 ..met......nim..
+| 3488: 09 00 01 03 75 74 65 03 05 03 00 00 06 63 69 6c ....ute......cil
+| 3504: 6c 75 6d 03 06 02 00 01 06 6f 6d 6d 6f 64 6f 03 lum......ommodo.
+| 3520: 04 07 00 02 09 6e 73 65 63 74 65 74 b5 72 03 01 .....nsectet.r..
+| 3536: 07 00 05 04 71 75 61 74 03 04 08 00 01 04 75 6c ....quat......ul
+| 3552: 70 61 03 08 04 00 02 07 70 69 64 61 74 61 74 03 pa......pidatat.
+| 3568: 07 05 00 00 08 64 65 73 65 72 75 6e 74 03 08 07 .....deserunt...
+| 3584: 00 01 01 6f 03 02 03 00 02 03 6c 6f 72 06 01 04 ...o......lor...
+| 3600: 00 04 05 00 05 01 65 06 02 0a 00 04 03 00 01 03 ......e.........
+| 3616: 75 69 73 03 05 02 00 00 02 65 61 03 04 06 00 01 uis......ea.....
+| 3632: 06 69 75 73 6d 6f 64 03 02 04 00 01 03 6c 69 74 .iusmod......lit
+| 3648: 03 01 09 00 01 03 6e 69 6d 03 03 03 00 01 03 73 ......nim......s
+| 3664: 73 65 03 05 0b 00 02 01 74 03 08 0b 00 01 01 74 se......t......t
+| 3680: 03 02 09 00 01 01 75 03 06 04 00 01 01 78 03 04 ......u......x..
+| 3696: 05 00 02 07 63 65 70 74 65 75 72 03 07 02 00 02 ....cepteur.....
+| 3712: 0a 65 72 63 69 74 61 74 69 6f 6e 03 03 09 00 00 .ercitation.....
+| 3728: 06 66 75 67 69 61 74 03 06 05 00 00 02 69 64 03 .fugiat......id.
+| 3744: 08 0a 00 01 01 6e 07 05 06 04 00 03 03 00 02 08 .....n..........
+| 3760: 63 69 64 69 64 75 6e 74 03 02 06 00 01 04 70 73 cididunt......ps
+| 3776: 75 6d 03 01 03 00 01 04 72 75 72 65 03 05 04 00 um......rure....
+| 3792: 00 06 6c 61 62 6f 72 65 03 02 08 00 05 02 69 73 ..labore......is
+| 3808: 03 03 0b 00 05 02 75 6d 03 08 0c 00 01 04 6f 72 ......um......or
+| 3824: 65 6d 03 01 02 00 00 05 6d 61 67 6e 61 03 02 0b em......magna...
+| 3840: 00 01 04 69 6e 69 6d 03 03 05 00 01 05 6f 6c 6c ...inim......oll
+| 3856: 69 74 03 08 08 00 00 04 6e 69 73 69 03 04 02 00 it......nisi....
+| 3872: 01 02 6f 6e 03 07 06 00 02 05 73 74 72 75 64 03 ..on......strud.
+| 3888: 03 08 00 01 04 75 6c 6c 61 03 06 06 00 00 08 6f .....ulla......o
+| 3904: 63 63 61 65 63 61 74 03 07 04 00 01 06 66 66 69 ccaecat......ffi
+| 3920: 63 69 61 03 08 06 00 00 08 70 61 72 69 61 74 75 cia......pariatu
+| 3936: 72 03 06 07 00 01 07 72 6f 69 64 65 6e 74 03 07 r......roident..
+| 3952: 07 00 00 03 71 75 69 03 08 05 00 03 01 73 03 03 ....qui......s..
+| 3968: 07 00 00 0d 72 65 70 72 65 68 65 6e 64 65 72 69 ....reprehenderi
+| 3984: 74 03 05 07 00 00 03 73 65 64 03 02 02 00 01 03 t......sed......
+| 4000: 69 6e 74 03 07 03 00 02 01 74 03 01 05 00 01 03 int......t......
+| 4016: 75 6e 74 03 08 02 00 00 06 74 65 6d 70 6f 72 03 unt......tempor.
+| 4032: 02 05 00 00 07 75 6c 6c 61 6d 63 6f 03 03 0a 00 .....ullamco....
+| 4048: 01 01 74 09 02 07 00 01 02 00 01 03 00 00 05 76 ..t............v
+| 4064: 65 6c 69 74 03 05 0a 00 02 04 6e 69 61 6d 03 03 elit......niam..
+| 4080: 06 00 01 08 6f 6c 75 70 74 61 74 65 03 05 09 00 ....oluptate....
+| page 5 offset 16384
+| 0: 0a 00 00 00 03 0f eb 00 0f fb 0f f3 0f eb 00 00 ................
+| 4064: 00 00 00 00 00 00 00 00 00 00 00 07 04 02 08 01 ................
+| 4080: 08 00 03 07 04 02 08 01 04 00 02 04 04 08 08 09 ................
+| page 6 offset 20480
+| 0: 0d 00 00 00 08 0f d0 00 0f fa 0f f4 0f ee 0f e8 ................
+| 16: 0f e2 0f dc 0f d6 0f d0 00 00 00 00 00 00 00 00 ................
+| 4048: 04 08 03 00 0e 0b 04 07 03 00 0e 06 04 06 03 00 ................
+| 4064: 0e 06 04 05 03 00 0e 0a 04 04 03 00 0e 07 04 03 ................
+| 4080: 03 00 0e 0a 04 02 03 00 0e 0b 04 01 03 00 0e 08 ................
+| page 7 offset 24576
+| 0: 0d 00 00 00 01 0f f7 00 0f f7 00 00 00 00 01 00 ................
+| 4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03 .............E..
+| end crash-58821b8eae6883.db
+}]} {}
+
+do_catchsql_test 49.1 {
+ SAVEPOINT one;
+ DELETE FROM t1 WHERE t1 MATCH 'c*';
+ SELECT matchinfo(t1,'pcx') IS NULL FROM t1 WHERE t1 MATCH 'f*e*';
+} {0 0}
+
+#-------------------------------------------------------------------------
+#
+reset_db
+do_test 50.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+.open --hexdb
+| size 28672 pagesize 4096 filename crash-14ab65782c9c45.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........
+| 32: 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 ................
+| 96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21 ...............!
+| 112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00 .....~..........
+| 3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c ...........1tabl
+| 3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42 et2t2.CREATE TAB
+| 3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01 LE t2(x).3......
+| 3536: 82 35 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72 .5tablet1_segdir
+| 3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45 t1_segdir.CREATE
+| 3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69 TABLE 't1_segdi
+| 3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52 r'(level INTEGER
+| 3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61 ,idx INTEGER,sta
+| 3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 rt_block INTEGER
+| 3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63 ,leaves_end_bloc
+| 3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c k INTEGER,end_bl
+| 3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74 ock INTEGER,root
+| 3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45 BLOB,PRIMARY KE
+| 3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06 Y(level, idx))1.
+| 3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74 ..E...indexsqlit
+| 3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73 e_autoindex_t1_s
+| 3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 68 64 69 72 egdir_1t1_sehdir
+| 3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01 .........f...##.
+| 3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e ..tablet1_segmen
+| 3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52 tst1_segments.CR
+| 3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 EATE TABLE 't1_s
+| 3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64 egments'(blockid
+| 3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
+| 3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 KEY, block BLOB
+| 3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74 )j...!!...tablet
+| 3888: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
+| 3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
+| 3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f 't1_content'(do
+| 3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d cid INTEGER PRIM
+| 3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20 ARY KEY, 'c0a',
+| 3968: 27 62 31 62 27 2c 20 27 63 32 63 27 29 38 02 06 'b1b', 'c2c')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 33 LE t1 USING fts3
+| 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 25 0b 48 00 0f d8 0f af 0f 86 0f 74 ....%.H........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 00 00 00 00 00 00 00 00 00 ................
+| 2880: 00 00 00 00 00 00 00 00 81 f9 25 06 00 82 7f 00 ..........%.....
+| 2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e .COMPILER=gcc-5.
+| 2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42 4.0 20160609 DEB
+| 2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54 UG ENABLE DBSTAT
+| 2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53 VTAB ENABLE FTS
+| 2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e 4 ENABLE FTS5 EN
+| 2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41 ABLE GEOPOLY ENA
+| 2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45 BLE JSON1 ENABLE
+| 3008: 20 4d 45 4d 53 59 53 35 20 45 4e 41 42 4c 45 20 MEMSYS5 ENABLE
+| 3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59 RTREE MAX MEMORY
+| 3040: 3d 37 a0 30 30 30 30 f2 30 20 4f 4d 49 54 20 4c =7.0000.0 OMIT L
+| 3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48 OAD EXTENSION TH
+| 3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 25 0f READSAFE=0.$..%.
+| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
+| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..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 54 53 41 46 45 3d ..%..THREATSAFE=
+| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM
+| 3168: 49 54 20 5c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT .OAD 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 46 1e 1f 05 00 33 0f 17 ONXNOCASF....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 44 52 49 4d 1f 1e 05 00 33 0f 19 IONXRDRIM....3..
+| 3264: 4d 41 68 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAh 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 16 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 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
+| 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: 4e 41 42 4c 45 20 4d 45 43 53 59 53 35 58 42 49 NABLE MECSYS5XBI
+| 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 58 42 49 NABLE GEOPOLYXBI
+| 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 43 41 53 45 E GEOPOLYXNOCASE
+| 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 46 20 46 54 53 34 58 52 54 52 49 4d 1e ABLF 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: 55 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d UAT VTABXNOCASE.
+| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
+| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
+| 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 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...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 58 42 49 4e 41 52 59 27 20160609XBINARY'
+| 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 00 00 00 00 00 00 00 00 9XNOCASE........
+| page 5 offset 16384
+| 0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00 ................
+| 2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33 ...........0 253
+| 2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36 ..0.%.....201606
+| 3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35 09.%....4.%....5
+| 3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a .%....0000000.%.
+| 3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00 ...compiler.%...
+| 3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75 .dbstat.%....ebu
+| 3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09 g.%....enable.%.
+| 3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f .........xtensio
+| 3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03 n.%....fts4.%...
+| 3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01 .5.%....gcc.%...
+| 3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f .eopoly.%....jso
+| 3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00 n1.%....load.%..
+| 3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79 ..max.%....emory
+| 3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04 .%....sys5.%....
+| 3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03 omit.%....rtree.
+| 3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03 %....threadsafe.
+| 3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01 %....vtab.%...P.
+| 3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30 ........0 835..0
+| 3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00 ................
+| 3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07 .....20160609...
+| 3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05 .........4......
+| 3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04 ......5.........
+| 3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04 ...0000000......
+| 3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02 ......binary<...
+| 3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 ................
+| 3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 ................
+| 3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 ................
+| 3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 38 70 69 ...........co8pi
+| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64 ler............d
+| 3440: 52 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 Rstat...........
+| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug...........
+| 3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 01 .enable?........
+| 3488: ff f1 02 00 01 02 00 01 02 00 01 02 00 01 02 00 ................
+| 3504: 01 02 00 01 03 00 01 01 00 02 02 00 01 02 00 01 ................
+| 3520: 02 00 01 02 00 01 12 00 01 02 00 01 02 00 01 02 ................
+| 3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f .........xtensio
+| 3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73 n............fts
+| 3568: 34 09 0a 03 00 01 03 00 01 04 00 03 01 35 09 0d 4............5..
+| 3584: 03 00 01 03 00 01 03 00 00 03 67 63 63 09 01 03 ..........gcc...
+| 3600: 00 01 03 0b 01 13 00 01 06 65 6f 70 6f 6c 79 09 .........eopoly.
+| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 83 6f 6e 31 ...........j.on1
+| 3632: 09 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64 ............load
+| 3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09 ............max.
+| 3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79 ...........emory
+| 3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35 ............sys5
+| 3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61 ............noca
+| 3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02 se<.............
+| 3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 ................
+| 3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 ................
+| 3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00 ................
+| 3776: 04 6f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00 .omit...........
+| 3792: 05 72 74 72 65 65 09 19 03 00 01 03 00 01 03 00 .rtree..........
+| 3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03 ..im<...........
+| 3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 ................
+| 3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 ................
+| 3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 ................
+| 3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02 ...threadsafe...
+| 3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04 .........vtab...
+| 3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02 .........x......
+| 3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 ................
+| 3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 ................
+| 3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 ................
+| 3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 ................
+| 3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 ................
+| 4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 ................
+| 4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 ................
+| 4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 ................
+| 4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 ................
+| 4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 ................
+| 4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 ................
+| page 6 offset 20480
+| 0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00 ................
+| 4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09 ................
+| page 7 offset 24576
+| 0: 0d 00 00 00 05 0f b8 00 0f f4 0f 00 00 00 00 00 ................
+| 4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f ...........#auto
+| 4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65 merge=5...#merge
+| 4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72 =100,8...+integr
+| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 00 00 00 00 ity-check.......
+| end crash-14ab65782c9c45.db
+}]} {}
+
+do_execsql_test 50.1 {
+ SELECT NULL FROM t1 WHERE t1 MATCH '"^enable"'
+} {
+ {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}
+}
+
+
+
+
finish_test
diff --git a/test/fts3corrupt6.test b/test/fts3corrupt6.test
index 9e22bdf68..fde2fba2e 100644
--- a/test/fts3corrupt6.test
+++ b/test/fts3corrupt6.test
@@ -11,8 +11,6 @@
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS3 module.
#
-# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
-#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -54,7 +52,27 @@ do_execsql_test 1.3 {
SELECT 42+matchinfo(t1,'yxyyxy') FROM t1 WHERE t1 MATCH x'2b0a312b0a312a312a2a0b5d0a0b0b0a312a0a0b0b0a312a0b310a392a0b0a27312a2a0b5d0a312a0b310a31315d0b310a312a316d2a0b313b15bceaa50a312a0b0a27312a2a0b5d0a312a0b310a312b0b2a310a312a0b2a0b2a0b2e5d0a0bff313336e34a2a312a0b0a3c310b0a0b4b4b0b4b2a4bec40322b2a0b310a0a312a0a0a0a0a0a0a0a0a0b310a312a2a2a0b5d0a0b0b0a312a0b310a312a0b0a4e4541530b310a5df5ced70a0a0a0a0a4f520a0a0a0a0a0a0a312a0b0a4e4541520b310a5d616161610a0a0a0a4f520a0a0a0a0a0a312b0a312a312a0a0a0a0a0a0a004a0b0a310b220a0b0a310a4a22310a0b0a7e6fe0e0e030e0e0e0e0e01176e02000e0e0e0e0e01131320226310a0b0a310a4a22310a0b0a310a766f8b8b4ee0e0300ae0090909090909090909090909090909090909090909090909090909090909090947aaaa540b09090909090909090909090909090909090909090909090909090909090909fae0e0f2f22164e0e0f273e07fefefef7d6dfafafafa6d6d6d6d';
} {42}
-set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
-finish_test
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.0 {
+ CREATE VIRTUAL TABLE t0 USING fts3(a);
+ INSERT INTO t0_segdir VALUES(0,0,0,0,'0 42',X'000131030782000103323334050100fff200010461616161050101020200000462626262050101030200');
+}
+do_execsql_test 2.1 {
+ SELECT count(*) FROM t0 WHERE t0 MATCH '(1 NEAR 1) AND (aaaa OR 1)';
+} 1
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE VIRTUAL TABLE main.Table0 USING fts3();
+ INSERT INTO Table0 VALUES (1), (printf('%8.1280000X') ), (1), (printf('%8.1280000X') ), (1) ;
+ INSERT INTO Table0 VALUES (0), (printf('%8.1280000X%8.1280000X') ), (1), (printf('%1280000.1280000X%#1280000.1280000E%8.1280000X') ), (1) ;
+ INSERT INTO Table0 VALUES (1) ;
+ UPDATE Table0_segdir SET start_block = 1;
+ INSERT INTO Table0 VALUES (1) ;
+ INSERT INTO Table0(Table0) VALUES('merge=6,8');
+}
+set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
+finish_test
diff --git a/test/fts3join.test b/test/fts3join.test
index f3b9b3639..9a7994193 100644
--- a/test/fts3join.test
+++ b/test/fts3join.test
@@ -97,10 +97,10 @@ do_eqp_test 4.2 {
WHERE t4.y = ?;
} {
QUERY PLAN
- |--MATERIALIZE xxxxxx
- | `--SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:
- |--SCAN TABLE t4
- `--SEARCH SUBQUERY xxxxxx AS rr USING AUTOMATIC COVERING INDEX (docid=?)
+ |--MATERIALIZE rr
+ | `--SCAN ft4 VIRTUAL TABLE INDEX 3:
+ |--SCAN t4
+ `--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?)
}
finish_test
diff --git a/test/fts3query.test b/test/fts3query.test
index ca3ee6695..70ee00529 100644
--- a/test/fts3query.test
+++ b/test/fts3query.test
@@ -119,29 +119,29 @@ do_eqp_test fts3query-4.2 {
SELECT t1.number FROM t1, ft WHERE t1.number=ft.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.3 {
SELECT t1.number FROM ft, t1 WHERE t1.number=ft.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.4 {
SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test fts3query-4.5 {
SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date
} {
QUERY PLAN
- |--SCAN TABLE t1 USING COVERING INDEX i1
- `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
+ |--SCAN t1 USING COVERING INDEX i1
+ `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}
diff --git a/test/fts3snippet2.test b/test/fts3snippet2.test
index fc3994189..607b01e0f 100644
--- a/test/fts3snippet2.test
+++ b/test/fts3snippet2.test
@@ -57,4 +57,3 @@ do_execsql_test 2.2 {
set sqlite_fts3_enable_parentheses 0
finish_test
-
diff --git a/test/fts4rename.test b/test/fts4rename.test
index c647d6928..5571ea7b1 100644
--- a/test/fts4rename.test
+++ b/test/fts4rename.test
@@ -29,7 +29,7 @@ do_execsql_test 1.0 {
do_catchsql_test 1.1 {
ALTER TABLE t1_content RENAME c0a TO docid;
-} {1 {duplicate column name: docid}}
+} {1 {error in table t1_content after rename: duplicate column name: docid}}
do_catchsql_test 1.2 {
UPDATE t1 SET Col0 = 1 ;
diff --git a/test/fts4unicode.test b/test/fts4unicode.test
index f4d1a3348..facf2bf9c 100644
--- a/test/fts4unicode.test
+++ b/test/fts4unicode.test
@@ -567,4 +567,22 @@ do_execsql_test 11.1 {
berlin@street sydney.road
}
+# Test for embedded nul characters in fts4 unicode index.
+#
+do_execsql_test 12.0 {
+ CREATE VIRTUAL TABLE t12 USING fts4(tokenize=unicode61);
+ INSERT INTO t12 VALUES('abc' || char(0) || 'def');
+ SELECT hex(CAST(content AS blob)) FROM t12;
+} {61626300646566}
+do_execsql_test 12.1 {
+ INSERT INTO t12(t12) VALUES('integrity-check');
+} {}
+do_execsql_test 12.2 {
+ CREATE VIRTUAL TABLE t12aux USING fts4aux(t12);
+ SELECT * FROM t12aux;
+} {abc * 1 1 abc 0 1 1}
+do_execsql_test 12.3 {
+ SELECT hex(CAST(content AS blob)) FROM t12 WHERE t12 MATCH 'abc'
+} {61626300646566}
+
finish_test
diff --git a/test/fts4upfrom.test b/test/fts4upfrom.test
index b1b43a037..889b64ad6 100644
--- a/test/fts4upfrom.test
+++ b/test/fts4upfrom.test
@@ -137,4 +137,3 @@ foreach {tn create_table} {
}
finish_test
-
diff --git a/test/func.test b/test/func.test
index 4b235bedb..38c003773 100644
--- a/test/func.test
+++ b/test/func.test
@@ -1111,6 +1111,13 @@ do_test func-22.22 {
execsql {SELECT typeof(trim('hello',NULL));}
} {null}
+# 2021-06-15 - infinite loop due to unsigned character counter
+# overflow, reported by Zimuzo Ezeozue
+#
+do_execsql_test func-22.23 {
+ SELECT trim('xyzzy',x'c0808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080');
+} {xyzzy}
+
# This is to test the deprecated sqlite3_aggregate_count() API.
#
ifcapable deprecated {
diff --git a/test/func7.test b/test/func7.test
new file mode 100644
index 000000000..c8ae2931e
--- /dev/null
+++ b/test/func7.test
@@ -0,0 +1,245 @@
+# 2020-12-07
+#
+# 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.
+#
+#*************************************************************************
+#
+# Test cases for SQL functions based off the standard math library
+#
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+ifcapable !mathlib {
+ finish_test
+ return
+}
+
+do_execsql_test func7-100 {
+ SELECT ceil(99.9), ceiling(-99.01), floor(17), floor(-17.99);
+} {100.0 -99.0 17 -18.0}
+do_execsql_test func7-110 {
+ SELECT quote(ceil(NULL)), ceil('-99.99');
+} {NULL -99.0}
+do_execsql_test func7-200 {
+ SELECT round(ln(5),2), log(100.0), log(100), log(2,'256');
+} {1.61 2.0 2.0 8.0}
+do_execsql_test func7-210 {
+ SELECT ln(-5), log(-5,100.0);
+} {{} {}}
+
+# Test cases derived from PostgreSQL documentation
+#
+do_execsql_test func7-pg-100 {
+ SELECT abs(-17.4)
+} {17.4}
+do_execsql_test func7-pg-110 {
+ SELECT ceil(42.2)
+} {43.0}
+do_execsql_test func7-pg-120 {
+ SELECT ceil(-42.2)
+} {-42.0}
+do_execsql_test func7-pg-130 {
+ SELECT round(exp(1.0),7)
+} {2.7182818}
+do_execsql_test func7-pg-140 {
+ SELECT floor(42.8)
+} {42.0}
+do_execsql_test func7-pg-150 {
+ SELECT floor(-42.8)
+} {-43.0}
+do_execsql_test func7-pg-160 {
+ SELECT round(ln(2.0),7)
+} {0.6931472}
+do_execsql_test func7-pg-170 {
+ SELECT log(100.0)
+} {2.0}
+do_execsql_test func7-pg-180 {
+ SELECT log10(1000.0)
+} {3.0}
+do_execsql_test func7-pg-190 {
+ SELECT log(2.0, 64.0)
+} {6.0}
+do_execsql_test func7-pg-200 {
+ SELECT mod(9,4);
+} {1.0}
+do_execsql_test func7-pg-210 {
+ SELECT round(pi(),7);
+} {3.1415927}
+do_execsql_test func7-pg-220 {
+ SELECT power(9,3);
+} {729.0}
+do_execsql_test func7-pg-230 {
+ SELECT round(radians(45.0),7);
+} {0.7853982}
+do_execsql_test func7-pg-240 {
+ SELECT round(42.4);
+} {42.0}
+do_execsql_test func7-pg-250 {
+ SELECT round(42.4382,2);
+} {42.44}
+do_execsql_test func7-pg-260 {
+ SELECT sign(-8.4);
+} {-1}
+do_execsql_test func7-pg-270 {
+ SELECT round( sqrt(2), 7);
+} {1.4142136}
+do_execsql_test func7-pg-280 {
+ SELECT trunc(42.8), trunc(-42.8);
+} {42.0 -42.0}
+do_execsql_test func7-pg-300 {
+ SELECT acos(1);
+} {0.0}
+do_execsql_test func7-pg-301 {
+ SELECT degrees(acos(0.5));
+} {60.0}
+do_execsql_test func7-pg-310 {
+ SELECT round( asin(1), 7);
+} {1.5707963}
+do_execsql_test func7-pg-311 {
+ SELECT degrees( asin(0.5) );
+} {30.0}
+do_execsql_test func7-pg-320 {
+ SELECT round( atan(1), 7);
+} {0.7853982}
+do_execsql_test func7-pg-321 {
+ SELECT degrees( atan(1) );
+} {45.0}
+do_execsql_test func7-pg-330 {
+ SELECT round( atan2(1,0), 7);
+} {1.5707963}
+do_execsql_test func7-pg-331 {
+ SELECT degrees( atan2(1,0) );
+} {90.0}
+do_execsql_test func7-pg-400 {
+ SELECT cos(0);
+} {1.0}
+do_execsql_test func7-pg-401 {
+ SELECT cos( radians(60.0) );
+} {0.5}
+do_execsql_test func7-pg-400 {
+ SELECT cos(0);
+} {1.0}
+do_execsql_test func7-pg-410 {
+ SELECT round( sin(1), 7);
+} {0.841471}
+do_execsql_test func7-pg-411 {
+ SELECT sin( radians(30) );
+} {0.5}
+do_execsql_test func7-pg-420 {
+ SELECT round( tan(1), 7);
+} {1.5574077}
+do_execsql_test func7-pg-421 {
+ SELECT tan( radians(45) );
+} {1.0}
+do_execsql_test func7-pg-500 {
+ SELECT round( sinh(1), 7);
+} {1.1752012}
+do_execsql_test func7-pg-510 {
+ SELECT round( cosh(0), 7);
+} {1.0}
+do_execsql_test func7-pg-520 {
+ SELECT round( tanh(1), 7);
+} {0.7615942}
+do_execsql_test func7-pg-530 {
+ SELECT round( asinh(1), 7);
+} {0.8813736}
+do_execsql_test func7-pg-540 {
+ SELECT round( acosh(1), 7);
+} {0.0}
+do_execsql_test func7-pg-550 {
+ SELECT round( atanh(0.5), 7);
+} {0.5493061}
+
+# Test cases derived from MySQL documentation
+#
+do_execsql_test func7-mysql-100 {
+ SELECT acos(1);
+} {0.0}
+do_execsql_test func7-mysql-110 {
+ SELECT acos(1.0001);
+} {{}}
+do_execsql_test func7-mysql-120 {
+ SELECT round( acos(0.0), 7);
+} {1.5707963}
+do_execsql_test func7-mysql-130 {
+ SELECT round( asin(0.2), 7);
+} {0.2013579}
+do_execsql_test func7-mysql-140 {
+ SELECT asin('foo');
+} {{}} ;# Note: MySQL returns 0 here, not NULL.
+ # SQLite deliberately returns NULL.
+ # SQLServer and Oracle throw an error.
+do_execsql_test func7-mysql-150 {
+ SELECT round( atan(2), 7), round( atan(-2), 7);
+} {1.1071487 -1.1071487}
+do_execsql_test func7-mysql-160 {
+ SELECT round( atan2(-2,2), 7), round( atan2(pi(),0), 7);
+} {-0.7853982 1.5707963}
+do_execsql_test func7-mysql-170 {
+ SELECT ceiling(1.23), ceiling(-1.23);
+} {2.0 -1.0}
+do_execsql_test func7-mysql-180 {
+ SELECT cos(pi());
+} {-1.0}
+do_execsql_test func7-mysql-190 {
+ SELECT degrees(pi()), degrees(pi()/2);
+} {180.0 90.0}
+do_execsql_test func7-mysql-190 {
+ SELECT round( exp(2), 7), round( exp(-2), 7), exp(0);
+} {7.3890561 0.1353353 1.0}
+do_execsql_test func7-mysql-200 {
+ SELECT floor(1.23), floor(-1.23);
+} {1.0 -2.0}
+do_execsql_test func7-mysql-210 {
+ SELECT round(ln(2),7), quote(ln(-2));
+} {0.6931472 NULL}
+#do_execsql_test func7-mysql-220 {
+# SELECT round(log(2),7), log(-2);
+#} {0.6931472 NULL}
+# log() means natural logarithm in MySQL
+do_execsql_test func7-mysql-230 {
+ SELECT log(2,65536), log(10,100), quote(log(1,100)), quote(log(0,100));
+} {16.0 2.0 NULL NULL}
+do_execsql_test func7-mysql-240 {
+ SELECT log2(65536), quote(log2(-100)), quote(log2(0));
+} {16.0 NULL NULL}
+do_execsql_test func7-mysql-250 {
+ SELECT round(log10(2),7), log10(100), quote(log10(-100));
+} {0.30103 2.0 NULL}
+do_execsql_test func7-mysql-260 {
+ SELECT mod(234,10), 253%7, mod(29,9), 29%9;
+} {4.0 1 2.0 2}
+do_execsql_test func7-mysql-270 {
+ SELECT mod(34.5,3);
+} {1.5}
+do_execsql_test func7-mysql-280 {
+ SELECT pow(2,2), pow(2,-2);
+} {4.0 0.25}
+do_execsql_test func7-mysql-281 {
+ SELECT power(2,2), power(2,-2);
+} {4.0 0.25}
+do_execsql_test func7-mysql-290 {
+ SELECT round(radians(90),7);
+} {1.5707963}
+do_execsql_test func7-mysql-300 {
+ SELECT sign(-32), sign(0), sign(234);
+} {-1 0 1}
+do_execsql_test func7-mysql-310 {
+ SELECT sin(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
+} {1}
+do_execsql_test func7-mysql-320 {
+ SELECT sqrt(4), round(sqrt(20),7), quote(sqrt(-16));
+} {2.0 4.472136 NULL}
+do_execsql_test func7-mysql-330 {
+ SELECT tan(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
+} {1}
+do_execsql_test func7-mysql-331 {
+ SELECT round(tan(pi()+1),7);
+} {1.5574077}
+
+
+finish_test
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index cf49956b4..3020086a2 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -63,7 +63,7 @@
** of the global variable g.zTextName[] will identify the specific XSQL and
** DB values that were running when the crash occurred.
**
-** DBSQLFUZZ:
+** DBSQLFUZZ: (Added 2020-02-25)
**
** The dbsqlfuzz fuzzer includes both a database file and SQL to run against
** that database in its input. This utility can now process dbsqlfuzz
@@ -108,10 +108,10 @@ typedef unsigned char uint8_t;
*/
typedef struct VFile VFile;
struct VFile {
- char *zFilename; /* Filename. NULL for delete-on-close. From malloc() */
- int sz; /* Size of the file in bytes */
- int nRef; /* Number of references to this file */
- unsigned char *a; /* Content of the file. From malloc() */
+ char *zFilename; /* Filename. NULL for delete-on-close. From malloc() */
+ int sz; /* Size of the file in bytes */
+ int nRef; /* Number of references to this file */
+ unsigned char *a; /* Content of the file. From malloc() */
};
typedef struct VHandle VHandle;
struct VHandle {
@@ -219,7 +219,7 @@ static int progressHandler(void *pVdbeLimitFlag){
#endif
/*
-** Reallocate memory. Show and error and quit if unable.
+** Reallocate memory. Show an error and quit if unable.
*/
static void *safe_realloc(void *pOld, int szNew){
void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew);
@@ -455,7 +455,12 @@ static void blobListFree(Blob *p){
}
}
-/* Return the current wall-clock time */
+/* Return the current wall-clock time
+**
+** The number of milliseconds since the julian epoch.
+** 1907-01-01 00:00:00 -> 210866716800000
+** 2021-01-01 00:00:00 -> 212476176000000
+*/
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
@@ -612,8 +617,8 @@ static int isOffset(
/*
** Decode the text starting at zIn into a binary database file.
-** The maximum length of zIn is nIn bytes. Compute the binary database
-** file contain in space obtained from sqlite3_malloc().
+** The maximum length of zIn is nIn bytes. Store the binary database
+** file in space obtained from sqlite3_malloc().
**
** Return the number of bytes of zIn consumed. Or return -1 if there
** is an error. One potential error is that the recipe specifies a
@@ -713,6 +718,7 @@ static int progress_handler(void *pClientData) {
sqlite3_int64 iNow = timeOfDay();
int rc = iNow>=p->iCutoffTime;
sqlite3_int64 iDiff = iNow - p->iLastCb;
+ /* printf("time-remaining: %lld\n", p->iCutoffTime - iNow); */
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
p->nCb++;
if( rc==0 && p->mxCb>0 && p->mxCb<=p->nCb ) rc = 1;
@@ -729,7 +735,7 @@ static int progress_handler(void *pClientData) {
** "PRAGMA parser_trace" since they can dramatically increase the
** amount of output without actually testing anything useful.
**
-** Also block ATTACH and DETACH
+** Also block ATTACH if attaching a file from the filesystem.
*/
static int block_troublesome_sql(
void *Notused,
@@ -744,18 +750,21 @@ static int block_troublesome_sql(
(void)zArg3;
(void)zArg4;
if( eCode==SQLITE_PRAGMA ){
- if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
- || sqlite3_stricmp("parser_trace", zArg1)==0
- || sqlite3_stricmp("temp_store_directory", zArg1)==0
- ){
- return SQLITE_DENY;
- }
- if( sqlite3_stricmp("oom",zArg1)==0 && zArg2!=0 && zArg2[0]!=0 ){
+ if( eVerbosity==0 ){
+ if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
+ || sqlite3_stricmp("parser_trace", zArg1)==0
+ || sqlite3_stricmp("temp_store_directory", zArg1)==0
+ ){
+ return SQLITE_DENY;
+ }
+ }else if( sqlite3_stricmp("oom",zArg1)==0
+ && zArg2!=0 && zArg2[0]!=0 ){
oomCounter = atoi(zArg2);
}
- }else if( (eCode==SQLITE_ATTACH || eCode==SQLITE_DETACH)
- && zArg1 && zArg1[0] ){
- return SQLITE_DENY;
+ }else if( eCode==SQLITE_ATTACH ){
+ if( zArg1==0 || (zArg1[0]!=0 && strcmp(zArg1,":memory:")!=0) ){
+ return SQLITE_DENY;
+ }
}
return SQLITE_OK;
}
@@ -835,7 +844,7 @@ static int runDbSql(sqlite3 *db, const char *zSql){
}
/* Invoke this routine to run a single test case */
-int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte){
+int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
int rc; /* SQLite API return value */
int iSql; /* Index in aData[] of start of SQL */
unsigned char *aDb = 0; /* Decoded database content */
@@ -882,7 +891,7 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte){
** elapsed since the start of the test.
*/
cx.iLastCb = timeOfDay();
- cx.iCutoffTime = cx.iLastCb + giTimeout; /* Now + giTimeout seconds */
+ cx.iCutoffTime = cx.iLastCb + (iTimeout=argc-1 ) fatalError("missing arguments on %s", argv[i]);
onlySqlid = integerValue(argv[++i]);
@@ -1757,10 +1779,25 @@ int main(int argc, char **argv){
rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
if( rc ) fatalError("cannot start a transaction");
for(i=iFirstInsArg; i0 && zLine[kk-1]<=' ' ) kk--;
+ sqlite3_bind_text(pStmt, 1, zLine, kk, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ if( rc ) fatalError("insert failed for %s", zLine);
+ }
+ }else{
+ sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
+ if( verboseFlag ) printf("loading %s\n", argv[i]);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ if( rc ) fatalError("insert failed for %s", argv[i]);
+ }
}
sqlite3_finalize(pStmt);
rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
@@ -1894,6 +1931,7 @@ int main(int argc, char **argv){
*/
if( !verboseFlag && !quietFlag && !bSpinner ) printf("%s:", zDbName);
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
+ tmStart = timeOfDay();
if( isDbSql(pSql->a, pSql->sz) ){
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
if( bSpinner ){
@@ -1917,9 +1955,13 @@ int main(int argc, char **argv){
if( nSkip>0 ){
nSkip--;
}else{
- runCombinedDbSqlInput(pSql->a, pSql->sz);
+ runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout);
}
nTest++;
+ if( bTimer ){
+ sqlite3_int64 tmEnd = timeOfDay();
+ printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
+ }
g.zTestName[0] = 0;
disableOom();
continue;
@@ -1972,7 +2014,9 @@ int main(int argc, char **argv){
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000);
sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50);
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
- setAlarm(iTimeout);
+ setAlarm((iTimeout+999)/1000);
+ /* Enable test functions */
+ sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, db);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( sqlFuzz || vdbeLimitFlag ){
sqlite3_progress_handler(db, 100000, progressHandler,
@@ -1998,6 +2042,10 @@ int main(int argc, char **argv){
}
reformatVfs();
nTest++;
+ if( bTimer ){
+ sqlite3_int64 tmEnd = timeOfDay();
+ printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
+ }
g.zTestName[0] = 0;
/* Simulate an error if the TEST_FAILURE environment variable is "5".
@@ -2018,7 +2066,8 @@ int main(int argc, char **argv){
}
}
if( bSpinner ){
- printf("\n");
+ int nTotal = g.nDb*g.nSql;
+ printf("\r%s: %d/%d \n", zDbName, nTotal, nTotal);
}else if( !quietFlag && !verboseFlag ){
printf(" 100%% - %d tests\n", g.nDb*g.nSql);
}
diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db
index 39191fc8b1f03935f6b661eab5af1e2e2fba7285..86217e4b421375154ba0316867b7d9aa9514c191 100644
GIT binary patch
delta 269924
zcmeFa31C#!*#^s)0|(Zl_1PNL8_X{lTWa`fN4-0rCvJ{6F{)
z;%37>T2+{HVNCVq9MhC3DwX;~-%_N%?yE=oN?#q)7yD46`h~uQNPp0`0O@0W^N`-(
zSA+ESzPU(m>6?x8#=codclDiv^s2rpq+jiuf%J;L=}0f{3nGp6RU+Ne7eKnX&x5qR
zPgKQJ>I?g(;$l-@1=0PNd6E@4q|Ux
q4{pWtvhM&*0A~}2^lJ9Op@^A~1{Tq>d
za|4n)n~{7YiiDbwd_98XDUpHU4qnnE)o-<&1nE^)klD}>izjheho;gepQX+zh@!&K0vGbE?}za
zpN8aHfT-#|09194AIV)lB)55y+#({m$%SMOV5`~S
zQ?<1eNws
zUsgSTNwv_?(N-n8rkj@6EUuZ;AXEwSmenm0!lF>OY;MgmVfOh#h^n8=9Yrs`Y?(+0
z-ZGA&_Z_;De24Nvulz!fyPQhj&KX08F3=c?gxb0WVPS3ZnXZm)ElmPh8ZAY-RSRmC
z)s)lH7YwCz@!iG>dj5d1fEs^k$)!0@=8ljGx7nvHiI#12wby%ub>jnNLUg-uk!y#0
zJ-xTxT1b2UY`BnqcGy@%^KY~k)1jZ4N7J6Wb!Iy99i4%ulh)0~&R8q7g?b_zTiTmD
z9Kzy-=hg^x5oxzr%BqFsj%`G_-5E!BikR-2<(VA;T)P
zY0w`NJg^0Eu|uyL#STmA@2JY$$Z^}o*6&{J<1b7}83
z&ba3sV;0TIGmfPL+qf}Q5-^(Sf_~iF(T#CmKQ+IEX5F5xr)&F-n{Rl>m`B2Ia*Co0^=fWMH^P>+(Mtyhlr@AoPAR
zWcl{uf|AqV37TePBbP<*{lyYKCB}T6o+a(X;ZdWHBW;dN85q|K+1>&0Q^T#f7JB{`
zor$V$(%B^Vn?m7kM`#l2Rng{~bdFDi3fXxnv>QMJJ3Y~!Zy1aL@872%L9_mrua}^&
znJh#=Y5m3#rw6=#S8GE**3;~^{gUJeX&Y?al$eqYoR(WjCSZRSMwUx
zSB!MDROjfAj9JM&Xwzuo8exo9qfy;1vitV_CBlO|m;2y&t;WdxQpGo^7jVDqx70t!
zP1~i?YgBu+&@4=I!AcuyWWLziu_47Uuvg%9JNvGok_WN`O;1mco!)yOYkZbmEy^!1r|SRC9zi>2fp5-zKQ~BE
zk1-c%g6{1us`eK6=*v|W<#O}!9MM}{TfO-F)ivO&E$yjZG1e9VbF)8WS6VL$GG%v#
z+AkDn@7Ih1EqNwSPj~IlDxmuPS!JWq76%BQb=khoKG1P6zYx9r8o$`&^5LJCrBweq
zUr5{U;Ib(9-mF5p@eVFG3*ePMqKP`+h$4}
zuo$NL*Nisu{neNs^I=S6>@;oY>e$lR80lz_gnArdr`=vI%v-p)0X)?qQ@bNH!ChWe
zC6-Id4jXZ>I*j}vqwx}VFnH~EL%}K2hg5wqUSc6%yeREp1!<$b8AZvl(L=>
zdrhGjNw0JYA;A%<65ZfJ;c{oZ+Gfj2HCxz0eOt{oO}NT#X9!ZdVgO-M#q`=eO>WU$
zS?O|nd{KXMB;p1*e9eA$Fwo?VHb?yakmz+cSBBl5CU2-R6clkY=&5XqHUZj|&0hL$
zbKWSXYN%-Dxh5}NzD-+fiijRTZYbsE8f=q$#6g;lL+O-E9Tn}NwrIJNVWNYMKcX#g
zRxcO2qM_FEVV@H+UM?qbYR-tP=wz2rT{~9@%?MKIKe>?<`X@Jvo_a8UJguLm%iq(V
z?<9RxSH=l6DXOc=SH^KtO7eth@B2DC&1&RwB8qn07(yfFtXQ!mHD1HEr?V@xp)J(d
z6AHIR8+#?CJEMh4_cEJJOYbT!5ESB;bdh9!j~Ei_Y9-Yf6N|CXt&ZLXJ!h9yZ5->X
z@O%Bk;|}8=DLybV$p_NeKq%7Dy)l#e^Q18k3mEU7Xm3wBJ+;tOLOU1aYG~)8f(fJ2
zdC_!}T~bq2nDG8ybxGVZdb6IwP&4;0q{G=9H0sxk28np8KN;}=hpc;a294@FmQ;Zn
zn)+9xZRIB`kcpL3Q6n9nqAQ?}^Ye>xYuzrp)85e@wS#~}+PpD)R7?TR%7rzngdU%x
zx10^r%Id`{YL=TEcDG9mPH~A-TpmGmPjk8OAL2Yc!z+m1XRlD{{5;w%hBg^j20@_*eyEzzv2KlrMaqfJYRS3wwLVHai_^(-qP0
zC+mymOVhLI8B+Z8oM%P-TqbWovde24ge3PUiQmmzxN1QBDx^P=#7$@{2_ksj3jx8I=O2EE6TLjF}c}r$dhN0ah(4)z4kH
zykTMO9Exqs&Y_9RFwJ~>vVMeXIB7n>$%h}$(pWk-{+vcG)n{eA$`$Rj*EMqr&6t{#
zyEKh!4j$!CHpub!{8k$AB&LQ;9T}BmLmBGGFnmbTLL38p=#2CcKQsdmBsbFx28;dX
zL23Y=^vX{T|m84V+f3xTcdc2VsQ-v}#
zp|Be|j|tBP!_DDf+6M}iJIWfu6eD+&T%M;n;uY~qz#oh>yO2FdQ4&2SH-s{)+S44(
zc+?9%=8mPQbtsjoanhqrgC3O?K2uTybTzq|eiv}Ly`o2qVmOpfK+^u8MIaYSm*{pe
z```%Ze@*U6<&BiWY4UhtO!1UePIo|l$Bl+D2)mgIipC7UO@`CpYdi^DU?VmJ83rQ<
zdclw(4Ztx;DGUK4(jaUa0I{2a9wmDv5T6Rd;LY;bWkA^Ejiey#@=MCED~v&5j|M%>
z;aD1ggBVhgDZCPdMFwls98N*hBx~P8K`biB09`#pOO_y<0bnsA7n)M(V@Zg93Y}h3
z{G-931jYdLZFwpX4OYs46d7QLfer&?2K@n9#ghPiC?rM30MZ~S15%XX3sN;@(kf^`
zYD6THG-H^845n2etvvE6(oCDSWYFp-nYE-(q(o1Q(X51Er-hwMf${*P6oeSKAtMNi
zV_?Q~Od>{UI_6R)Xwp;+G?t%Q(@?aO;iiT{TT44r{r)d2
zBeBn18A;Bl3r6;_i*
zb&ZD^NRx`JY1P7p1@at^%_i)-dJq+j=V240RR?|Br(QJg6x7q*hk!2(Z4
z^{~MY?n8{(q0X)o%*K-5g;VyR#~T(-)r*+YjloU-q8b%TjrFOO0bo!Ps|O7~;}8Yp?X3B4{Cz!s%d5!G>(>Nx22CH+@MXK7Sd
zSJA#_bcOUsL1&3M1~JZZpmUOBUFA-PePgJzb35kh4sV6KTv%4quwq&5!rJ*T(1E%`
zp^#Gu!_qVi1CDfbwAz({$7EYBC%pjJFecINeR^vlvgM}-il0QC9(^IbE9i1!5;~u>
zQ3G{1g_$W)n%!fTo-9)aJ*p^|dNQ~LgJ$>cffh$P=CK|uGo|`GiNt`hFy`}_QgR;V
z)=a~+=omVr6DxP@u=j4i2;=w}3~o8IU3~GQ3tCj{CWGoe`*D?qRT))&z90{)mU&=|
zq1}6Qqse?c$4Wb&$j!=A?2X-#jnOu&%hSR2+CI8ry*9|toEac-y|#%y4r$A%?18Ki
z^vvZt_vCWfFCaXl3btDKD~L|4z{~gSq44&L>_W}*Io0(wLRg@_kXGPk(0gI+D9%Ao
zgtVXvfGl
z;`WGkdeIaVTC;dLj7*SKLQU=5a$&{{dMcu=4&WkX?dcIKV4jsk6?`%vuRIlPRk+z}
zl984DWGf*(p6T?5v4+WnRc{kLWil9J!iw63c%yppVn9Rk?hq#{?i!Kg8eQ)U5$3dr
zTQTe8KOX4jMaxY9>5sAC@y75cC=Ski3ChzHbeQZqW0h3|mx-)5uI0M$j
z9Xn3iAf*$GjR+~?5PE%b$7AUnduTt;qye95FtltmQe{AaRXm9Lfo-K~*ii@1HD=tc!AUzB^)v!bAq+he?U+gI3?7V)V$!w_HA?&~ku|S~;ZUlL@>MbKhN6&x-Oa{6=TJ=>^SlIJDu1-&7
z*&5XY3zv4>D;lX-4;zFTil-4+
zMR>XiXiB^PloiYsCx?V3)eUnN2=<B9ln*l
zbTFP%Q0Qb9^lg(oOvZw_GiNw~Zr!gN8y^w1W
z*e~`T{)(>TFKJcWgjIL8UW?4m76(f^wk5ASwnb5%l&ADfdKEpJ&wiNj13hDWu6D)Z
z#dx=Sb61b_h|<$!hw)b)0!X^{2%eCKvPY!O@o?hX)33A8uNYeboTienUpJFZ+^@56
z+vurVbfq-vCah1b-UE-fcmKp~FkrLX2p$Z5ALh{hxi
zz4sek@tCl{I=Ng}jOAGfIH%B*c7qPzuM_C`n}KS*dvp`%&@(v}YCM*wrN30!wsRY(
zd#3H1dbs}yzzo{_fpsnIILEeisw5s1Q30touNvyWbW^posxG@aY=8<{TfGFH5Ab84
zL-*?(2J~?bdZwb#%~%y}yhS&O+fMuU>qg-Z#%mTe?9VY%$^Gy|ynT-@mo=-5?){Dq
zi>G^ZIda>+y3LYB|EjWejoctO2QSb=M`tPt9sjenj;4HI&DCscX&30vGi^?7WS|FY
z-?zfYNp7-4q7BOy&Yur|fG!dL6;+wUt@;8wc0ZgmFW8Uad1H^Rik{q$hOZ|y#(a}5
zi;mr*E1|CO#sXyqvK#KRn1Nhjy=`rdM)gEhn#F)Ybq5`<&=-uIJm3^E3{2r_Qc9hB
zQ1H>04AzQm!b~^_OgA+&R5Qsktu5Nt(Y1Y=#Gyi4dRc23lTmuW*7v4VgXJo^83bId
zP+2Jo%xP5cc_iJbR`3Ud@*PjmBWrSQzt0O>A&mD-pJROJ%PE{SQOEr{J-zi`1`9)B
zQ!!>mPWytI73ZEiPUt*;ZfnJink991YTly@WT#C$Ceh~qGK`uoW=^mMrdnFA0I
z(H^0xqZPl(>@@XKgOytP;bS`~XwK5DtY+>9lCOZ6;VaPVN$Kj5A;O30%3!nf-dD^8
z1t_n_$$O<
z&`0-gHJ3QOGpn}CZW-HMGt!mRl>7)aH@CF6^lW#8=-^*5rTI2%DDzmkrO_f3bfk+r
z$(J}n`wxP=U%g##p0TC9wdKNSE8eYgLnUM0AIgnzReELRrc_qT#tv}(NR_mZZKHKJ
zTE}F`V+=9dP)GZ+bz`z6jRQhZQsLLWqb*}omkG4{AKF#4_a9md{pKBQE&X;STuHpY
z)y~1H_{3jpf6DN?z~Er+m(D379rhT@DK<4fm*z88bn7kfJAV9tZj`1+>=mf`dE@Ar
zidgQ6wspe02k=jgO41op%=9+dUe~4G)G)ylE9HzQ`br
zTS-OlXkTV%Y^OiIqn)2Z-Wqc4Fj#Yx>7~S-(l;wir~PjkN7LbEZnO#XAWwH3wCm>F
zBHFd0cwFgBkg925yM!KoKz*2zs%!
zj-@7#C*Xsc;}U^vDHcFt%(#MH-=Hm~AFnO2h}$okd{LEOB711xGiGAus383CPSMlp
zIYECT-9FtW(56!TEG|mlDb=qos1oeeFks1l%GsV02R%DZUqNfi^x1`(Tu#OSdLtL!
z$h#~W^XIZrAeUTU%Jb9uUs`e~@{Qb52J$TJrw|=PbBrw{ynt;I|F04Rbo_yw!nk>a
zp>`Wgd2nEkGU`*1H93pMRFEMcz*a8r*_mz{Mr@>*lF#XJ(Z0)aMr3;`DueDyueUNf
z#YMZnnlpl8yj4%XyiIRj_-RDTbkksoLWRH99vdVdc5c&-$lj1-m1Rw3gCs^#nx|G8
zIoQp?G
z4p(Fs8=%@_1Da|Q9lpC54wy-X7dth>n=V=GO=Vl!TRPh3cZE7PHuiLdA{R!xrY&SL
zEZPLqb5pdd%&~B;Qz%R3ZE0^~J0IqTdZJ~{)ZLcuWl(*$GAGT{-B{POmhQUFo|Z_c
zHFdLVT4-yirB!}V*ubh~>nNt=!b{nlY1mgaZC*=j6jg-k!keOzo-)i1QdOOC17hgO
z=^6n2X}R1AdG461C36T&LoA+WFeb6#2Icfk@>Tj+qqZvzs-Bh{`Lk_O>CZ0md6I@%vUK{Zqor+^U0ca7R`#Cmil~^m6<~(l+8OyvtXEa
zX7H+ExP;88SVlA0$Kn_^hg3%*(eCbO6ZlW^{v233dou1U$BsTS1vb(x)+4HH>PFQZEFWa2g+ZJYL|30wKT_Cq*{{X3lDIxSIk7@_lMzqGNB}!
z|EXIaOZNDaHUHGDAHq0?!XtJv>PxnZjnwA|pj7`)3ZYYXQDMaCL{mMSa5@Q(X^(ws
zNP-VIKRGVO7!f3q@pN4shQSYo=-B}@_QjK2MlWO229unxau~_+X}fvSUdCFZpA%=v
z=;koJlm$_YDOZZPo_pqq%Zwfa-0V|uONRev!7fkNsbM78sX>>ie|&0UJZnOX4J#E+
z*Ue!hVmtW26tsV^QanT?LdP0Vnj2$G=Yj<_+SS<=g~Y4wR#f?+_njw|Mnj5l3PV|c
zX1&ScV*~Y`j71Jp`tV$L_!>@KK@5|IWLpNFbPCw*Gg#}GJ&iq>Hg-ebJF6~8Y$ld2
zIWVpHOlugVYcf@Ha0Spm27!NQABG(uriToxF%GWb)D^@e*N~L49bwhV^pN%;4)^hmQ(v>w|`dytzc6=f{x-Xc#m!TL~Q8}@QH
zZ10q`K3ukj+Ba-L@D8Tt;j*(88`T>iUFOK;DYrL7p$Ued;mOyrX-(1YNLLGHz#Z+%
zBTX&c5xm?cYm6wWDcTurZ<3TvR*y78k}HXHv`IaYueL_Jx><~Yid0cbU(y&f3Q%rJ
zT2)NZdvUv^3B7J)aAgK@3tt`!WZJksrXeA-V*;)`j82635cIPzz4xws{hjg{LFzp46J4O
zBVpC&5A0!J9sA6HJ*>nThUhc-Ta3jWO0l0LRxtYgVvr)1r1{U73v@7jU}`3f4#x#z
z8I!9oo(sfeHZTlkd}fGoQe}Z5M{JNt$i$A%A30)YAR`8`42GPa8OMl8vTiuc_+k(v
zCQGi9%7@PvF}y--kdaVU@=nV(J~PBf(*Gw?9?l3czz19>*B@d-6^KtIPZYHVO3Imu
zlNeLAKB@BX86XFne-5ua3~vVj?R}=mk%a%}u4tTuYsAh%v-~^|gUvrad#&=!5hErq
zMxBjT>8m`+yy}x6hQj~80A&MwKuk?LQk*09Sxq}WA#ym4CIK(le5oI*%;0Q
zb#kr|gGWx<9*Hkp6OBz9G$Bo4#utMaF$MF}P5c9+JcW4%0uRjerR0r!BV3-%Am
z0_79}_^%j((^mUg15Ro3lI)9}ZmFf2GygMcDdbN^Q>9sVW;v{XXVA)FxUbwcPh)p<
zbJh*tjh)sRSfD6tR&3V7*@Qy
zLUMI*hYF*b)E?Zjt&PoP^0vy9A4I3rH(yyrnbIDqAok=m)-TB=V&Itp>_|Sgb=r#5
zb3^UqUa8#VvuI?RgGGj)ftc~&)-qFk-{ivB>77P^=ID27rGHSFSj$azRPn|FZA&&f-3tT7h-t6Q8SJCPYD>O1;9tbv65!-GC;-&L<;-!GYLDejWDZ?phH>?@
z(W&J
ztdDQnWbvKU&C`7fCr{?qSpo;yTv~rywvOJtBQMW-MqZq^<_&V+JY(0*u|r}!4e!L@jUZ^aUCbb51pld=sbxyc|hC=}ul
zr`zEpgb(Kk%9T-dIH$mBXU^)%)*YZ7nI6eD)!o0f0i|baw6TX}Rdvs$L4eR`wa(z_<(pLAdZlFoOeL3oh
z>;~F7HK%}++&M>B6z}yxzVIyYi5BtN6c_5D&hS(kG|OJ=>T(l-=52K3H`ZVCAt6HI
zTh{UP`rFpAwDY(%hxWf|9YaUnw&v06zp*aYc;TSC=Pm0bc7Ku$n|}}@1WYd#UU3=D
zD^LZf`c3N`iyg6QCrO)=wuZXc)SPx5w@#q-Z(Fsr@wnAa*Su}5OB_3H71Xr!w!E4&
z4|zJ!P+V;FOECv31Foc>a2kDSB?oqFm$1#s;J95_b?a)vKJwH)AZ2G7fdL;AE$o`{zwP&
zvWwYa3zN@+Khn{Jx%dni;2E;&MulTrV+wSwOK
zS@tMrk|zzJ`*LB$au#9+9Mj{Fxhfs|jdkg#=AnD8Hfr_Uc$K<^8{cmkZR7MeyUiNa
zLoM|2i$CLn1sXlwyg$cH@%=fY=-2}}I-2`hPAMI|
z*=pmlYk~!CE>P4x?BTDOo19};1tqBxmX4pHOHLR^@pa1t+IGU&oOt}jYzv3INqzSe
zk7qcvdwcr~_|*G=UMXxDbDUvB;5EA%t6Qv0`BnpmlJ+SOt`muBB%T}=E7rjb0t_|U-{
za+lCEMQRsyZm~A=5VCaCtnt#g$m=x2?~qP6emmXMgQDNzU^U$dMI_jUB=DSQzd+Oks*
ze5tfuC4DD3l;e!ik-##xRywEWWMHB996CSUf6!{q_637(Pe3_FXZ^)iXC}ZH1{A67
zP{m)%vB>~=Vx~n;SN{&%ol%M}ZOmUS&`fyHsnh6cRon?xEoNx5^_Q3A|#P?MjOVR<6W^^CaUDx>IF{v@fKwX{Vd6)>`_f
zJF?Z>IoG+0wS^kh?ogc53-Rf$rJC7a=`85q<=UF1^QrjjI3JD*Dd%)oFDurlZlcm?
zZfX3nbF9k{)l~WfTwX+}ls+cqmi&jsg=EqC5!_P#nAZ53*CDW_%N=z`pzPtC0qNsM
zoLL{-RK2Zv>>DkzCx&|u%Qgfr2LAL;DzrxqIGPd4b;
z2~;+KV)*UCX6jKX%SM?Ht@x#c!E4ioX4DmN728S*{P7)*ztnx_IBBLL+|Sf24U`
zd~bEpNUuNW5BMwnEHJMUmK32{5!bajUVmOuyze@@32`??(;9CivM#$<)W=#q07wu}pkY*Z3{n3c3REV{w72jBBs2=KS%^Jq7V4drX{&8jID<
z?)W9wTk}k75J7jH=rXNA;p@cs)Ry8gD5)9oKyk~o20f|_`q$x52Co=Eq*iyl^!h>p
zL0H+bB`ka>8o}C$N`3NS47je0TUM9mHiys-_K!su^~YzeE{p|y(l7)9UKEFrVJO11
zCKU3nYp!f=HmwPZu60U}118fN0DfHx<`|p^LmR}lWlf8i)-*-j>(BrkXCMX;o>>}S
z6wDfxc_)PM>S8mp^4;=?q8RBD0w%=v6vy1n-Y80Sd6{5K=e&W;Fcp|INX*54o*mj6
z3oL{?Qd}5EIuBym?74E}o~i(#&wLiywBIo6Z~E)j>U6iM)Y;r^pq}eE!=b4*t*URQ
zOk|IpQ>?~`6$hJg1R7mzFtH=h7RIC2{(V&^I4zFuQ!R?`+faP2dmsuM#t6iNh}1aH
zBkD)w*Cg=(vR)Ppo26p7i47*uWu2GBGWNSg(Ff3qz9!1P!!|A-P-PGMF!ElIrWfbX
zRNrBn;*fCBkN4aFk{`K<{_H|{Ft-Z<>rHYQm7+JuN*R%Ze2hL~S)*DnEuLT)3Hn-c
zhpi;W-UQ+$OJWa5rQt8*1X8^ynVm3VLJOrEKHQK>Lf=@Uq-*7#55cIt`0Yb=h*9D4
z0w;a!8Cqyn2UO7ernc!E7ST;K7KNAA0cN+%i|^qujB0`s6Qn`o!OT15XClVvhW
z5ynx6C;s==k{GUJU?2c(`Uk^}8VB$i1cIQ+00#@590ff!0VGWzq6k7eM*xa&GrkD4
zj1bZy;*8^v6+8=st_+z#d3Y#*3v`=t0}&y*MFe~XdyFE%2ZZd3BBu%LGlF`;cs&G|
z1*7;PzY_TjHYPtF@Wl^4GBUo`tBFOV(AJ`e14CH109gro?3fl8BSWAL@?55jOys#D
zQZ#F1;>4Hai+G8Zjyx9lnB_$?@))EeCMlvd%WU$n5YbYV>`kVLoh!Y~A{?^^A{lS9
zi->d>4a>thH1fM9)>ei~$Yf!US!O7iDdkChVJFl`dBOC&n1_u`M2c&T7foVidaj4T
zDUccOjGEIBOY}++tVINVce^1PqaFalhf`eK;M`5kk#IEV6QkiMVw(HiQTgBk*6OBlm3_G0rT)M{^D8oS1K*an#E|9wKamj
zUg<<15e%pqvRpy|Fyv@TxG5Z8Vo~fJpQ|aB%#;)au=q%&*9W>_LJlz#B7rdDZqN-N
zkWd@@fR3WF0Ag3ZN_HhSfu@>}69IRJ0wE&KzKAA?VO#@K#1NAu7$c}ejG*uZ!6E*8
z3~Uf30?v>&t|+=5MMprDt_TK5q9Jr2q=bO(pdk!{G=33uok>A(8L&W3x~@=6G67a(C=cQt
zBcf0n)GhfJ2$Hc!p!+~pa|}!a*w5mur*5MJ7Stb9BR`1n^2#;XN06OP0dP#eoa
z)1iB$RVC3jau@+aIUFtrfQ0gg91vSzKsMv07^7aq7aQ&^c9h`~5OFn#$T!l2!v7x
zHxF==R6odow5(W)GY=~RBu3Bp;Sdaxr2|@iDjA^6>>zHLa0DwB8TvpBf!jnuJyGa?
zXC%5qnC}c0-IC-66F*DIjbTWW+_Ax;JJNg-(LFq$WM@ufFiM5!&s1_N@{eHwV`9U@
zO%dH`U<*`YB7>o1gg;brdqgHZh6S7SQX14S{BgGwxD{9wN?$V_WM&y;1WuXLhb#&J1a8FQl^6Ft@=7p+>>j=b6ZR^M5
zUaPfeT<;77p6Uvg6(M3fUTMI#KQJ-6mBpQ^C6sU!@S_v(RV-Dp<+(Ezm2s|a^
zJ22-d0ZD@*3pYBW3d?drR!$-1{U+O}MKtAbRlIt9vBguKTyc?2atNWv0)FEt&Aj>n
zM~93vcn7a6o+Q>*%EO4rwni)lJD69SVpzB+cs%V6qnQKncJxk@oJM?XBlV
ztI7~(rga+PrbnlD_jGk!hz+vQCgtapZ7oeb8>fk7(n52(wQ|skNi%T|>K4)CBTch&
zBx9%IJAy_|!E(&bzgP)<2kziUF(S0
zGUy(km+1~AgRc*^+%Z!YW3v+fr4e`7ikY1Hj~Va(fEf?WJtCb&$4p+6CShRVHz=@pa3(!NE04AgfXUC{vR{mf6RE$EHkVCOxgbTnek3J85l4sFpdAy
znDCfUVbC<@bQ6KIFese08DU@|z$RfC69MpulTHLqJr6jQ36ISKaMB_(;X!L@_>URy
zKW03TJ+nhF-RS>-84r#4JWY74pUjL03i`L0@G!_Y=@^}4rg-lVyC1SYUlSf<@`ILf
zzz0@jGz4QaygleYW;|vN4gAN92PB3btt`NuQgVM{Gv0uP{F$2Ym<5k5V>L(qJtjOR
zxnuuE6CShR!HhWE>KpjLN>KjER^a}BVa8*dRnFLWH-Y(Et(q@;&0z<)!-SWeqh88`ueqxZS;_&5?Xs2^o%)@8odhinD5FA?4WgQnPG1i*iGKv3x7e
z&rQBB3Jz?T9Jt1d0K<8R|1ZV<&uGDC(g4;#`f@CP)Hx?_aQX^HUzB+O&}zhOG9
zI;rVYu^cm)sFvX*r~1X!b8wQBY)B4Or3|xYVi(mbcG38y7mlzgcrv{GGxnL-Kb0zy
zo4tF&*mCZ$hlOc^I0**Qfdi&-a8sm=osZ)v>rqF_D!RlD7*g3b;vS(Hm+T6=u}*1E
zJ-7p>13mPLrG)AqgsA-VKUtazX#J
zWk2MMtAF4h0Tua
zcUKP2we@SRM;Yz$qqmIjcii|Y&vnF)-eimKy?uS$eDBi!pWN!_xz6~}JEz7^?9s=c
zywlMi-n)Q3%?D5I>?TEW5w|~mr_Zl=~HLAbS@uzjA{eQn-r{*ra?toK+
zEvQ7HnOTnh^A3EAGxS`35q4W#u^mmD&_DIT4O!Y!ch!;Q9YV8`;&A#MQljy)J1_PaV2)jV)Ym8IweB?E?
z;j)`1Pt>R$T$6n0%lg=^9azHJN0#%=V*F39Po_UwOcM-f;SPLv(&5XE)8m~#KezvD
z$F}oaA055XSkdqP_0cTuONrwe^C+IoG4*kV2VW*}v8IR)6laa3V-IK9=tO&79$oq&
zZ>Ek5a~t}f{Gf*CzCzWNxhwlu|LvPRcLi0?$bGK=$iF;1cV*(lFYL}zc(R}?H!=%KC
zLN1TjUWF!IL!1Ao!&cf!oGwve<9?y%b|vZs&ZE`@eBJ<^SZyn$Yhrvc39so!Cw@}K
zm2y8)g!#$8)1Ob*PD+SZ6zj3($w_kp1!tI!EH837nauHzsmrJhqFm
zWvPjIgZAanzFOX|lTM!x(t8t)I8CgUpF(%pxsih(jURlWgdTWNH%?|eGgaJ2s+ri)
z;?~E-DH_#18`wxxCSsGgot)vic()VW=)%;!1)MtAOy={j|L%>+Tn@drgP#EKV|6ho
za8?G*Yw?ZK?pHWp0=J%#DEEehAaE0T^yuQF*6W(H8lbboR@4Jk*Cgx7yCUDs9(fM=TDEjh5PSnBX+5bshP|6+OfD0((!Opu-GQT(^K^Mf^O+V=pF>yEl+zCBEZ9f
zF{rr%D)o5oK)DpFC&lA
zyYg_#=*yguc2457^wpAY$M;3FuhT9kCo*GB5x8Z!DSvRURbmYe-ePT&H_lTamlgv*WXC!8w$Ei(P
zUmEbk06ureBTd|c8m(WW`bM7I-FG*#4&D7oE4NRh3E)2M85Sd2T