From 0295b255a5bede27b481aa6769469919a45a961a Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 12 Jun 2019 16:13:25 -0400 Subject: [PATCH 01/24] extension point for additional built in functions --- src/crypto.c | 4 ++++ src/func.c | 15 +++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 64d1eae..5016020 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1151,5 +1151,9 @@ end_of_export: #endif +#ifdef SQLCIPHER_FUNCS +#include "sqlcipher-func.c" +#endif + /* END SQLCIPHER */ #endif diff --git a/src/func.c b/src/func.c index 2b4e54f..39bc754 100644 --- a/src/func.c +++ b/src/func.c @@ -1791,13 +1791,6 @@ static void groupConcatValue(sqlite3_context *context){ */ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ int rc = sqlite3_overload_function(db, "MATCH", 2); -/* BEGIN SQLCIPHER */ -#ifdef SQLITE_HAS_CODEC -#ifndef OMIT_EXPORT - extern void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **); -#endif -#endif -/* END SQLCIPHER */ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); @@ -1805,7 +1798,13 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ /* BEGIN SQLCIPHER */ #ifdef SQLITE_HAS_CODEC #ifndef OMIT_EXPORT - sqlite3CreateFunc(db, "sqlcipher_export", -1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0, 0, 0); + { + extern void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **); + sqlite3CreateFunc(db, "sqlcipher_export", -1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0, 0, 0); + } +#endif +#ifdef SQLCIPHER_FUNCS +#include "sqlcipher-func.h" #endif #endif /* END SQLCIPHER */ From d9ade80e4fcfdbd825c72809c213848dc7c4b3ca Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Thu, 13 Jun 2019 16:49:09 -0400 Subject: [PATCH 02/24] allow files to be picked up in amalgamation --- src/crypto.c | 2 +- src/func.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 5016020..0b7c6c9 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1152,7 +1152,7 @@ end_of_export: #endif #ifdef SQLCIPHER_FUNCS -#include "sqlcipher-func.c" +#include "sqlcipher_funcs_impl.h" #endif /* END SQLCIPHER */ diff --git a/src/func.c b/src/func.c index 39bc754..31967bd 100644 --- a/src/func.c +++ b/src/func.c @@ -1804,7 +1804,7 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ } #endif #ifdef SQLCIPHER_FUNCS -#include "sqlcipher-func.h" +#include "sqlcipher_funcs_init.h" #endif #endif /* END SQLCIPHER */ From d211c296e6e60090b879c9bcc69150c30e6de4ee Mon Sep 17 00:00:00 2001 From: Edouard Oger Date: Fri, 24 May 2019 13:21:33 -0400 Subject: [PATCH 03/24] NSS crypto implementation --- Makefile.in | 6 +- Makefile.msc | 1 + config.h.in | 3 + configure | 54 +++++++ configure.ac | 8 + src/crypto.h | 1 + src/crypto_impl.c | 3 + src/crypto_nss.c | 314 ++++++++++++++++++++++++++++++++++++ test/sqlcipher-pragmas.test | 10 ++ test/sqlcipher.tcl | 6 + tool/mksqlite3c.tcl | 1 + 11 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 src/crypto_nss.c diff --git a/Makefile.in b/Makefile.in index d3e8ae9..f95512b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -148,14 +148,16 @@ CRYPTOLIBOBJ = \ crypto_impl.lo \ crypto_openssl.lo \ crypto_libtomcrypt.lo \ + crypto_nss.lo \ crypto_cc.lo - + CRYPTOSRC = \ $(TOP)/src/crypto.h \ $(TOP)/src/sqlcipher.h \ $(TOP)/src/crypto.c \ $(TOP)/src/crypto_impl.c \ $(TOP)/src/crypto_libtomcrypt.c \ + $(TOP)/src/crypto_nss.c \ $(TOP)/src/crypto_openssl.c \ $(TOP)/src/crypto_cc.c @@ -820,6 +822,8 @@ crypto_impl.lo: $(TOP)/src/crypto_impl.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/crypto_impl.c crypto_openssl.lo: $(TOP)/src/crypto_openssl.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/crypto_openssl.c +crypto_nss.lo: $(TOP)/src/crypto_nss.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/crypto_nss.c crypto_libtomcrypt.lo: $(TOP)/src/crypto_libtomcrypt.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/crypto_libtomcrypt.c crypto_cc.lo: $(TOP)/src/crypto_cc.c $(HDR) diff --git a/Makefile.msc b/Makefile.msc index 2180936..dc0d4da 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1270,6 +1270,7 @@ SRC00 = \ $(TOP)\src\crypto_cc.c \ $(TOP)\src\crypto_impl.c \ $(TOP)\src\crypto_libtomcrypt.c \ + $(TOP)\src\crypto_nss.c \ $(TOP)\src\crypto_openssl.c \ $(TOP)\src\crypto.h \ $(TOP)\src\sqlcipher.h \ diff --git a/config.h.in b/config.h.in index 306eb88..b91f1f7 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,9 @@ /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO +/* Define to 1 if you have the `nss3' library (-lnss3). */ +#undef HAVE_LIBNSS3 + /* Define to 1 if you have the `tomcrypt' library (-ltomcrypt). */ #undef HAVE_LIBTOMCRYPT diff --git a/configure b/configure index 74c822c..ce73879 100755 --- a/configure +++ b/configure @@ -12029,6 +12029,59 @@ else fi else + if test "$crypto_lib" = "nss"; then + CFLAGS+=" -DSQLCIPHER_CRYPTO_NSS" + 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 +$as_echo_n "checking for PK11_Decrypt in -lnss3... " >&6; } +if ${ac_cv_lib_nss3_PK11_Decrypt+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnss3 $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 PK11_Decrypt (); +int +main () +{ +return PK11_Decrypt (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nss3_PK11_Decrypt=yes +else + ac_cv_lib_nss3_PK11_Decrypt=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_PK11_Decrypt" >&5 +$as_echo "$ac_cv_lib_nss3_PK11_Decrypt" >&6; } +if test "x$ac_cv_lib_nss3_PK11_Decrypt" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSS3 1 +_ACEOF + + LIBS="-lnss3 $LIBS" + +else + as_fn_error $? "Library crypto not found. Install nss!\"" "$LINENO" 5 +fi + + else CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL" BUILD_CFLAGS+=" -DSQLCIPHER_CRYPTO_OPENSSL" { $as_echo "$as_me:${as_lineno-$LINENO}: result: openssl" >&5 @@ -12080,6 +12133,7 @@ else as_fn_error $? "Library crypto not found. Install openssl!\"" "$LINENO" 5 fi + fi fi fi fi diff --git a/configure.ac b/configure.ac index a05248f..f13ea6a 100644 --- a/configure.ac +++ b/configure.ac @@ -219,11 +219,19 @@ else 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" + 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" AC_MSG_RESULT([openssl]) AC_CHECK_LIB([crypto], [HMAC_Init_ex], , AC_MSG_ERROR([Library crypto not found. Install openssl!"])) + fi fi fi fi diff --git a/src/crypto.h b/src/crypto.h index aa734c2..cc6f8ac 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -48,6 +48,7 @@ void sqlite3pager_reset(Pager *pPager); #if !defined (SQLCIPHER_CRYPTO_CC) \ && !defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) \ + && !defined (SQLCIPHER_CRYPTO_NSS) \ && !defined (SQLCIPHER_CRYPTO_OPENSSL) #define SQLCIPHER_CRYPTO_OPENSSL #endif diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 112e2fc..6679bf6 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -205,6 +205,9 @@ void sqlcipher_activate() { #elif defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) extern int sqlcipher_ltc_setup(sqlcipher_provider *p); sqlcipher_ltc_setup(p); +#elif defined (SQLCIPHER_CRYPTO_NSS) + extern int sqlcipher_nss_setup(sqlcipher_provider *p); + sqlcipher_nss_setup(p); #elif defined (SQLCIPHER_CRYPTO_OPENSSL) extern int sqlcipher_openssl_setup(sqlcipher_provider *p); sqlcipher_openssl_setup(p); diff --git a/src/crypto_nss.c b/src/crypto_nss.c new file mode 100644 index 0000000..abfa133 --- /dev/null +++ b/src/crypto_nss.c @@ -0,0 +1,314 @@ +/* +** SQLCipher +** http://sqlcipher.net +** +** Copyright (c) 2008 - 2013, ZETETIC LLC +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the ZETETIC LLC nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY +** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*/ +/* BEGIN SQLCIPHER */ +#ifdef SQLITE_HAS_CODEC +#ifdef SQLCIPHER_CRYPTO_NSS +#include "crypto.h" +#include "sqlcipher.h" +#include +#include +#include + +static NSSInitContext* nss_init_context = NULL; +static unsigned int nss_init_count = 0; +static sqlite3_mutex* nss_rand_mutex = NULL; + +int sqlcipher_nss_setup(sqlcipher_provider *p); + +static int sqlcipher_nss_activate(void *ctx) { + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering static master mutex\n"); + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered static master mutex\n"); + if (nss_init_context == NULL) { + nss_init_context = NSS_InitContext("", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | + NSS_INIT_FORCEOPEN | NSS_INIT_OPTIMIZESPACE | NSS_INIT_NOROOTINIT); + } + nss_init_count++; + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving static master mutex\n"); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left static master mutex\n"); + return SQLITE_OK; +} + +static int sqlcipher_nss_deactivate(void *ctx) { + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: entering static master mutex\n"); + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: entered static master mutex\n"); + nss_init_count--; + if (nss_init_count == 0 && nss_init_context != NULL) { + NSS_ShutdownContext(nss_init_context); + nss_init_context = NULL; + } + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: leaving static master mutex\n"); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: left static master mutex\n"); + return SQLITE_OK; +} + +static int sqlcipher_nss_add_random(void *ctx, void *buffer, int length) { + return SQLITE_OK; +} + +/* generate a defined number of random bytes */ +static int sqlcipher_nss_random (void *ctx, void *buffer, int length) { + // PK11_GenerateRandom should be thread-safe. + return (PK11_GenerateRandom((unsigned char *)buffer, length) == SECSuccess) ? SQLITE_OK : SQLITE_ERROR; +} + +static const char* sqlcipher_nss_get_provider_name(void *ctx) { + return "nss"; +} + +static const char* sqlcipher_nss_get_provider_version(void *ctx) { + return NSS_GetVersion(); +} + +static const char* sqlcipher_nss_get_cipher(void *ctx) { + return "aes-256-cbc"; +} + +static int sqlcipher_nss_get_key_sz(void *ctx) { + return AES_256_KEY_LENGTH; +} + +static int sqlcipher_nss_get_iv_sz(void *ctx) { + return AES_BLOCK_SIZE; +} + +static int sqlcipher_nss_get_block_sz(void *ctx) { + return AES_BLOCK_SIZE; +} + +static int sqlcipher_nss_get_hmac_sz(void *ctx, int algorithm) { + switch(algorithm) { + case SQLCIPHER_HMAC_SHA1: + return SHA1_LENGTH; + break; + case SQLCIPHER_HMAC_SHA256: + return SHA256_LENGTH; + break; + case SQLCIPHER_HMAC_SHA512: + return SHA512_LENGTH; + break; + default: + return 0; + } +} + +static int sqlcipher_nss_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) { + int rc = SQLITE_OK; + unsigned int length; + unsigned int outLen; + PK11Context* context = NULL; + PK11SlotInfo * slot = NULL; + PK11SymKey* symKey = NULL; + if(in == NULL) goto error; + CK_MECHANISM_TYPE mech; + switch(algorithm) { + case SQLCIPHER_HMAC_SHA1: + mech = CKM_SHA_1_HMAC; + break; + case SQLCIPHER_HMAC_SHA256: + mech = CKM_SHA256_HMAC; + break; + case SQLCIPHER_HMAC_SHA512: + mech = CKM_SHA512_HMAC; + break; + default: + goto error; + } + length = sqlcipher_nss_get_hmac_sz(ctx, algorithm); + slot = PK11_GetInternalSlot(); + if (slot == NULL) goto error; + SECItem keyItem; + keyItem.data = hmac_key; + keyItem.len = key_sz; + symKey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, + CKA_SIGN, &keyItem, NULL); + if (symKey == NULL) goto error; + SECItem noParams; + noParams.data = 0; + noParams.len = 0; + context = PK11_CreateContextBySymKey(mech, CKA_SIGN, symKey, &noParams); + if (context == NULL) goto error; + if (PK11_DigestBegin(context) != SECSuccess) goto error; + if (PK11_DigestOp(context, in, in_sz) != SECSuccess) goto error; + if (in2 != NULL) { + if (PK11_DigestOp(context, in2, in2_sz) != SECSuccess) goto error; + } + if (PK11_DigestFinal(context, out, &outLen, length) != SECSuccess) goto error; + + goto cleanup; + error: + rc = SQLITE_ERROR; + cleanup: + if (context) PK11_DestroyContext(context, PR_TRUE); + if (symKey) PK11_FreeSymKey(symKey); + if (slot) PK11_FreeSlot(slot); + return rc; +} + +static int sqlcipher_nss_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) { + int rc = SQLITE_OK; + PK11SlotInfo * slot = NULL; + SECAlgorithmID * algid = NULL; + PK11SymKey* symKey = NULL; + SECOidTag oidtag; + switch(algorithm) { + case SQLCIPHER_HMAC_SHA1: + oidtag = SEC_OID_HMAC_SHA1; + break; + case SQLCIPHER_HMAC_SHA256: + oidtag = SEC_OID_HMAC_SHA256; + break; + case SQLCIPHER_HMAC_SHA512: + oidtag = SEC_OID_HMAC_SHA512; + break; + default: + goto error; + } + SECItem secSalt; + secSalt.data = salt; + secSalt.len = salt_sz; + // Always pass SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this parameter + // is unused for key generation. It is currently only used + // for PBKDF2 authentication or key (un)wrapping when specifying an + // encryption algorithm (PBES2). + algid = PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA1, + oidtag, key_sz, workfactor, &secSalt); + if (algid == NULL) goto error; + slot = PK11_GetInternalSlot(); + if (slot == NULL) goto error; + SECItem pwItem; + pwItem.data = (unsigned char *) pass; // PK11_PBEKeyGen doesn't modify the key. + pwItem.len = pass_sz; + symKey = PK11_PBEKeyGen(slot, algid, &pwItem, PR_FALSE, NULL); + if (symKey == NULL) goto error; + if (PK11_ExtractKeyValue(symKey) != SECSuccess) goto error; + // No need to free keyData as it is a buffer managed by symKey. + SECItem* keyData = PK11_GetKeyData(symKey); + if (keyData == NULL) goto error; + memcpy(key, keyData->data, key_sz); + + goto cleanup; + error: + rc = SQLITE_ERROR; + cleanup: + if (slot) PK11_FreeSlot(slot); + if (algid) SECOID_DestroyAlgorithmID(algid, PR_TRUE); + if (symKey) PK11_FreeSymKey(symKey); + return rc; +} + +static int sqlcipher_nss_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) { + int rc = SQLITE_OK; + PK11SlotInfo * slot = NULL; + PK11SymKey* symKey = NULL; + unsigned int outLen; + SECItem params; + params.data = iv; + params.len = sqlcipher_nss_get_iv_sz(ctx); + slot = PK11_GetInternalSlot(); + if (slot == NULL) goto error; + SECItem keyItem; + keyItem.data = key; + keyItem.len = key_sz; + symKey = PK11_ImportSymKey(slot, CKM_AES_CBC, PK11_OriginUnwrap, + CKA_ENCRYPT, &keyItem, NULL); + if (symKey == NULL) goto error; + SECStatus rv; + if (mode == CIPHER_ENCRYPT) { + rv = PK11_Encrypt(symKey, CKM_AES_CBC, ¶ms, out, &outLen, + in_sz + 16, in, in_sz); + } else { + rv = PK11_Decrypt(symKey, CKM_AES_CBC, ¶ms, out, &outLen, + in_sz + 16, in, in_sz); + } + if (rv != SECSuccess) goto error; + + goto cleanup; + error: + rc = SQLITE_ERROR; + cleanup: + if (slot) PK11_FreeSlot(slot); + if (symKey) PK11_FreeSymKey(symKey); + return rc; +} + +static int sqlcipher_nss_ctx_copy(void *target_ctx, void *source_ctx) { + return SQLITE_OK; +} + +static int sqlcipher_nss_ctx_cmp(void *c1, void *c2) { + return 1; /* always indicate contexts are the same */ +} + +static int sqlcipher_nss_ctx_init(void **ctx) { + sqlcipher_nss_activate(NULL); + return SQLITE_OK; +} + +static int sqlcipher_nss_ctx_free(void **ctx) { + sqlcipher_nss_deactivate(NULL); + return SQLITE_OK; +} + +static int sqlcipher_nss_fips_status(void *ctx) { + return 0; +} + +int sqlcipher_nss_setup(sqlcipher_provider *p) { + p->activate = sqlcipher_nss_activate; + p->deactivate = sqlcipher_nss_deactivate; + p->random = sqlcipher_nss_random; + p->get_provider_name = sqlcipher_nss_get_provider_name; + p->hmac = sqlcipher_nss_hmac; + p->kdf = sqlcipher_nss_kdf; + p->cipher = sqlcipher_nss_cipher; + p->get_cipher = sqlcipher_nss_get_cipher; + p->get_key_sz = sqlcipher_nss_get_key_sz; + p->get_iv_sz = sqlcipher_nss_get_iv_sz; + p->get_block_sz = sqlcipher_nss_get_block_sz; + p->get_hmac_sz = sqlcipher_nss_get_hmac_sz; + p->ctx_copy = sqlcipher_nss_ctx_copy; + p->ctx_cmp = sqlcipher_nss_ctx_cmp; + p->ctx_init = sqlcipher_nss_ctx_init; + p->ctx_free = sqlcipher_nss_ctx_free; + p->add_random = sqlcipher_nss_add_random; + p->fips_status = sqlcipher_nss_fips_status; + p->get_provider_version = sqlcipher_nss_get_provider_version; + return SQLITE_OK; +} + +#endif +#endif +/* END SQLCIPHER */ diff --git a/test/sqlcipher-pragmas.test b/test/sqlcipher-pragmas.test index 8f532ed..31c99fe 100644 --- a/test/sqlcipher-pragmas.test +++ b/test/sqlcipher-pragmas.test @@ -377,6 +377,16 @@ if_built_with_commoncrypto verify-default-cipher { db close file delete -force test.db +if_built_with_nss verify-default-cipher { + sqlite_orig db test.db + execsql { + PRAGMA key='test'; + PRAGMA cipher; + } +} {aes-256-cbc} +db close +file delete -force test.db + do_test verify-cipher_settings_default { sqlite_orig db test.db execsql { diff --git a/test/sqlcipher.tcl b/test/sqlcipher.tcl index 3c48d67..4129dca 100644 --- a/test/sqlcipher.tcl +++ b/test/sqlcipher.tcl @@ -85,6 +85,12 @@ proc if_built_with_commoncrypto {name cmd expected} { } } +proc if_built_with_nss {name cmd expected} { + if {[get_cipher_provider] == "nss"} { + do_test $name $cmd $expected + } +} + proc cmpFilesChunked {file1 file2 {chunksize 16384}} { set f1 [open $file1]; fconfigure $f1 -translation binary set f2 [open $file2]; fconfigure $f2 -translation binary diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 5a1de8b..7f95c2f 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -300,6 +300,7 @@ foreach file { crypto.c crypto_impl.c crypto_libtomcrypt.c + crypto_nss.c crypto_openssl.c crypto_cc.c From 8319ae00014eb2d9171b7f5540b5474549f69c29 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 24 Sep 2019 09:19:19 -0400 Subject: [PATCH 04/24] fix extension points --- src/crypto.c | 4 ---- src/crypto_impl.c | 9 +++++++++ src/func.c | 2 +- src/main.c | 7 +++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 0b7c6c9..64d1eae 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1151,9 +1151,5 @@ end_of_export: #endif -#ifdef SQLCIPHER_FUNCS -#include "sqlcipher_funcs_impl.h" -#endif - /* END SQLCIPHER */ #endif diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 112e2fc..ee4da66 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -43,6 +43,9 @@ #include #endif #endif +#ifdef SQLCIPHER_EXT +#include "sqlcipher_ext.h" +#endif static volatile unsigned int default_flags = DEFAULT_CIPHER_FLAGS; static volatile unsigned char hmac_salt_mask = HMAC_SALT_MASK; @@ -212,6 +215,9 @@ void sqlcipher_activate() { #error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED" #endif CODEC_TRACE("sqlcipher_activate: calling sqlcipher_register_provider(%p)\n", p); +#ifdef SQLCIPHER_EXT + sqlcipher_ext_provider_setup(p); +#endif sqlcipher_register_provider(p); CODEC_TRACE("sqlcipher_activate: called sqlcipher_register_provider(%p)\n",p); } @@ -252,6 +258,9 @@ void sqlcipher_deactivate() { sqlcipher_provider_mutex = NULL; sqlcipher_activate_count = 0; /* reset activation count */ +#ifdef SQLCIPHER_EXT + sqlcipher_ext_provider_destroy(); +#endif } CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving static master mutex\n"); diff --git a/src/func.c b/src/func.c index 31967bd..574618b 100644 --- a/src/func.c +++ b/src/func.c @@ -1803,7 +1803,7 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ sqlite3CreateFunc(db, "sqlcipher_export", -1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0, 0, 0); } #endif -#ifdef SQLCIPHER_FUNCS +#ifdef SQLCIPHER_EXT #include "sqlcipher_funcs_init.h" #endif #endif diff --git a/src/main.c b/src/main.c index 24f7f20..7cc9ced 100644 --- a/src/main.c +++ b/src/main.c @@ -3282,6 +3282,13 @@ static int openDatabase( } #endif +#ifdef SQLCIPHER_EXT + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlcipherVtabInit(sqlite3 *); + rc = sqlcipherVtabInit(db); + } +#endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. From 2ced1363de3220c78c7bc1de82a5551ac52e44d8 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 24 Sep 2019 09:25:32 -0400 Subject: [PATCH 05/24] remove unused functions from provider interface --- src/crypto_cc.c | 10 ---------- src/crypto_libtomcrypt.c | 10 ---------- src/crypto_openssl.c | 11 ----------- src/sqlcipher.h | 2 -- 4 files changed, 33 deletions(-) diff --git a/src/crypto_cc.c b/src/crypto_cc.c index 647f5b3..a800830 100644 --- a/src/crypto_cc.c +++ b/src/crypto_cc.c @@ -154,14 +154,6 @@ static int sqlcipher_cc_get_hmac_sz(void *ctx, int algorithm) { } } -static int sqlcipher_cc_ctx_copy(void *target_ctx, void *source_ctx) { - return SQLITE_OK; -} - -static int sqlcipher_cc_ctx_cmp(void *c1, void *c2) { - return 1; /* always indicate contexts are the same */ -} - static int sqlcipher_cc_ctx_init(void **ctx) { return SQLITE_OK; } @@ -185,8 +177,6 @@ int sqlcipher_cc_setup(sqlcipher_provider *p) { p->get_iv_sz = sqlcipher_cc_get_iv_sz; p->get_block_sz = sqlcipher_cc_get_block_sz; p->get_hmac_sz = sqlcipher_cc_get_hmac_sz; - p->ctx_copy = sqlcipher_cc_ctx_copy; - p->ctx_cmp = sqlcipher_cc_ctx_cmp; p->ctx_init = sqlcipher_cc_ctx_init; p->ctx_free = sqlcipher_cc_ctx_free; p->add_random = sqlcipher_cc_add_random; diff --git a/src/crypto_libtomcrypt.c b/src/crypto_libtomcrypt.c index efb24fd..9e1e50c 100644 --- a/src/crypto_libtomcrypt.c +++ b/src/crypto_libtomcrypt.c @@ -250,14 +250,6 @@ static int sqlcipher_ltc_get_hmac_sz(void *ctx, int algorithm) { return hash_descriptor[hash_idx].hashsize; } -static int sqlcipher_ltc_ctx_copy(void *target_ctx, void *source_ctx) { - return SQLITE_OK; -} - -static int sqlcipher_ltc_ctx_cmp(void *c1, void *c2) { - return 1; -} - static int sqlcipher_ltc_ctx_init(void **ctx) { sqlcipher_ltc_activate(NULL); return SQLITE_OK; @@ -285,8 +277,6 @@ int sqlcipher_ltc_setup(sqlcipher_provider *p) { p->get_iv_sz = sqlcipher_ltc_get_iv_sz; p->get_block_sz = sqlcipher_ltc_get_block_sz; p->get_hmac_sz = sqlcipher_ltc_get_hmac_sz; - p->ctx_copy = sqlcipher_ltc_ctx_copy; - p->ctx_cmp = sqlcipher_ltc_ctx_cmp; p->ctx_init = sqlcipher_ltc_ctx_init; p->ctx_free = sqlcipher_ltc_ctx_free; p->add_random = sqlcipher_ltc_add_random; diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 3662b7d..bd75ed5 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -323,15 +323,6 @@ static int sqlcipher_openssl_get_hmac_sz(void *ctx, int algorithm) { } } -static int sqlcipher_openssl_ctx_copy(void *target_ctx, void *source_ctx) { - memcpy(target_ctx, source_ctx, sizeof(openssl_ctx)); - return SQLITE_OK; -} - -static int sqlcipher_openssl_ctx_cmp(void *c1, void *c2) { - return ((openssl_ctx *)c1)->evp_cipher == ((openssl_ctx *)c2)->evp_cipher; -} - static int sqlcipher_openssl_ctx_init(void **ctx) { openssl_ctx *o_ctx; @@ -371,8 +362,6 @@ int sqlcipher_openssl_setup(sqlcipher_provider *p) { p->get_iv_sz = sqlcipher_openssl_get_iv_sz; p->get_block_sz = sqlcipher_openssl_get_block_sz; p->get_hmac_sz = sqlcipher_openssl_get_hmac_sz; - p->ctx_copy = sqlcipher_openssl_ctx_copy; - p->ctx_cmp = sqlcipher_openssl_ctx_cmp; p->ctx_init = sqlcipher_openssl_ctx_init; p->ctx_free = sqlcipher_openssl_ctx_free; p->add_random = sqlcipher_openssl_add_random; diff --git a/src/sqlcipher.h b/src/sqlcipher.h index 2402d02..e8bda8e 100644 --- a/src/sqlcipher.h +++ b/src/sqlcipher.h @@ -65,8 +65,6 @@ typedef struct { int (*get_iv_sz)(void *ctx); int (*get_block_sz)(void *ctx); int (*get_hmac_sz)(void *ctx, int algorithm); - int (*ctx_copy)(void *target_ctx, void *source_ctx); - int (*ctx_cmp)(void *c1, void *c2); int (*ctx_init)(void **ctx); int (*ctx_free)(void **ctx); int (*fips_status)(void *ctx); From 498941c67348f9147758358bbb5ab17d4895aeca Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 24 Sep 2019 10:05:27 -0400 Subject: [PATCH 06/24] add id and status functions for providers --- src/crypto_cc.c | 10 ++++++++++ src/crypto_libtomcrypt.c | 10 ++++++++++ src/crypto_nss.c | 20 ++++++++++---------- src/crypto_openssl.c | 10 ++++++++++ src/sqlcipher.h | 2 ++ 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/crypto_cc.c b/src/crypto_cc.c index a800830..a89f7fd 100644 --- a/src/crypto_cc.c +++ b/src/crypto_cc.c @@ -166,6 +166,14 @@ static int sqlcipher_cc_fips_status(void *ctx) { return 0; } +static int sqlcipher_cc_id(void *ctx) { + return 1633265; +} + +static void* sqlcipher_cc_status(void *ctx) { + return NULL; +} + int sqlcipher_cc_setup(sqlcipher_provider *p) { p->random = sqlcipher_cc_random; p->get_provider_name = sqlcipher_cc_get_provider_name; @@ -182,6 +190,8 @@ int sqlcipher_cc_setup(sqlcipher_provider *p) { p->add_random = sqlcipher_cc_add_random; p->fips_status = sqlcipher_cc_fips_status; p->get_provider_version = sqlcipher_cc_get_provider_version; + p->id = sqlcipher_cc_id; + p->status = sqlcipher_cc_status; return SQLITE_OK; } diff --git a/src/crypto_libtomcrypt.c b/src/crypto_libtomcrypt.c index 9e1e50c..9b5e581 100644 --- a/src/crypto_libtomcrypt.c +++ b/src/crypto_libtomcrypt.c @@ -264,6 +264,14 @@ static int sqlcipher_ltc_fips_status(void *ctx) { return 0; } +static int sqlcipher_ltc_id(void *ctx) { + return 4658016; +} + +static void* sqlcipher_ltc_status(void *ctx) { + return NULL; +} + int sqlcipher_ltc_setup(sqlcipher_provider *p) { p->activate = sqlcipher_ltc_activate; p->deactivate = sqlcipher_ltc_deactivate; @@ -282,6 +290,8 @@ int sqlcipher_ltc_setup(sqlcipher_provider *p) { p->add_random = sqlcipher_ltc_add_random; p->fips_status = sqlcipher_ltc_fips_status; p->get_provider_version = sqlcipher_ltc_get_provider_version; + p->id = sqlcipher_ltc_id; + p->status = sqlcipher_ltc_status; return SQLITE_OK; } diff --git a/src/crypto_nss.c b/src/crypto_nss.c index abfa133..5df1a67 100644 --- a/src/crypto_nss.c +++ b/src/crypto_nss.c @@ -264,14 +264,6 @@ static int sqlcipher_nss_cipher(void *ctx, int mode, unsigned char *key, int key return rc; } -static int sqlcipher_nss_ctx_copy(void *target_ctx, void *source_ctx) { - return SQLITE_OK; -} - -static int sqlcipher_nss_ctx_cmp(void *c1, void *c2) { - return 1; /* always indicate contexts are the same */ -} - static int sqlcipher_nss_ctx_init(void **ctx) { sqlcipher_nss_activate(NULL); return SQLITE_OK; @@ -286,6 +278,14 @@ static int sqlcipher_nss_fips_status(void *ctx) { return 0; } +static int sqlcipher_nss_id(void *ctx) { + return 6342402; +} + +static void* sqlcipher_nss_status(void *ctx) { + return NULL; +} + int sqlcipher_nss_setup(sqlcipher_provider *p) { p->activate = sqlcipher_nss_activate; p->deactivate = sqlcipher_nss_deactivate; @@ -299,13 +299,13 @@ int sqlcipher_nss_setup(sqlcipher_provider *p) { p->get_iv_sz = sqlcipher_nss_get_iv_sz; p->get_block_sz = sqlcipher_nss_get_block_sz; p->get_hmac_sz = sqlcipher_nss_get_hmac_sz; - p->ctx_copy = sqlcipher_nss_ctx_copy; - p->ctx_cmp = sqlcipher_nss_ctx_cmp; p->ctx_init = sqlcipher_nss_ctx_init; p->ctx_free = sqlcipher_nss_ctx_free; p->add_random = sqlcipher_nss_add_random; p->fips_status = sqlcipher_nss_fips_status; p->get_provider_version = sqlcipher_nss_get_provider_version; + p->id = sqlcipher_nss_id; + p->status = sqlcipher_nss_status; return SQLITE_OK; } diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index bd75ed5..1f1996e 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -349,6 +349,14 @@ static int sqlcipher_openssl_fips_status(void *ctx) { #endif } +static int sqlcipher_openssl_id(void *ctx) { + return 2678498; +} + +static void* sqlcipher_openssl_status(void *ctx) { + return NULL; +} + int sqlcipher_openssl_setup(sqlcipher_provider *p) { p->activate = sqlcipher_openssl_activate; p->deactivate = sqlcipher_openssl_deactivate; @@ -367,6 +375,8 @@ int sqlcipher_openssl_setup(sqlcipher_provider *p) { p->add_random = sqlcipher_openssl_add_random; p->fips_status = sqlcipher_openssl_fips_status; p->get_provider_version = sqlcipher_openssl_get_provider_version; + p->id = sqlcipher_openssl_id; + p->status = sqlcipher_openssl_status; return SQLITE_OK; } diff --git a/src/sqlcipher.h b/src/sqlcipher.h index e8bda8e..bf680e8 100644 --- a/src/sqlcipher.h +++ b/src/sqlcipher.h @@ -69,6 +69,8 @@ typedef struct { int (*ctx_free)(void **ctx); int (*fips_status)(void *ctx); const char* (*get_provider_version)(void *ctx); + int (*id)(void *ctx); + void* (*status)(void *ctx); } sqlcipher_provider; /* utility functions */ From 28441205b7c99fc0c40692c3744c81f306383968 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 24 Sep 2019 10:24:03 -0400 Subject: [PATCH 07/24] boringssl compatibility change for #329 --- src/crypto_openssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 1f1996e..4f7ff3c 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -36,6 +36,7 @@ #include "sqlcipher.h" #include #include +#include #include #include @@ -292,7 +293,7 @@ cleanup: } static const char* sqlcipher_openssl_get_cipher(void *ctx) { - return EVP_CIPHER_name(((openssl_ctx *)ctx)->evp_cipher); + return OBJ_nid2sn(EVP_CIPHER_nid(((openssl_ctx *)ctx)->evp_cipher)); } static int sqlcipher_openssl_get_key_sz(void *ctx) { From 400c015f3f34f7c8ec30ba4ecdf7bf635f6968ac Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 25 Sep 2019 10:27:57 -0400 Subject: [PATCH 08/24] Snapshot of upstream SQLite 3.29.0 --- README.md | 27 +- VERSION | 2 +- config.guess | 1340 +++++++++------- config.sub | 2680 ++++++++++++++++--------------- configure | 70 +- ext/fts3/fts3_write.c | 59 +- ext/fts5/fts5_buffer.c | 11 +- ext/fts5/fts5_index.c | 24 +- ext/fts5/fts5_vocab.c | 6 +- ext/fts5/test/fts5corrupt3.test | 1046 +++++++++++- ext/fts5/test/fts5corrupt4.test | 61 + ext/misc/blobio.c | 2 +- ext/misc/dbdata.c | 851 ++++++++++ ext/misc/fossildelta.c | 1 + ext/misc/json1.c | 2 +- ext/rbu/rbu_common.tcl | 8 +- ext/rbu/rbufault2.test | 9 + ext/rbu/rbufault3.test | 2 - ext/rbu/rbumisc.test | 180 +++ ext/rbu/rbupartial.test | 4 + ext/rbu/rbutemplimit.test | 1 + ext/rbu/rbuvacuum4.test | 116 ++ ext/rbu/sqlite3rbu.c | 317 +++- ext/rtree/rtree.c | 14 +- ext/session/sqlite3session.c | 6 +- main.mk | 1 + manifest | 275 ++-- manifest.uuid | 2 +- src/alter.c | 36 +- src/backup.c | 2 +- src/btree.c | 43 +- src/build.c | 99 +- src/ctime.c | 2 +- src/date.c | 6 +- src/expr.c | 265 ++- src/fkey.c | 10 +- src/func.c | 44 +- src/global.c | 9 +- src/insert.c | 36 +- src/main.c | 100 +- src/msvc.h | 5 + src/parse.y | 26 +- src/pcache.c | 7 +- src/pcache1.c | 2 +- src/pragma.c | 45 +- src/pragma.h | 13 +- src/printf.c | 20 +- src/resolve.c | 35 +- src/select.c | 49 +- src/shell.c.in | 979 ++++++++++- src/sqlite.h.in | 47 +- src/sqliteInt.h | 37 +- src/test1.c | 52 +- src/test_demovfs.c | 5 +- src/test_devsym.c | 1 + src/test_vfs.c | 4 +- src/treeview.c | 2 +- src/update.c | 24 +- src/util.c | 152 +- src/vacuum.c | 1 + src/vdbe.c | 245 ++- src/vdbeInt.h | 8 +- src/vdbeapi.c | 130 +- src/vdbeaux.c | 64 +- src/vdbemem.c | 159 +- src/vdbetrace.c | 2 +- src/vtab.c | 2 + src/wal.c | 6 +- src/where.c | 23 +- src/whereInt.h | 4 + src/wherecode.c | 6 +- src/whereexpr.c | 40 +- src/window.c | 44 +- test/altertab.test | 35 + test/altertab2.test | 22 +- test/altertab3.test | 100 +- test/autoindex5.test | 14 + test/between.test | 20 + test/cast.test | 103 +- test/check.test | 2 + test/chunksize.test | 41 + test/collate1.test | 16 + test/corruptL.test | 222 +++ test/countofview.test | 13 + test/dbdata.test | 115 ++ test/dbfuzz2.c | 2 + test/e_expr.test | 57 +- test/expr2.test | 54 + test/fkey7.test | 36 + test/fkey8.test | 31 + test/fts3corrupt4.test | 1183 +++++++++++++- test/fts3corrupt5.test | 60 + test/fts4rename.test | 44 + test/func.test | 3 + test/func3.test | 13 + test/fuzzdata7.db | Bin 16793600 -> 16811008 bytes test/fuzzdata8.db | Bin 1057792 -> 1239040 bytes test/in.test | 16 +- test/index.test | 28 +- test/index6.test | 28 + test/index7.test | 14 +- test/indexexpr2.test | 18 + test/intreal.test | 86 + test/istrue.test | 14 + test/join5.test | 21 + test/jrnlmode.test | 11 +- test/json104.test | 27 + test/like.test | 19 + test/like3.test | 32 + test/oserror.test | 32 +- test/permutations.test | 2 +- test/pragma4.test | 10 + test/quote.test | 57 +- test/recover.test | 134 ++ test/reindex.test | 34 + test/releasetest.tcl | 2 +- test/releasetest_data.tcl | 2 +- test/round1.test | 41 + test/rowid.test | 68 + test/select3.test | 45 + test/select6.test | 17 +- test/speedtest1.c | 13 + test/subquery2.test | 17 + test/tkt-78e04e52ea.test | 2 +- test/tkt-a8a0d2996a.test | 8 +- test/view.test | 23 + test/vtab1.test | 16 +- test/vtabH.test | 20 +- test/wapptest.tcl | 346 +++- test/window2.tcl | 7 + test/window2.test | 496 +++++- test/window9.test | 102 ++ test/windowfault.test | 3 +- test/with1.test | 49 + test/with3.test | 36 + test/without_rowid1.test | 18 + tool/lemon.c | 78 +- tool/mkpragmatab.tcl | 5 +- tool/mkshellc.tcl | 8 +- tool/showdb.c | 48 +- 140 files changed, 11261 insertions(+), 2986 deletions(-) create mode 100644 ext/fts5/test/fts5corrupt4.test create mode 100644 ext/misc/dbdata.c create mode 100644 ext/rbu/rbumisc.test create mode 100644 ext/rbu/rbuvacuum4.test create mode 100644 test/chunksize.test create mode 100644 test/dbdata.test create mode 100644 test/expr2.test create mode 100644 test/fts3corrupt5.test create mode 100644 test/fts4rename.test create mode 100644 test/intreal.test create mode 100644 test/recover.test create mode 100644 test/round1.test create mode 100644 test/window9.test diff --git a/README.md b/README.md index 6f9510a..c12b77c 100644 --- a/README.md +++ b/README.md @@ -306,30 +306,13 @@ describes its purpose and role within the larger system. ## Verifying Code Authenticity -If you obtained an SQLite source tree from a secondary source, such as a -GitHub mirror, and you want to verify that it has not been altered, there -are a couple of ways to do that. - -If you have a release version of SQLite, and you are using the -`sqlite3.c` amalgamation, then SHA3-256 hashes for the amalgamation are -available in the [change log](https://www.sqlite.org/changes.html) on -the official website. After building the `sqlite3.c` file, you can check -that it is authentic by comparing the hash. This does not ensure that the -test scripts are unaltered, but it does validate the deliverable part of -the code and the verification process only involves computing and -comparing a single hash. - -For versions other than an official release, or if you are building the -`sqlite3.c` amalgamation using non-standard build options, the verification -process is a little more involved. The `manifest` file at the root directory -of the source tree +The `manifest` file at the root directory of the source tree contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for -older files) for every source file in the repository. You can write a script -to extracts hashes from `manifest` and verifies the hashes against the -corresponding files in the source tree. The SHA3-256 hash of the `manifest` +older files) for every source file in the repository. +The SHA3-256 hash of the `manifest` file itself is the official name of the version of the source tree that you -have. The `manifest.uuid` file should contain the SHA3-256 hash of the -`manifest` file. If all of the above hash comparisons are correct, then +have. The `manifest.uuid` file should contain the SHA3-256 hash of the +`manifest` file. If all of the above hash comparisons are correct, then you can be confident that your source tree is authentic and unadulterated. The format of the `manifest` file should be mostly self-explanatory, but diff --git a/VERSION b/VERSION index a72fd67..c7c9773 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.28.0 +3.29.0 diff --git a/config.guess b/config.guess index 34093cc..ae71394 100644 --- a/config.guess +++ b/config.guess @@ -1,14 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2007-07-22' +timestamp='2019-05-28' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -17,26 +15,22 @@ timestamp='2007-07-22' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + me=`echo "$0" | sed -e 's,.*/,,'` @@ -45,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -56,8 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -91,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -103,34 +94,38 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -139,29 +134,40 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -if [ "${UNAME_SYSTEM}" = "Linux" ] ; then - eval $set_cc_for_build - cat << EOF > $dummy.c +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + set_cc_for_build + cat <<-EOF > "$dummy.c" #include - #ifdef __UCLIBC__ - # ifdef __UCLIBC_CONFIG_VERSION__ - LIBC=uclibc __UCLIBC_CONFIG_VERSION__ - # else + #if defined(__UCLIBC__) LIBC=uclibc - # endif + #elif defined(__dietlibc__) + LIBC=dietlibc #else LIBC=gnu #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'` -fi + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -171,23 +177,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -197,7 +213,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -205,42 +228,62 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi-}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -250,60 +293,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -312,12 +349,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -341,20 +378,39 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -363,25 +419,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -392,44 +448,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -438,23 +494,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -478,21 +534,21 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -507,7 +563,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -519,14 +575,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -537,7 +593,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -549,28 +605,29 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -585,67 +642,67 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -656,23 +713,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -697,11 +754,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -710,7 +767,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -718,9 +775,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -728,205 +785,137 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in + *:Interix*:*) + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; - EM64T | authenticamd) - echo x86_64-unknown-interix${UNAME_RELEASE} + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin + echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix exit ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -937,108 +926,172 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; - xtensa:Linux:*:*) - echo xtensa-unknown-linux-${LIBC} + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-${LIBC}coff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld" - exit ;; - esac - # This should get integrated into the C code below, but now we hack - if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1046,54 +1099,54 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1103,17 +1156,20 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1122,9 +1178,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1144,29 +1200,39 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1177,15 +1243,15 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1197,25 +1263,25 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1225,53 +1291,101 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1280,18 +1394,19 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + # shellcheck disable=SC2154 + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1312,14 +1427,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1328,21 +1443,39 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < "$dummy.c" < -# include +#include +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif #endif main () { @@ -1355,22 +1488,14 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" @@ -1410,39 +1535,54 @@ main () #endif #if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); + struct utsname un; + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif #endif #if defined (alliant) && defined (i860) @@ -1453,54 +1593,38 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } +echo "$0: unable to guess system type" >&2 -# Convex versions that predate uname can use getsysinfo(1) +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1519,16 +1643,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config.sub b/config.sub index 63cdd0a..5b158ac 100644 --- a/config.sub +++ b/config.sub @@ -1,44 +1,40 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2007-06-28' +timestamp='2019-05-23' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -57,12 +53,11 @@ timestamp='2007-06-28' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -72,8 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -95,12 +89,12 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -116,1079 +110,1167 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) - os= - basic_machine=$1 + *-*-*-*) + basic_machine=$field1-$field2 + os=$field3-$field4 ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ + | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + os=linux-android + ;; + *) + basic_machine=$field1-$field2 + os=$field3 + ;; + esac ;; - -scout) + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; + esac ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + os=bsd + ;; + a29khif) + basic_machine=a29k-amd + os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=scout + ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; + am29k) + basic_machine=a29k-none + os=bsd + ;; + amdahl) + basic_machine=580-amdahl + os=sysv + ;; + amiga) + basic_machine=m68k-unknown + os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=bsd + ;; + aros) + basic_machine=i386-pc + os=aros + ;; + aux) + basic_machine=m68k-apple + os=aux + ;; + balance) + basic_machine=ns32k-sequent + os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=linux + ;; + cegcc) + basic_machine=arm-unknown + os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; + cray) + basic_machine=j90-cray + os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= + ;; + delta88) + basic_machine=m88k-motorola + os=sysv3 + ;; + dicos) + basic_machine=i686-pc + os=dicos + ;; + djgpp) + basic_machine=i586-pc + os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=ose + ;; + gmicro) + basic_machine=tron-gmicro + os=sysv + ;; + go32) + basic_machine=i386-pc + os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=hms + ;; + harris) + basic_machine=m88k-harris + os=sysv3 + ;; + hp300) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=hpux + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=proelf + ;; + i386mach) + basic_machine=i386-mach + os=mach + ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; + isi68 | isi) + basic_machine=m68k-isi + os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=sysv + ;; + merlin) + basic_machine=ns32k-utek + os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + os=coff + ;; + morphos) + basic_machine=powerpc-unknown + os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=moxiebox + ;; + msdos) + basic_machine=i386-pc + os=msdos + ;; + msys) + basic_machine=i686-pc + os=msys + ;; + mvs) + basic_machine=i370-ibm + os=mvs + ;; + nacl) + basic_machine=le32-unknown + os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=newsos + ;; + news1000) + basic_machine=m68030-sony + os=newsos + ;; + necv70) + basic_machine=v70-nec + os=sysv + ;; + nh3000) + basic_machine=m68k-harris + os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=cxux + ;; + nindy960) + basic_machine=i960-intel + os=nindy + ;; + mon960) + basic_machine=i960-intel + os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=ose + ;; + os68k) + basic_machine=m68k-none + os=os68k + ;; + paragon) + basic_machine=i860-intel + os=osf + ;; + parisc) + basic_machine=hppa-unknown + os=linux + ;; + pw32) + basic_machine=i586-unknown + os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=rdos + ;; + rdos32) + basic_machine=i386-pc + os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=coff + ;; + sa29200) + basic_machine=a29k-amd + os=udi + ;; + sei) + basic_machine=mips-sei + os=seiux + ;; + sequent) + basic_machine=i386-sequent + os= + ;; + sps7) + basic_machine=m68k-bull + os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + os= + ;; + stratus) + basic_machine=i860-stratus + os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + os= + ;; + sun2os3) + basic_machine=m68000-sun + os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + os= + ;; + sun3os3) + basic_machine=m68k-sun + os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + os= + ;; + sun4os3) + basic_machine=sparc-sun + os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; + sv1) + basic_machine=sv1-cray + os=unicos + ;; + symmetry) + basic_machine=i386-sequent + os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=unicos + ;; + t90) + basic_machine=t90-cray + os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + os=tpf + ;; + udi29k) + basic_machine=a29k-amd + os=udi + ;; + ultra3) + basic_machine=a29k-nyu + os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=none + ;; + vaxv) + basic_machine=vax-dec + os=sysv + ;; + vms) + basic_machine=vax-dec + os=vms + ;; + vxworks960) + basic_machine=i960-wrs + os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=vxworks + ;; + xbox) + basic_machine=i686-pc + os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + os=unicos + ;; + *) + basic_machine=$1 + os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx | dvp \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | mt \ - | msp430 \ - | nios | nios2 \ - | ns16k | ns32k \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none + op50n) + cpu=hppa1.1 + vendor=oki ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + op60c) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + os=${os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + os=${os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $os in + irix*) + ;; + *) + os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + os=nextstep2 + ;; + *) + os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` + ;; + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsEE* | ee | ps2) - basic_machine=mips64r5900el-scei - case $os in - -linux*) - ;; - *) - os=-elf - ;; - esac - ;; - iop) - basic_machine=mipsel-scei - os=-irx - ;; - dvp) - basic_machine=dvp-scei - os=-elf - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 + cpu=$basic_machine + vendor=pc ;; + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" pc98) - basic_machine=i386-pc + cpu=i386 + vendor=pc ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + x64 | amd64) + cpu=x86_64 + vendor=pc ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - pentium4) - basic_machine=i786-pc + fx80-unknown) + vendor=alliant ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + romp-unknown) + vendor=ibm ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + mmix-unknown) + vendor=knuth ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + rs6000-unknown) + vendor=ibm ;; - pn) - basic_machine=pn-gould + vax-unknown) + vendor=dec ;; - power) basic_machine=power-ibm + pdp11-unknown) + vendor=dec ;; - ppc) basic_machine=powerpc-unknown + we32k-unknown) + vendor=att ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + cydra-unknown) + vendor=cydrome ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown + i370-ibm*) + vendor=ibm ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + orion-unknown) + vendor=highlevel ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - op50n) - basic_machine=hppa1.1-oki + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - op60c) - basic_machine=hppa1.1-oki + blackfin-*) + cpu=bfin + os=linux ;; - romp) - basic_machine=romp-ibm + c54x-*) + cpu=tic54x ;; - mmix) - basic_machine=mmix-knuth + c55x-*) + cpu=tic55x ;; - rs6000) - basic_machine=rs6000-ibm + c6x-*) + cpu=tic6x ;; - vax) - basic_machine=vax-dec + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown + mips3*-*) + cpu=mips64 ;; - pdp11) - basic_machine=pdp11-dec + ms1-*) + cpu=mt ;; - we32k) - basic_machine=we32k-att + m68knommu-*) + cpu=m68k + os=linux ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun + openrisc-*) + cpu=or32 ;; - cydra) - basic_machine=cydra-cydrome + parisc-*) + cpu=hppa + os=linux ;; - orion) - basic_machine=orion-highlevel + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - orion105) - basic_machine=clipper-highlevel + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + pentium4-*) + cpu=i786 ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + pc98-*) + cpu=i386 ;; + ppc-* | ppcbe-*) + cpu=powerpc + ;; + ppcle-* | powerpclittle-*) + cpu=powerpcle + ;; + ppc64-*) + cpu=powerpc64 + ;; + ppc64le-* | powerpc64little-*) + cpu=powerpc64le + ;; + sb1-*) + cpu=mipsisa64sb1 + ;; + sb1el-*) + cpu=mipsisa64sb1el + ;; + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` + ;; + spur-*) + cpu=spur + ;; + strongarm-* | thumb-*) + cpu=arm + ;; + tx39-*) + cpu=mipstx39 + ;; + tx39el-*) + cpu=mipstx39el + ;; + x64-*) + cpu=x86_64 + ;; + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` + ;; + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} + ;; + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis + ;; + cris-* | etrax*-*) + cpu=cris + vendor=axis + ;; + crx-*) + os=${os:-elf} + ;; + neo-tandem) + cpu=neo + vendor=tandem + ;; + nse-tandem) + cpu=nse + vendor=tandem + ;; + nsr-tandem) + cpu=nsr + vendor=tandem + ;; + nsv-tandem) + cpu=nsv + vendor=tandem + ;; + nsx-tandem) + cpu=nsx + vendor=tandem + ;; + s390-*) + cpu=s390 + vendor=ibm + ;; + s390x-*) + cpu=s390x + vendor=ibm + ;; + tile*-*) + os=${os:-linux-gnu} + ;; + *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1196,190 +1278,246 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if [ x$os != x ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux + ;; + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; - -solaris) - os=-solaris2 + solaris) + os=solaris2 ;; - -svr4*) - os=-sysv4 + unixware*) + os=sysv4.2uw ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) + gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*) + # Each alternative MUST end in a * to match a version number. + # sysv* is not here because it comes later, after sysvr4. + gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | kopensolaris* | plan9* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | knetbsd* | mirbsd* | netbsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ + | linux-newlib* | linux-musl* | linux-uclibc* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* \ + | morphos* | superux* | rtmk* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*) # Remember, each alternative MUST END IN *, to match a version number. ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) + qnx*) + case $cpu in + x86 | i*86) ;; *) - os=-nto$os + os=nto-$os ;; esac ;; - -nto-qnx*) + hiux*) + os=hiuxwe2 ;; - -nto*) + nto-qnx*) + ;; + nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + sim | xray | os68k* | v88r* \ + | windows* | osx | abug | netware* | os9* \ + | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + linux-dietlibc) + os=linux-dietlibc ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) + linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + lynx*178) + os=lynxos178 ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + lynx*5) + os=lynxos5 ;; - -opened*) - os=-openedition + lynx*) + os=lynxos ;; - -os400*) - os=-os400 + mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` ;; - -wince*) - os=-wince + opened*) + os=openedition ;; - -osfrose*) - os=-osfrose + os400*) + os=os400 ;; - -osf*) - os=-osf + sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; - -utek*) - os=-bsd + sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; - -dynix*) - os=-bsd + wince*) + os=wince ;; - -acis*) - os=-aos + utek*) + os=bsd ;; - -atheos*) - os=-atheos + dynix*) + os=bsd ;; - -syllable*) - os=-syllable + acis*) + os=aos ;; - -386bsd) - os=-bsd + atheos*) + os=atheos ;; - -ctix* | -uts*) - os=-sysv + syllable*) + os=syllable ;; - -nova*) - os=-rtmk-nova + 386bsd) + os=bsd ;; - -ns2 ) - os=-nextstep2 + ctix* | uts*) + os=sysv ;; - -nsk*) - os=-nsk + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 + ;; + nsk*) + os=nsk ;; # Preserve the version number of sinix5. - -sinix5.*) + sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; - -sinix*) - os=-sysv4 + sinix*) + os=sysv4 ;; - -tpf*) - os=-tpf + tpf*) + os=tpf ;; - -triton*) - os=-sysv3 + triton*) + os=sysv3 ;; - -oss*) - os=-sysv3 + oss*) + os=sysv3 ;; - -svr4) - os=-sysv4 + svr4*) + os=sysv4 ;; - -svr3) - os=-sysv3 + svr3) + os=sysv3 ;; - -sysvr4) - os=-sysv4 + sysvr4) + os=sysv4 ;; - # This must come after -sysvr4. - -sysv*) + # This must come after sysvr4. + sysv*) ;; - -ose*) - os=-ose + ose*) + os=ose ;; - -es1800*) - os=-ose + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint ;; - -xenix) - os=-xenix + zvmoe) + os=zvmoe ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + dicos*) + os=dicos ;; - -aros*) - os=-aros + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $cpu in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac ;; - -kaos*) - os=-kaos + nacl*) ;; - -zvmoe) - os=-zvmoe + ios) ;; - -none) + none) + ;; + *-eabi) ;; *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1395,249 +1533,265 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in - score-*) - os=-elf +case $cpu-$vendor in + score-*) + os=elf ;; - spu-*) - os=-elf + spu-*) + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + os=linux ;; arm*-semi) - os=-aout + os=aout ;; - c4x-* | tic4x-*) - os=-coff + c4x-* | tic4x-*) + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf + ;; + tic54x-*) + os=coff + ;; + tic55x-*) + os=coff + ;; + tic6x-*) + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; - mep-*) - os=-elf + mep-*) + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 + ;; + pru-*) + os=elf ;; *-be) - os=-beos - ;; - *-haiku) - os=-haiku + os=beos ;; *-ibm) - os=-aix + os=aix ;; - *-knuth) - os=-mmixware + *-knuth) + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs + os=luna ;; *-next) - os=-nextstep3 + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in - -riscix*) + riscix*) vendor=acorn ;; - -sunos*) + sunos*) vendor=sun ;; - -aix*) + cnk*|-aix*) vendor=ibm ;; - -beos*) + beos*) vendor=be ;; - -hpux*) + hpux*) vendor=hp ;; - -mpeix*) + mpeix*) vendor=hp ;; - -hiux*) + hiux*) vendor=hitachi ;; - -unos*) + unos*) vendor=crds ;; - -dgux*) + dgux*) vendor=dg ;; - -luna*) + luna*) vendor=omron ;; - -genix*) + genix*) vendor=ns ;; - -mvs* | -opened*) + clix*) + vendor=intergraph + ;; + mvs* | opened*) vendor=ibm ;; - -os400*) + os400*) vendor=ibm ;; - -ptx*) + ptx*) vendor=sequent ;; - -tpf*) + tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + vxsim* | vxworks* | windiss*) vendor=wrs ;; - -aux*) + aux*) vendor=apple ;; - -hms*) + hms*) vendor=hitachi ;; - -mpw* | -macos*) + mpw* | macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) vendor=atari ;; - -vos*) + vos*) vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$cpu-$vendor-$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure b/configure index b957c3c..a8b1214 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.28.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.29.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.28.0' -PACKAGE_STRING='sqlite 3.28.0' +PACKAGE_VERSION='3.29.0' +PACKAGE_STRING='sqlite 3.29.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -863,7 +863,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -965,7 +964,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1218,15 +1216,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1364,7 +1353,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1477,7 +1466,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.28.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.29.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1517,7 +1506,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1543,7 +1531,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.28.0:";; + short | recursive ) echo "Configuration of sqlite 3.29.0:";; esac cat <<\_ACEOF @@ -1669,7 +1657,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.28.0 +sqlite configure 3.29.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2088,7 +2076,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.28.0, which was +It was created by sqlite $as_me 3.29.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3946,13 +3934,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:3949: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3937: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:3952: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:3955: output\"" >&5) + (eval echo "\"\$as_me:3943: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5158,7 +5146,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5161 "configure"' > conftest.$ac_ext + echo '#line 5149 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6683,11 +6671,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:6686: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6674: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6690: \$? = $ac_status" >&5 + echo "$as_me:6678: \$? = $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. @@ -7022,11 +7010,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:7025: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7013: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7029: \$? = $ac_status" >&5 + echo "$as_me:7017: \$? = $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. @@ -7127,11 +7115,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:7130: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7118: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7134: \$? = $ac_status" >&5 + echo "$as_me:7122: \$? = $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 @@ -7182,11 +7170,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:7185: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7173: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7189: \$? = $ac_status" >&5 + echo "$as_me:7177: \$? = $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 @@ -9562,7 +9550,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9565 "configure" +#line 9553 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -9658,7 +9646,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9661 "configure" +#line 9649 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10007,7 +9995,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -10053,7 +10041,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -10077,7 +10065,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -10122,7 +10110,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -10146,7 +10134,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12244,7 +12232,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.28.0, which was +This file was extended by sqlite $as_me 3.29.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12310,7 +12298,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.28.0 +sqlite config.status 3.29.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 31d6b5f..889a674 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -2619,14 +2619,14 @@ static void fts3ColumnFilter( nList -= (int)(p - pList); pList = p; - if( nList==0 ){ + if( nList<=0 ){ break; } p = &pList[1]; p += fts3GetVarint32(p, &iCurrent); } - if( bZero && &pList[nList]!=pEnd ){ + if( bZero && (pEnd - &pList[nList])>0){ memset(&pList[nList], 0, pEnd - &pList[nList]); } *ppList = pList; @@ -3754,7 +3754,7 @@ static int nodeReaderNext(NodeReader *p){ } p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); - if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){ + if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){ return FTS_CORRUPT_VTAB; } blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); @@ -3773,7 +3773,7 @@ static int nodeReaderNext(NodeReader *p){ } } - assert( p->iOff<=p->nNode ); + assert_fts3_nc( p->iOff<=p->nNode ); return rc; } @@ -3934,7 +3934,7 @@ static int fts3AppendToNode( /* Node must have already been started. There must be a doclist for a ** leaf node, and there must not be a doclist for an internal node. */ assert( pNode->n>0 ); - assert( (pNode->a[0]=='\0')==(aDoclist!=0) ); + assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) ); blobGrowBuffer(pPrev, nTerm, &rc); if( rc!=SQLITE_OK ) return rc; @@ -4150,7 +4150,7 @@ static int fts3TermCmp( int nCmp = MIN(nLhs, nRhs); int res; - res = memcmp(zLhs, zRhs, nCmp); + res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0); if( res==0 ) res = nLhs - nRhs; return res; @@ -4282,10 +4282,13 @@ static int fts3IncrmergeLoad( pNode = &pWriter->aNodeWriter[nHeight]; pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; - blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc); + blobGrowBuffer(&pNode->block, + MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc + ); if( rc==SQLITE_OK ){ memcpy(pNode->block.a, aRoot, nRoot); pNode->block.n = nRoot; + memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING); } for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ @@ -4293,23 +4296,28 @@ static int fts3IncrmergeLoad( pNode = &pWriter->aNodeWriter[i]; rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); - blobGrowBuffer(&pNode->key, reader.term.n, &rc); - if( rc==SQLITE_OK ){ - 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); - blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aBlock, nBlock); - pNode->block.n = nBlock; + if( reader.aNode ){ + while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); + blobGrowBuffer(&pNode->key, reader.term.n, &rc); + if( rc==SQLITE_OK ){ + 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); + 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; + memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING); + } + sqlite3_free(aBlock); } - sqlite3_free(aBlock); } } nodeReaderRelease(&reader); @@ -4552,7 +4560,10 @@ static int fts3TruncateNode( NodeReader reader; /* Reader object */ Blob prev = {0, 0, 0}; /* Previous term written to new node */ int rc = SQLITE_OK; /* Return code */ - int bLeaf = aNode[0]=='\0'; /* True for a leaf node */ + int bLeaf; /* True for a leaf node */ + + if( nNode<1 ) return FTS_CORRUPT_VTAB; + bLeaf = aNode[0]=='\0'; /* Allocate required output space */ blobGrowBuffer(pNew, nNode, &rc); diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index b3d4984..cb768eb 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -178,10 +178,19 @@ int sqlite3Fts5PoslistNext64( i64 iOff = *piOff; int iVal; fts5FastGetVarint32(a, i, iVal); - if( iVal==1 ){ + if( iVal<=1 ){ + if( iVal==0 ){ + *pi = i; + return 0; + } fts5FastGetVarint32(a, i, iVal); iOff = ((i64)iVal) << 32; fts5FastGetVarint32(a, i, iVal); + if( iVal<2 ){ + /* This is a corrupt record. So stop parsing it here. */ + *piOff = -1; + return 1; + } } *piOff = iOff + ((iVal-2) & 0x7FFFFFFF); *pi = i; diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 2bdeab1..73249b0 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -992,7 +992,7 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); - if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){ + if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); } fts5DataRelease(pData); @@ -4953,8 +4953,14 @@ static void fts5MergePrefixLists( ** 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. */ - if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return; + ** 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); @@ -4965,6 +4971,7 @@ static void fts5MergePrefixLists( fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize); fts5DoclistIterNext(&i1); if( i1.aPoslist==0 ) break; + assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) ); } else if( i2.iRowid!=i1.iRowid ){ /* Copy entry from i2 */ @@ -4972,6 +4979,7 @@ static void fts5MergePrefixLists( 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) ); } else{ /* Merge the two position lists. */ @@ -4995,7 +5003,7 @@ static void fts5MergePrefixLists( sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); - assert( iPos1>=0 && iPos2>=0 ); + assert_nc( iPos1>=0 && iPos2>=0 ); if( iPos1=0 && iPos2>=0 ){ while( 1 ){ if( iPos1=0 && iPos2!=iPrev ); + assert_nc( iPos2>=0 && iPos2!=iPrev ); sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); aCopy = &a2[iOff2]; nCopy = i2.nPoslist - iOff2; @@ -5043,8 +5050,9 @@ static void fts5MergePrefixLists( fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); fts5DoclistIterNext(&i1); fts5DoclistIterNext(&i2); - assert( out.n<=(p1->n+p2->n+9) ); + 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) ); } } @@ -5056,7 +5064,7 @@ static void fts5MergePrefixLists( fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); } - assert( out.n<=(p1->n+p2->n+9) ); + assert_nc( out.n<=(p1->n+p2->n+9) ); fts5BufferSet(&p->rc, p1, out.n, out.p); fts5BufferFree(&tmp); diff --git a/ext/fts5/fts5_vocab.c b/ext/fts5/fts5_vocab.c index 2550c9d..36a3673 100644 --- a/ext/fts5/fts5_vocab.c +++ b/ext/fts5/fts5_vocab.c @@ -573,8 +573,10 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ } if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ - while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++; - assert( pCsr->iColpFts5->pConfig->nCol ); + for(/* noop */; pCsr->iColaDoc[pCsr->iCol]==0; pCsr->iCol++); + if( pCsr->iCol==nCol ){ + rc = FTS5_CORRUPT; + } } return rc; } diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test index f7d3fd2..c5544c8 100644 --- a/ext/fts5/test/fts5corrupt3.test +++ b/ext/fts5/test/fts5corrupt3.test @@ -4668,7 +4668,6 @@ do_execsql_test 38.1 { do_execsql_test 38.2 { UPDATE t1_data SET block = X'000202' WHERE rowid=1; } -breakpoint do_catchsql_test 38.3 { SELECT * FROM t1('a b') ORDER BY rank; } {1 {database disk image is malformed}} @@ -5813,12 +5812,12 @@ do_execsql_test 44.1 { } {} do_catchsql_test 44.2 { -INSERT INTO t1(t1) VALUES('integrity-check'); + INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} -do_catchsql_test 44.2 { +do_catchsql_test 44.3 { SELECT snippet(t1, -1, '.', '..', '', 2 ) FROM t1('g h') ORDER BY rank; -} {1 {database disk image is malformed}} +} {0 {{.g.. .h..} {.g.. h} {.g.. .h..}}} #-------------------------------------------------------------------------- reset_db @@ -6418,11 +6417,17 @@ do_test 47.0 { }]} {} do_catchsql_test 47.1 { - SELECT snippet(t1, -1, '.', '..', '[', 50), - highlight(t1, 2, '[', ']') FROM t1('g h') - WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank; + INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} +do_catchsql_test 47.2 { + SELECT count(*) FROM ( + SELECT snippet(t1, -1, '.', '..', '[', 50), + highlight(t1, 2, '[', ']') FROM t1('g h') + WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank + ) +} {0 3} + #-------------------------------------------------------------------------- reset_db do_test 48.0 { @@ -8128,6 +8133,1033 @@ do_catchsql_test 57.1 { INSERT INTO t1(t1) VALUES('optimize') } {1 {database disk image is malformed}} +#------------------------------------------------------------------------- +reset_db +do_test 58.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 24576 pagesize 4096 filename crash-5a5acd0ab42d31.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 06 0e 0f 00 0f aa 0f 53 ...............S +| 112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00 .....3.......... +| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................ +| 3600: 06 06 17 11 11 01 31 74 61 62 6c 65 62 62 62 62 ......1tablebbbb +| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb +| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table +| 3648: 74 31 5f 63 2a 6e 66 69 68 74 31 5f 63 6f 6e 66 t1_c*nfiht1_conf +| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE +| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR +| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI +| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...! +| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 73 73 !...tablet1_doss +| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR +| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 EATE TABLE 't1_d +| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG +| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, +| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i....... +| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i +| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE +| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid, +| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM +| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t +| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO +| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl +| 3936: 65 74 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 et1_datat1_data. +| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1 +| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE +| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b +| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 11 11 lock BLOB)T..... +| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA +| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE +| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a +| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 32 2c 32 2c 33 ,b,prefix=.2,2,3 +| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..) +| page 2 offset 4096 +| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L.... +| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ae ...m.K.,........ +| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........ +| 48: 0d 97 0d 76 0d 54 0d 30 fd 15 0c f3 0c d3 0c b5 ...v.T.0........ +| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........ +| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 0a cc 0a ad ...~.H.......... +| 96: 0a 8c 0a 6d 0a 4d 0a 2b 0a 0c 00 00 00 00 00 00 ...m.M.+........ +| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................ +| 2384: 30 00 00 00 9c 01 03 35 00 03 01 01 12 02 01 12 0......5........ +| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>... +| 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 05 62 03 04 0a 19 8c 80 80 ....tab.b....... +| 2544: 80 80 0c 03 00 38 00 00 00 14 03 39 a7 68 03 02 .....8.....9.h.. +| 2560: 04 10 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: 80 80 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 ff 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: 80 80 80 06 03 00 36 00 00 00 13 04 02 31 66 03 ......6......1f. +| 2752: 02 01 f1 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 14 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 cc 03 02 03 07 1c 8c 80 80 80 .0tabl.......... +| 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 02 06 04 0d 13 8c r.......of...... +| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02 .......,........ +| 2880: 30 6e 03 06 01 01 02 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 14 2a 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 16 00 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 3e 10 00 00 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 0e 03 05 0c 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 01 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 bf 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 03 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 02 12 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 71 01 07 .......0the..q.. +| 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: 08 f0 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 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2 +| 3504: 02 02 07 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 03 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 03 f8 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 00 02 04 04 09 19 84 80 .......e........ +| 3760: 80 80 80 0a 03 10 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 00 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 de 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 80 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 00 f2 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 c1 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 13 .V.M.A.8./.&.... +| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d7 0e cd ................ +| 80: 0e c3 0e ba 0e b0 0e a8 0e 9f 0e 96 0e 8e 0e 85 ................ +| 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 34 03 33 74 68 1c 08 04 01 10 01 03 ....4.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 0f f1 03 31 74 10 08 ....2.......1t.. +| 3744: 04 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 30 fc .....1n.......0. +| 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 05 52 08 04 01 ...0n.......R... +| 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 08 04 01 10 01 02 32 74 1a 08 04 01 10 b3 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 10 01 02 31 6e 12 08 ...1t.......1n.. +| 3888: 04 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 09 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 f4 09 11 01 33 66 1a .....3p......3f. +| 4000: 08 04 09 12 01 32 74 68 18 07 04 09 10 01 32 e4 .....2th......2. +| 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 00 00 00 00 00 00 00 ......0t........ +| page 4 offset 12288 +| 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 +| 4080: 00 00 23 03 02 01 03 03 02 00 00 00 00 00 00 00 ..#............. +| end crash-5a5acd0ab42d31.db +}]} {} + +do_execsql_test 58.1 { + SELECT * FROM t1('t*'); +} {{} {} {} {} {} {}} + +#------------------------------------------------------------------------- +do_test 59.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 32768 pagesize 4096 filename crash-96b136358d01ec.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 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 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 3 offset 8192 +| 0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30 ...........21160 +| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1 609...........3. +| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 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 01 f2 03 06 4e 02 02 03 06 01 ..........N..... +| 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 13 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 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................ +| 3472: 01 02 02 01 02 02 01 02 01 f1 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 25 0d 02 03 01 02 03 01 ........%....... +| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc......... +| 3568: 02 06 65 6f 70 6f 6c 79 0f f2 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: 00 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 13 06 00 f2 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 0a 22 74 72 65 65 19 02 03 01 02 03 01 02 03 ...tree......... +| 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 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe.... +| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab..... +| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x......... +| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................ +| 3888: 01 06 01 11 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 01 f1 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 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 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 45 ed 0XRTRIM.!..3..E. +| 3168: 49 54 20 4c 4f 41 44 21 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 5a 29 MIT LOAD EXTENZ) +| 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 56 a9 4d 1f 1e 05 00 33 0f 19 IONXRTV.M....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 31 52 59 1f 1d 05 00 33 0f 000WBIN1RY....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 32 0000XNOCASE....2 +| 3328: 0f 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 ..NAX 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 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 .f.%..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 76 35 58 52 54 52 49 4d 18 15 05 10 25 MSYv5XRTRIM....% +| 3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN@BLE 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 32 58 4e 4f 43 41 53 45 17 LE JSON2XNOCASE. +| 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 5f 81 42 4c NARY....)..E_.BL +| 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 1a 45 4e 41 42 4c 45 20 56 54 43 35 58 42 49 ..ENABLE VTC5XBI +| 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 48 4e 4f 43 41 53 45 16 1d 05 E FTS5HNOCASE... +| 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: 57 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e WNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e ABLE FTS4.RTRIM. +| 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 3f 87 ...C..COMPILER?. +| 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: 45 0d 60 59 4c 45 52 3d 67 63 63 2d 35 2e 34 00 E.`YLER=gcc-5.4. +| page 6 offset 20480 +| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#...... +| 3824: 06 22 03 01 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 02 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 10 12 02 01 01 ................ +| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 07 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| page 8 offset 28672 +| 4048: 00 00 00 00 00 00 5d 03 02 2b 69 6e 74 00 00 00 ......]..+int... +| end crash-96b136358d01ec.db +}]} {} + +do_catchsql_test 59.1 { + SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*eŸ' +} {0 {}} + +#------------------------------------------------------------------------- +do_test 60.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 32768 pagesize 4096 filename crash-c77b90b929dc92.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 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 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 3 offset 8192 +| 0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30 ...........21160 +| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1 609...........3. +| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 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 01 f2 03 06 4e 02 02 03 06 01 ..........N..... +| 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 13 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 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 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 76 b4 65 6e 73 69 6f 6e 1f 02 ......v.ension.. +| 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 25 0d 02 03 01 02 03 01 ........%....... +| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc......... +| 3568: 02 06 65 6f 70 6f 6c 79 0f f2 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: 00 03 6d 61 78 1c 02 0c 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 13 06 00 f2 02 03 ocase........... +| 3680: 06 01 12 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 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe.... +| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab..... +| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x......... +| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................ +| 3888: 01 06 01 11 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 01 f1 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 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 01 0f 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 24 0c 0a 00 0f 00 00 00 00 00 00 00 ....$........... +| 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 43 41 46 45 3d ..%..THREADCAFE= +| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM +| 3168: 49 54 20 4b 4f 41 44 21 45 58 54 45 4e 53 49 4f IT KOAD!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 56 a9 4d 1f 1e 05 00 33 0f 19 IONXRTV.M....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 31 52 59 1f 1d 05 00 33 0f 000WBIN1RY....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 32 0000XNOCASE....2 +| 3328: 0f 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 ..NAX 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 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 .f.%..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 10 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN@BLE 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 32 58 4e 4f 43 41 53 45 17 LE JSON2XNOCASE. +| 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 81 42 4c NARY....)..EO.BL +| 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 1a 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 48 4e 4f 43 41 53 45 16 1d 05 E FTS5HNOCASE... +| 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: 57 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e WNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e ABLE FTS4.RTRIM. +| 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 8a 4e 41 52 .....DEBUGXB.NAR +| 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 3f 87 ...C..COMPILER?. +| 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: 45 0d 60 59 4c 45 52 3d 67 63 63 2d 35 2e 34 2e E.`YLER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 30 39 68 52 54 52 49 4d 0 20160609hRTRIM +| page 6 offset 20480 +| 0: 0d 00 00 00 24 0e 00 00 00 00 00 00 00 00 00 00 ....$........... +| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#...... +| 3824: 06 22 03 01 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 02 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: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| page 8 offset 28672 +| 4048: 00 00 00 00 00 00 5d 03 00 00 00 00 00 00 00 00 ......]......... +| end crash-c77b90b929dc92.db +}]} {} + + +do_catchsql_test 60.2 { + SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ' +} {0 {}} + +#------------------------------------------------------------------------- +do_test 61.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-e5fa281edabddf.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 0f c7 00 06 0d b6 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 00 00 00 00 00 00 00 00 ...k............ +| 3504: 00 00 00 00 00 00 56 07 06 17 1f 1f 01 7d 74 61 ......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 51 62 6c 65 74 31 5f 64 ..!!...tQblet1_d +| 3616: 6f 63 73 69 7a 65 74 31 5f 63 6f 63 73 69 7a 65 ocsizet1_cocsize +| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't +| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN +| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE +| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...! +| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont +| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR +| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c +| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG +| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, +| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i.... +| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt +| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB +| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi +| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P +| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid +| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT +| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t +| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da +| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE +| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT +| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY +| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8.. +| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 ea 74 31 43 52 ...._tablet.t1CR +| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB +| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5 +| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c)......... +| page 3 offset 8192 +| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 1f 02 13 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 01 609...........4. +| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5..... +| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000... +| 3312: 01 02 04 01 02 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 06 65 ebug...........e +| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 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 03 01 02 03 01 02 03 ....gcc......... +| 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 11 02 03 01 06 6e sys5...........n +| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase........... +| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 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 02 03 06 01 02 02 03 06 01 02 01 13 05 01 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe.... +| 3840: 02 02 01 01 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 0e 16 01 01 02 01 06 01 01 02 01 06 01 02 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 01 06 01 01 02 ................ +| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................ +| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................ +| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 07 01 ................ +| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................ +| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................ +| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G.......... +| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 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 e2 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 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 40 52 59 1f 20 05 00 33 0f 19 4f NXBIN@RY. ..3..O +| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4d 41 58 20 4e 45 4d 4f 52 59 3d 35 30 30 30 30 MAX NEMORY=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 45 30 30 30 .MAX MEMORY=E000 +| 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 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE. +| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 20 54 52 ...%..ENABLE TR +| 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 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 e5 54 53 35 58 42 49 ..ENABLE .TS5XBI +| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4d NARY....#..ENABM +| 3712: 45 b5 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 b7 4e 41 52 59 17 0b LE FTS4XB.NARY.. +| 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 53 9XNOCASE&...C..S +| 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 2f 31 00 00 00 00 00 00 00 00 00 00 00 0 2/1........... +| page 6 offset 20480 +| 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 10 12 02 01 01 ................ +| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................ +| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................ +| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................ +| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................ +| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................ +| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................ +| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................ +| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 06 06 03 00 12 01 01 01 06 05 03 01 12 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| end crash-e5fa281edabddf.db +}]} {} + +do_execsql_test 61.1 { + CREATE VIRTUAL TABLE t3 USING fts5vocab('t1'(),'col' ); +} + +do_catchsql_test 61.2 { + SELECT * FROM t3 ORDER BY rowid; +} {1 {database disk image is malformed}} + +breakpoint +#------------------------------------------------------------------------- +do_test 62.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-44942694542e1e.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 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 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 79 67 74 31 5f 63 blet1_confygt1_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 52 4c 4f 42 29 5e 05 07 17 21 Y, sz RLOB)^...! +| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont +| 3712: 65 6e 74 74 35 ff 63 6f 6e 74 65 6e 74 05 43 52 entt5.content.CR +| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c +| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG +| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, +| 3776: 63 30 2c 20 63 31 2c 20 63 42 29 69 04 07 17 19 c0, c1, cB)i.... +| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt +| 3808: 31 5f 79 64 78 04 43 52 45 41 54 45 20 54 41 42 1_ydx.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 74 61 ablet1_datat1_ta +| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE +| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT +| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY +| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8.. +| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR +| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB +| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5 +| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c)......... +| page 3 offset 8192 +| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 2f 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 01 609...........4. +| 3280: 02 05 01 02 c7 01 02 05 01 01 35 01 02 04 01 02 ..........5..... +| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000... +| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary.. +| 3328: 01 02 02 04 16 01 02 02 03 06 01 02 02 02 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 02 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 00 02 03 01 02 03 02 04 bstat........... +| 3424: 65 62 74 67 04 02 02 01 02 02 01 02 02 01 06 65 ebtg...........e +| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 01 f1 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 45 02 02 01 02 02 01 02 02 01 02 .....E.......... +| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension.. +| 3520: 04 01 02 09 c1 02 04 01 04 66 74 73 34 0a 02 03 .........fts4... +| 3536: 01 02 03 01 02 03 04 00 35 0d 02 03 01 02 04 01 ........5....... +| 3552: 02 03 01 0f d7 63 63 01 02 03 01 02 03 01 02 03 .....cc......... +| 3568: 02 06 65 6f 70 6f 6b 79 10 02 03 01 02 03 01 02 ..eopoky........ +| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 14 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 12 03 06 01 02 02 03 ocase........... +| 3680: 06 01 02 02 03 06 01 02 02 09 f6 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 11 02 ................ +| 3728: 02 01 04 6f 7d 69 74 1f 02 02 01 02 02 01 02 02 ...o.it......... +| 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 02 03 06 01 02 02 03 06 01 02 02 03 06 11 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 00 fa 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 03 04 01 40 .......vtab....@ +| 3856: 04 01 02 04 11 01 78 01 06 01 01 02 01 06 01 01 ......x......... +| 3872: 02 01 06 01 00 02 01 06 01 01 02 01 03 91 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 01 06 01 01 02 ................ +| 3968: 01 06 01 01 02 01 76 01 01 02 01 06 01 01 02 5c ......v......... +| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 11 06 ................ +| 4000: 01 02 02 01 06 08 11 02 01 06 01 01 02 01 06 01 ................ +| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 05 01 01 ................ +| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................ +| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 ca 0e 10 0f .D...G.......... +| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 14 24 0f D..@.......$Z.$. +| 4080: 0a 03 00 24 ff ff ff ff 01 01 02 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 01 0f fb 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 24 0c 09 00 00 00 00 00 00 00 00 00 ....$........... +| 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 47 17 22 DSAFE=0XNOCASG.. +| 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 3f 41 44 20 45 58 54 45 4e 53 49 4f IT L?AD EXTENSIO +| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O +| 3200: 4d 49 64 20 4c 4f 41 44 20 45 58 54 45 d9 53 49 MId LOAD EXTE.SI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 39 54 20 4c 4f 41 44 20 45 58 55 45 4e 53 OM9T LOAD EXUENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4c 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 LAX 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 af 4f 43 41 53 45 1e 1c 05 00 33 0000X.OCASE....3 +| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500 +| 3344: 30 30 ab 30 30 58 62 54 52 49 4d 18 1b 05 00 25 00.00XbTRIM....% +| 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 1b 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 4d 53 59 63 35 58 42 49 NABLE MEMSYc5XBI +| 3456: 4e 41 52 59 1a 17 04 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 3d 45 ....)..ENABLE =E +| 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 46 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LF 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 46 45 46 50 4f 4c 59 57 42 49 NABLE FEFPOLYWBI +| 3616: 4e 41 52 59 18 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 5f 43 41 53 45 E GEOPOLYXN_CASE +| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 42 ....)..ENABLE GB +| 3664: 2f 50 4f 4c 59 58 51 54 52 49 4d 17 0f 05 00 23 /POLYXQTRIM....# +| 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 1c 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 16 0b LE FTS4XBINARY.. +| 3776: 05 00 22 0f e9 45 4e 41 42 4c 35 20 46 54 53 34 .....ENABL5 FTS4 +| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 00 47 45 4e XNOCASE....#.GEN +| 3808: 41 42 4c 45 20 46 54 53 34 57 52 54 52 49 4d 1e ABLE FTS4WRTRIM. +| 3824: 60 05 00 31 0f 19 45 4e 41 42 4c 55 20 43 42 53 `..1..ENABLU CBS +| 3840: 54 41 54 20 56 54 42 42 58 42 49 4e 41 52 59 1e TAT VTBBXBINARY. +| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS +| 3872: 54 40 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d T@T VTABXNOCASE. +| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 55 20 44 42 53 ...1..ENABLU DBS +| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 12 06 TAT VTABXRTRIM.. +| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR +| 3936: 59 21 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 18 44 45 42 55 47 CASE.......DEBUG +| 3968: 58 42 54 52 49 4d 27 11 05 00 43 0f 19 43 4f 4d XBTRIM'...C..COM +| 3984: 50 49 48 f5 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PIH.R=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 22 32 30 31 36 30 36 30 cc-5.4.0.2016060 +| 4048: 39 c2 3e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9.>OCASE&...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 30 32 30 31 26 30 36 30 39 58 52 54 52 49 4d 00201&0609XRTRIM +| page 6 offset 20480 +| 0: 0d 00 00 00 24 0e e0 00 00 00 00 00 00 00 00 00 ....$........... +| 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 00 f6 17 03 00 19 e2 f9 01 ................ +| 3920: 06 16 03 00 12 02 05 01 06 15 03 00 12 02 01 01 ................ +| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................ +| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................ +| 3968: 06 10 03 10 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 00 f1 ................ +| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................ +| 4016: 06 0a 03 00 12 02 01 01 05 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 06 06 03 00 12 01 01 01 06 05 02 ff 84 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 07 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| end crash-44942694542e1e.db +}]} {} + +do_catchsql_test 62.1 { + WITH c(x) AS (VALUES(false) UNION ALL SELECT x+1 FROM c WHERE x<72) + INSERT INTO t1(a) SELECT randomblob(2829) FROM c; +} {0 {}} sqlite3_fts5_may_be_corrupt 0 finish_test diff --git a/ext/fts5/test/fts5corrupt4.test b/ext/fts5/test/fts5corrupt4.test new file mode 100644 index 0000000..dc9ca66 --- /dev/null +++ b/ext/fts5/test/fts5corrupt4.test @@ -0,0 +1,61 @@ +# 2019 May 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. +# +#*********************************************************************** +# +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5corrupt4 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} +sqlite3_fts5_may_be_corrupt 1 + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ttt USING fts5(a, b); + INSERT INTO ttt + VALUES('e ee eee e ee eee e ee eee', 'eee ee e e e ee eee ee ee'); + INSERT INTO ttt SELECT a||a, b||b FROM ttt; + INSERT INTO ttt SELECT a||a, b||b FROM ttt; +} + +proc mutate {blob i} { + set o [expr {$i % [string length $blob]}] + set a [string range $blob 0 $o-1] + set b [string range $blob $o+1 end] + set v [expr int(rand()*255) - 127] + return "$a[binary format c $v]$b" +} +db func mutate mutate + +for {set j 1000} {$j <= 5000} {incr j 1000} { + do_test 1.$j { + for {set i 0} {$i < 1000} {incr i} { + execsql { + BEGIN; + UPDATE ttt_data SET block = mutate(block, $i) WHERE id>10; + } + foreach sql { + {SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e*')} + {SELECT snippet(ttt, -1, '.', '..', '[', ']'), * FROM ttt('e* NOT ee*')} + } { + catch { execsql $sql } + } + execsql ROLLBACK + } + } {} +} + +sqlite3_fts5_may_be_corrupt 0 +finish_test + diff --git a/ext/misc/blobio.c b/ext/misc/blobio.c index 65ca467..3a1ee84 100644 --- a/ext/misc/blobio.c +++ b/ext/misc/blobio.c @@ -76,7 +76,7 @@ static void readblobFunc( sqlite3_blob_close(pBlob); if( rc ){ sqlite3_free(aData); - sqlite3_result_error(context, "BLOB write failed", -1); + sqlite3_result_error(context, "BLOB read failed", -1); }else{ sqlite3_result_blob(context, aData, nData, sqlite3_free); } diff --git a/ext/misc/dbdata.c b/ext/misc/dbdata.c new file mode 100644 index 0000000..7405e7c --- /dev/null +++ b/ext/misc/dbdata.c @@ -0,0 +1,851 @@ +/* +** 2019-04-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 contains an implementation of two eponymous virtual tables, +** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the +** "sqlite_dbpage" eponymous virtual table be available. +** +** SQLITE_DBDATA: +** sqlite_dbdata is used to extract data directly from a database b-tree +** page and its associated overflow pages, bypassing the b-tree layer. +** The table schema is equivalent to: +** +** CREATE TABLE sqlite_dbdata( +** pgno INTEGER, +** cell INTEGER, +** field INTEGER, +** value ANY, +** schema TEXT HIDDEN +** ); +** +** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE +** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND +** "schema". +** +** Each page of the database is inspected. If it cannot be interpreted as +** a b-tree page, or if it is a b-tree page containing 0 entries, the +** sqlite_dbdata table contains no rows for that page. Otherwise, the +** table contains one row for each field in the record associated with +** each cell on the page. For intkey b-trees, the key value is stored in +** field -1. +** +** For example, for the database: +** +** CREATE TABLE t1(a, b); -- root page is page 2 +** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five'); +** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten'); +** +** the sqlite_dbdata table contains, as well as from entries related to +** page 1, content equivalent to: +** +** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES +** (2, 0, -1, 5 ), +** (2, 0, 0, 'v' ), +** (2, 0, 1, 'five'), +** (2, 1, -1, 10 ), +** (2, 1, 0, 'x' ), +** (2, 1, 1, 'ten' ); +** +** If database corruption is encountered, this module does not report an +** error. Instead, it attempts to extract as much data as possible and +** ignores the corruption. +** +** SQLITE_DBPTR: +** The sqlite_dbptr table has the following schema: +** +** CREATE TABLE sqlite_dbptr( +** pgno INTEGER, +** child INTEGER, +** schema TEXT HIDDEN +** ); +** +** It contains one entry for each b-tree pointer between a parent and +** child page in the database. +*/ +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" + +typedef unsigned char u8; + +#endif +SQLITE_EXTENSION_INIT1 +#include +#include + +#define DBDATA_PADDING_BYTES 100 + +typedef struct DbdataTable DbdataTable; +typedef struct DbdataCursor DbdataCursor; + +/* Cursor object */ +struct DbdataCursor { + sqlite3_vtab_cursor base; /* Base class. Must be first */ + sqlite3_stmt *pStmt; /* For fetching database pages */ + + int iPgno; /* Current page number */ + u8 *aPage; /* Buffer containing page */ + int nPage; /* Size of aPage[] in bytes */ + int nCell; /* Number of cells on aPage[] */ + int iCell; /* Current cell number */ + int bOnePage; /* True to stop after one page */ + int szDb; + sqlite3_int64 iRowid; + + /* Only for the sqlite_dbdata table */ + u8 *pRec; /* Buffer containing current record */ + int nRec; /* Size of pRec[] in bytes */ + int nHdr; /* Size of header in bytes */ + int iField; /* Current field number */ + u8 *pHdrPtr; + u8 *pPtr; + + sqlite3_int64 iIntkey; /* Integer key value */ +}; + +/* Table object */ +struct DbdataTable { + sqlite3_vtab base; /* Base class. Must be first */ + sqlite3 *db; /* The database connection */ + sqlite3_stmt *pStmt; /* For fetching database pages */ + int bPtr; /* True for sqlite3_dbptr table */ +}; + +/* Column and schema definitions for sqlite_dbdata */ +#define DBDATA_COLUMN_PGNO 0 +#define DBDATA_COLUMN_CELL 1 +#define DBDATA_COLUMN_FIELD 2 +#define DBDATA_COLUMN_VALUE 3 +#define DBDATA_COLUMN_SCHEMA 4 +#define DBDATA_SCHEMA \ + "CREATE TABLE x(" \ + " pgno INTEGER," \ + " cell INTEGER," \ + " field INTEGER," \ + " value ANY," \ + " schema TEXT HIDDEN" \ + ")" + +/* Column and schema definitions for sqlite_dbptr */ +#define DBPTR_COLUMN_PGNO 0 +#define DBPTR_COLUMN_CHILD 1 +#define DBPTR_COLUMN_SCHEMA 2 +#define DBPTR_SCHEMA \ + "CREATE TABLE x(" \ + " pgno INTEGER," \ + " child INTEGER," \ + " schema TEXT HIDDEN" \ + ")" + +/* +** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual +** table. +*/ +static int dbdataConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + DbdataTable *pTab = 0; + int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); + + if( rc==SQLITE_OK ){ + pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable)); + if( pTab==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pTab, 0, sizeof(DbdataTable)); + pTab->db = db; + pTab->bPtr = (pAux!=0); + } + } + + *ppVtab = (sqlite3_vtab*)pTab; + return rc; +} + +/* +** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table. +*/ +static int dbdataDisconnect(sqlite3_vtab *pVtab){ + DbdataTable *pTab = (DbdataTable*)pVtab; + if( pTab ){ + sqlite3_finalize(pTab->pStmt); + sqlite3_free(pVtab); + } + return SQLITE_OK; +} + +/* +** This function interprets two types of constraints: +** +** schema=? +** pgno=? +** +** If neither are present, idxNum is set to 0. If schema=? is present, +** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit +** in idxNum is set. +** +** If both parameters are present, schema is in position 0 and pgno in +** position 1. +*/ +static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){ + DbdataTable *pTab = (DbdataTable*)tab; + int i; + int iSchema = -1; + int iPgno = -1; + int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA); + + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdx->aConstraint[i]; + if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + if( p->iColumn==colSchema ){ + if( p->usable==0 ) return SQLITE_CONSTRAINT; + iSchema = i; + } + if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){ + iPgno = i; + } + } + } + + if( iSchema>=0 ){ + pIdx->aConstraintUsage[iSchema].argvIndex = 1; + pIdx->aConstraintUsage[iSchema].omit = 1; + } + if( iPgno>=0 ){ + pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0); + pIdx->aConstraintUsage[iPgno].omit = 1; + pIdx->estimatedCost = 100; + pIdx->estimatedRows = 50; + + if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){ + int iCol = pIdx->aOrderBy[0].iColumn; + if( pIdx->nOrderBy==1 ){ + pIdx->orderByConsumed = (iCol==0 || iCol==1); + }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){ + pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1); + } + } + + }else{ + pIdx->estimatedCost = 100000000; + pIdx->estimatedRows = 1000000000; + } + pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00); + return SQLITE_OK; +} + +/* +** Open a new sqlite_dbdata or sqlite_dbptr cursor. +*/ +static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + DbdataCursor *pCsr; + + pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor)); + if( pCsr==0 ){ + return SQLITE_NOMEM; + }else{ + memset(pCsr, 0, sizeof(DbdataCursor)); + pCsr->base.pVtab = pVTab; + } + + *ppCursor = (sqlite3_vtab_cursor *)pCsr; + return SQLITE_OK; +} + +/* +** Restore a cursor object to the state it was in when first allocated +** by dbdataOpen(). +*/ +static void dbdataResetCursor(DbdataCursor *pCsr){ + DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab); + if( pTab->pStmt==0 ){ + pTab->pStmt = pCsr->pStmt; + }else{ + sqlite3_finalize(pCsr->pStmt); + } + pCsr->pStmt = 0; + pCsr->iPgno = 1; + pCsr->iCell = 0; + pCsr->iField = 0; + pCsr->bOnePage = 0; + sqlite3_free(pCsr->aPage); + sqlite3_free(pCsr->pRec); + pCsr->pRec = 0; + pCsr->aPage = 0; +} + +/* +** Close an sqlite_dbdata or sqlite_dbptr cursor. +*/ +static int dbdataClose(sqlite3_vtab_cursor *pCursor){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + dbdataResetCursor(pCsr); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** Utility methods to decode 16 and 32-bit big-endian unsigned integers. +*/ +static unsigned int get_uint16(unsigned char *a){ + return (a[0]<<8)|a[1]; +} +static unsigned int get_uint32(unsigned char *a){ + return ((unsigned int)a[0]<<24) + | ((unsigned int)a[1]<<16) + | ((unsigned int)a[2]<<8) + | ((unsigned int)a[3]); +} + +/* +** Load page pgno from the database via the sqlite_dbpage virtual table. +** If successful, set (*ppPage) to point to a buffer containing the page +** data, (*pnPage) to the size of that buffer in bytes and return +** SQLITE_OK. In this case it is the responsibility of the caller to +** eventually free the buffer using sqlite3_free(). +** +** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and +** return an SQLite error code. +*/ +static int dbdataLoadPage( + DbdataCursor *pCsr, /* Cursor object */ + unsigned int pgno, /* Page number of page to load */ + u8 **ppPage, /* OUT: pointer to page buffer */ + int *pnPage /* OUT: Size of (*ppPage) in bytes */ +){ + int rc2; + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = pCsr->pStmt; + + *ppPage = 0; + *pnPage = 0; + sqlite3_bind_int64(pStmt, 2, pgno); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nCopy = sqlite3_column_bytes(pStmt, 0); + if( nCopy>0 ){ + u8 *pPage; + pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES); + if( pPage==0 ){ + rc = SQLITE_NOMEM; + }else{ + const u8 *pCopy = sqlite3_column_blob(pStmt, 0); + memcpy(pPage, pCopy, nCopy); + memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES); + } + *ppPage = pPage; + *pnPage = nCopy; + } + } + rc2 = sqlite3_reset(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + + return rc; +} + +/* +** Read a varint. Put the value in *pVal and return the number of bytes. +*/ +static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){ + sqlite3_int64 v = 0; + int i; + for(i=0; i<8; i++){ + v = (v<<7) + (z[i]&0x7f); + if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } + } + v = (v<<8) + (z[i]&0xff); + *pVal = v; + return 9; +} + +/* +** Return the number of bytes of space used by an SQLite value of type +** eType. +*/ +static int dbdataValueBytes(int eType){ + switch( eType ){ + case 0: case 8: case 9: + case 10: case 11: + return 0; + case 1: + return 1; + case 2: + return 2; + case 3: + return 3; + case 4: + return 4; + case 5: + return 6; + case 6: + case 7: + return 8; + default: + if( eType>0 ){ + return ((eType-12) / 2); + } + return 0; + } +} + +/* +** Load a value of type eType from buffer pData and use it to set the +** result of context object pCtx. +*/ +static void dbdataValue( + sqlite3_context *pCtx, + int eType, + u8 *pData, + int nData +){ + if( eType>=0 && dbdataValueBytes(eType)<=nData ){ + switch( eType ){ + case 0: + case 10: + case 11: + sqlite3_result_null(pCtx); + break; + + case 8: + sqlite3_result_int(pCtx, 0); + break; + case 9: + sqlite3_result_int(pCtx, 1); + break; + + case 1: case 2: case 3: case 4: case 5: case 6: case 7: { + sqlite3_uint64 v = (signed char)pData[0]; + pData++; + switch( eType ){ + case 7: + case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 4: v = (v<<8) + pData[0]; pData++; + case 3: v = (v<<8) + pData[0]; pData++; + case 2: v = (v<<8) + pData[0]; pData++; + } + + if( eType==7 ){ + double r; + memcpy(&r, &v, sizeof(r)); + sqlite3_result_double(pCtx, r); + }else{ + sqlite3_result_int64(pCtx, (sqlite3_int64)v); + } + break; + } + + default: { + int n = ((eType-12) / 2); + if( eType % 2 ){ + sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT); + }else{ + sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT); + } + } + } + } +} + +/* +** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry. +*/ +static int dbdataNext(sqlite3_vtab_cursor *pCursor){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + + pCsr->iRowid++; + while( 1 ){ + int rc; + int iOff = (pCsr->iPgno==1 ? 100 : 0); + int bNextPage = 0; + + if( pCsr->aPage==0 ){ + while( 1 ){ + if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; + rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); + if( rc!=SQLITE_OK ) return rc; + if( pCsr->aPage ) break; + pCsr->iPgno++; + } + pCsr->iCell = pTab->bPtr ? -2 : 0; + pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); + } + + if( pTab->bPtr ){ + if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ + pCsr->iCell = pCsr->nCell; + } + pCsr->iCell++; + if( pCsr->iCell>=pCsr->nCell ){ + sqlite3_free(pCsr->aPage); + pCsr->aPage = 0; + if( pCsr->bOnePage ) return SQLITE_OK; + pCsr->iPgno++; + }else{ + return SQLITE_OK; + } + }else{ + /* If there is no record loaded, load it now. */ + if( pCsr->pRec==0 ){ + int bHasRowid = 0; + int nPointer = 0; + sqlite3_int64 nPayload = 0; + sqlite3_int64 nHdr = 0; + int iHdr; + int U, X; + int nLocal; + + switch( pCsr->aPage[iOff] ){ + case 0x02: + nPointer = 4; + break; + case 0x0a: + break; + case 0x0d: + bHasRowid = 1; + break; + default: + /* This is not a b-tree page with records on it. Continue. */ + pCsr->iCell = pCsr->nCell; + break; + } + + if( pCsr->iCell>=pCsr->nCell ){ + bNextPage = 1; + }else{ + + iOff += 8 + nPointer + pCsr->iCell*2; + if( iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff = get_uint16(&pCsr->aPage[iOff]); + } + + /* For an interior node cell, skip past the child-page number */ + iOff += nPointer; + + /* Load the "byte of payload including overflow" field */ + if( bNextPage || iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); + } + + /* If this is a leaf intkey cell, load the rowid */ + if( bHasRowid && !bNextPage && iOffnPage ){ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); + } + + /* Figure out how much data to read from the local page */ + U = pCsr->nPage; + if( bHasRowid ){ + X = U-35; + }else{ + X = ((U-12)*64/255)-23; + } + if( nPayload<=X ){ + nLocal = nPayload; + }else{ + int M, K; + M = ((U-12)*32/255)-23; + K = M+((nPayload-M)%(U-4)); + if( K<=X ){ + nLocal = K; + }else{ + nLocal = M; + } + } + + if( bNextPage || nLocal+iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + + /* Allocate space for payload. And a bit more to catch small buffer + ** overruns caused by attempting to read a varint or similar from + ** near the end of a corrupt record. */ + pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES); + if( pCsr->pRec==0 ) return SQLITE_NOMEM; + memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES); + pCsr->nRec = nPayload; + + /* Load the nLocal bytes of payload */ + memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); + iOff += nLocal; + + /* Load content from overflow pages */ + if( nPayload>nLocal ){ + sqlite3_int64 nRem = nPayload - nLocal; + unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); + while( nRem>0 ){ + u8 *aOvfl = 0; + int nOvfl = 0; + int nCopy; + rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); + assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage ); + if( rc!=SQLITE_OK ) return rc; + if( aOvfl==0 ) break; + + nCopy = U-4; + if( nCopy>nRem ) nCopy = nRem; + memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); + nRem -= nCopy; + + pgnoOvfl = get_uint32(aOvfl); + sqlite3_free(aOvfl); + } + } + + iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); + pCsr->nHdr = nHdr; + pCsr->pHdrPtr = &pCsr->pRec[iHdr]; + pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; + pCsr->iField = (bHasRowid ? -1 : 0); + } + } + }else{ + pCsr->iField++; + if( pCsr->iField>0 ){ + sqlite3_int64 iType; + if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ + bNextPage = 1; + }else{ + pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType); + pCsr->pPtr += dbdataValueBytes(iType); + } + } + } + + if( bNextPage ){ + sqlite3_free(pCsr->aPage); + sqlite3_free(pCsr->pRec); + pCsr->aPage = 0; + pCsr->pRec = 0; + if( pCsr->bOnePage ) return SQLITE_OK; + pCsr->iPgno++; + }else{ + if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){ + return SQLITE_OK; + } + + /* Advance to the next cell. The next iteration of the loop will load + ** the record and so on. */ + sqlite3_free(pCsr->pRec); + pCsr->pRec = 0; + pCsr->iCell++; + } + } + } + + assert( !"can't get here" ); + return SQLITE_OK; +} + +/* +** Return true if the cursor is at EOF. +*/ +static int dbdataEof(sqlite3_vtab_cursor *pCursor){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + return pCsr->aPage==0; +} + +/* +** Determine the size in pages of database zSchema (where zSchema is +** "main", "temp" or the name of an attached database) and set +** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise, +** an SQLite error code. +*/ +static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){ + DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab; + char *zSql = 0; + int rc, rc2; + sqlite3_stmt *pStmt = 0; + + zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + pCsr->szDb = sqlite3_column_int(pStmt, 0); + } + rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + return rc; +} + +/* +** xFilter method for sqlite_dbdata and sqlite_dbptr. +*/ +static int dbdataFilter( + sqlite3_vtab_cursor *pCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + int rc = SQLITE_OK; + const char *zSchema = "main"; + + dbdataResetCursor(pCsr); + assert( pCsr->iPgno==1 ); + if( idxNum & 0x01 ){ + zSchema = (const char*)sqlite3_value_text(argv[0]); + } + if( idxNum & 0x02 ){ + pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]); + pCsr->bOnePage = 1; + }else{ + pCsr->nPage = dbdataDbsize(pCsr, zSchema); + rc = dbdataDbsize(pCsr, zSchema); + } + + if( rc==SQLITE_OK ){ + if( pTab->pStmt ){ + pCsr->pStmt = pTab->pStmt; + pTab->pStmt = 0; + }else{ + rc = sqlite3_prepare_v2(pTab->db, + "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, + &pCsr->pStmt, 0 + ); + } + } + if( rc==SQLITE_OK ){ + rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); + }else{ + pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); + } + if( rc==SQLITE_OK ){ + rc = dbdataNext(pCursor); + } + return rc; +} + +/* +** Return a column for the sqlite_dbdata or sqlite_dbptr table. +*/ +static int dbdataColumn( + sqlite3_vtab_cursor *pCursor, + sqlite3_context *ctx, + int i +){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + if( pTab->bPtr ){ + switch( i ){ + case DBPTR_COLUMN_PGNO: + sqlite3_result_int64(ctx, pCsr->iPgno); + break; + case DBPTR_COLUMN_CHILD: { + int iOff = pCsr->iPgno==1 ? 100 : 0; + if( pCsr->iCell<0 ){ + iOff += 8; + }else{ + iOff += 12 + pCsr->iCell*2; + if( iOff>pCsr->nPage ) return SQLITE_OK; + iOff = get_uint16(&pCsr->aPage[iOff]); + } + if( iOff<=pCsr->nPage ){ + sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff])); + } + break; + } + } + }else{ + switch( i ){ + case DBDATA_COLUMN_PGNO: + sqlite3_result_int64(ctx, pCsr->iPgno); + break; + case DBDATA_COLUMN_CELL: + sqlite3_result_int(ctx, pCsr->iCell); + break; + case DBDATA_COLUMN_FIELD: + sqlite3_result_int(ctx, pCsr->iField); + break; + case DBDATA_COLUMN_VALUE: { + if( pCsr->iField<0 ){ + sqlite3_result_int64(ctx, pCsr->iIntkey); + }else{ + sqlite3_int64 iType; + dbdataGetVarint(pCsr->pHdrPtr, &iType); + dbdataValue( + ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr + ); + } + break; + } + } + } + return SQLITE_OK; +} + +/* +** Return the rowid for an sqlite_dbdata or sqlite_dptr table. +*/ +static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + *pRowid = pCsr->iRowid; + return SQLITE_OK; +} + + +/* +** Invoke this routine to register the "sqlite_dbdata" virtual table module +*/ +static int sqlite3DbdataRegister(sqlite3 *db){ + static sqlite3_module dbdata_module = { + 0, /* iVersion */ + 0, /* xCreate */ + dbdataConnect, /* xConnect */ + dbdataBestIndex, /* xBestIndex */ + dbdataDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + dbdataOpen, /* xOpen - open a cursor */ + dbdataClose, /* xClose - close a cursor */ + dbdataFilter, /* xFilter - configure scan constraints */ + dbdataNext, /* xNext - advance a cursor */ + dbdataEof, /* xEof - check for end of scan */ + dbdataColumn, /* xColumn - read data */ + dbdataRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ + }; + + int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1); + } + return rc; +} + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_dbdata_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + return sqlite3DbdataRegister(db); +} diff --git a/ext/misc/fossildelta.c b/ext/misc/fossildelta.c index 7e78f6f..2c71548 100644 --- a/ext/misc/fossildelta.c +++ b/ext/misc/fossildelta.c @@ -849,6 +849,7 @@ static int deltaparsevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ */ static int deltaparsevtabClose(sqlite3_vtab_cursor *cur){ deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur; + sqlite3_free(pCur->aDelta); sqlite3_free(pCur); return SQLITE_OK; } diff --git a/ext/misc/json1.c b/ext/misc/json1.c index d99d360..0bb4e1c 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1123,7 +1123,7 @@ static JsonNode *jsonLookupStep( u32 iStart, iLabel; JsonNode *pNode; iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); - iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); + iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); zPath += i; pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); if( pParse->oom ) return 0; diff --git a/ext/rbu/rbu_common.tcl b/ext/rbu/rbu_common.tcl index b5e63aa..c4e9878 100644 --- a/ext/rbu/rbu_common.tcl +++ b/ext/rbu/rbu_common.tcl @@ -89,16 +89,16 @@ proc step_rbu_legacy {target rbu} { proc do_rbu_vacuum_test {tn step {statedb state.db}} { forcedelete $statedb if {$statedb=="" && $step==1} breakpoint - uplevel [list do_test $tn.1 [string map [list %state% $statedb] { - if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}} + uplevel [list do_test $tn.1 [string map [list %state% $statedb %step% $step] { + if {%step%==0} { sqlite3rbu_vacuum rbu test.db {%state%}} while 1 { - if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}} + if {%step%==1} { sqlite3rbu_vacuum rbu test.db {%state%}} set state [rbu state] check_prestep_state test.db $state set rc [rbu step] check_poststep_state $rc test.db $state if {$rc!="SQLITE_OK"} break - if {$step==1} { rbu close } + if {%step%==1} { rbu close } } rbu close }] {SQLITE_DONE}] diff --git a/ext/rbu/rbufault2.test b/ext/rbu/rbufault2.test index 5b006f7..36f2b6b 100644 --- a/ext/rbu/rbufault2.test +++ b/ext/rbu/rbufault2.test @@ -52,6 +52,15 @@ do_faultsim_test 1 -faults oom* -prep { } +sqlite3rbu_create_vfs -default rbu "" +sqlite3 db test.db +set ::vfsname [file_control_vfsname db] +do_faultsim_test 2 -faults oom* -prep { +} -body { + file_control_vfsname db +} +db close +sqlite3rbu_destroy_vfs rbu finish_test diff --git a/ext/rbu/rbufault3.test b/ext/rbu/rbufault3.test index 5d44885..4f69028 100644 --- a/ext/rbu/rbufault3.test +++ b/ext/rbu/rbufault3.test @@ -83,7 +83,6 @@ foreach {fault errlist} { do_faultsim_test 3 -faults $fault -prep { faultsim_restore_and_reopen - forcedelete test.db2 } -body { sqlite3rbu_vacuum rbu test.db test.db2 rbu step @@ -91,7 +90,6 @@ foreach {fault errlist} { } -test { eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist] } - } finish_test diff --git a/ext/rbu/rbumisc.test b/ext/rbu/rbumisc.test new file mode 100644 index 0000000..c2a3906 --- /dev/null +++ b/ext/rbu/rbumisc.test @@ -0,0 +1,180 @@ +# 2014 August 30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set ::testprefix rbumisc + +db close +sqlite3_shutdown +sqlite3_config_uri 1 +reset_db + +proc populate_rbu_db {} { + forcedelete rbu.db + sqlite3 rbu rbu.db + rbu eval { + CREATE TABLE data_x1(a, b, c, rbu_control); + INSERT INTO data_x1 VALUES(1, 1, 1, 0); + INSERT INTO data_x1 VALUES(2, 2, 2, 0); + + CREATE TABLE dat(a, b, c, rbu_control); + CREATE TABLE "data x1"(a, b, c, rbu_control); + CREATE TABLE datax1(a, b, c, rbu_control); + CREATE TABLE data_(a, b, c, rbu_control); + + INSERT INTO "data x1" VALUES(3, 3, 3, 0); + INSERT INTO datax1 VALUES(3, 3, 3, 0); + INSERT INTO data_ VALUES(3, 3, 3, 0); + INSERT INTO dat VALUES(3, 3, 3, 0); + } + rbu close +} + +#------------------------------------------------------------------------- +# Ensure that RBU is not confused by oddly named tables in an RBU +# database. +# +do_execsql_test 1.0 { + CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY); +} +do_test 1.1 { + populate_rbu_db +} {} + +do_test 1.2 { + step_rbu test.db rbu.db + db eval { SELECT * FROM x1 } +} {1 1 1 2 2 2} + +do_test 1.3 { + db eval { DELETE FROM x1 } + sqlite3 rbu rbu.db + rbu eval { DELETE FROM rbu_state } + rbu close + step_rbu test.db rbu.db + db eval { SELECT * FROM x1 } +} {1 1 1 2 2 2} + +do_test 1.4 { + db eval { DELETE FROM x1 } + populate_rbu_db + + sqlite3rbu rbu test.db rbu.db + rbu step + rbu step + rbu close + + forcecopy test.db-oal test.db-wal + sqlite3rbu rbu test.db rbu.db + rbu step + list [catch { rbu close } msg] $msg +} {1 {SQLITE_ERROR - cannot update wal mode database}} + +#------------------------------------------------------------------------- +# Test the effect of a wal file appearing after the target database has +# been opened, but before it has been locked. +# +catch { db close } +testvfs tvfs -default 1 + +for {set N 1} {$N < 10} {incr N} { + reset_db + populate_rbu_db + do_execsql_test 2.$N.0 { + CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY); + } + + set nAccessCnt 0 + do_test 2.$N.1 { + sqlite3rbu rbu test.db rbu.db + rbu step + rbu step + rbu close + } {SQLITE_OK} + + tvfs script xAccess + tvfs filter xAccess + set nAccessCnt 0 + proc xAccess {method file args} { + global nAccessCnt + if {[file tail $file]=="test.db-wal"} { + incr nAccessCnt -1 + if {$nAccessCnt==0} { + set fd [open test.db-wal w] + puts -nonewline $fd [string repeat 0 2000] + close $fd + } + } + return SQLITE_OK + } + + foreach r { + {1 {SQLITE_ERROR - cannot update wal mode database}} + {0 SQLITE_OK} + {1 {SQLITE_CANTOPEN - unable to open database file}} + } { + set RES($r) 1 + } + do_test 2.$N.2 { + set ::nAccessCnt $N + set res [list [catch { + sqlite3rbu rbu test.db rbu.db + rbu step + rbu close + } msg ] $msg] + set RES($res) + } {1} + catch {rbu close} +} +catch {db close} +catch {tvfs delete} + +#------------------------------------------------------------------------- +testvfs tvfs -default 1 +reset_db +populate_rbu_db +do_execsql_test 3.0 { + CREATE TABLE x1(a, b, c INTEGER PRIMARY KEY); +} + +tvfs script xFileControl +tvfs filter xFileControl + +proc xFileControl {method file verb args} { + if {$verb=="ZIPVFS" && [info exists ::zipvfs_filecontrol]} { + return $::zipvfs_filecontrol + } + return "SQLITE_NOTFOUND" +} + +breakpoint +foreach {tn ret err} { + 1 SQLITE_OK 0 + 2 SQLITE_ERROR 1 + 3 SQLITE_NOTFOUND 0 + 4 SQLITE_OMIT 1 +} { + set ::zipvfs_filecontrol $ret + do_test 3.$tn.1 { + catch { + sqlite3rbu rbu test.db rbu.db + rbu step + rbu close + } + } $err +} +catch {db close} +catch {tvfs delete} + +#------------------------------------------------------------------------- + +finish_test diff --git a/ext/rbu/rbupartial.test b/ext/rbu/rbupartial.test index 3cb076f..9b0dce6 100644 --- a/ext/rbu/rbupartial.test +++ b/ext/rbu/rbupartial.test @@ -80,6 +80,10 @@ foreach {tn without_rowid a b c d} { set step 0 do_rbu_vacuum_test $tn.1.5 0 + + do_test $tn.1.6 { + execsql { PRAGMA integrity_check } + } {ok} }] } diff --git a/ext/rbu/rbutemplimit.test b/ext/rbu/rbutemplimit.test index 9397b56..958b2bf 100644 --- a/ext/rbu/rbutemplimit.test +++ b/ext/rbu/rbutemplimit.test @@ -65,6 +65,7 @@ proc step_rbu_cachesize {target rbu stepsize cachesize temp_limit} { while 1 { sqlite3rbu rbu $target $rbu rbu temp_size_limit $temp_limit + if { [rbu temp_size_limit -1]!=$temp_limit } { error "round trip problem!" } sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize" for {set i 0} {$i < $stepsize} {incr i} { set rc [rbu step] diff --git a/ext/rbu/rbuvacuum4.test b/ext/rbu/rbuvacuum4.test new file mode 100644 index 0000000..5cf33d6 --- /dev/null +++ b/ext/rbu/rbuvacuum4.test @@ -0,0 +1,116 @@ +# 2019 Jan 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 for the RBU module. More specifically, it +# contains tests to ensure that the sqlite3rbu_vacuum() API works as +# expected. +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set testprefix rbuvacuum4 + +set step 1 + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); +} +do_rbu_vacuum_test 1.1 1 + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 2.0 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c)) WITHOUT ROWID; + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); +} +do_rbu_vacuum_test 2.1 1 +do_execsql_test 2.2 { + SELECT * FROM t1; +} {1 2 3 4 5 6 7 8 9} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 3.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 oN t1(b, c); + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); + + CREATE TABLE t2(a, b, c INTEGER, PRIMARY KEY(c)); + CREATE INDEX i2 oN t2(b, a); + INSERT INTO t2 VALUES('a', 'b', -1); + INSERT INTO t2 VALUES('c', 'd', -2); + INSERT INTO t2 VALUES('e', 'f', -3); +} + +do_rbu_vacuum_test 3.1 1 + +do_execsql_test 3.2 { + SELECT * FROM t1; + SELECT * FROM t2; +} {1 2 3 4 5 6 7 8 9 e f -3 c d -2 a b -1} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE x1(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID; + INSERT INTO x1 VALUES(1, 1, 1, 1); + INSERT INTO x1 VALUES(1, 1, 2, 1); + INSERT INTO x1 VALUES(1, 2, 2, 1); + + INSERT INTO x1 VALUES(NULL, 2, 3, NULL); + INSERT INTO x1 VALUES(NULL, 2, 4, NULL); + INSERT INTO x1 VALUES(NULL, 2, 5, NULL); + + CREATE INDEX x1ad ON x1(d, a); + CREATE INDEX x1null ON x1(d, a) WHERE d>15; +} + +do_rbu_vacuum_test 4.1.1 1 + +do_execsql_test 4.2 { + SELECT count(*) fROM x1 +} 6 + +do_rbu_vacuum_test 4.1.2 0 + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE "a b c"(a, "b b" PRIMARY KEY, "c c"); + CREATE INDEX abc1 ON "a b c"(a, "c c"); + + INSERT INTO "a b c" VALUES(NULL, 'a', NULL); + INSERT INTO "a b c" VALUES(NULL, 'b', NULL); + INSERT INTO "a b c" VALUES(NULL, 'c', NULL); + + INSERT INTO "a b c" VALUES(1, 2, 3); + INSERT INTO "a b c" VALUES(3, 9, 1); + INSERT INTO "a b c" VALUES('aaa', 'bbb', 'ccc'); + + CREATE INDEX abc2 ON "a b c"("c c" DESC, a); + + CREATE TABLE x(a); + INSERT INTO x VALUES('a'), ('b'), ('d'); + CREATE UNIQUE INDEX y ON x(a); +} + +do_rbu_vacuum_test 5.1 1 + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 0160b83..a4fbeb6 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -930,7 +930,8 @@ static void rbuTargetNameFunc( zIn = (const char*)sqlite3_value_text(argv[0]); if( zIn ){ if( rbuIsVacuum(p) ){ - if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ + assert( argc==2 ); + if( 0==sqlite3_value_int(argv[1]) ){ sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); } }else{ @@ -1381,7 +1382,8 @@ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ } pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); - pIter->abTblPk[iOrder] = (iPk!=0); + assert( iPk>=0 ); + pIter->abTblPk[iOrder] = (u8)iPk; pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); iOrder++; } @@ -1416,6 +1418,213 @@ static char *rbuObjIterGetCollist( return zList; } +/* +** Return a comma separated list of the quoted PRIMARY KEY column names, +** in order, for the current table. Before each column name, add the text +** zPre. After each column name, add the zPost text. Use zSeparator as +** the separator text (usually ", "). +*/ +static char *rbuObjIterGetPkList( + sqlite3rbu *p, /* RBU object */ + RbuObjIter *pIter, /* Object iterator for column names */ + const char *zPre, /* Before each quoted column name */ + const char *zSeparator, /* Separator to use between columns */ + const char *zPost /* After each quoted column name */ +){ + int iPk = 1; + char *zRet = 0; + const char *zSep = ""; + while( 1 ){ + int i; + for(i=0; inTblCol; i++){ + if( (int)pIter->abTblPk[i]==iPk ){ + const char *zCol = pIter->azTblCol[i]; + zRet = rbuMPrintf(p, "%z%s%s\"%w\"%s", zRet, zSep, zPre, zCol, zPost); + zSep = zSeparator; + break; + } + } + if( i==pIter->nTblCol ) break; + iPk++; + } + return zRet; +} + +/* +** This function is called as part of restarting an RBU vacuum within +** stage 1 of the process (while the *-oal file is being built) while +** updating a table (not an index). The table may be a rowid table or +** a WITHOUT ROWID table. It queries the target database to find the +** largest key that has already been written to the target table and +** constructs a WHERE clause that can be used to extract the remaining +** rows from the source table. For a rowid table, the WHERE clause +** is of the form: +** +** "WHERE _rowid_ > ?" +** +** and for WITHOUT ROWID tables: +** +** "WHERE (key1, key2) > (?, ?)" +** +** Instead of "?" placeholders, the actual WHERE clauses created by +** this function contain literal SQL values. +*/ +static char *rbuVacuumTableStart( + sqlite3rbu *p, /* RBU handle */ + RbuObjIter *pIter, /* RBU iterator object */ + int bRowid, /* True for a rowid table */ + const char *zWrite /* Target table name prefix */ +){ + sqlite3_stmt *pMax = 0; + char *zRet = 0; + if( bRowid ){ + p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, + sqlite3_mprintf( + "SELECT max(_rowid_) FROM \"%s%w\"", zWrite, pIter->zTbl + ) + ); + if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ + sqlite3_int64 iMax = sqlite3_column_int64(pMax, 0); + zRet = rbuMPrintf(p, " WHERE _rowid_ > %lld ", iMax); + } + rbuFinalize(p, pMax); + }else{ + char *zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", " DESC"); + char *zSelect = rbuObjIterGetPkList(p, pIter, "quote(", "||','||", ")"); + char *zList = rbuObjIterGetPkList(p, pIter, "", ", ", ""); + + if( p->rc==SQLITE_OK ){ + p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, + sqlite3_mprintf( + "SELECT %s FROM \"%s%w\" ORDER BY %s LIMIT 1", + zSelect, zWrite, pIter->zTbl, zOrder + ) + ); + if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ + const char *zVal = (const char*)sqlite3_column_text(pMax, 0); + zRet = rbuMPrintf(p, " WHERE (%s) > (%s) ", zList, zVal); + } + rbuFinalize(p, pMax); + } + + sqlite3_free(zOrder); + sqlite3_free(zSelect); + sqlite3_free(zList); + } + return zRet; +} + +/* +** This function is called as part of restating an RBU vacuum when the +** current operation is writing content to an index. If possible, it +** queries the target index b-tree for the largest key already written to +** it, then composes and returns an expression that can be used in a WHERE +** clause to select the remaining required rows from the source table. +** It is only possible to return such an expression if: +** +** * The index contains no DESC columns, and +** * The last key written to the index before the operation was +** suspended does not contain any NULL values. +** +** The expression is of the form: +** +** (index-field1, index-field2, ...) > (?, ?, ...) +** +** except that the "?" placeholders are replaced with literal values. +** +** If the expression cannot be created, NULL is returned. In this case, +** the caller has to use an OFFSET clause to extract only the required +** rows from the sourct table, just as it does for an RBU update operation. +*/ +char *rbuVacuumIndexStart( + sqlite3rbu *p, /* RBU handle */ + RbuObjIter *pIter /* RBU iterator object */ +){ + char *zOrder = 0; + char *zLhs = 0; + char *zSelect = 0; + char *zVector = 0; + char *zRet = 0; + int bFailed = 0; + const char *zSep = ""; + int iCol = 0; + sqlite3_stmt *pXInfo = 0; + + p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) + ); + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ + int iCid = sqlite3_column_int(pXInfo, 1); + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); + const char *zCol; + if( sqlite3_column_int(pXInfo, 3) ){ + bFailed = 1; + break; + } + + if( iCid<0 ){ + if( pIter->eType==RBU_PK_IPK ){ + int i; + for(i=0; pIter->abTblPk[i]==0; i++); + assert( inTblCol ); + zCol = pIter->azTblCol[i]; + }else{ + zCol = "_rowid_"; + } + }else{ + zCol = pIter->azTblCol[iCid]; + } + + zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q", + zLhs, zSep, zCol, zCollate + ); + zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC", + zOrder, zSep, iCol, zCol, zCollate + ); + zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")", + zSelect, zSep, iCol, zCol + ); + zSep = ", "; + iCol++; + } + rbuFinalize(p, pXInfo); + if( bFailed ) goto index_start_out; + + if( p->rc==SQLITE_OK ){ + sqlite3_stmt *pSel = 0; + + p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg, + sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1", + zSelect, pIter->zTbl, zOrder + ) + ); + if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){ + zSep = ""; + for(iCol=0; iColnCol; iCol++){ + const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol); + if( zQuoted[0]=='N' ){ + bFailed = 1; + break; + } + zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted); + zSep = ", "; + } + + if( !bFailed ){ + zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector); + } + } + rbuFinalize(p, pSel); + } + + index_start_out: + sqlite3_free(zOrder); + sqlite3_free(zSelect); + sqlite3_free(zVector); + sqlite3_free(zLhs); + return zRet; +} + /* ** This function is used to create a SELECT list (the list of SQL ** expressions that follows a SELECT keyword) for a SELECT statement @@ -2092,12 +2301,24 @@ static int rbuObjIterPrepareAll( if( p->rc==SQLITE_OK ){ char *zSql; if( rbuIsVacuum(p) ){ + char *zStart = 0; + if( nOffset ){ + zStart = rbuVacuumIndexStart(p, pIter); + if( zStart ){ + sqlite3_free(zLimit); + zLimit = 0; + } + } + zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' %s ORDER BY %s%s", + "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s", zCollist, pIter->zDataTbl, - zPart, zCollist, zLimit + zPart, + (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart, + zCollist, zLimit ); + sqlite3_free(zStart); }else if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ @@ -2120,7 +2341,11 @@ static int rbuObjIterPrepareAll( zCollist, zLimit ); } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); + if( p->rc==SQLITE_OK ){ + p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql); + }else{ + sqlite3_free(zSql); + } } sqlite3_free(zImposterCols); @@ -2220,18 +2445,42 @@ static int rbuObjIterPrepareAll( /* Create the SELECT statement to read keys from data_xxx */ if( p->rc==SQLITE_OK ){ const char *zRbuRowid = ""; + char *zStart = 0; + char *zOrder = 0; if( bRbuRowid ){ zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, - sqlite3_mprintf( - "SELECT %s,%s rbu_control%s FROM '%q'%s", - zCollist, - (rbuIsVacuum(p) ? "0 AS " : ""), - zRbuRowid, - pIter->zDataTbl, zLimit - ) - ); + + if( rbuIsVacuum(p) ){ + if( nOffset ){ + zStart = rbuVacuumTableStart(p, pIter, bRbuRowid, zWrite); + if( zStart ){ + sqlite3_free(zLimit); + zLimit = 0; + } + } + if( bRbuRowid ){ + zOrder = rbuMPrintf(p, "_rowid_"); + }else{ + zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", ""); + } + } + + if( p->rc==SQLITE_OK ){ + p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, + sqlite3_mprintf( + "SELECT %s,%s rbu_control%s FROM '%q'%s %s %s %s", + zCollist, + (rbuIsVacuum(p) ? "0 AS " : ""), + zRbuRowid, + pIter->zDataTbl, (zStart ? zStart : ""), + (zOrder ? "ORDER BY" : ""), zOrder, + zLimit + ) + ); + } + sqlite3_free(zStart); + sqlite3_free(zOrder); } sqlite3_free(zWhere); @@ -4458,9 +4707,7 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ }else if( rc==SQLITE_NOTFOUND ){ pRbu->pTargetFd = p; p->pRbu = pRbu; - if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ - rbuMainlistAdd(p); - } + rbuMainlistAdd(p); if( p->pWalFd ) p->pWalFd->pRbu = pRbu; rc = SQLITE_OK; } @@ -4523,10 +4770,7 @@ static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY; }else{ int bCapture = 0; - if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE) - && pRbu && pRbu->eStage==RBU_STAGE_CAPTURE - && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0) - ){ + if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ bCapture = 1; } @@ -4559,20 +4803,24 @@ static int rbuVfsShmMap( ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space ** instead of a file on disk. */ assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ - if( iRegion<=p->nShm ){ - sqlite3_int64 nByte = (iRegion+1) * sizeof(char*); - char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); - if( apNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); - p->apShm = apNew; - p->nShm = iRegion+1; - } + if( eStage==RBU_STAGE_OAL ){ + sqlite3_int64 nByte = (iRegion+1) * sizeof(char*); + char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); + + /* This is an RBU connection that uses its own heap memory for the + ** pages of the *-shm file. Since no other process can have run + ** recovery, the connection must request *-shm pages in order + ** from start to finish. */ + assert( iRegion==p->nShm ); + if( apNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); + p->apShm = apNew; + p->nShm = iRegion+1; } - if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ + if( rc==SQLITE_OK ){ char *pNew = (char*)sqlite3_malloc64(szRegion); if( pNew==0 ){ rc = SQLITE_NOMEM; @@ -4801,7 +5049,8 @@ static int rbuVfsAccess( */ if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); - if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + if( pDb && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + assert( pDb->pRbu ); if( *pResOut ){ rc = SQLITE_CANTOPEN; }else{ diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 78849bd..ea5e737 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -63,10 +63,6 @@ #include "sqlite3.h" #endif -#include -#include -#include - #ifndef SQLITE_AMALGAMATION #include "sqlite3rtree.h" typedef sqlite3_int64 i64; @@ -74,7 +70,17 @@ typedef sqlite3_uint64 u64; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 #endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif +#endif + +#include +#include +#include /* The following macro is used to suppress compiler warnings. */ diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index acf455a..ecc7644 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1624,7 +1624,9 @@ int sqlite3session_diff( } sqlite3_free((char*)azCol); if( bMismatch ){ - *pzErrMsg = sqlite3_mprintf("table schemas do not match"); + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); + } rc = SQLITE_SCHEMA; } if( bHasPk==0 ){ @@ -1830,7 +1832,7 @@ int sqlite3session_attach( ** set *pRc to SQLITE_NOMEM and return non-zero. */ static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){ - if( *pRc==SQLITE_OK && p->nAlloc-p->nBufnAlloc-p->nBuf)nAlloc ? p->nAlloc : 128; do { diff --git a/main.mk b/main.mk index f418eec..508554d 100644 --- a/main.mk +++ b/main.mk @@ -738,6 +738,7 @@ SHELL_SRC = \ $(TOP)/ext/expert/sqlite3expert.h \ $(TOP)/ext/misc/zipfile.c \ $(TOP)/ext/misc/memtrace.c \ + $(TOP)/ext/misc/dbdata.c \ $(TOP)/src/test_windirent.c shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl diff --git a/manifest b/manifest index d0c2842..e459550 100644 --- a/manifest +++ b/manifest @@ -1,13 +1,13 @@ -C Version\s3.28.0 -D 2019-04-16T19:49:53.412 +C Version\s3.29.0 +D 2019-07-10T17:32:03.802 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 4640daf826b80947a924ac44275c451ffc13007c7c866a5730c8ce5cf9e1dc74 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 26957950b2b4f3b26e311eeea70437f85a77765f71d3a06489466d66ee321100 -F README.md 74745e53db87fdc86f571dd7ec1bd18e154d0abd6d37d2292a1062e931318a29 -F VERSION 288d756b1b7be03ecdbf1795c23af2c8425f2e46ba6979a14ef53360308f080d +F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a +F VERSION cc8cd90333c65cdf4cb346f356a2ce1eb0f5b7fa1d17a34d7350103e7320af1f F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -31,10 +31,10 @@ F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5 F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928 F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291 F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 -F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 +F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc -F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure b013bf805064650b072817c7c7f0a295cfcec5b1afec15e59ea4e9996543f51e x +F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559 +F configure 4a97fb6ccce582ebb3dc5a7e281e5e2823574dad851b8ccf814aa6de9f4c7ad2 x F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd @@ -99,7 +99,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f -F ext/fts3/fts3_write.c 1d814248a42ddecc6ebd8d9e09673228de2ff5ae1410b8b7f1b22e04b7299fdf +F ext/fts3/fts3_write.c 9e88111ca9f70e4079880d842c8323bffc4968b39ee38c0a75962a3485af9333 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73 @@ -112,11 +112,11 @@ F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7 F ext/fts5/fts5Int.h 5c26dce0ec9272fca726c6fddb92f634d0c912d4ca170330270d488a94b80416 F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa -F ext/fts5/fts5_buffer.c 7d91caa0d862079d787660ec405d2fda6fd4f206d95b870dc7adc3b8f66a400f +F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70 F ext/fts5/fts5_config.c d7523cba5e66da077233c023aecbc3e6a37978ff75a18131c5ab5b1229d5bac7 F ext/fts5/fts5_expr.c 840c88d55e78083a5e61a35968df877712ae28791b347eced1e98e3b337d2d3c F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75 -F ext/fts5/fts5_index.c 9146da94d0b9f62217c6ad234342fda3fbac3c254455d0b3f53957ad85262e08 +F ext/fts5/fts5_index.c 5a89e0341297fade9a8f2c7aecc1ebd2e7e0989da84ece4d287a153da73cf0e6 F ext/fts5/fts5_main.c abd04720e2729ba5bab2648d9d541faab18f45d481ae21fc30f125b55e979d6b F ext/fts5/fts5_storage.c b24f6916fcdd68989a549f25962f286bdba9d9d59c7581567a6a0eb647cd07cc F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95 @@ -125,7 +125,7 @@ F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3 F ext/fts5/fts5_tokenize.c 2e508c6a3bd8ee56c48e98a38052e1a650e49b32a484cce9b189984114bc3b88 F ext/fts5/fts5_unicode2.c 8bd0cd07396b74c1a05590e4070d635bccfc849812c305619f109e6c0485e250 F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80 -F ext/fts5/fts5_vocab.c 906dff069840347e68f654b12ca60a53a27cd1780daf155fbe7dd331f27c2329 +F ext/fts5/fts5_vocab.c c3f12188570abb423303cd193b16dd19ba54e21c2e930e9b748d743de3b385f5 F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 @@ -157,7 +157,8 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0 F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116 F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f -F ext/fts5/test/fts5corrupt3.test d3a07e6fe172ade03310af6056cae45ac3d2880a9bba187908eba735bd170742 +F ext/fts5/test/fts5corrupt3.test ee32b76e1b4beae8051f0bd5bc9cc9609667fdaed87886eda69b96b305d21897 +F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91 F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775 F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11 @@ -277,21 +278,22 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23 F ext/misc/amatch.c 50a9ef2d38dabfa371f8c1904097d493271e63d58ccb0e9b79a4fa4a94e66660 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 -F ext/misc/blobio.c 085bbfa57ea58bb15d994ba4cd397bff6f0c38c4f618adbc62cf4d3780e5d88a +F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243 F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 F ext/misc/csv.c 7f047aeb68f5802e7ce6639292095d622a488bb43526ed04810e0649faa71ceb +F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940 F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287c336 F ext/misc/eval.c 4b4757592d00fd32e44c7a067e6a0e4839c81a4d57abc4131ee7806d1be3104e F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f F ext/misc/fileio.c 288e7230e0fe464d71b0694e2d8bdd3a353118ac2e31da3964b95f460f09915f -F ext/misc/fossildelta.c 910510968a30ab77b8ac1a27931f2cb834e9db9fd5ab122f53b6045b4315665d +F ext/misc/fossildelta.c 5c04d0a5657615daf4c6cd01c4281de8983dd28f6eed592b2691c10e3f6710e1 F ext/misc/fuzzer.c c4e27daf41433a64cad5265cd27dbcb891147e9994d0422200ce81ce9a54b625 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c 8af4672f43634257dbcfdb4515b4070325463d67c6968b4be1bd414de28d4d58 +F ext/misc/json1.c c99b5f04fccba87c1c8c5ab5c0e53eef37c0144086e33911290a67dfba541d59 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 @@ -337,28 +339,30 @@ F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74 F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3 F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b -F ext/rbu/rbu_common.tcl 4b3d033b3e3844292ae3a1aefc0e524e64b0db5a0e4310657919e4504ac3073f +F ext/rbu/rbu_common.tcl 60d904133ff843fe72cc0514e9dd2486707181e6e0fbab20979da28c48d21de9 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/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20 F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8 -F ext/rbu/rbufault2.test 06e735c002c17802d93debca41f59b027e7429db7de17f2a81318ecfd3c651d4 -F ext/rbu/rbufault3.test e0052ccba428ffdd2bb989d3ae84716f058ec5ab5f7196c64ba407b9d23c7255 +F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1e73fd3d0c +F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179 F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d +F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9 -F ext/rbu/rbupartial.test 73baf12a5941fe6891a829106a6f2e0a973f89aa49bd8659b12f547beb29b482 +F ext/rbu/rbupartial.test 1c8bd6d42615b94caf08f129f5817fa26975523f0f51bceda1dca90e8114c7c4 F ext/rbu/rbuprogress.test 04614ff8820bab9c1ec1b7dbec1edc4b45474421d4fe7abbd2a879a9c02884f9 F ext/rbu/rburesume.test dbdc4ca504e9c76375a69e5f0d91205db967dcc509a5166ca80231f8fda49eb1 F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926 F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8 -F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341 +F ext/rbu/rbutemplimit.test 05ceefa90a2e26a99f40dd48282ed63a00df5e59c1f2bfd479c143e201a1b0ba F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534 F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc -F ext/rbu/sqlite3rbu.c f222350c33f063cbc754001cd4e9683164c6cb06be76ae43f15b396ec6fc1993 +F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10 +F ext/rbu/sqlite3rbu.c 8741c0ee1496b41ff888b983a1a32547bc8822602603c68b3e524e5e0e287395 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -372,7 +376,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350 F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/geopoly.c c591164125808f8bba9659e92665b78412cd263e654b6f05294f3a8da7cdd9fb -F ext/rtree/rtree.c f2ce90120f3e2e01f8a510a227cafbea224c08ba2bf6809b0139c671de2873dc +F ext/rtree/rtree.c 78c0d989c32e5baac471f0463e83cda5006c7e71ded39d633b5fc001a301a26e F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 7573134f1b4f59df36c1b0a6de51268fd3b9c714d91f3811482263e734e416ea F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -431,7 +435,7 @@ F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b295 F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810 F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5 F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d -F ext/session/sqlite3session.c 12c958dcd093fca229ca3d3fd833f2f99f1d9c70093dca60f697d5f8e20ebde1 +F ext/session/sqlite3session.c 3d9d3a414be386b87d83e642f4d93c8cbe83fe7b975d17b398f96caa1bfdc2cf F ext/session/sqlite3session.h 919be6649d39d6413ce7a63fc3e3bca3270e18bc2d57ad4040a70007b9e54397 F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 @@ -440,7 +444,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 23d3660f7053d196aef76938bf78b10fc3ce1831a85d96bd71565758788f34d4 +F main.mk 125adda36bb32c99dc3a11340bd029ef373b9523eac2b2af76087bfe82d4fdf8 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -452,37 +456,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 25f54387121a0c5fd0f49b299f4070c81af8f26a84edaae6de679c4e4b71b1ff +F src/alter.c c1b5e5639b88dcc146db326315f2dea4f7f1c599e524eeb421d544927a0b1e86 F src/analyze.c 58db66344a5c58dcabb57f26696f6f2993956c830446da40b444051d2fdaf644 F src/attach.c 78e986baee90cb7b83fb9eafa79c22581a8ada14030fd633b0683c95cf11213c F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df -F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab +F src/backup.c b1d37f6f7f5913944583733ed0f9e182f3ece0d42c27f46701142141a6e6fd33 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 958939f608e351a36756e3749596472baa0e5aae54eebd14e6beffe7a68aafc7 +F src/btree.c 1dbc191e5c1d9bca84a956fed5d73924c574ae5390855009f067bd0f6422e462 F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f -F src/build.c 61655dad911a967a69fb49df57268fd15ce8f1af3fe0a1bd90c128ef2cacfb7a +F src/build.c 23a0253ab53e62feadcc0c6f31e7e418ef9d4b92c82a1398e98433776b920a4e F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b -F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 +F src/ctime.c 37f3d21193c4f7d141d0691cced5b39c99951bfef78df9887faf9167b9c42f37 +F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf -F src/expr.c e100212835d20498780e7c6d2bdb16c677ecc04350fb75db3bf192a86ba48c92 +F src/expr.c 2756d2875ac5b7a7efcc54edea3c8a31f4126684ded18da6fb406f4d3780a5f5 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c bd0138acdc008c1845ccf92f8e73787880562de649471804801c06fed814c765 -F src/func.c 2ccf4ae12430b1ae7096be5f0675887e1bd0732828af0ac0f7496339b7c6edee -F src/global.c 0dea3065ea72a65ae941559b6686aad6516d4913e76fa4f79a95ff7787f624ec +F src/fkey.c 0e14d4bef8eac2d87bbd517e492d9084c65008d117823f8922c5e7b2b599bd33 +F src/func.c 905c0424900979fade3731b4a271592059425c988cb7d5b245032253712dd7c8 +F src/global.c 1e942b1e6fb6a2a15e6015bda72be0abefc4b1339a8640a47b1b71b7f317917b F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c fc3cf5c371f9a400144e8c2f148ab29cd3f67f7da7eaf47e6a6959f8255fd92c +F src/insert.c f20925c2c08144442dabeb73dcd0f5026f5f085d827f3d5635f7c45e5d195320 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c -F src/main.c 16eea1ab004331312da0538dafb497cc0ed82fd9bb2e67f7684b40bf2797b666 +F src/main.c 591a0084b1a6b0ed6741f77181bd1a630ca10bb460420f00e8c11809da7df5b9 F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -491,7 +495,7 @@ F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memdb.c 02a5fcec19b9d40dd449ca802dc1b2e8f93f255fbf2a886277a3c3800d8d35db F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 -F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 +F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8 F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 @@ -507,28 +511,28 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 -F src/parse.y 8de9b1da4dc0f9615cfa9f4cbdd368b4ac822e1cbbc57b0fe071d9a83988df6d -F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee +F src/parse.y 026e3e6fff32432166a4eae0bdb78ad09a53c84eb49acb44dc32e49b4c0b8a48 +F src/pcache.c fd2d0553b3222d6b9f7cb251079e5bca1299d1161da3027b525932d8bf46340a F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 -F src/pcache1.c be64b2f3908a7f97c56c963676eb12f0d6254c95b28cdc1d73a186eff213219d -F src/pragma.c af67dedaad8bafe9a5f9adcec32a0da6dd118617dd8220ad1d118f5a6bf83a02 -F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177 +F src/pcache1.c e6373934cdafea272d94feb224344f9fd93ff94318221b64ccabd72d98b4672e +F src/pragma.c 925bcac0afd98a0d4255c7524b93239ab4d83893d96f7f8fdccd78d4929a39bb +F src/pragma.h 4a9fabff14db4487a734dfeeb4be984ce662bfdccfae16145b9c732327735e13 F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3 -F src/printf.c 67f79227273a9009d86a017619717c3f554f50b371294526da59faa6014ed2cd +F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8 +F src/resolve.c 93b7bc7c45efa6322d92293361c51a873690daed50cf77eeff88a448246b0d5a F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49 -F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810 -F src/sqlite.h.in 38390767acc1914d58930e03149595ee4710afa4e3c43ab6c3a8aea3f1a6b8cd +F src/select.c 62f21307b280791c50554c9fa3766758dd695ed66a05d2408d213355c7b0aa89 +F src/shell.c.in 82f8a473c01662f52233c6c75b9bf88d0d2cab276086d5d4ca6f2ff57a3e48eb +F src/sqlite.h.in 83ebc8ab1a2e82d92214006ea2c15bf8a0604f3fac2c31dd9ce9021f568c71f2 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5 -F src/sqliteInt.h d229b6a5f70fe6c57d2f91f0edc60a9c4437397b4a5b59fd72fe9eb3b94d3437 +F src/sqliteInt.h bf65dfa6565fae2e0d501088fc9c5212244adc1429a543827a16b2f5eaf41982 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c cfe7f93daf9d8787f65e099efb67d7cdfc2c35236dec5d3f6758520bd3519424 -F src/test1.c 0dc98af0769302672dcefd07a6128ee14e837b9f6e338a1aaca7ac31e4d8d2f8 +F src/test1.c f57c229ad7878215d0b3bb5d59ffe94772c099ce5b5e147a4a59d3157923a988 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb @@ -545,8 +549,8 @@ F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31 F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 F src/test_config.c 5ebafbcd5c75ac1c16bb0c8fe926dc325cc03e780943a88ca50e0d9a4fc4d2f5 F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f -F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e -F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 +F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91 +F src/test_devsym.c 6109b45c3db3ef7b002320947ed448c027356ab8b885156ff535fd8684d4a571 F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480 F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276 F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d @@ -575,7 +579,7 @@ F src/test_tclsh.c eeafce33ad2136d57e5dec10f1e9a4347447eb72ffd504a1c7b9c6bfe2e71 F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858 F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43 -F src/test_vfs.c 0868f1d4d7cdc7c6df60e895ca26b19e4f433dd1be0fc9c18c3ee63755804039 +F src/test_vfs.c 32618cbd953963278804bb47e97be7085d9e0d8755b1e734c3e54e9b9e115277 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1 F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215 @@ -583,32 +587,32 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e -F src/treeview.c 56724725c62a0d0f408f7c257475dc33309198afee36a1d18be1bc268b09055e +F src/treeview.c cf03f9f6efb93288c7b9f17374ea48e4ce9111b0bc7e428d6850c3eee532b461 F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73 -F src/update.c 0b973357d88092140531e07ff641139c26fb4380b0b9f5ed98c5f7691b4604d1 +F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 -F src/util.c e12939405e77906d06ab0b78c5f513dcd2b7cec2fbb553877b0abfece6067141 -F src/vacuum.c 72690ccb6877a88f8473a893cf9f6d7592236f3eebfebfa840b19c708acde574 -F src/vdbe.c 711ef421b3bb3db3b2476067b2dc3c71ef5844d9b1a723026578f89f6da621e8 +F src/util.c aef606a78b85d042138a841babbc0f98471b19b9a340b962e8fae307bc8cf3da +F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf +F src/vdbe.c aaa36d1ac7d55baf007e9c03ee7c826834a51dfe7a56ba4c386318695dd87c99 F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237 -F src/vdbeInt.h 2c12704db9740c8e899786ecfc7a5797a9d067563496eb1b6ed03c592d7b8d90 -F src/vdbeapi.c 2ddd60f4a351f15ee98d841e346af16111ad59dfa4d25d2dd4012e9875bf7d92 -F src/vdbeaux.c f873b5c2efcf8a4d6ecfc5b1a5b06fd810419198f3bd882175d371cc03801873 +F src/vdbeInt.h 3ba14553508d66f58753952d6dd287dce4ec735de02c6440858b4891aed51c17 +F src/vdbeapi.c f9161e5c77f512fbb80091ce8af621d19c9556bda5e734cffaac1198407400da +F src/vdbeaux.c 3a803d75875031309204df90977059b12ffb706d16b4baa5e2d99f4353962582 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 -F src/vdbemem.c 8e6889761e344babdb8a56dd1ac8911501fa648396544d1644f1cd6a87c80dc0 +F src/vdbemem.c f6f277d17d50972571d1394535d4c3d156fdea871d8f327f5b9479984054015a F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47 -F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 -F src/vtab.c 4c5959e00b7a142198d178e3a822f4e05f36f2d1a3c57657373f9487154fc06b +F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0 +F src/vtab.c 1fa256c6ddad7a81e2a4dc080d015d4b0a7135767717d311298e47f6fca64bb3 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 9eccc7ebb532a7b0fd3cabc16cff576b9afa763472272db67d84fb8cec96f5c0 +F src/wal.c b09a2a9cab50efa08451a8c81d47052120ad5da174048c6d0b08d405384abdf2 F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c 7607f1a68130c028255d8d56094ea602fc402c79e1e35a46e6282849d90d5fe4 -F src/where.c ff2955dc2743c1af05ba5a8232ab72724d9a63b76dbee256368f40fd3ef82db5 -F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88 -F src/wherecode.c 83be72e8d1c0231d0db06ffe5cfd32c7834bd00d2ed869306a2c1e0828488752 -F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c -F src/window.c 038c248267e74ff70a2bb9b1884d40fd145c5183b017823ecb6cbb14bc781478 +F src/where.c 2f11eeb14335b7640f886b2fb441f54a94c35ab5cde8b53461a1074bfd587081 +F src/whereInt.h 1b728f71654ebf8421a1715497a587f02d6f538e819af58dc826908f8577e810 +F src/wherecode.c 37a1004237d630d785c47bba2290eac652a7a8b0047518eba3cb7c808b604c4a +F src/whereexpr.c 5e559bdd24b06e3bc2e68f258bf751302954dc1e432daf71fdd8098a71462326 +F src/window.c 3408c0f606574d41033d461506bad68790239844b23e70610738a71152873d05 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -626,9 +630,9 @@ F test/altercol.test 54374d2ba18af25bb24e23acf18a60270d4ec120b7ec0558078b59d5aa1 F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b -F test/altertab.test 6e13f13d8c30708f16187908c31dadb1bfff9e3cb2a07a7392a7a5e076f58f4a -F test/altertab2.test 5d423a2d1006085b05cc1b788863d5a860ea2da21c4f892d15e2f2a34c78348a -F test/altertab3.test 40f2ce9be675e354d3e55c72f8baf38813be975ff4dd9e6b3144493c3c5bc033 +F test/altertab.test b6901287474841cffbd8f90b098d3bd7d8445868b42caeb01b27034698f7245f +F test/altertab2.test 8883693952f6d7fb5f754dbf1d694ed780aa883027bef04cb1fb99a3b88c9272 +F test/altertab3.test 7a2419829b2b908985b2c83d680388ef2eb9a74e446b68cee7b9b1551ae69078 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 @@ -668,7 +672,7 @@ F test/autoindex1.test 96185415f5faacd5b8d7a7f505efddd5abb1f111d58338e9c0b1dc40b F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf -F test/autoindex5.test 1d8c1134e1488a35c6fa205b2f52e72fc220972d946c59492d10bba01d6fecd4 +F test/autoindex5.test a5d72fe8c217cc0ea356dc6fa06a282a8a3fc53aa807709d79dba07a8f248102 F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e @@ -688,7 +692,7 @@ F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b792 F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601 F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9 F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4 -F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c +F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802 F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b @@ -719,13 +723,14 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bccc4 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe -F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857 +F test/cast.test 3619f0c58c2e4b2a94aa86e75607e497d34ef40ab74418e71aef7b4ca5155895 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef -F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a +F test/check.test dcc952a127c394ce0de2aa634d26c78207e855327cc63a24d3638ca8fbfa641e +F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760 F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8 F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 -F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846 +F test/collate1.test f9b653f515ef3324a0c4e3c6adbf136bb1903622af678d482a60c11c9c054e6c F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5 F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd @@ -762,10 +767,10 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af -F test/corruptL.test a569f3cece872a1f21568bd5378f55ce5c365c50845a06fae65a2721cce62264 +F test/corruptL.test 15882a75d06de29df9ad33a3503eb0fe21efbd1afcd676949c0d82e1f4e55360 F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c -F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf +F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86 F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 @@ -786,10 +791,11 @@ F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8 F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10 +F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e F test/dbfuzz001.test e32d14465f1c77712896fda6a1ccc0f037b481c191c1696a9c44f6c9e4964faf F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee -F test/dbfuzz2.c 6c355cf70c4a308b1b84a11a65282bcac5b4038db77de5cfc8ad080ef371f109 +F test/dbfuzz2.c b93db9056ad057733463ba333f89d2d195a95155805065c5962422955d7fb011 F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38 F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef @@ -815,7 +821,7 @@ F test/e_createtable.test 1c602347e73ab80b11b9fa083f47155861aaafcff8054aac9e0b76 F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5 -F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89 +F test/e_expr.test e6048fe3901241799c4315bdd625f39dae790ff089c454979ca85f03b644dc6f F test/e_fkey.test 2febb2084aef9b0186782421c07bc9d377abf067c9cb4efd49d9647ae31f5afe F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07 F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e @@ -844,6 +850,7 @@ F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac F test/expr.test 7cb55e80aeb41d65fec968c08212505123063fea60bdc355d764d747670e9eea +F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717 @@ -855,8 +862,8 @@ F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0 -F test/fkey7.test 24076d43d3449f12f25503909ca4bfb5fc5fefd5af1f930723a496343eb28454 -F test/fkey8.test 863c6d84f0d289fd2c1a1c293abb9803f77efd35211d9012c0986c8f6ccf5d5a +F test/fkey7.test 64fb28da03da5dfe3cdef5967aa7e832c2507bf7fb8f0780cacbca1f2338d031 +F test/fkey8.test 1d44df25d3b9cba72db4b4324201daf6ae1fc8a85cb68146bd6669a977d8867d F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb @@ -923,7 +930,8 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f -F test/fts3corrupt4.test af68ede153cbeff7309f7da2f9d8fd12a01f7e1debb03eb748c302079ac5ae05 +F test/fts3corrupt4.test c311911898e9ddac93fe71b947660a9716b285e2e600ad02810c231ff79a5925 +F test/fts3corrupt5.test 1911bd38381fe7eb28b204e7171937d09e113e5ceb018399ded9f42ec7e6ae66 F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338 F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de @@ -973,12 +981,13 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7 F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a +F test/fts4rename.test 6015a355ec3a11a51eb5b88802b3b2c1788786c54b77b17f3e077b7c93ff8611 F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429 F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test 150270b6e2e0281697c116e5ca0e46b41ace8d34b1c92461d88fdd9968c9b03c +F test/func.test e4313baba80bf933e58eb89a7c617bec0f0c348c862b096ec4387f36e05ad0a6 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f -F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c +F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6 F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c @@ -996,8 +1005,8 @@ F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 -F test/fuzzdata7.db f46c9a5698c1ca75ca6280c7c879a3f46dc82fe4b1ce246827496b806488952d -F test/fuzzdata8.db 5f12b6a8579e89616da9bd6dede1f38748eb04a1265f0b89117274f44d76b227 +F test/fuzzdata7.db babb1c560fef766171972c119c1bc3b7be20b134e2f46ae0c52390cd3059b6f4 +F test/fuzzdata8.db c69ca6d4bf1b25fd56ab432e9b96f2db0da752cfc6aa32700867f3a2d8a0514a F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -1011,7 +1020,7 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8 F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 -F test/in.test 4b985774a64f143f486418cec53379bed3aeb0503179353cc7c7ce15fb464349 +F test/in.test 63e642e97bc22c8fd970752fb4f0b3992a957003ea87524fe69e5a700500c500 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 @@ -1028,18 +1037,18 @@ F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635 -F test/index.test df4cddf4435314a948237fdfa9acee67de21f7bebc789beab4b89b575b4f6a70 +F test/index.test a2e948ed949e575487b5c1d521767d4584ac42d352f2dcd8e48004638e7bc7dc F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 -F test/index6.test 6b3e6cd4bef343ed4541e74c55936ed112962a6552c085242612b598e12910a4 -F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98 +F test/index6.test a6cf96bb70bf57b2221e102060a18af46bc366f704722f410d6f42c13a75534a +F test/index7.test 2222ccd1858097f734d6ac3d39117334fd1cc26460f92fced4ef57cd15c940c1 F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test 38020c247ee77ba19322fadde99db84bdf2aef34f714866786563c3834bb2dce +F test/indexexpr2.test d319e7d1b1043403f39a20c892d512e02b5549c6004806b977030f2430c60208 F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 9773604f8e1a2595f51488a5643c359d8a11dc55a11cb185910d93387d378458 @@ -1054,6 +1063,7 @@ F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054 F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8 +F test/intreal.test 2c80b5c90c597e65c6606b333515261c73a534b6c527b7009e97ed6b78f8b79a F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26 @@ -1061,31 +1071,31 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b -F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a +F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a F test/join.test d53a3662762eff50b65da8775201e609878a27dd0885a1ae7bcde9bb46cecbc5 F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 -F test/join5.test f8b5ffdf3c1513486b52ad4e49225507ecee5005f210eb18688f791d25370972 +F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7 F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 F test/journal3.test 939a3578396dffa0cdaa9b2685088c5a1a644db90d61aca08bd7e19d33932c00 -F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539 +F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test 8f8977b00ba02f9a26c1d1f52f29f540f6d5eb162cbd5eb78bb805366d4ab26d F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b -F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa +F test/json104.test cf0dbd220cba81e6c3cf8bc326e2321049cec05ab0b529308d76f28a52529800 F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7 -F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6 +F test/like.test 5013f18e7242fe118524fcf8e484b8827bcd5906b509d106f3587c7bfcf274ae F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da -F test/like3.test 0ce2630e39e32e42ce02d171f0a315189ca71fec37c5ddfb0191eecc3fe9d4da +F test/like3.test 62bf82ac674b7d4126e73532e1ad96cdcd8e1752a4ed90b28a6f98305f5a66aa F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04 @@ -1183,7 +1193,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859 F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 -F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace +F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6abbc5 F test/ossfuzz.c 18af635fa73d12a109b305faca727a734c1fa28a421b161d9d15c5a84a4998a2 F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17 F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f @@ -1200,12 +1210,12 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test b8f0da2f53ef1bd7ff149a140ee625aa7276c94ae15eb9acc2d8ed4af8f22b13 +F test/permutations.test 4282fb00e5ac0f8c2cd1be62652f6da4ac03ce3c58b7d785fa17f4684492a0e0 F test/pg_common.tcl 4740dc35190d6acdab14c097783331361301ab504a94d948f6afbb56ce0a51e8 F test/pragma.test cf066fe0f7f5d49f4758de4986407b8676c61aaa7871599340d64f42a8edc352 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 -F test/pragma4.test 26b250531f1c58d9b6187b663f411cd6baf227a4afeffa8f75d0f4c101f4920d +F test/pragma4.test 1cb4b32f1a304ed9e291d7c4d49c91c2c8dc1b9450e6d2c1198b2cc895d40d77 F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9 @@ -1219,24 +1229,26 @@ 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 215897dbe8de1a6f701265836d6601cc6ed103e6 +F test/quote.test 626149eda89ee64d81a3790de370f9f0211921b11568a49c28c861f394330508 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/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 204efd3a87ec1d62da2efde42c673b18b955350a9d3c6ac0b4dbba5bc8595808 x -F test/releasetest_data.tcl c3746248b5ad8f99a29020f83501bb25e024156ecc37e05c71c76da4fc8601c6 +F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d +F test/releasetest.tcl 968fc1e8fd23e113fb8a04379747f3a9f2c12d207b2de85aeff5a825962e1cd7 x +F test/releasetest_data.tcl 146a73e8c8212f962b6558fee0711b895f11b607ee0610e6910781dc8f83797d F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6 F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a +F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab21e F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 -F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d +F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3 F test/rowvalue.test b8680f07d19c8c5223b808bba998faffcec6d505f5689ff6070280119173bb51 F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256 @@ -1268,10 +1280,10 @@ F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2f F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 F test/select1.test 7d41f354998524070317207d4e2b68e725e4cf14a57835fc746d4bea686a8714 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 -F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 +F test/select3.test 3905450067c28766bc83ee397f6d87342de868baa60f2bcfd00f286dfbd62cb9 F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328 F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546 -F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 +F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801 F test/select7.test f659f231489349e8c5734e610803d7654207318f F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 @@ -1339,7 +1351,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c -F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb +F test/speedtest1.c f3bfe3c6a87cbd88e4c4e38005d972bcc1019d1b2fe9569425f86629b11f6c31 F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 @@ -1353,7 +1365,7 @@ F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec7 F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5 F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49 F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f -F test/subquery2.test 8250dfd6a773b04c7a5c37ac63276f62b329157ce171244d0cbe1acc365e3303 +F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12 F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 @@ -1415,7 +1427,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 1b5be1bac961833a9fd70fe50738cb4064822c61f82c54f7d488435ec806ea62 +F test/tkt-78e04e52ea.test cb44d0f5e7940223be740a39913a1b9b9b30d7e4a17ed3349141f893bae1b8f2 F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18 F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8 @@ -1429,7 +1441,7 @@ F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667 F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6 F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4 -F test/tkt-a8a0d2996a.test 76662ff0622c90e7ce7bbcb4d9e1129acddf877d17c3489f2da7f17ddfaad1f4 +F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72e0d32fac73e F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3 @@ -1593,8 +1605,8 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2 F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f -F test/vtab1.test 60b4f70aafa6078d6fdfc11417af3bd216d7ef5eafce16707a6ca3dae5166d20 +F test/view.test 40d54c9ddf5b9fdee692bf936d3352159fe467838f92742aa1d08c7c7d1eac73 +F test/vtab1.test 47b935205d7b6290765973abd6fce0e13e94e040017099170f43f81886efa5ba F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1609,7 +1621,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b -F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be450 +F test/vtabH.test e65540eed0f7434cdf0b160374570b51f3e3179548f0fa5e99b1d33f8dcdf9a0 F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783 @@ -1652,7 +1664,7 @@ F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 F test/walvfs.test c0faffda13d045a96dfc541347886bb1a3d6f3205857fc98e683edfab766ea88 F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec -F test/wapptest.tcl 78aff97afe76fd9728cf5f84710a772412735bc68a612b4789279072177a424e x +F test/wapptest.tcl 56d2b7974ecd8cca3189a670f757306d5ff3334cc9fe3744f7a6ad7ae4380e8c x F test/where.test 0607caa5a1fbfe7b93b95705981b463a3a0408038f22ae6e9dc11b36902b0e95 F test/where2.test 478d2170637b9211f593120648858593bf2445a1 F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c @@ -1684,8 +1696,8 @@ F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc F test/window1.test 8d453bfaa3f8f0873ba16ca1270c7368f18445065a0003a1b5954ac4e95797b4 -F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 -F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e +F test/window2.tcl 0c2918ef2a1640553fd791972d458356808a608418c64c02a0a379cecfc7fb0d +F test/window2.test 96ef949f0197c025652f6c6e5812cdbfb948989bd40cf79cbb02104249a89513 F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03 F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb F test/window4.tcl 5fbaab489677914ee5686b2008426e336daf88a2f58be7df92757f780a5ebf91 @@ -1696,15 +1708,16 @@ F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d761 F test/window7.test ce7f865241fdd1c5c4db869cd7bb2986c3be836bc2e73649a6846dd920f63e0f F test/window8.tcl 9e9a82ae9eea90a4a83481d641a812b974980c38f9247f3b89a6e3c8bed45518 F test/window8.test df187dc19921f7be0ab709d531d681bd80ccaac96a913a89ecee8b272b91d43f +F test/window9.test 06495ac733843849b1fca8a79d13ba330d04aba02099703198af2ba7e231f90c F test/windowerr.tcl abf4d6d0c6d360213af98ed7d538295d905689e83692106f3ece0e3afb9d7f36 F test/windowerr.test 675b5e6debfc9370bfacb0b91e2a93a8923512f92600b16f4ea70a1cd9b8e6e4 -F test/windowfault.test 16e906a2c4110c88372ff4bd5de59ac7397ec2f025912eff8e5677eedd126898 -F test/with1.test a07b5aad7f77acdf13e52e8814ea94606fcc72e9ea4c99baf293e9d7c63940be +F test/windowfault.test 403693d7d951c5473f052f7ecddb61ed15ac9d212f238b8904ea270ba90f83e5 +F test/with1.test d32792084dcb5f6c047d77bb8a032822ef9fe050ade07d0aeffa37753a05e3c9 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab -F test/with3.test 8d26920c88283e0a473ceebd3451554922108ce7b2a6a1157c47eb0a7011212c +F test/with3.test b5f1372097690c6ef84db2f13fc7e64a88c7263c3f88493605f90597e8a68d45 F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 -F test/without_rowid1.test b5ec93f7df2c1d684e0923247dac6aca8888e088bf50a9f244c3933e0e813a72 +F test/without_rowid1.test 89d101a7c6e0802882002cf3713f405319ddb6b9f08449dcc08c6082c995cab1 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a @@ -1737,7 +1750,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c 900a15b9efba9890d10e7959914db94c4ad5162912127f061c4328add122d6fb +F tool/lemon.c cc43148d2793ab93668e74a6a6319bb71c2e65c1ffcd6deeaa59e12be9362a43 F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -1751,8 +1764,8 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 49039adedafbc430d2959400da2e0e8f20ef8dcf6898e447c946e7d50ef5906b -F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5 +F tool/mkpragmatab.tcl 8250ef3df54aee09f6c6ed36cad390bb6dd20bbe71927d8bff069ed9fe0bbf98 +F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f @@ -1768,7 +1781,7 @@ 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 af978d1437562776fa4d94bf0cb772314c464e71ef24134a6e2301564ae60bc2 +F tool/showdb.c 97d14a1ce32d5edda84081a5c939bd8975abd89568a773b288940e67e4c7e3ad F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818 F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809 @@ -1818,11 +1831,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P af61a2fc45a0fa1277d7453779238b77de4c298a9f60714b7dc62ddca5874f80 -R 53d48b50e3fea254b204992be6aac766 +P 6f328c35947d6b3a0741514757b8944692203e89bdb2e7f9bbce8ad9288be344 +R 3dc95c8af87e7b557da20a5426ebc03a T +bgcolor * #d0c0ff T +sym-release * -T +sym-version-3.28.0 * +T +sym-version-3.29.0 * U drh -Z 50f60d1cc2f388d0c03013011d963653 +Z 4d356946c4c6edd871b6d6986b095a05 # Remove this line to create a well-formed manifest. diff --git a/manifest.uuid b/manifest.uuid index 24a372e..3f05969 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50 +fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6 diff --git a/src/alter.c b/src/alter.c index d710747..3957ede 100644 --- a/src/alter.c +++ b/src/alter.c @@ -54,7 +54,7 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM \"%w\".%s " - "WHERE name NOT LIKE 'sqlite_%%'" + "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" " AND sql NOT LIKE 'create virtual%%'" " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ", zDb, MASTER_NAME, @@ -65,7 +65,7 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ sqlite3NestedParse(pParse, "SELECT 1 " "FROM temp.%s " - "WHERE name NOT LIKE 'sqlite_%%'" + "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" " AND sql NOT LIKE 'create virtual%%'" " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ", MASTER_NAME, zDb @@ -186,7 +186,7 @@ void sqlite3AlterRenameTable( "UPDATE \"%w\".%s SET " "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" - "AND name NOT LIKE 'sqlite_%%'" + "AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName ); @@ -197,7 +197,8 @@ void sqlite3AlterRenameTable( "tbl_name = %Q, " "name = CASE " "WHEN type='table' THEN %Q " - "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' " + " AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name,%d+18) " "ELSE name END " "WHERE tbl_name=%Q COLLATE nocase AND " @@ -571,7 +572,8 @@ void sqlite3AlterRenameColumn( sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) " - "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" + "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' " + " AND (type != 'index' OR tbl_name = %Q)" " AND sql NOT LIKE 'create virtual%%'", zDb, MASTER_NAME, zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, @@ -725,6 +727,29 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } +/* +** Walker callback used by sqlite3RenameExprUnmap(). +*/ +static int renameUnmapSelectCb(Walker *pWalker, Select *p){ + Parse *pParse = pWalker->pParse; + int i; + if( ALWAYS(p->pEList) ){ + ExprList *pList = p->pEList; + for(i=0; inExpr; i++){ + if( pList->a[i].zName ){ + sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zName); + } + } + } + if( ALWAYS(p->pSrc) ){ /* Every Select as a SrcList, even if it is empty */ + SrcList *pSrc = p->pSrc; + for(i=0; inSrc; i++){ + sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName); + } + } + return WRC_Continue; +} + /* ** Remove all nodes that are part of expression pExpr from the rename list. */ @@ -733,6 +758,7 @@ void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = pParse; sWalker.xExprCallback = renameUnmapExprCb; + sWalker.xSelectCallback = renameUnmapSelectCb; sqlite3WalkExpr(&sWalker, pExpr); } diff --git a/src/backup.c b/src/backup.c index 4200940..2090b49 100644 --- a/src/backup.c +++ b/src/backup.c @@ -274,7 +274,7 @@ static int backupOnePage( if( nSrcReserve!=nDestReserve ){ u32 newPgsz = nSrcPgsz; rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); - if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; + if( rc==SQLITE_OK && newPgsz!=(u32)nSrcPgsz ) rc = SQLITE_READONLY; } #endif diff --git a/src/btree.c b/src/btree.c index b31f74e..6c73a94 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1628,7 +1628,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ top = get2byte(&data[hdr+5]); - assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */ + assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; @@ -1925,7 +1925,7 @@ static int btreeComputeFreeSpace(MemPage *pPage){ ** serves to verify that the offset to the start of the cell-content ** area, according to the page header, lies within the page. */ - if( nFree>usableSize ){ + if( nFree>usableSize || nFreenFree = (u16)(nFree - iCellFirst); @@ -4153,6 +4153,18 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ return rc; } +/* +** Set the pBt->nPage field correctly, according to the current +** state of the database. Assume pBt->pPage1 is valid. +*/ +static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){ + int nPage = get4byte(&pPage1->aData[28]); + testcase( nPage==0 ); + if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); + testcase( pBt->nPage!=nPage ); + pBt->nPage = nPage; +} + /* ** Rollback the transaction in progress. ** @@ -4198,11 +4210,7 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ - int nPage = get4byte(28+(u8*)pPage1->aData); - testcase( nPage==0 ); - if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); - testcase( pBt->nPage!=nPage ); - pBt->nPage = nPage; + btreeSetNPage(pBt, pPage1); releasePageOne(pPage1); } assert( countValidCursors(pBt, 1)==0 ); @@ -4282,12 +4290,11 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ pBt->nPage = 0; } rc = newDatabase(pBt); - pBt->nPage = get4byte(28 + pBt->pPage1->aData); + btreeSetNPage(pBt, pBt->pPage1); - /* The database size was written into the offset 28 of the header - ** when the transaction started, so we know that the value at offset - ** 28 is nonzero. */ - assert( pBt->nPage>0 ); + /* pBt->nPage might be zero if the database was corrupt when + ** the transaction was started. Otherwise, it must be at least 1. */ + assert( CORRUPT_DB || pBt->nPage>0 ); } sqlite3BtreeLeave(p); } @@ -5295,6 +5302,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( pCur->ix==pCur->pPage->nCell-1 ); assert( pCur->pPage->leaf ); #endif + *pRes = 0; return SQLITE_OK; } @@ -5516,6 +5524,7 @@ int sqlite3BtreeMovetoUnpacked( ** case this happens. */ void *pCellKey; u8 * const pCellBody = pCell - pPage->childPtrSize; + const int nOverrun = 18; /* Size of the overrun padding */ pPage->xParseCell(pPage, pCellBody, &pCur->info); nCell = (int)pCur->info.nKey; testcase( nCell<0 ); /* True if key size is 2^32 or more */ @@ -5526,13 +5535,14 @@ int sqlite3BtreeMovetoUnpacked( rc = SQLITE_CORRUPT_PAGE(pPage); goto moveto_finish; } - pCellKey = sqlite3Malloc( nCell+18 ); + pCellKey = sqlite3Malloc( nCell+nOverrun ); if( pCellKey==0 ){ rc = SQLITE_NOMEM_BKPT; goto moveto_finish; } pCur->ix = (u16)idx; rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); + memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */ pCur->curFlags &= ~BTCF_ValidOvfl; if( rc ){ sqlite3_free(pCellKey); @@ -7637,6 +7647,7 @@ static int balance_nonroot( u16 maskPage = pOld->maskPage; u8 *piCell = aData + pOld->cellOffset; u8 *piEnd; + VVA_ONLY( int nCellAtStart = b.nCell; ) /* Verify that all sibling pages are of the same "type" (table-leaf, ** table-interior, index-leaf, or index-interior). @@ -7665,6 +7676,10 @@ static int balance_nonroot( */ memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow)); if( pOld->nOverflow>0 ){ + if( limitaiOvfl[0] ){ + rc = SQLITE_CORRUPT_BKPT; + goto balance_cleanup; + } limit = pOld->aiOvfl[0]; for(j=0; jnCell+pOld->nOverflow) ); cntOld[i] = b.nCell; if( i=0 && iOldnCell + pOld->nOverflow + !leafData; } diff --git a/src/build.c b/src/build.c index 9ecd31b..5331459 100644 --- a/src/build.c +++ b/src/build.c @@ -618,10 +618,14 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ #ifdef SQLITE_DEBUG /* Record the number of outstanding lookaside allocations in schema Tables - ** prior to doing any free() operations. Since schema Tables do not use - ** lookaside, this number should not change. */ + ** prior to doing any free() operations. Since schema Tables do not use + ** lookaside, this number should not change. + ** + ** If malloc has already failed, it may be that it failed while allocating + ** a Table object that was going to be marked ephemeral. So do not check + ** that no lookaside memory is used in this case either. */ int nLookaside = 0; - if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){ + if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ nLookaside = sqlite3LookasideUsed(db, 0); } #endif @@ -1329,7 +1333,7 @@ void sqlite3AddDefaultValue( ** accept it. This routine does the necessary conversion. It converts ** the expression given in its argument from a TK_STRING into a TK_ID ** if the expression is just a TK_STRING with an optional COLLATE clause. -** If the epxression is anything other than TK_STRING, the expression is +** If the expression is anything other than TK_STRING, the expression is ** unchanged. */ static void sqlite3StringToId(Expr *p){ @@ -1726,10 +1730,51 @@ static void estimateIndexWidth(Index *pIdx){ pIdx->szIdxRow = sqlite3LogEst(wIndex*4); } -/* Return true if value x is found any of the first nCol entries of aiCol[] +/* Return true if column number x is any of the first nCol entries of aiCol[]. +** This is used to determine if the column number x appears in any of the +** first nCol entries of an index. */ static int hasColumn(const i16 *aiCol, int nCol, int x){ - while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1; + while( nCol-- > 0 ){ + assert( aiCol[0]>=0 ); + if( x==*(aiCol++) ){ + return 1; + } + } + return 0; +} + +/* +** Return true if any of the first nKey entries of index pIdx exactly +** match the iCol-th entry of pPk. pPk is always a WITHOUT ROWID +** PRIMARY KEY index. pIdx is an index on the same table. pIdx may +** or may not be the same index as pPk. +** +** The first nKey entries of pIdx are guaranteed to be ordinary columns, +** not a rowid or expression. +** +** This routine differs from hasColumn() in that both the column and the +** collating sequence must match for this routine, but for hasColumn() only +** the column name must match. +*/ +static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){ + int i, j; + assert( nKey<=pIdx->nColumn ); + assert( iColnColumn,pPk->nKeyCol) ); + assert( pPk->idxType==SQLITE_IDXTYPE_PRIMARYKEY ); + assert( pPk->pTable->tabFlags & TF_WithoutRowid ); + assert( pPk->pTable==pIdx->pTable ); + testcase( pPk==pIdx ); + j = pPk->aiColumn[iCol]; + assert( j!=XN_ROWID && j!=XN_EXPR ); + for(i=0; iaiColumn[i]>=0 || j>=0 ); + if( pIdx->aiColumn[i]==j + && sqlite3StrICmp(pIdx->azColl[i], pPk->azColl[iCol])==0 + ){ + return 1; + } + } return 0; } @@ -1818,13 +1863,16 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); if( pList==0 ) return; + if( IN_RENAME_OBJECT ){ + sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); + } pList->a[0].sortOrder = pParse->iPkSortOrder; assert( pParse->pNewTable==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; pPk = sqlite3PrimaryKeyIndex(pTab); - pTab->iPKey = -1; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); @@ -1835,9 +1883,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ ** code assumes the PRIMARY KEY contains no repeated columns. */ for(i=j=1; inKeyCol; i++){ - if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ + if( isDupColumn(pPk, j, pPk, i) ){ pPk->nColumn--; }else{ + testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ); pPk->aiColumn[j++] = pPk->aiColumn[i]; } } @@ -1867,7 +1916,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ int n; if( IsPrimaryKeyIndex(pIdx) ) continue; for(i=n=0; iaiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++; + if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){ + testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); + n++; + } } if( n==0 ){ /* This index is a superset of the primary key */ @@ -1876,9 +1928,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ } if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return; for(i=0, j=pIdx->nKeyCol; iaiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){ + if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){ + testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); pIdx->aiColumn[j] = pPk->aiColumn[i]; pIdx->azColl[j] = pPk->azColl[i]; + if( pPk->aSortOrder[i] ){ + /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */ + pIdx->bAscKeyBug = 1; + } j++; } } @@ -2997,10 +3054,27 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); sqlite3VdbeJumpHere(v, j2); }else{ + /* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not + ** abort. The exception is if one of the indexed expressions contains a + ** user function that throws an exception when it is evaluated. But the + ** overhead of adding a statement journal to a CREATE INDEX statement is + ** very small (since most of the pages written do not contain content that + ** needs to be restored if the statement aborts), so we call + ** sqlite3MayAbort() for all CREATE INDEX statements. */ + sqlite3MayAbort(pParse); addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); + if( !pIndex->bAscKeyBug ){ + /* This OP_SeekEnd opcode makes index insert for a REINDEX go much + ** faster by avoiding unnecessary seeks. But the optimization does + ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables + ** with DESC primary keys, since those indexes have there keys in + ** a different order from the main table. + ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf + */ + sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); + } sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); @@ -3392,9 +3466,10 @@ void sqlite3CreateIndex( for(j=0; jnKeyCol; j++){ int x = pPk->aiColumn[j]; assert( x>=0 ); - if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){ + if( isDupColumn(pIndex, pIndex->nKeyCol, pPk, j) ){ pIndex->nColumn--; }else{ + testcase( hasColumn(pIndex->aiColumn,pIndex->nKeyCol,x) ); pIndex->aiColumn[i] = x; pIndex->azColl[i] = pPk->azColl[j]; pIndex->aSortOrder[i] = pPk->aSortOrder[j]; diff --git a/src/ctime.c b/src/ctime.c index 27fc4fe..ebb6e85 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -14,7 +14,7 @@ ** SQLite was built with. */ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */ /* ** Include the configuration header output by 'configure' if we're using the diff --git a/src/date.c b/src/date.c index 313c7f9..e271210 100644 --- a/src/date.c +++ b/src/date.c @@ -388,7 +388,7 @@ static int parseDateOrTime( return 0; }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ return setDateTimeToCurrent(context, p); - }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ setRawDateNumber(p, r); return 0; } @@ -722,7 +722,7 @@ static int parseModifier( ** date is already on the appropriate weekday, this is a no-op. */ if( sqlite3_strnicmp(z, "weekday ", 8)==0 - && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 && (n=(int)r)==r && n>=0 && r<7 ){ sqlite3_int64 Z; computeYMD_HMS(p); @@ -781,7 +781,7 @@ static int parseModifier( double rRounder; int i; for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} - if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ + if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ rc = 1; break; } diff --git a/src/expr.c b/src/expr.c index 9a5e034..c4f201a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -44,8 +44,12 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){ */ char sqlite3ExprAffinity(Expr *pExpr){ int op; - pExpr = sqlite3ExprSkipCollate(pExpr); if( pExpr->flags & EP_Generic ) return 0; + while( ExprHasProperty(pExpr, EP_Skip) ){ + assert( pExpr->op==TK_COLLATE ); + pExpr = pExpr->pLeft; + assert( pExpr!=0 ); + } op = pExpr->op; if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); @@ -106,7 +110,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ ** or likelihood() function at the root of an expression. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ - while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ + while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( pExpr->x.pList->nExpr>0 ); @@ -773,7 +777,7 @@ Expr *sqlite3ExprAlloc( pNew->iAgg = -1; if( pToken ){ if( nExtra==0 ){ - pNew->flags |= EP_IntValue|EP_Leaf; + pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse); pNew->u.iValue = iValue; }else{ pNew->u.zToken = (char*)&pNew[1]; @@ -850,20 +854,16 @@ Expr *sqlite3PExpr( Expr *pRight /* Right operand */ ){ Expr *p; - if( op==TK_AND && pParse->nErr==0 && !IN_RENAME_OBJECT ){ - /* Take advantage of short-circuit false optimization for AND */ - p = sqlite3ExprAnd(pParse->db, pLeft, pRight); - }else{ - p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); - if( p ){ - memset(p, 0, sizeof(Expr)); - p->op = op & 0xff; - p->iAgg = -1; - } + p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); + if( p ){ + memset(p, 0, sizeof(Expr)); + p->op = op & 0xff; + p->iAgg = -1; sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); - } - if( p ) { sqlite3ExprCheckHeight(pParse, p->nHeight); + }else{ + sqlite3ExprDelete(pParse->db, pLeft); + sqlite3ExprDelete(pParse->db, pRight); } return p; } @@ -884,33 +884,6 @@ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){ } -/* -** If the expression is always either TRUE or FALSE (respectively), -** then return 1. If one cannot determine the truth value of the -** expression at compile-time return 0. -** -** This is an optimization. If is OK to return 0 here even if -** the expression really is always false or false (a false negative). -** But it is a bug to return 1 if the expression might have different -** boolean values in different circumstances (a false positive.) -** -** Note that if the expression is part of conditional for a -** LEFT JOIN, then we cannot determine at compile-time whether or not -** is it true or false, so always return 0. -*/ -static int exprAlwaysTrue(Expr *p){ - int v = 0; - if( ExprHasProperty(p, EP_FromJoin) ) return 0; - if( !sqlite3ExprIsInteger(p, &v) ) return 0; - return v!=0; -} -static int exprAlwaysFalse(Expr *p){ - int v = 0; - if( ExprHasProperty(p, EP_FromJoin) ) return 0; - if( !sqlite3ExprIsInteger(p, &v) ) return 0; - return v==0; -} - /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. @@ -919,19 +892,18 @@ static int exprAlwaysFalse(Expr *p){ ** of returning an AND expression, just return a constant expression with ** a value of false. */ -Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ - if( pLeft==0 ){ +Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ + sqlite3 *db = pParse->db; + if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; - }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); + }else if( ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight) ){ + sqlite3ExprUnmapAndDelete(pParse, pLeft); + sqlite3ExprUnmapAndDelete(pParse, pRight); return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); }else{ - Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); - sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); - return pNew; + return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); } } @@ -1088,6 +1060,18 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } +/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the +** expression. +*/ +void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){ + if( p ){ + if( IN_RENAME_OBJECT ){ + sqlite3RenameExprUnmap(pParse, p); + } + sqlite3ExprDeleteNN(pParse->db, p); + } +} + /* ** Return the number of bytes allocated for the expression structure ** passed as the first argument. This is always one of EXPR_FULLSIZE, @@ -1670,10 +1654,7 @@ ExprList *sqlite3ExprListAppendVector( } vector_append_error: - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprUnmap(pParse, pExpr); - } - sqlite3ExprDelete(db, pExpr); + sqlite3ExprUnmapAndDelete(pParse, pExpr); sqlite3IdListDelete(db, pColumns); return pList; } @@ -1821,6 +1802,7 @@ int sqlite3ExprIdToTrueFalse(Expr *pExpr){ || sqlite3StrICmp(pExpr->u.zToken, "false")==0) ){ pExpr->op = TK_TRUEFALSE; + ExprSetProperty(pExpr, pExpr->u.zToken[4]==0 ? EP_IsTrue : EP_IsFalse); return 1; } return 0; @@ -1831,12 +1813,40 @@ int sqlite3ExprIdToTrueFalse(Expr *pExpr){ ** and 0 if it is FALSE. */ int sqlite3ExprTruthValue(const Expr *pExpr){ + pExpr = sqlite3ExprSkipCollate((Expr*)pExpr); assert( pExpr->op==TK_TRUEFALSE ); assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); return pExpr->u.zToken[4]==0; } +/* +** If pExpr is an AND or OR expression, try to simplify it by eliminating +** terms that are always true or false. Return the simplified expression. +** Or return the original expression if no simplification is possible. +** +** Examples: +** +** (x<10) AND true => (x<10) +** (x<10) AND false => false +** (x<10) AND (y=22 OR false) => (x<10) AND (y=22) +** (x<10) AND (y=22 OR true) => (x<10) +** (y=22) OR true => true +*/ +Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ + assert( pExpr!=0 ); + if( pExpr->op==TK_AND || pExpr->op==TK_OR ){ + Expr *pRight = sqlite3ExprSimplifiedAndOr(pExpr->pRight); + Expr *pLeft = sqlite3ExprSimplifiedAndOr(pExpr->pLeft); + if( ExprAlwaysTrue(pLeft) || ExprAlwaysFalse(pRight) ){ + pExpr = pExpr->op==TK_AND ? pRight : pLeft; + }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){ + pExpr = pExpr->op==TK_AND ? pLeft : pRight; + } + } + return pExpr; +} + /* ** These routines are Walker callbacks used to check expressions to @@ -2081,7 +2091,7 @@ int sqlite3ExprContainsSubquery(Expr *p){ */ int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; - if( p==0 ) return 0; /* Can only happen following on OOM */ + if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */ /* If an expression is an integer literal that fits in a signed 32-bit ** integer, then the EP_IntValue flag will have already been set */ @@ -2810,6 +2820,7 @@ void sqlite3CodeRhsOfIN( */ if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce); + ExprClearProperty(pExpr, EP_Subrtn); addrOnce = 0; } @@ -3376,7 +3387,8 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ ** register iReg. The caller must ensure that iReg already contains ** the correct value for the expression. */ -static void exprToRegister(Expr *p, int iReg){ +static void exprToRegister(Expr *pExpr, int iReg){ + Expr *p = sqlite3ExprSkipCollate(pExpr); p->op2 = p->op; p->op = TK_REGISTER; p->iTable = iReg; @@ -4428,18 +4440,23 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ if( NEVER(pExpr==0) ) return; /* No way this can happen */ op = pExpr->op; switch( op ){ - case TK_AND: { - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - break; - } + case TK_AND: case TK_OR: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); + if( pAlt!=pExpr ){ + sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull); + }else if( op==TK_AND ){ + int d2 = sqlite3VdbeMakeLabel(pParse); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, + jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + }else{ + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + } break; } case TK_NOT: { @@ -4525,9 +4542,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ #endif default: { default_expr: - if( exprAlwaysTrue(pExpr) ){ + if( ExprAlwaysTrue(pExpr) ){ sqlite3VdbeGoto(v, dest); - }else if( exprAlwaysFalse(pExpr) ){ + }else if( ExprAlwaysFalse(pExpr) ){ /* No-op */ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); @@ -4595,18 +4612,23 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ - case TK_AND: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - break; - } + case TK_AND: case TK_OR: { - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); + Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); + if( pAlt!=pExpr ){ + sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull); + }else if( pExpr->op==TK_AND ){ + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + }else{ + int d2 = sqlite3VdbeMakeLabel(pParse); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, + jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + } break; } case TK_NOT: { @@ -4695,9 +4717,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ #endif default: { default_expr: - if( exprAlwaysFalse(pExpr) ){ + if( ExprAlwaysFalse(pExpr) ){ sqlite3VdbeGoto(v, dest); - }else if( exprAlwaysTrue(pExpr) ){ + }else if( ExprAlwaysTrue(pExpr) ){ /* no-op */ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); @@ -4853,6 +4875,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ && (combinedFlags & EP_Reduced)==0 ){ if( pA->iColumn!=pB->iColumn ) return 2; + if( pA->op2!=pB->op2 ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } @@ -4900,6 +4923,76 @@ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ iTab); } +/* +** Return non-zero if Expr p can only be true if pNN is not NULL. +*/ +static int exprImpliesNotNull( + Parse *pParse, /* Parsing context */ + Expr *p, /* The expression to be checked */ + Expr *pNN, /* The expression that is NOT NULL */ + int iTab, /* Table being evaluated */ + int seenNot /* True if p is an operand of NOT */ +){ + assert( p ); + assert( pNN ); + if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ) return 1; + switch( p->op ){ + case TK_IN: { + if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0; + assert( ExprHasProperty(p,EP_xIsSelect) + || (p->x.pList!=0 && p->x.pList->nExpr>0) ); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + } + case TK_BETWEEN: { + ExprList *pList = p->x.pList; + assert( pList!=0 ); + assert( pList->nExpr==2 ); + if( seenNot ) return 0; + if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, seenNot) + || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, seenNot) + ){ + return 1; + } + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + } + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_PLUS: + case TK_MINUS: + case TK_STAR: + case TK_REM: + case TK_BITAND: + case TK_BITOR: + case TK_SLASH: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: { + if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1; + /* Fall thru into the next case */ + } + case TK_SPAN: + case TK_COLLATE: + case TK_BITNOT: + case TK_UPLUS: + case TK_UMINUS: { + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + } + case TK_TRUTH: { + if( seenNot ) return 0; + if( p->op2!=TK_IS ) return 0; + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + } + case TK_NOT: { + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); + } + } + return 0; +} + /* ** Return true if we can prove the pE2 will always be true if pE1 is ** true. Return false if we cannot complete the proof or if pE2 might @@ -4935,10 +5028,10 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){ ){ return 1; } - if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ - Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); - testcase( pX!=pE1->pLeft ); - if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1; + if( pE2->op==TK_NOTNULL + && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0) + ){ + return 1; } return 0; } diff --git a/src/fkey.c b/src/fkey.c index 9633c41..14ee983 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -591,7 +591,7 @@ static void fkScanChildren( zCol = pFKey->pFrom->aCol[iCol].zName; pRight = sqlite3Expr(db, TK_ID, zCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); + pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); } /* If the child table is the same as the parent table, then add terms @@ -625,11 +625,11 @@ static void fkScanChildren( pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName); pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight); - pAll = sqlite3ExprAnd(db, pAll, pEq); + pAll = sqlite3ExprAnd(pParse, pAll, pEq); } pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); } - pWhere = sqlite3ExprAnd(db, pWhere, pNe); + pWhere = sqlite3ExprAnd(pParse, pWhere, pNe); } /* Resolve the references in the WHERE clause. */ @@ -1235,7 +1235,7 @@ static Trigger *fkActionTrigger( sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) ); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); + pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); /* For ON UPDATE, construct the next term of the WHEN clause. ** The final WHEN clause will be like this: @@ -1251,7 +1251,7 @@ static Trigger *fkActionTrigger( sqlite3ExprAlloc(db, TK_ID, &tNew, 0), sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) ); - pWhen = sqlite3ExprAnd(db, pWhen, pEq); + pWhen = sqlite3ExprAnd(pParse, pWhen, pEq); } if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ diff --git a/src/func.c b/src/func.c index 03595b7..5aea2d7 100644 --- a/src/func.c +++ b/src/func.c @@ -16,6 +16,7 @@ #include "sqliteInt.h" #include #include +#include #include "vdbeInt.h" /* @@ -386,10 +387,10 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ ** handle the rounding directly, ** otherwise use printf. */ - if( n==0 && r>=0 && r+4503599627370496.0 ){ + /* The value has no fractional part so there is nothing to round */ + }else if( n==0 ){ + r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); }else{ zBuf = sqlite3_mprintf("%.*f",n,r); if( zBuf==0 ){ @@ -843,8 +844,6 @@ static void likeFunc( return; } #endif - zB = sqlite3_value_text(argv[0]); - zA = sqlite3_value_text(argv[1]); /* Limit the length of the LIKE or GLOB pattern to avoid problems ** of deep recursion and N*N behavior in patternCompare(). @@ -856,8 +855,6 @@ static void likeFunc( sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); return; } - assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ - if( argc==3 ){ /* The escape character string must consist of a single UTF-8 character. ** Otherwise, return an error. @@ -873,6 +870,8 @@ static void likeFunc( }else{ escape = pInfo->matchSet; } + zB = sqlite3_value_text(argv[0]); + zA = sqlite3_value_text(argv[1]); if( zA && zB ){ #ifdef SQLITE_TEST sqlite3_like_count++; @@ -1798,39 +1797,24 @@ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ } /* -** Set the LIKEOPT flag on the 2-argument function with the given name. -*/ -static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ - FuncDef *pDef; - pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0); - if( ALWAYS(pDef) ){ - pDef->funcFlags |= flagVal; - } - pDef = sqlite3FindFunction(db, zName, 3, SQLITE_UTF8, 0); - if( pDef ){ - pDef->funcFlags |= flagVal; - } -} - -/* -** Register the built-in LIKE and GLOB functions. The caseSensitive +** Re-register the built-in LIKE functions. The caseSensitive ** parameter determines whether or not the LIKE operator is case -** sensitive. GLOB is always case sensitive. +** sensitive. */ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ struct compareInfo *pInfo; + int flags; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; + flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; + flags = SQLITE_FUNC_LIKE; } sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); - sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, - (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 0, 0); - setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); - setLikeOptFlag(db, "like", - caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); + sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags; + sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags; } /* diff --git a/src/global.c b/src/global.c index a78ea65..b512e6f 100644 --- a/src/global.c +++ b/src/global.c @@ -153,8 +153,15 @@ const unsigned char sqlite3CtypeMap[256] = { ** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if ** that compile-time option is omitted. */ -#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN +#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN) # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 +#else +# if !SQLITE_ALLOW_COVERING_INDEX_SCAN +# error "Compile-time disabling of covering index scan using the\ + -DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\ + Contact SQLite developers if this is a problem for you, and\ + delete this #error macro to continue with your build." +# endif #endif /* The minimum PMA size is set to this value multiplied by the database diff --git a/src/insert.c b/src/insert.c index ee63eed..2fe015f 100644 --- a/src/insert.c +++ b/src/insert.c @@ -814,7 +814,7 @@ void sqlite3Insert( int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); - aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); + aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+2)); if( aRegIdx==0 ){ goto insert_cleanup; } @@ -823,6 +823,7 @@ void sqlite3Insert( aRegIdx[i] = ++pParse->nMem; pParse->nMem += pIdx->nColumn; } + aRegIdx[i] = ++pParse->nMem; /* Register to store the table record */ } #ifndef SQLITE_OMIT_UPSERT if( pUpsert ){ @@ -1226,6 +1227,14 @@ int sqlite3ExprReferencesUpdatedColumn( ** the same as the order of indices on the linked list of indices ** at pTab->pIndex. ** +** (2019-05-07) The generated code also creates a new record for the +** main table, if pTab is a rowid table, and stores that record in the +** register identified by aRegIdx[nIdx] - in other words in the first +** entry of aRegIdx[] past the last index. It is important that the +** record be generated during constraint checks to avoid affinity changes +** to the register content that occur after constraint checks but before +** the new record is inserted. +** ** The caller must have already opened writeable cursors on the main ** table and all applicable indices (that is to say, all indices for which ** aRegIdx[] is not zero). iDataCur is the cursor for the main table when @@ -1416,7 +1425,7 @@ void sqlite3GenerateConstraintChecks( }else{ char *zName = pCheck->a[i].zName; if( zName==0 ) zName = pTab->zName; - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, onError, zName, P4_TRANSIENT, P5_ConstraintCheck); @@ -1845,6 +1854,16 @@ void sqlite3GenerateConstraintChecks( sqlite3VdbeJumpHere(v, ipkBottom); } + /* Generate the table record */ + if( HasRowid(pTab) ){ + int regRec = aRegIdx[ix]; + sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nCol, regRec); + sqlite3SetMakeRecordP5(v, pTab); + if( !bAffinityDone ){ + sqlite3TableAffinity(v, pTab, 0); + } + } + *pbMayReplace = seenReplace; VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); } @@ -1894,10 +1913,7 @@ void sqlite3CompleteInsertion( Vdbe *v; /* Prepared statements under construction */ Index *pIdx; /* An index being inserted or updated */ u8 pik_flags; /* flag values passed to the btree insert */ - int regData; /* Content registers (after the rowid) */ - int regRec; /* Register holding assembled record for the table */ int i; /* Loop counter */ - u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ assert( update_flags==0 || update_flags==OPFLAG_ISUPDATE @@ -1909,7 +1925,6 @@ void sqlite3CompleteInsertion( assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; - bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); @@ -1937,13 +1952,6 @@ void sqlite3CompleteInsertion( sqlite3VdbeChangeP5(v, pik_flags); } if( !HasRowid(pTab) ) return; - regData = regNewData + 1; - regRec = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - sqlite3SetMakeRecordP5(v, pTab); - if( !bAffinityDone ){ - sqlite3TableAffinity(v, pTab, 0); - } if( pParse->nested ){ pik_flags = 0; }else{ @@ -1956,7 +1964,7 @@ void sqlite3CompleteInsertion( if( useSeekResult ){ pik_flags |= OPFLAG_USESEEKRESULT; } - sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); + sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, aRegIdx[i], regNewData); if( !pParse->nested ){ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } diff --git a/src/main.c b/src/main.c index 24f7f20..6127006 100644 --- a/src/main.c +++ b/src/main.c @@ -845,6 +845,9 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| SQLITE_NoSchemaError }, + { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter }, + { SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL }, + { SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -875,28 +878,17 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ return rc; } - -/* -** Return true if the buffer z[0..n-1] contains all spaces. -*/ -static int allSpaces(const char *z, int n){ - while( n>0 && z[n-1]==' ' ){ n--; } - return n==0; -} - /* ** This is the default collating function named "BINARY" which is always ** available. -** -** If the padFlag argument is not NULL then space padding at the end -** of strings is ignored. This implements the RTRIM collation. */ static int binCollFunc( - void *padFlag, + void *NotUsed, int nKey1, const void *pKey1, int nKey2, const void *pKey2 ){ int rc, n; + UNUSED_PARAMETER(NotUsed); n = nKey1xCmp!=binCollFunc || p->pUser!=0 - || strcmp(p->zName,"BINARY")==0 ); - return p==0 || (p->xCmp==binCollFunc && p->pUser==0); + assert( p==0 || p->xCmp!=binCollFunc || strcmp(p->zName,"BINARY")==0 ); + return p==0 || p->xCmp==binCollFunc; } /* @@ -3077,7 +3073,35 @@ static int openDatabase( db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; db->nMaxSorterMmap = 0x7FFFFFFF; - db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill + db->flags |= SQLITE_ShortColNames + | SQLITE_EnableTrigger + | SQLITE_CacheSpill + +/* The SQLITE_DQS compile-time option determines the default settings +** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML. +** +** SQLITE_DQS SQLITE_DBCONFIG_DQS_DDL SQLITE_DBCONFIG_DQS_DML +** ---------- ----------------------- ----------------------- +** undefined on on +** 3 on on +** 2 on off +** 1 off on +** 0 off off +** +** Legacy behavior is 3 (double-quoted string literals are allowed anywhere) +** and so that is the default. But developers are encouranged to use +** -DSQLITE_DQS=0 (best) or -DSQLITE_DQS=1 (second choice) if possible. +*/ +#if !defined(SQLITE_DQS) +# define SQLITE_DQS 3 +#endif +#if (SQLITE_DQS&1)==1 + | SQLITE_DqsDML +#endif +#if (SQLITE_DQS&2)==2 + | SQLITE_DqsDDL +#endif + #if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX | SQLITE_AutoIndex #endif @@ -3128,7 +3152,7 @@ static int openDatabase( createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0); createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0); createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); - createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); + createCollation(db, "RTRIM", SQLITE_UTF8, 0, rtrimCollFunc, 0); if( db->mallocFailed ){ goto opendb_out; } @@ -4104,6 +4128,22 @@ int sqlite3_test_control(int op, ...){ break; } #endif /* defined(YYCOVERAGE) */ + + /* sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, sqlite3_context*); + ** + ** This test-control causes the most recent sqlite3_result_int64() value + ** to be interpreted as a MEM_IntReal instead of as an MEM_Int. Normally, + ** MEM_IntReal values only arise during an INSERT operation of integer + ** values into a REAL column, so they can be challenging to test. This + ** test-control enables us to write an intreal() SQL function that can + ** inject an intreal() value at arbitrary places in an SQL statement, + ** for testing purposes. + */ + case SQLITE_TESTCTRL_RESULT_INTREAL: { + sqlite3_context *pCtx = va_arg(ap, sqlite3_context*); + sqlite3ResultIntReal(pCtx); + break; + } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ diff --git a/src/msvc.h b/src/msvc.h index 3914b05..f174227 100644 --- a/src/msvc.h +++ b/src/msvc.h @@ -33,4 +33,9 @@ #pragma warning(disable : 4706) #endif /* defined(_MSC_VER) */ +#if defined(_MSC_VER) && !defined(_WIN64) +#undef SQLITE_4_BYTE_ALIGNED_MALLOC +#define SQLITE_4_BYTE_ALIGNED_MALLOC +#endif /* defined(_MSC_VER) && !defined(_WIN64) */ + #endif /* SQLITE_MSVC_H */ diff --git a/src/parse.y b/src/parse.y index beb4eeb..fc5bff1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -301,6 +301,10 @@ scanpt(A) ::= . { assert( yyLookahead!=YYNOCODE ); A = yyLookaheadToken.z; } +scantok(A) ::= . { + assert( yyLookahead!=YYNOCODE ); + A = yyLookaheadToken; +} // "carglist" is a list of additional constraints that come after the // column name and column type in a CREATE TABLE statement. @@ -308,17 +312,17 @@ scanpt(A) ::= . { carglist ::= carglist ccons. carglist ::= . ccons ::= CONSTRAINT nm(X). {pParse->constraintName = X;} -ccons ::= DEFAULT scanpt(A) term(X) scanpt(Z). - {sqlite3AddDefaultValue(pParse,X,A,Z);} +ccons ::= DEFAULT scantok(A) term(X). + {sqlite3AddDefaultValue(pParse,X,A.z,&A.z[A.n]);} ccons ::= DEFAULT LP(A) expr(X) RP(Z). {sqlite3AddDefaultValue(pParse,X,A.z+1,Z.z);} -ccons ::= DEFAULT PLUS(A) term(X) scanpt(Z). - {sqlite3AddDefaultValue(pParse,X,A.z,Z);} -ccons ::= DEFAULT MINUS(A) term(X) scanpt(Z). { +ccons ::= DEFAULT PLUS(A) scantok(Z) term(X). + {sqlite3AddDefaultValue(pParse,X,A.z,&Z.z[Z.n]);} +ccons ::= DEFAULT MINUS(A) scantok(Z) term(X). { Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0); - sqlite3AddDefaultValue(pParse,p,A.z,Z); + sqlite3AddDefaultValue(pParse,p,A.z,&Z.z[Z.n]); } -ccons ::= DEFAULT scanpt id(X). { +ccons ::= DEFAULT scantok id(X). { Expr *p = tokenExpr(pParse, TK_STRING, X); if( p ){ sqlite3ExprIdToTrueFalse(p); @@ -1064,7 +1068,7 @@ expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. { } } -expr(A) ::= expr(A) AND(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} +expr(A) ::= expr(A) AND expr(Y). {A=sqlite3ExprAnd(pParse,A,Y);} expr(A) ::= expr(A) OR(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} @@ -1169,10 +1173,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - if( IN_RENAME_OBJECT==0 ){ - sqlite3ExprDelete(pParse->db, A); - A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); - } + sqlite3ExprUnmapAndDelete(pParse, A); + A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); }else if( Y->nExpr==1 ){ /* Expressions of the form: ** diff --git a/src/pcache.c b/src/pcache.c index 8311049..9125d5d 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -243,9 +243,10 @@ static int numberOfCachePages(PCache *p){ ** suggested cache size is set to N. */ return p->szCache; }else{ - /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then - ** the number of cache pages is adjusted to use approximately abs(N*1024) - ** bytes of memory. */ + /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the + ** number of cache pages is adjusted to be a number of pages that would + ** use approximately abs(N*1024) bytes of memory based on the current + ** page size. */ return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); } } diff --git a/src/pcache1.c b/src/pcache1.c index ff01ae3..c9d5586 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -778,6 +778,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ }else{ pGroup = &pcache1.grp; } + pcache1EnterMutex(pGroup); if( pGroup->lru.isAnchor==0 ){ pGroup->lru.isAnchor = 1; pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru; @@ -787,7 +788,6 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ pCache->szExtra = szExtra; pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); pCache->bPurgeable = (bPurgeable ? 1 : 0); - pcache1EnterMutex(pGroup); pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; diff --git a/src/pragma.c b/src/pragma.c index 1dcd214..a62fc99 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -644,6 +644,11 @@ void sqlite3Pragma( ** then do a query */ eMode = PAGER_JOURNALMODE_QUERY; } + if( eMode==PAGER_JOURNALMODE_OFF && (db->flags & SQLITE_Defensive)!=0 ){ + /* Do not allow journal-mode "OFF" in defensive since the database + ** can become corrupted using ordinary SQL when the journal is off */ + eMode = PAGER_JOURNALMODE_QUERY; + } } if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ @@ -1421,6 +1426,7 @@ void sqlite3Pragma( #endif /* !defined(SQLITE_OMIT_TRIGGER) */ #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ +#ifndef SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA /* Reinstall the LIKE and GLOB functions. The variant of LIKE ** used will be case sensitive or not depending on the RHS. */ @@ -1430,6 +1436,7 @@ void sqlite3Pragma( } } break; +#endif /* SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA */ #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 @@ -2123,28 +2130,30 @@ void sqlite3Pragma( */ case PragTyp_KEY: { if( zRight ){ - int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1; - if( (pPragma->iArg & 1)==0 ){ - sqlite3_key_v2(db, zDb, zRight, n); + char zBuf[40]; + const char *zKey = zRight; + int n; + if( pPragma->iArg==2 || pPragma->iArg==3 ){ + u8 iByte; + int i; + for(i=0, iByte=0; iiArg<4 ? sqlite3Strlen30(zRight) : -1; } if( (pPragma->iArg & 1)==0 ){ - sqlite3_key_v2(db, zDb, zKey, i/2); + rc = sqlite3_key_v2(db, zDb, zKey, n); }else{ - sqlite3_rekey_v2(db, zDb, zKey, i/2); + rc = sqlite3_rekey_v2(db, zDb, zKey, n); + } + if( rc==SQLITE_OK && n!=0 ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "ok", SQLITE_STATIC); + returnSingleText(v, "ok"); } } break; diff --git a/src/pragma.h b/src/pragma.h index c156e3a..11e55ee 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -46,10 +46,9 @@ #define PragTyp_WAL_AUTOCHECKPOINT 38 #define PragTyp_WAL_CHECKPOINT 39 #define PragTyp_ACTIVATE_EXTENSIONS 40 -#define PragTyp_HEXKEY 41 -#define PragTyp_KEY 42 -#define PragTyp_LOCK_STATUS 43 -#define PragTyp_STATS 44 +#define PragTyp_KEY 41 +#define PragTyp_LOCK_STATUS 42 +#define PragTyp_STATS 43 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -178,11 +177,13 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA) {/* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, /* ePragFlg: */ PragFlg_NoColumns, /* ColNames: */ 0, 0, /* iArg: */ 0 }, +#endif {/* zName: */ "cell_size_check", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -320,12 +321,12 @@ static const PragmaName aPragmaName[] = { #endif #if defined(SQLITE_HAS_CODEC) {/* zName: */ "hexkey", - /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragTyp: */ PragTyp_KEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, /* iArg: */ 2 }, {/* zName: */ "hexrekey", - /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragTyp: */ PragTyp_KEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, /* iArg: */ 3 }, diff --git a/src/printf.c b/src/printf.c index 0f66bc2..fc77f68 100644 --- a/src/printf.c +++ b/src/printf.c @@ -99,6 +99,12 @@ static const et_info fmtinfo[] = { { 'r', 10, 1, etORDINAL, 0, 0 }, }; +/* 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, + 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10, +}; + /* ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point ** conversions will work. @@ -517,8 +523,18 @@ void sqlite3_str_vappendf( } if( xtype==etGENERIC && precision>0 ) precision--; testcase( precision>0xfff ); - for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} - if( xtype==etFLOAT ) realvalue += rounder; + idx = precision & 0xfff; + rounder = arRound[idx%10]; + while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; } + if( xtype==etFLOAT ){ + double rx = (double)realvalue; + sqlite3_uint64 u; + int ex; + memcpy(&u, &rx, sizeof(u)); + ex = -1023 + (int)((u>>52)&0x7ff); + if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16; + realvalue += rounder; + } /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; if( sqlite3IsNaN((double)realvalue) ){ diff --git a/src/resolve.c b/src/resolve.c index 50755e5..8dac077 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -148,6 +148,23 @@ int sqlite3MatchSpanName( return 1; } +/* +** Return TRUE if the double-quoted string mis-feature should be supported. +*/ +static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){ + if( db->init.busy ) return 1; /* Always support for legacy schemas */ + if( pTopNC->ncFlags & NC_IsDDL ){ + /* Currently parsing a DDL statement */ + if( sqlite3WritableSchema(db) && (db->flags & SQLITE_DqsDML)!=0 ){ + return 1; + } + return (db->flags & SQLITE_DqsDDL)!=0; + }else{ + /* Currently parsing a DML statement */ + return (db->flags & SQLITE_DqsDML)!=0; + } +} + /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr @@ -476,7 +493,9 @@ static int lookupName( */ if( cnt==0 && zTab==0 ){ assert( pExpr->op==TK_ID ); - if( ExprHasProperty(pExpr,EP_DblQuoted) ){ + if( ExprHasProperty(pExpr,EP_DblQuoted) + && areDoubleQuotedStringsEnabled(db, pTopNC) + ){ /* If a double-quoted identifier does not match any known column name, ** then treat it as a string. ** @@ -745,7 +764,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ }else{ is_agg = pDef->xFinalize!=0; if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ - ExprSetProperty(pExpr, EP_Unlikely|EP_Skip); + ExprSetProperty(pExpr, EP_Unlikely); if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ @@ -866,7 +885,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #ifndef SQLITE_OMIT_WINDOWFUNC if( pExpr->y.pWin ){ Select *pSel = pNC->pWinSelect; - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); + if( IN_RENAME_OBJECT==0 ){ + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); + } sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); @@ -926,11 +947,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } case TK_IS: case TK_ISNOT: { - Expr *pRight; + Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); 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 = pExpr->pRight)->op==TK_ID ){ + if( pRight->op==TK_ID ){ int rc = resolveExprStep(pWalker, pRight); if( rc==WRC_Abort ) return WRC_Abort; if( pRight->op==TK_TRUEFALSE ){ @@ -1652,7 +1673,7 @@ int sqlite3ResolveExprNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ - u16 savedHasAgg; + int savedHasAgg; Walker w; if( pExpr==0 ) return SQLITE_OK; @@ -1766,7 +1787,7 @@ int sqlite3ResolveSelfReference( } sNC.pParse = pParse; sNC.pSrcList = &sSrc; - sNC.ncFlags = type; + sNC.ncFlags = type | NC_IsDDL; if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc; if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList); return rc; diff --git a/src/select.c b/src/select.c index 7d8a425..53d33a7 100644 --- a/src/select.c +++ b/src/select.c @@ -355,7 +355,7 @@ static void addWhereTerm( ExprSetVVAProperty(pEq, EP_NoReduce); pEq->iRightJoinTable = (i16)pE2->iTable; } - *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq); + *ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq); } /* @@ -489,7 +489,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ */ if( pRight->pOn ){ if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor); - p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); + p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn); pRight->pOn = 0; } @@ -2096,9 +2096,6 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ if( pTab==0 ){ return 0; } - /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside - ** is disabled */ - assert( db->lookaside.bDisable ); pTab->nTabRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); @@ -2540,6 +2537,7 @@ static int multiSelect( */ assert( p && p->pPrior ); /* Calling function guarantees this much */ assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION ); + assert( p->selFlags & SF_Compound ); db = pParse->db; pPrior = p->pPrior; dest = *pDest; @@ -4034,7 +4032,7 @@ static int flattenSubquery( if( isLeftJoin>0 ){ setJoinExpr(pWhere, iNewParent); } - pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); + pParent->pWhere = sqlite3ExprAnd(pParse, pWhere, pParent->pWhere); if( db->mallocFailed==0 ){ SubstContext x; x.pParse = pParse; @@ -4045,10 +4043,10 @@ static int flattenSubquery( substSelect(&x, pParent, 0); } - /* The flattened query is distinct if either the inner or the - ** outer query is distinct. - */ - pParent->selFlags |= pSub->selFlags & SF_Distinct; + /* The flattened query is a compound if either the inner or the + ** outer query is a compound. */ + pParent->selFlags |= pSub->selFlags & SF_Compound; + assert( (pSub->selFlags & SF_Distinct)==0 ); /* restriction (17b) */ /* ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; @@ -4369,9 +4367,9 @@ static int pushDownWhereTerms( x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); if( pSubq->selFlags & SF_Aggregate ){ - pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew); + pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew); }else{ - pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); + pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew); } pSubq = pSubq->pPrior; } @@ -4797,7 +4795,7 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral; - return SQLITE_OK; + return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; } /* @@ -4843,6 +4841,10 @@ static int selectExpander(Walker *pWalker, Select *p){ if( (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } + if( pWalker->eCode ){ + /* Renumber selId because it has been copied from a view */ + p->selId = ++pParse->nSelect; + } pTabList = p->pSrc; pEList = p->pEList; sqlite3WithPush(pParse, p->pWith, 0); @@ -4892,12 +4894,15 @@ static int selectExpander(Walker *pWalker, Select *p){ #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( IsVirtual(pTab) || pTab->pSelect ){ i16 nCol; + u8 eCodeOrig = pWalker->eCode; if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); nCol = pTab->nCol; pTab->nCol = -1; + pWalker->eCode = 1; /* Turn on Select.selId renumbering */ sqlite3WalkSelect(pWalker, pFrom->pSelect); + pWalker->eCode = eCodeOrig; pTab->nCol = nCol; } #endif @@ -5147,6 +5152,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ } w.xSelectCallback = selectExpander; w.xSelectCallback2 = selectPopWith; + w.eCode = 0; sqlite3WalkSelect(&w, pSelect); } @@ -5418,7 +5424,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); - pNew = sqlite3ExprAnd(db, pWhere, pNew); + pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew); pS->pWhere = pNew; pWalker->eCode = 1; } @@ -5473,15 +5479,19 @@ static struct SrcList_item *isSelfJoinView( if( pItem->pSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; if( pItem->zName==0 ) continue; - if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue; + assert( pItem->pTab!=0 ); + assert( pThis->pTab!=0 ); + if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue; if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue; pS1 = pItem->pSelect; - if( pThis->pSelect->selId!=pS1->selId ){ + if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){ /* The query flattener left two different CTE tables with identical ** names in the same FROM clause. */ continue; } - if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){ + if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) + || sqlite3ExprCompare(0, pThis->pSelect->pHaving, pS1->pHaving, -1) + ){ /* The view was modified by some other optimization such as ** pushDownWhereTerms() */ continue; @@ -5506,7 +5516,8 @@ static struct SrcList_item *isSelfJoinView( ** * The subquery is a UNION ALL of two or more terms ** * The subquery does not have a LIMIT clause ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries -** * The outer query is a simple count(*) +** * The outer query is a simple count(*) with no WHERE clause or other +** extraneous syntax. ** ** Return TRUE if the optimization is undertaken. */ @@ -5517,6 +5528,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ sqlite3 *db; if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ + if( p->pWhere ) return 0; + if( p->pGroupBy ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ diff --git a/src/shell.c.in b/src/shell.c.in index d8c57b4..f3edee2 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -948,6 +948,10 @@ INCLUDE ../ext/misc/sqlar.c INCLUDE ../ext/expert/sqlite3expert.h INCLUDE ../ext/expert/sqlite3expert.c +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) +INCLUDE ../ext/misc/dbdata.c +#endif + #if defined(SQLITE_ENABLE_SESSION) /* ** State information for a single open session @@ -1677,6 +1681,8 @@ static int shellAuth( ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements. */ static void printSchemaLine(FILE *out, const char *z, const char *zTail){ + if( z==0 ) return; + if( zTail==0 ) return; if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); }else{ @@ -3489,7 +3495,7 @@ static const char *(azHelp[]) = { " Options:", " --preserve-rowids Include ROWID values in the output", " --newlines Allow unescaped newline characters in output", - " TABLE is LIKE pattern for the tables to dump", + " TABLE is a LIKE pattern for the tables to dump", ".echo on|off Turn command echo on or off", ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", " Other Modes:", @@ -3504,6 +3510,8 @@ static const char *(azHelp[]) = { /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ /*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ + ".filectrl CMD ... Run various sqlite3_file_control() operations", + " Run \".filectrl\" with no arguments for details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", @@ -3574,6 +3582,9 @@ static const char *(azHelp[]) = { ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", ".read FILE Read input from FILE", +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) + ".recover Recover as much data as possible from corrupt db.", +#endif ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ".save FILE Write in-memory database into FILE", ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", @@ -3618,6 +3629,8 @@ static const char *(azHelp[]) = { #endif ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", ".testcase NAME Begin redirecting output to 'testcase-out.txt'", + ".testctrl CMD ... Run various sqlite3_test_control() operations", + " Run \".testctrl\" with no arguments for details", ".timeout MS Try opening locked tables for MS milliseconds", ".timer on|off Turn SQL timer on or off", #ifndef SQLITE_OMIT_TRACE @@ -3858,7 +3871,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){ int j, k; int rc; FILE *in; - unsigned char x[16]; + unsigned int x[16]; char zLine[1000]; if( p->zDbFilename ){ in = fopen(p->zDbFilename, "r"); @@ -3870,14 +3883,15 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){ }else{ in = p->in; nLine = p->lineno; + if( in==0 ) in = stdin; } *pnData = 0; nLine++; if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); if( rc!=2 ) goto readHexDb_error; - if( n<=0 ) goto readHexDb_error; - a = sqlite3_malloc( n ); + if( n<0 ) goto readHexDb_error; + a = sqlite3_malloc( n ? n : 1 ); if( a==0 ){ utf8_printf(stderr, "Out of memory!\n"); goto readHexDb_error; @@ -3896,14 +3910,14 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){ if( strncmp(zLine, "| end ", 6)==0 ){ break; } - rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx" - " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx", + rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]); if( rc==17 ){ k = iOffset+j; if( k+16<=n ){ - memcpy(a+k, x, 16); + int ii; + for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff; } } } @@ -3916,7 +3930,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){ return a; readHexDb_error: - if( in!=stdin ){ + if( in!=p->in ){ fclose(in); }else{ while( fgets(zLine, sizeof(zLine), p->in)!=0 ){ @@ -3931,6 +3945,127 @@ readHexDb_error: } #endif /* SQLITE_ENABLE_DESERIALIZE */ +/* +** Scalar function "shell_int32". The first argument to this function +** must be a blob. The second a non-negative integer. This function +** reads and returns a 32-bit big-endian integer from byte +** offset (4*) of the blob. +*/ +static void shellInt32( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *pBlob; + int nBlob; + int iInt; + + UNUSED_PARAMETER(argc); + nBlob = sqlite3_value_bytes(argv[0]); + pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]); + iInt = sqlite3_value_int(argv[1]); + + if( iInt>=0 && (iInt+1)*4<=nBlob ){ + const unsigned char *a = &pBlob[iInt*4]; + sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24) + + ((sqlite3_int64)a[1]<<16) + + ((sqlite3_int64)a[2]<< 8) + + ((sqlite3_int64)a[3]<< 0); + sqlite3_result_int64(context, iVal); + } +} + +/* +** Scalar function "shell_escape_crnl" used by the .recover command. +** The argument passed to this function is the output of built-in +** function quote(). If the first character of the input is "'", +** indicating that the value passed to quote() was a text value, +** then this function searches the input for "\n" and "\r" characters +** and adds a wrapper similar to the following: +** +** replace(replace(, '\n', char(10), '\r', char(13)); +** +** Or, if the first character of the input is not "'", then a copy +** of the input is returned. +*/ +static void shellEscapeCrnl( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zText = (const char*)sqlite3_value_text(argv[0]); + UNUSED_PARAMETER(argc); + if( zText[0]=='\'' ){ + int nText = sqlite3_value_bytes(argv[0]); + int i; + char zBuf1[20]; + char zBuf2[20]; + const char *zNL = 0; + const char *zCR = 0; + int nCR = 0; + int nNL = 0; + + for(i=0; zText[i]; i++){ + if( zNL==0 && zText[i]=='\n' ){ + zNL = unused_string(zText, "\\n", "\\012", zBuf1); + nNL = (int)strlen(zNL); + } + if( zCR==0 && zText[i]=='\r' ){ + zCR = unused_string(zText, "\\r", "\\015", zBuf2); + nCR = (int)strlen(zCR); + } + } + + if( zNL || zCR ){ + int iOut = 0; + i64 nMax = (nNL > nCR) ? nNL : nCR; + i64 nAlloc = nMax * nText + (nMax+64)*2; + char *zOut = (char*)sqlite3_malloc64(nAlloc); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + return; + } + + if( zNL && zCR ){ + memcpy(&zOut[iOut], "replace(replace(", 16); + iOut += 16; + }else{ + memcpy(&zOut[iOut], "replace(", 8); + iOut += 8; + } + for(i=0; zText[i]; i++){ + if( zText[i]=='\n' ){ + memcpy(&zOut[iOut], zNL, nNL); + iOut += nNL; + }else if( zText[i]=='\r' ){ + memcpy(&zOut[iOut], zCR, nCR); + iOut += nCR; + }else{ + zOut[iOut] = zText[i]; + iOut++; + } + } + + if( zNL ){ + memcpy(&zOut[iOut], ",'", 2); iOut += 2; + memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; + memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12; + } + if( zCR ){ + memcpy(&zOut[iOut], ",'", 2); iOut += 2; + memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; + memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12; + } + + sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT); + sqlite3_free(zOut); + return; + } + } + + sqlite3_result_value(context, argv[0]); +} + /* Flags for open_db(). ** ** The default behavior of open_db() is to exit(1) if the database fails to @@ -3999,6 +4134,9 @@ static void open_db(ShellState *p, int openFlags){ sqlite3_fileio_init(p->db, 0, 0); sqlite3_shathree_init(p->db, 0, 0); sqlite3_completion_init(p->db, 0, 0); +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) + sqlite3_dbdata_init(p->db, 0, 0); +#endif #ifdef SQLITE_HAVE_ZLIB sqlite3_zipfile_init(p->db, 0, 0); sqlite3_sqlar_init(p->db, 0, 0); @@ -4009,6 +4147,10 @@ static void open_db(ShellState *p, int openFlags){ shellModuleSchema, 0, 0); sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, shellPutsFunc, 0, 0); + sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0, + shellEscapeCrnl, 0, 0); + sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, + shellInt32, 0, 0); #ifndef SQLITE_NOHAVE_SYSTEM sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); @@ -4032,7 +4174,6 @@ static void open_db(ShellState *p, int openFlags){ }else{ aData = readHexDb(p, &nData); if( aData==0 ){ - utf8_printf(stderr, "Error in hexdb input\n"); return; } } @@ -4712,6 +4853,7 @@ static void output_reset(ShellState *p){ sqlite3_free(zCmd); outputModePop(p); p->doXdgOpen = 0; + sqlite3_sleep(100); } #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ } @@ -5263,10 +5405,7 @@ static int lintDotCommand( return SQLITE_ERROR; } -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) -/********************************************************************************* -** The ".archive" or ".ar" command. -*/ +#if !defined SQLITE_OMIT_VIRTUALTABLE static void shellPrepare( sqlite3 *db, int *pRc, @@ -5285,7 +5424,14 @@ static void shellPrepare( } } -static void shellPreparePrintf( +/* +** Create a prepared statement using printf-style arguments for the SQL. +** +** This routine is could be marked "static". But it is not always used, +** depending on compile-time options. By omitting the "static", we avoid +** nuisance compiler warnings about "defined but not used". +*/ +void shellPreparePrintf( sqlite3 *db, int *pRc, sqlite3_stmt **ppStmt, @@ -5308,7 +5454,13 @@ static void shellPreparePrintf( } } -static void shellFinalize( +/* Finalize the prepared statement created using shellPreparePrintf(). +** +** This routine is could be marked "static". But it is not always used, +** depending on compile-time options. By omitting the "static", we avoid +** nuisance compiler warnings about "defined but not used". +*/ +void shellFinalize( int *pRc, sqlite3_stmt *pStmt ){ @@ -5324,7 +5476,13 @@ static void shellFinalize( } } -static void shellReset( +/* Reset the prepared statement created using shellPreparePrintf(). +** +** This routine is could be marked "static". But it is not always used, +** depending on compile-time options. By omitting the "static", we avoid +** nuisance compiler warnings about "defined but not used". +*/ +void shellReset( int *pRc, sqlite3_stmt *pStmt ){ @@ -5337,6 +5495,12 @@ static void shellReset( *pRc = rc; } } +#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ + +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) +/********************************************************************************* +** The ".archive" or ".ar" command. +*/ /* ** Structure representing a single ".ar" command. */ @@ -6026,6 +6190,635 @@ end_ar_command: **********************************************************************************/ #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) +/* +** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op. +** Otherwise, the SQL statement or statements in zSql are executed using +** database connection db and the error code written to *pRc before +** this function returns. +*/ +static void shellExec(sqlite3 *db, int *pRc, const char *zSql){ + int rc = *pRc; + if( rc==SQLITE_OK ){ + char *zErr = 0; + rc = sqlite3_exec(db, zSql, 0, 0, &zErr); + if( rc!=SQLITE_OK ){ + raw_printf(stderr, "SQL error: %s\n", zErr); + } + *pRc = rc; + } +} + +/* +** Like shellExec(), except that zFmt is a printf() style format string. +*/ +static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){ + char *z = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + shellExec(db, pRc, z); + } + sqlite3_free(z); + } +} + +/* +** If *pRc is not SQLITE_OK when this function is called, it is a no-op. +** Otherwise, an attempt is made to allocate, zero and return a pointer +** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set +** to SQLITE_NOMEM and NULL returned. +*/ +static void *shellMalloc(int *pRc, sqlite3_int64 nByte){ + void *pRet = 0; + if( *pRc==SQLITE_OK ){ + pRet = sqlite3_malloc64(nByte); + if( pRet==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + memset(pRet, 0, nByte); + } + } + return pRet; +} + +/* +** If *pRc is not SQLITE_OK when this function is called, it is a no-op. +** Otherwise, zFmt is treated as a printf() style string. The result of +** formatting it along with any trailing arguments is written into a +** buffer obtained from sqlite3_malloc(), and pointer to which is returned. +** It is the responsibility of the caller to eventually free this buffer +** using a call to sqlite3_free(). +** +** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL +** pointer returned. +*/ +static char *shellMPrintf(int *pRc, const char *zFmt, ...){ + char *z = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; + } + } + return z; +} + +/* +** When running the ".recover" command, each output table, and the special +** orphaned row table if it is required, is represented by an instance +** of the following struct. +*/ +typedef struct RecoverTable RecoverTable; +struct RecoverTable { + char *zQuoted; /* Quoted version of table name */ + int nCol; /* Number of columns in table */ + char **azlCol; /* Array of column lists */ + int iPk; /* Index of IPK column */ +}; + +/* +** Free a RecoverTable object allocated by recoverFindTable() or +** recoverOrphanTable(). +*/ +static void recoverFreeTable(RecoverTable *pTab){ + if( pTab ){ + sqlite3_free(pTab->zQuoted); + if( pTab->azlCol ){ + int i; + for(i=0; i<=pTab->nCol; i++){ + sqlite3_free(pTab->azlCol[i]); + } + sqlite3_free(pTab->azlCol); + } + sqlite3_free(pTab); + } +} + +/* +** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. +** Otherwise, it allocates and returns a RecoverTable object based on the +** final four arguments passed to this function. It is the responsibility +** of the caller to eventually free the returned object using +** recoverFreeTable(). +*/ +static RecoverTable *recoverNewTable( + int *pRc, /* IN/OUT: Error code */ + const char *zName, /* Name of table */ + const char *zSql, /* CREATE TABLE statement */ + int bIntkey, + int nCol +){ + sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */ + int rc = *pRc; + RecoverTable *pTab = 0; + + pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable)); + if( rc==SQLITE_OK ){ + int nSqlCol = 0; + int bSqlIntkey = 0; + sqlite3_stmt *pStmt = 0; + + rc = sqlite3_open("", &dbtmp); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0); + if( rc==SQLITE_ERROR ){ + rc = SQLITE_OK; + goto finished; + } + } + shellPreparePrintf(dbtmp, &rc, &pStmt, + "SELECT count(*) FROM pragma_table_info(%Q)", zName + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + nSqlCol = sqlite3_column_int(pStmt, 0); + } + shellFinalize(&rc, pStmt); + + if( rc!=SQLITE_OK || nSqlColiPk to the index + ** of the column, where columns are 0-numbered from left to right. + ** Or, if this is a WITHOUT ROWID table or if there is no IPK column, + ** leave zPk as "_rowid_" and pTab->iPk at -2. */ + pTab->iPk = -2; + if( bIntkey ){ + shellPreparePrintf(dbtmp, &rc, &pPkFinder, + "SELECT cid, name FROM pragma_table_info(%Q) " + " WHERE pk=1 AND type='integer' COLLATE nocase" + " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)" + , zName, zName + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){ + pTab->iPk = sqlite3_column_int(pPkFinder, 0); + zPk = (const char*)sqlite3_column_text(pPkFinder, 1); + } + } + + pTab->zQuoted = shellMPrintf(&rc, "%Q", zName); + pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1)); + pTab->nCol = nSqlCol; + + if( bIntkey ){ + pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk); + }else{ + pTab->azlCol[0] = shellMPrintf(&rc, ""); + } + i = 1; + shellPreparePrintf(dbtmp, &rc, &pStmt, + "SELECT %Q || group_concat(name, ', ') " + " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) " + "FROM pragma_table_info(%Q)", + bIntkey ? ", " : "", pTab->iPk, + bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ", + zName + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zText = (const char*)sqlite3_column_text(pStmt, 0); + pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText); + i++; + } + shellFinalize(&rc, pStmt); + + shellFinalize(&rc, pPkFinder); + } + } + + finished: + sqlite3_close(dbtmp); + *pRc = rc; + if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){ + recoverFreeTable(pTab); + pTab = 0; + } + return pTab; +} + +/* +** This function is called to search the schema recovered from the +** sqlite_master table of the (possibly) corrupt database as part +** of a ".recover" command. Specifically, for a table with root page +** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the +** table must be a WITHOUT ROWID table, or if non-zero, not one of +** those. +** +** If a table is found, a (RecoverTable*) object is returned. Or, if +** no such table is found, but bIntkey is false and iRoot is the +** root page of an index in the recovered schema, then (*pbNoop) is +** set to true and NULL returned. Or, if there is no such table or +** index, NULL is returned and (*pbNoop) set to 0, indicating that +** the caller should write data to the orphans table. +*/ +static RecoverTable *recoverFindTable( + ShellState *pState, /* Shell state object */ + int *pRc, /* IN/OUT: Error code */ + int iRoot, /* Root page of table */ + int bIntkey, /* True for an intkey table */ + int nCol, /* Number of columns in table */ + int *pbNoop /* OUT: True if iRoot is root of index */ +){ + sqlite3_stmt *pStmt = 0; + RecoverTable *pRet = 0; + int bNoop = 0; + const char *zSql = 0; + const char *zName = 0; + + /* Search the recovered schema for an object with root page iRoot. */ + shellPreparePrintf(pState->db, pRc, &pStmt, + "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot + ); + while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zType = (const char*)sqlite3_column_text(pStmt, 0); + if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){ + bNoop = 1; + break; + } + if( sqlite3_stricmp(zType, "table")==0 ){ + zName = (const char*)sqlite3_column_text(pStmt, 1); + zSql = (const char*)sqlite3_column_text(pStmt, 2); + pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol); + break; + } + } + + shellFinalize(pRc, pStmt); + *pbNoop = bNoop; + return pRet; +} + +/* +** Return a RecoverTable object representing the orphans table. +*/ +static RecoverTable *recoverOrphanTable( + ShellState *pState, /* Shell state object */ + int *pRc, /* IN/OUT: Error code */ + const char *zLostAndFound, /* Base name for orphans table */ + int nCol /* Number of user data columns */ +){ + RecoverTable *pTab = 0; + if( nCol>=0 && *pRc==SQLITE_OK ){ + int i; + + /* This block determines the name of the orphan table. The prefered + ** name is zLostAndFound. But if that clashes with another name + ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1 + ** and so on until a non-clashing name is found. */ + int iTab = 0; + char *zTab = shellMPrintf(pRc, "%s", zLostAndFound); + sqlite3_stmt *pTest = 0; + shellPrepare(pState->db, pRc, + "SELECT 1 FROM recovery.schema WHERE name=?", &pTest + ); + if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); + while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){ + shellReset(pRc, pTest); + sqlite3_free(zTab); + zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++); + sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); + } + shellFinalize(pRc, pTest); + + pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable)); + if( pTab ){ + pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab); + pTab->nCol = nCol; + pTab->iPk = -2; + if( nCol>0 ){ + pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1)); + if( pTab->azlCol ){ + pTab->azlCol[nCol] = shellMPrintf(pRc, ""); + for(i=nCol-1; i>=0; i--){ + pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]); + } + } + } + + if( *pRc!=SQLITE_OK ){ + recoverFreeTable(pTab); + pTab = 0; + }else{ + raw_printf(pState->out, + "CREATE TABLE %s(rootpgno INTEGER, " + "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted + ); + for(i=0; iout, ", c%d", i); + } + raw_printf(pState->out, ");\n"); + } + } + sqlite3_free(zTab); + } + return pTab; +} + +/* +** This function is called to recover data from the database. A script +** to construct a new database containing all recovered data is output +** on stream pState->out. +*/ +static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ + int rc = SQLITE_OK; + sqlite3_stmt *pLoop = 0; /* Loop through all root pages */ + sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */ + sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */ + const char *zRecoveryDb = ""; /* Name of "recovery" database */ + const char *zLostAndFound = "lost_and_found"; + int i; + int nOrphan = -1; + RecoverTable *pOrphan = 0; + + int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ + for(i=1; idb, &rc, + /* Attach an in-memory database named 'recovery'. Create an indexed + ** cache of the sqlite_dbptr virtual table. */ + "ATTACH %Q AS recovery;" + "DROP TABLE IF EXISTS recovery.dbptr;" + "DROP TABLE IF EXISTS recovery.freelist;" + "DROP TABLE IF EXISTS recovery.map;" + "DROP TABLE IF EXISTS recovery.schema;" + "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb + ); + + if( bFreelist ){ + shellExec(pState->db, &rc, + "WITH trunk(pgno) AS (" + " SELECT shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x " + " WHERE x>0" + " UNION" + " SELECT shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x " + " FROM trunk WHERE x>0" + ")," + "freelist(data, n, freepgno) AS (" + " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno " + " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno" + " UNION ALL" + " SELECT data, n-1, shell_int32(data, 2+n) " + " FROM freelist WHERE n>=0" + ")" + "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;" + ); + } + + shellExec(pState->db, &rc, + "CREATE TABLE recovery.dbptr(" + " pgno, child, PRIMARY KEY(child, pgno)" + ") WITHOUT ROWID;" + "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) " + " SELECT * FROM sqlite_dbptr" + " WHERE pgno NOT IN freelist AND child NOT IN freelist;" + + /* Delete any pointer to page 1. This ensures that page 1 is considered + ** a root page, regardless of how corrupt the db is. */ + "DELETE FROM recovery.dbptr WHERE child = 1;" + + /* Delete all pointers to any pages that have more than one pointer + ** to them. Such pages will be treated as root pages when recovering + ** data. */ + "DELETE FROM recovery.dbptr WHERE child IN (" + " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1" + ");" + + /* Create the "map" table that will (eventually) contain instructions + ** for dealing with each page in the db that contains one or more + ** records. */ + "CREATE TABLE recovery.map(" + "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT" + ");" + + /* Populate table [map]. If there are circular loops of pages in the + ** database, the following adds all pages in such a loop to the map + ** as individual root pages. This could be handled better. */ + "WITH pages(i, maxlen) AS (" + " SELECT page_count, (" + " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count" + " ) FROM pragma_page_count WHERE page_count>0" + " UNION ALL" + " SELECT i-1, (" + " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1" + " ) FROM pages WHERE i>=2" + ")" + "INSERT INTO recovery.map(pgno, maxlen, intkey, root) " + " SELECT i, maxlen, NULL, (" + " WITH p(orig, pgno, parent) AS (" + " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)" + " UNION " + " SELECT i, p.parent, " + " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p" + " )" + " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" + ") " + "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;" + "UPDATE recovery.map AS o SET intkey = (" + " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" + ");" + + /* Extract data from page 1 and any linked pages into table + ** recovery.schema. With the same schema as an sqlite_master table. */ + "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);" + "INSERT INTO recovery.schema SELECT " + " max(CASE WHEN field=0 THEN value ELSE NULL END)," + " max(CASE WHEN field=1 THEN value ELSE NULL END)," + " max(CASE WHEN field=2 THEN value ELSE NULL END)," + " max(CASE WHEN field=3 THEN value ELSE NULL END)," + " max(CASE WHEN field=4 THEN value ELSE NULL END)" + "FROM sqlite_dbdata WHERE pgno IN (" + " SELECT pgno FROM recovery.map WHERE root=1" + ")" + "GROUP BY pgno, cell;" + "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);" + ); + + /* Open a transaction, then print out all non-virtual, non-"sqlite_%" + ** CREATE TABLE statements that extracted from the existing schema. */ + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + raw_printf(pState->out, "BEGIN;\n"); + raw_printf(pState->out, "PRAGMA writable_schema = on;\n"); + shellPrepare(pState->db, &rc, + "SELECT sql FROM recovery.schema " + "WHERE type='table' AND sql LIKE 'create table%'", &pStmt + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0); + raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", + &zCreateTable[12] + ); + } + shellFinalize(&rc, pStmt); + } + + /* Figure out if an orphan table will be required. And if so, how many + ** user columns it should contain */ + shellPrepare(pState->db, &rc, + "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1" + , &pLoop + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ + nOrphan = sqlite3_column_int(pLoop, 0); + } + shellFinalize(&rc, pLoop); + pLoop = 0; + + shellPrepare(pState->db, &rc, + "SELECT pgno FROM recovery.map WHERE root=?", &pPages + ); + shellPrepare(pState->db, &rc, + "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')" + "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" + "GROUP BY cell", &pCells + ); + + /* Loop through each root page. */ + shellPrepare(pState->db, &rc, + "SELECT root, intkey, max(maxlen) FROM recovery.map" + " WHERE root>1 GROUP BY root, intkey ORDER BY root=(" + " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'" + ")", &pLoop + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ + int iRoot = sqlite3_column_int(pLoop, 0); + int bIntkey = sqlite3_column_int(pLoop, 1); + int nCol = sqlite3_column_int(pLoop, 2); + int bNoop = 0; + RecoverTable *pTab; + + pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop); + if( bNoop || rc ) continue; + if( pTab==0 ){ + if( pOrphan==0 ){ + pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); + } + pTab = pOrphan; + if( pTab==0 ) break; + } + + if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){ + raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); + } + sqlite3_bind_int(pPages, 1, iRoot); + sqlite3_bind_int(pCells, 2, pTab->iPk); + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ + int iPgno = sqlite3_column_int(pPages, 0); + sqlite3_bind_int(pCells, 1, iPgno); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ + int nField = sqlite3_column_int(pCells, 0); + const char *zVal = (const char*)sqlite3_column_text(pCells, 1); + + nField = nField+1; + if( pTab==pOrphan ){ + raw_printf(pState->out, + "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n", + pTab->zQuoted, iRoot, iPgno, nField, + bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField] + ); + }else{ + raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", + pTab->zQuoted, pTab->azlCol[nField], zVal + ); + } + } + shellReset(&rc, pCells); + } + shellReset(&rc, pPages); + if( pTab!=pOrphan ) recoverFreeTable(pTab); + } + shellFinalize(&rc, pLoop); + shellFinalize(&rc, pPages); + shellFinalize(&rc, pCells); + recoverFreeTable(pOrphan); + + /* The rest of the schema */ + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + shellPrepare(pState->db, &rc, + "SELECT sql, name FROM recovery.schema " + "WHERE sql NOT LIKE 'create table%'", &pStmt + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); + if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){ + const char *zName = (const char*)sqlite3_column_text(pStmt, 1); + char *zPrint = shellMPrintf(&rc, + "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)", + zName, zName, zSql + ); + raw_printf(pState->out, "%s;\n", zPrint); + sqlite3_free(zPrint); + }else{ + raw_printf(pState->out, "%s;\n", zSql); + } + } + shellFinalize(&rc, pStmt); + } + + if( rc==SQLITE_OK ){ + raw_printf(pState->out, "PRAGMA writable_schema = off;\n"); + raw_printf(pState->out, "COMMIT;\n"); + } + sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); + return rc; +} +#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ + /* ** If an input line begins with "." then invoke this routine to @@ -6282,15 +7075,19 @@ static int do_meta_command(char *zLine, ShellState *p){ const char *zName; int op; } aDbConfig[] = { - { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, - { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, - { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, - { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, - { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, - { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, - { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, - { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, - { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, + { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, + { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, + { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, + { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, + { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, }; int ii, v; open_db(p, 0); @@ -6313,6 +7110,13 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = shell_dbinfo_command(p, nArg, azArg); }else +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) + if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){ + open_db(p, 0); + rc = recoverDatabaseCmd(p, nArg, azArg); + }else +#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ + if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ const char *zLike = 0; int i; @@ -6350,7 +7154,9 @@ static int do_meta_command(char *zLine, ShellState *p){ zLike = azArg[i]; } } + open_db(p, 0); + /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ @@ -6398,7 +7204,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); - raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); p->showHeader = savedShowHeader; p->shellFlgs = savedShellFlags; }else @@ -6479,6 +7285,127 @@ static int do_meta_command(char *zLine, ShellState *p){ }else #endif + if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + 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, "" }, + { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" }, + { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" }, + }; + int filectrl = -1; + int iCtrl = -1; + sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */ + int isOk = 0; /* 0: usage 1: %lld 2: no-result */ + int n2, i; + const char *zCmd = 0; + + open_db(p, 0); + zCmd = nArg>=2 ? azArg[1] : "help"; + + /* The argument can optionally begin with "-" or "--" */ + if( zCmd[0]=='-' && zCmd[1] ){ + zCmd++; + if( zCmd[0]=='-' && zCmd[1] ) zCmd++; + } + + /* --help lists all file-controls */ + if( strcmp(zCmd,"help")==0 ){ + utf8_printf(p->out, "Available file-controls:\n"); + for(i=0; iout, " .filectrl %s %s\n", + aCtrl[i].zCtrlName, aCtrl[i].zUsage); + } + rc = 1; + goto meta_command_exit; + } + + /* convert filectrl text option to value. allow any unique prefix + ** of the option name, or a numerical value. */ + n2 = strlen30(zCmd); + for(i=0; idb, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes); + isOk = 1; + break; + } + case SQLITE_FCNTL_LOCK_TIMEOUT: + case SQLITE_FCNTL_CHUNK_SIZE: { + int x; + if( nArg!=3 ) break; + x = (int)integerValue(azArg[2]); + sqlite3_file_control(p->db, 0, filectrl, &x); + isOk = 2; + break; + } + case SQLITE_FCNTL_PERSIST_WAL: + case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { + int x; + if( nArg!=2 && nArg!=3 ) break; + x = nArg==3 ? booleanValue(azArg[2]) : -1; + sqlite3_file_control(p->db, 0, filectrl, &x); + iRes = x; + isOk = 1; + break; + } + case SQLITE_FCNTL_HAS_MOVED: { + int x; + if( nArg!=2 ) break; + sqlite3_file_control(p->db, 0, filectrl, &x); + iRes = x; + isOk = 1; + break; + } + case SQLITE_FCNTL_TEMPFILENAME: { + char *z = 0; + if( nArg!=2 ) break; + sqlite3_file_control(p->db, 0, filectrl, &z); + if( z ){ + utf8_printf(p->out, "%s\n", z); + sqlite3_free(z); + } + isOk = 2; + break; + } + } + } + if( isOk==0 && iCtrl>=0 ){ + utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); + rc = 1; + }else if( isOk==1 ){ + char zBuf[100]; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes); + raw_printf(p->out, "%s\n", zBuf); + } + }else + if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ ShellState data; char *zErrMsg = 0; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index cf390ac..4dd14ac 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1296,8 +1296,14 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test whether a file is at least readable. The file can be a -** directory. +** to test whether a file is at least readable. The SQLITE_ACCESS_READ +** flag is never actually used and is not implemented in the built-in +** VFSes of SQLite. The file is named by the second argument and can be a +** directory. The xAccess method returns [SQLITE_OK] on success or some +** non-zero error code if there is an I/O error or if the name of +** the file given in the second argument is illegal. If SQLITE_OK +** is returned, then non-zero or zero is written into *pResOut to indicate +** whether or not the file is accessible. ** ** ^SQLite will always allocate at least mxPathname+1 bytes for the ** output buffer xFullPathname. The exact size of the output buffer @@ -2198,6 +2204,7 @@ struct sqlite3_mem_methods { ** features include but are not limited to the following: **
    **
  • The [PRAGMA writable_schema=ON] statement. +**
  • The [PRAGMA journal_mode=OFF] statement. **
  • Writes to the [sqlite_dbpage] virtual table. **
  • Direct writes to [shadow tables]. **
@@ -2213,6 +2220,34 @@ struct sqlite3_mem_methods { ** integer into which is written 0 or 1 to indicate whether the writable_schema ** is enabled or disabled following this call. ** +** +** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] +**
SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
+**
The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates +** the legacy behavior of the [ALTER TABLE RENAME] command such it +** behaves as it did prior to [version 3.24.0] (2018-06-04). See the +** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for +** additional information. This feature can also be turned on and off +** using the [PRAGMA legacy_alter_table] statement. +**
+** +** [[SQLITE_DBCONFIG_DQS_DML]] +**
SQLITE_DBCONFIG_DQS_DML +**
The SQLITE_DBCONFIG_DQS_DML option activates or deactivates +** the legacy [double-quoted string literal] misfeature for DML statement +** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The +** default value of this setting is determined by the [-DSQLITE_DQS] +** compile-time option. +**
+** +** [[SQLITE_DBCONFIG_DQS_DDL]] +**
SQLITE_DBCONFIG_DQS_DDL +**
The SQLITE_DBCONFIG_DQS option activates or deactivates +** the legacy [double-quoted string literal] misfeature for DDL statements, +** such as CREATE TABLE and CREATE INDEX. The +** default value of this setting is determined by the [-DSQLITE_DQS] +** compile-time option. +**
** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2227,7 +2262,10 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ #define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1011 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ +#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ +#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -7319,7 +7357,8 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 -#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_RESULT_INTREAL 27 +#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 72953e6..1c46183 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -830,12 +830,13 @@ typedef INT16_TYPE LogEst; ** at run-time. */ #ifndef SQLITE_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__arm__) || defined(_M_ARM64) +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ + defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) # define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ppc__) +# elif defined(sparc) || defined(__ppc__) || \ + defined(__ARMEB__) || defined(__AARCH64EB__) # define SQLITE_BYTEORDER 4321 # else # define SQLITE_BYTEORDER 0 @@ -1547,6 +1548,8 @@ struct sqlite3 { #define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ #define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ #define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ +#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ +#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ /* Flags used only if debugging */ #define HI(X) ((u64)(X)<<32) @@ -2253,6 +2256,7 @@ struct Index { unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ unsigned bNoQuery:1; /* Do not use this index to optimize queries */ + unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ @@ -2480,7 +2484,7 @@ struct Expr { ** 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 */ - u8 op2; /* TK_REGISTER: original value of Expr.op + u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ @@ -2514,7 +2518,7 @@ struct Expr { #define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ #define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ +#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ #define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ #define EP_Win 0x008000 /* Contains window functions */ @@ -2530,6 +2534,8 @@ struct Expr { #define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ #define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ #define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ +#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ +#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -2545,6 +2551,8 @@ struct Expr { #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) +#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue) +#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse) /* The ExprSetVVAProperty() macro is used for Verification, Validation, ** and Accreditation only. It works like ExprSetProperty() during VVA @@ -2761,7 +2769,7 @@ struct NameContext { 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 */ - u16 ncFlags; /* Zero or more NC_* flags defined below */ + int ncFlags; /* Zero or more NC_* flags defined below */ Select *pWinSelect; /* SELECT statement for any window functions */ }; @@ -2788,6 +2796,7 @@ struct NameContext { #define NC_Complex 0x2000 /* True if a function or subquery seen */ #define NC_AllowWin 0x4000 /* Window functions are allowed here */ #define NC_HasWin 0x8000 /* One or more window functions seen */ +#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */ /* ** An instance of the following object describes a single ON CONFLICT @@ -3794,8 +3803,12 @@ void sqlite3MutexWarnOnContention(sqlite3_mutex*); #endif #ifndef SQLITE_OMIT_FLOATING_POINT +# define EXP754 (((u64)0x7ff)<<52) +# define MAN754 ((((u64)1)<<52)-1) +# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) int sqlite3IsNaN(double); #else +# define IsNaN(X) 0 # define sqlite3IsNaN(X) 0 #endif @@ -3854,10 +3867,12 @@ Expr *sqlite3Expr(sqlite3*,int,const char*); void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); void sqlite3PExprAddSelect(Parse*, Expr*, Select*); -Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); +Expr *sqlite3ExprSimplifiedAndOr(Expr*); Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); +void sqlite3ExprUnmapAndDelete(Parse*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); void sqlite3ExprListSetSortOrder(ExprList*,int); @@ -4166,6 +4181,7 @@ int sqlite3FixSelect(DbFixer*, Select*); int sqlite3FixExpr(DbFixer*, Expr*); int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); +int sqlite3RealSameAsInt(double,sqlite3_int64); int sqlite3AtoF(const char *z, double*, int, u8); int sqlite3GetInt32(const char *, int*); int sqlite3Atoi(const char*); @@ -4267,6 +4283,9 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueSetNull(sqlite3_value*); void sqlite3ValueFree(sqlite3_value*); +#ifndef SQLITE_UNTESTABLE +void sqlite3ResultIntReal(sqlite3_context*); +#endif sqlite3_value *sqlite3ValueNew(sqlite3 *); #ifndef SQLITE_OMIT_UTF16 char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); diff --git a/src/test1.c b/src/test1.c index 17819b9..9aaf792 100644 --- a/src/test1.c +++ b/src/test1.c @@ -998,6 +998,20 @@ static void nondeterministicFunction( sqlite3_result_int(context, cnt++); } +/* +** This SQL function returns the integer value of its argument as a MEM_IntReal +** value. +*/ +static void intrealFunction( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_int64 v = sqlite3_value_int64(argv[0]); + sqlite3_result_int64(context, v); + sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context); +} + /* ** Usage: sqlite3_create_function DB ** @@ -1062,6 +1076,14 @@ static int SQLITE_TCLAPI test_create_function( 0, nondeterministicFunction, 0, 0); } + /* The intreal() function converts its argument to an integer and returns + ** it as a MEM_IntReal. + */ + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "intreal", 1, SQLITE_UTF8, + 0, intrealFunction, 0, 0); + } + #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ @@ -7586,15 +7608,19 @@ static int SQLITE_TCLAPI test_sqlite3_db_config( const char *zName; int eVal; } aSetting[] = { - { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY }, - { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER }, - { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, - { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, - { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, - { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, - { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP }, - { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, - { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, + { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "NO_CKPT_ON_CLOSE", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, + { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, + { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, + { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, + { "DQS_DML", SQLITE_DBCONFIG_DQS_DML }, + { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL }, }; int i; int v; @@ -7699,7 +7725,7 @@ static int SQLITE_TCLAPI test_decode_hexdb( int iOffset = 0; int j, k; int rc; - unsigned char x[16]; + unsigned int x[16]; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HEXDB"); return TCL_ERROR; @@ -7731,14 +7757,14 @@ static int SQLITE_TCLAPI test_decode_hexdb( iOffset = k; continue; } - rc = sscanf(zIn+i,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx" - " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx", + rc = sscanf(zIn+i,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]); if( rc==17 ){ k = iOffset+j; if( k+16<=n ){ - memcpy(a+k, x, 16); + int ii; + for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff; } continue; } diff --git a/src/test_demovfs.c b/src/test_demovfs.c index ba7af86..eaba208 100644 --- a/src/test_demovfs.c +++ b/src/test_demovfs.c @@ -240,6 +240,9 @@ static int demoRead( if( nRead==iAmt ){ return SQLITE_OK; }else if( nRead>=0 ){ + if( nReadpReal, op, pArg); diff --git a/src/treeview.c b/src/treeview.c index 981ae2f..6b4a98e 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -514,7 +514,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ }; assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); assert( pExpr->pRight ); - assert( pExpr->pRight->op==TK_TRUEFALSE ); + assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE ); x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); zUniOp = azOp[x]; break; diff --git a/src/update.c b/src/update.c index 132837d..bbeaa3d 100644 --- a/src/update.c +++ b/src/update.c @@ -155,11 +155,12 @@ void sqlite3Update( Index *pIdx; /* For looping over indices */ Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ int nIdx; /* Number of indices that need updating */ + int nAllIdx; /* Total number of indexes */ int iBaseCur; /* Base cursor number */ int iDataCur; /* Cursor for the canonical data btree */ int iIdxCur; /* Cursor for the first index */ sqlite3 *db; /* The database structure */ - int *aRegIdx = 0; /* First register in array assigned to each index */ + int *aRegIdx = 0; /* Registers for to each index and the main table */ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ @@ -273,10 +274,10 @@ void sqlite3Update( /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. ** Initialize aXRef[] and aToOpen[] to their default values. */ - aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); + aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 ); if( aXRef==0 ) goto update_cleanup; aRegIdx = aXRef+pTab->nCol; - aToOpen = (u8*)(aRegIdx+nIdx); + aToOpen = (u8*)(aRegIdx+nIdx+1); memset(aToOpen, 1, nIdx+1); aToOpen[nIdx+1] = 0; for(i=0; inCol; i++) aXRef[i] = -1; @@ -355,7 +356,7 @@ void sqlite3Update( ** the key for accessing each index. */ if( onError==OE_Replace ) bReplace = 1; - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){ int reg; if( chngKey || hasFK>1 || pIdx==pPk || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) @@ -375,9 +376,10 @@ void sqlite3Update( } } } - if( reg==0 ) aToOpen[j+1] = 0; - aRegIdx[j] = reg; + if( reg==0 ) aToOpen[nAllIdx+1] = 0; + aRegIdx[nAllIdx] = reg; } + aRegIdx[nAllIdx] = ++pParse->nMem; /* Register storing the table record */ if( bReplace ){ /* If REPLACE conflict resolution might be invoked, open cursors on all ** indexes in case they are needed to delete records. */ @@ -392,7 +394,13 @@ void sqlite3Update( /* Allocate required registers. */ if( !IsVirtual(pTab) ){ - regRowSet = ++pParse->nMem; + /* For now, regRowSet and aRegIdx[nAllIdx] share the same register. + ** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be + ** reallocated. aRegIdx[nAllIdx] is the register in which the main + ** table record is written. regRowSet holds the RowSet for the + ** two-pass update algorithm. */ + assert( aRegIdx[nAllIdx]==pParse->nMem ); + regRowSet = aRegIdx[nAllIdx]; regOldRowid = regNewRowid = ++pParse->nMem; if( chngPk || pTrigger || hasFK ){ regOld = pParse->nMem + 1; @@ -522,6 +530,8 @@ void sqlite3Update( ** leave it in register regOldRowid. */ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); if( eOnePass==ONEPASS_OFF ){ + /* We need to use regRowSet, so reallocate aRegIdx[nAllIdx] */ + aRegIdx[nAllIdx] = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); } }else{ diff --git a/src/util.c b/src/util.c index 4fa92f8..764bfe9 100644 --- a/src/util.c +++ b/src/util.c @@ -17,9 +17,7 @@ */ #include "sqliteInt.h" #include -#if HAVE_ISNAN || SQLITE_HAVE_ISNAN -# include -#endif +#include /* ** Routine needed to support the testcase() macro. @@ -60,47 +58,11 @@ int sqlite3FaultSim(int iTest){ #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Return true if the floating point value is Not a Number (NaN). -** -** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. -** Otherwise, we have our own implementation that works on most systems. */ int sqlite3IsNaN(double x){ - int rc; /* The value return */ -#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN - /* - ** Systems that support the isnan() library function should probably - ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have - ** found that many systems do not have a working isnan() function so - ** this implementation is provided as an alternative. - ** - ** This NaN test sometimes fails if compiled on GCC with -ffast-math. - ** On the other hand, the use of -ffast-math comes with the following - ** warning: - ** - ** This option [-ffast-math] should never be turned on by any - ** -O option since it can result in incorrect output for programs - ** which depend on an exact implementation of IEEE or ISO - ** rules/specifications for math functions. - ** - ** Under MSVC, this NaN test may fail if compiled with a floating- - ** point precision mode other than /fp:precise. From the MSDN - ** documentation: - ** - ** The compiler [with /fp:precise] will properly handle comparisons - ** involving NaN. For example, x != x evaluates to true if x is NaN - ** ... - */ -#ifdef __FAST_MATH__ -# error SQLite will not work correctly with the -ffast-math option of GCC. -#endif - volatile double y = x; - volatile double z = y; - rc = (y!=z); -#else /* if HAVE_ISNAN */ - rc = isnan(x); -#endif /* HAVE_ISNAN */ - testcase( rc ); - return rc; + u64 y; + memcpy(&y,&x,sizeof(y)); + return IsNaN(y); } #endif /* SQLITE_OMIT_FLOATING_POINT */ @@ -322,12 +284,18 @@ int sqlite3_stricmp(const char *zLeft, const char *zRight){ } int sqlite3StrICmp(const char *zLeft, const char *zRight){ unsigned char *a, *b; - int c; + int c, x; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; for(;;){ - c = (int)UpperToLower[*a] - (int)UpperToLower[*b]; - if( c || *a==0 ) break; + c = *a; + x = *b; + if( c==x ){ + if( c==0 ) break; + }else{ + c = (int)UpperToLower[c] - (int)UpperToLower[x]; + if( c ) break; + } a++; b++; } @@ -355,15 +323,15 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ static LONGDOUBLE_TYPE sqlite3Pow10(int E){ #if defined(_MSC_VER) static const LONGDOUBLE_TYPE x[] = { - 1.0e+001, - 1.0e+002, - 1.0e+004, - 1.0e+008, - 1.0e+016, - 1.0e+032, - 1.0e+064, - 1.0e+128, - 1.0e+256 + 1.0e+001L, + 1.0e+002L, + 1.0e+004L, + 1.0e+008L, + 1.0e+016L, + 1.0e+032L, + 1.0e+064L, + 1.0e+128L, + 1.0e+256L }; LONGDOUBLE_TYPE r = 1.0; int i; @@ -393,8 +361,15 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){ ** uses the encoding enc. The string is not necessarily zero-terminated. ** ** Return TRUE if the result is a valid real number (or integer) and FALSE -** if the string is empty or contains extraneous text. Valid numbers -** are in one of these formats: +** if the string is empty or contains extraneous text. More specifically +** return +** 1 => The input string is a pure integer +** 2 or more => The input has a decimal point or eNNN clause +** 0 or less => The input string is not a valid number +** -1 => Not a valid number, but has a valid prefix which +** includes a decimal point and/or an eNNN clause +** +** Valid numbers are in one of these formats: ** ** [+-]digits[E[+-]digits] ** [+-]digits.[digits][E[+-]digits] @@ -419,8 +394,8 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ double result; - int nDigits = 0; - int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ + int nDigit = 0; /* Number of digits processed */ + int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ @@ -431,8 +406,10 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ int i; incr = 2; assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + testcase( enc==SQLITE_UTF16LE ); + testcase( enc==SQLITE_UTF16BE ); for(i=3-enc; i=((LARGEST_INT64-9)/10) ){ + /* skip non-significant significand digits + ** (increase exponent by d to shift decimal left) */ + while( z=zEnd ) goto do_atof_calc; /* if decimal point is present */ if( *z=='.' ){ z+=incr; + eType++; /* copy digits from after decimal to significand ** (decrease exponent by d to shift decimal right) */ while( z=zEnd ) goto do_atof_calc; @@ -479,6 +459,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ if( *z=='e' || *z=='E' ){ z+=incr; eValid = 0; + eType++; /* This branch is needed to avoid a (harmless) buffer overread. The ** special comment alerts the mutation tester that the correct answer @@ -577,7 +558,13 @@ do_atof_calc: *pResult = result; /* return true if number and no extra non-whitespace chracters after */ - return z==zEnd && nDigits>0 && eValid && nonNum==0; + if( z==zEnd && nDigit>0 && eValid && eType>0 ){ + return eType; + }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ + return -1; + }else{ + return 0; + } #else return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ @@ -620,6 +607,7 @@ static int compare2pow63(const char *zNum, int incr){ ** ** Returns: ** +** -1 Not even a prefix of the input text looks like an integer ** 0 Successful transformation. Fits in a 64-bit signed integer. ** 1 Excess non-space text after the integer value ** 2 Integer too large for a 64-bit signed integer or is malformed @@ -679,9 +667,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ *pNum = (i64)u; } rc = 0; - if( (i==0 && zStart==zNum) /* No digits */ - || nonNum /* UTF16 with high-order bytes non-zero */ - ){ + if( i==0 && zStart==zNum ){ /* No digits */ + rc = -1; + }else if( nonNum ){ /* UTF16 with high-order bytes non-zero */ rc = 1; }else if( &zNum[i]=0 ){ + *v = *p; return 1; } - - p++; - b = *p; - /* b: p1 (unmasked) */ - if (!(b&0x80)) - { - a &= 0x7f; - a = a<<7; - a |= b; - *v = a; + if( ((signed char*)p)[1]>=0 ){ + *v = ((u32)(p[0]&0x7f)<<7) | p[1]; return 2; } @@ -936,8 +913,9 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); - p++; - a = a<<14; + a = ((u32)p[0])<<14; + b = p[1]; + p += 2; a |= *p; /* a: p0<<14 | p2 (unmasked) */ if (!(a&0x80)) diff --git a/src/vacuum.c b/src/vacuum.c index 74e6d7d..e8555ef 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -106,6 +106,7 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){ Vdbe *v = sqlite3GetVdbe(pParse); int iDb = 0; if( v==0 ) goto build_vacuum_end; + if( pParse->nErr ) goto build_vacuum_end; if( pNm ){ #ifndef SQLITE_BUG_COMPATIBLE_20160819 /* Default behavior: Report an error if the argument to VACUUM is diff --git a/src/vdbe.c b/src/vdbe.c index c004137..d697d6b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -195,14 +195,6 @@ int sqlite3_found_count = 0; } #endif -/* -** Convert the given register into a string if it isn't one -** already. Return non-zero if a malloc() fails. -*/ -#define Stringify(P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ - { goto no_mem; } - /* ** An ephemeral string value (signified by the MEM_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity @@ -264,7 +256,7 @@ static VdbeCursor *allocateCursor( ** 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. */ - p->apCsr[iCur]->isEphemeral = 0; + if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0; sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } @@ -284,6 +276,21 @@ static VdbeCursor *allocateCursor( return pCx; } +/* +** The string in pRec is known to look like an integer and to have a +** floating point value of rValue. Return true and set *piValue to the +** integer value if the string is in range to be an integer. Otherwise, +** return false. +*/ +static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ + i64 iValue = (double)rValue; + if( sqlite3RealSameAsInt(rValue,iValue) ){ + *piValue = iValue; + return 1; + } + return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc); +} + /* ** Try to convert a value into a numeric representation if we can ** do so without loss of information. In other words, if the string @@ -301,12 +308,12 @@ static VdbeCursor *allocateCursor( */ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; - i64 iValue; u8 enc = pRec->enc; - assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str ); - if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; - if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ - pRec->u.i = iValue; + int rc; + assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); + rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc); + if( rc<=0 ) return; + if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ pRec->flags |= MEM_Int; }else{ pRec->u.r = rValue; @@ -360,11 +367,14 @@ static void applyAffinity( ** there is already a string rep, but it is pointless to waste those ** CPU cycles. */ if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/ - if( (pRec->flags&(MEM_Real|MEM_Int)) ){ + if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){ + testcase( pRec->flags & MEM_Int ); + testcase( pRec->flags & MEM_Real ); + testcase( pRec->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pRec, enc, 1); } } - pRec->flags &= ~(MEM_Real|MEM_Int); + pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal); } } @@ -403,13 +413,21 @@ void sqlite3ValueApplyAffinity( ** accordingly. */ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ - assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); + int rc; + sqlite3_int64 ix; + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ); assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); ExpandBlob(pMem); - if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ - return 0; - } - if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){ + 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 ){ + pMem->u.i = ix; + return MEM_Int; + }else{ + return MEM_Real; + } + }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){ + pMem->u.i = ix; return MEM_Int; } return MEM_Real; @@ -423,10 +441,15 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ ** But it does set pMem->u.r and pMem->u.i appropriately. */ static u16 numericType(Mem *pMem){ - if( pMem->flags & (MEM_Int|MEM_Real) ){ - return pMem->flags & (MEM_Int|MEM_Real); + if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal) ){ + testcase( pMem->flags & MEM_Int ); + testcase( pMem->flags & MEM_Real ); + testcase( pMem->flags & MEM_IntReal ); + return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal); } if( pMem->flags & (MEM_Str|MEM_Blob) ){ + testcase( pMem->flags & MEM_Str ); + testcase( pMem->flags & MEM_Blob ); return computeNumericType(pMem); } return 0; @@ -522,6 +545,8 @@ static void memTracePrint(Mem *p){ printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ printf(" si:%lld", p->u.i); + }else if( (p->flags & (MEM_IntReal))!=0 ){ + printf(" ir:%lld", p->u.i); }else if( p->flags & MEM_Int ){ printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -1463,33 +1488,57 @@ case OP_ResultRow: { ** to avoid a memcpy(). */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ - i64 nByte; + i64 nByte; /* Total size of the output string or blob */ + u16 flags1; /* Initial flags for P1 */ + u16 flags2; /* Initial flags for P2 */ pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; pOut = &aMem[pOp->p3]; + testcase( pIn1==pIn2 ); + testcase( pOut==pIn2 ); assert( pIn1!=pOut ); - if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + flags1 = pIn1->flags; + testcase( flags1 & MEM_Null ); + testcase( pIn2->flags & MEM_Null ); + if( (flags1 | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); break; } - if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; - Stringify(pIn1, encoding); - Stringify(pIn2, encoding); + if( (flags1 & (MEM_Str|MEM_Blob))==0 ){ + if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem; + flags1 = pIn1->flags & ~MEM_Str; + }else if( (flags1 & MEM_Zero)!=0 ){ + if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; + flags1 = pIn1->flags & ~MEM_Str; + } + flags2 = pIn2->flags; + if( (flags2 & (MEM_Str|MEM_Blob))==0 ){ + if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem; + flags2 = pIn2->flags & ~MEM_Str; + }else if( (flags2 & MEM_Zero)!=0 ){ + if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem; + flags2 = pIn2->flags & ~MEM_Str; + } nByte = pIn1->n + pIn2->n; if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ + if( sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){ goto no_mem; } MemSetTypeFlag(pOut, MEM_Str); if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); + assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) ); + pIn2->flags = flags2; } memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); + pIn1->flags = flags1; pOut->z[nByte]=0; pOut->z[nByte+1] = 0; + pOut->z[nByte+2] = 0; pOut->flags |= MEM_Term; pOut->n = (int)nByte; pOut->enc = encoding; @@ -1540,7 +1589,6 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ - char bIntint; /* Started out as two integer operands */ u16 flags; /* Combined MEM_* flags from both inputs */ u16 type1; /* Numeric type of left operand */ u16 type2; /* Numeric type of right operand */ @@ -1558,7 +1606,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ if( (type1 & type2 & MEM_Int)!=0 ){ iA = pIn1->u.i; iB = pIn2->u.i; - bIntint = 1; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; @@ -1581,7 +1628,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ }else if( (flags & MEM_Null)!=0 ){ goto arithmetic_result_is_null; }else{ - bIntint = 0; fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); @@ -1613,9 +1659,6 @@ fp_math: } pOut->u.r = rB; MemSetTypeFlag(pOut, MEM_Real); - if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ - sqlite3VdbeIntegerAffinity(pOut); - } #endif } break; @@ -1784,7 +1827,9 @@ case OP_MustBeInt: { /* jump, in1 */ */ case OP_RealAffinity: { /* in1 */ pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Int ){ + if( pIn1->flags & (MEM_Int|MEM_IntReal) ){ + testcase( pIn1->flags & MEM_Int ); + testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemRealify(pIn1); } break; @@ -1976,7 +2021,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ if( (flags1 | flags3)&MEM_Str ){ - if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); assert( flags3==pIn3->flags ); /* testcase( flags3!=pIn3->flags ); @@ -1986,7 +2031,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** in case our analysis is incorrect, so it is left in. */ flags3 = pIn3->flags; } - if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3,0); } } @@ -1999,17 +2044,19 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ goto compare_op; } }else if( affinity==SQLITE_AFF_TEXT ){ - if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ + if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); + testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); assert( pIn1!=pIn3 ); } - if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){ + if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); + testcase( pIn3->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn3, encoding, 1); testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); @@ -2765,12 +2812,21 @@ case OP_Affinity: { assert( pOp->p2>0 ); assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; - do{ + while( 1 /*edit-by-break*/ ){ assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] ); assert( memIsValid(pIn1) ); - applyAffinity(pIn1, *(zAffinity++), encoding); + applyAffinity(pIn1, zAffinity[0], encoding); + if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){ + /* When applying REAL affinity, if the result is still MEM_Int, + ** indicate that REAL is actually desired */ + pIn1->flags |= MEM_IntReal; + pIn1->flags &= ~MEM_Int; + } + REGISTER_TRACE((int)(pIn1-aMem), pIn1); + zAffinity++; + if( zAffinity[0]==0 ) break; pIn1++; - }while( zAffinity[0] ); + } break; } @@ -2791,7 +2847,6 @@ case OP_Affinity: { ** If P4 is NULL then all index fields have the affinity BLOB. */ case OP_MakeRecord: { - u8 *zNewRecord; /* A buffer to hold the data for the new record */ Mem *pRec; /* The new record */ u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ @@ -2804,9 +2859,9 @@ case OP_MakeRecord: { int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] header */ - int j; /* Space used in zNewRecord[] content */ u32 len; /* Length of a field */ + u8 *zHdr; /* Where to write next byte of the header */ + u8 *zPayload; /* Where to write next byte of the payload */ /* Assuming the record contains N fields, the record format looks ** like this: @@ -2845,7 +2900,14 @@ case OP_MakeRecord: { if( zAffinity ){ pRec = pData0; do{ - applyAffinity(pRec++, *(zAffinity++), encoding); + applyAffinity(pRec, zAffinity[0], encoding); + if( zAffinity[0]==SQLITE_AFF_REAL && (pRec->flags & MEM_Int) ){ + pRec->flags |= MEM_IntReal; + pRec->flags &= ~(MEM_Int); + } + REGISTER_TRACE((int)(pRec-aMem), pRec); + zAffinity++; + pRec++; assert( zAffinity[0]==0 || pRec<=pLast ); }while( zAffinity[0] ); } @@ -2933,34 +2995,34 @@ case OP_MakeRecord: { goto no_mem; } } - zNewRecord = (u8 *)pOut->z; - - /* Write the record */ - i = putVarint32(zNewRecord, nHdr); - j = nHdr; - assert( pData0<=pLast ); - pRec = pData0; - do{ - serial_type = pRec->uTemp; - /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more - ** additional varints, one per column. */ - i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ - /* EVIDENCE-OF: R-64536-51728 The values for each column in the record - ** immediately follow the header. */ - j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ - }while( (++pRec)<=pLast ); - assert( i==nHdr ); - assert( j==nByte ); - - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->n = (int)nByte; pOut->flags = MEM_Blob; if( nZero ){ pOut->u.nZero = nZero; pOut->flags |= MEM_Zero; } - REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); + zHdr = (u8 *)pOut->z; + zPayload = zHdr + nHdr; + + /* Write the record */ + zHdr += putVarint32(zHdr, nHdr); + assert( pData0<=pLast ); + pRec = pData0; + do{ + serial_type = pRec->uTemp; + /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more + ** additional varints, one per column. */ + zHdr += putVarint32(zHdr, serial_type); /* serial type */ + /* EVIDENCE-OF: R-64536-51728 The values for each column in the record + ** immediately follow the header. */ + zPayload += sqlite3VdbeSerialPut(zPayload, pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( nHdr==(int)(zHdr - (u8*)pOut->z) ); + assert( nByte==(int)(zPayload - (u8*)pOut->z) ); + + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + REGISTER_TRACE(pOp->p3, pOut); break; } @@ -2990,8 +3052,9 @@ case OP_Count: { /* out2 */ /* Opcode: Savepoint P1 * * P4 * ** ** Open, release or rollback the savepoint named by parameter P4, depending -** on the value of P1. To open a new savepoint, P1==0. To release (commit) an -** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. +** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN). +** To release (commit) an existing savepoint set P1==1 (SAVEPOINT_RELEASE). +** To rollback an existing savepoint set P1==2 (SAVEPOINT_ROLLBACK). */ case OP_Savepoint: { int p1; /* Value of P1 operand */ @@ -3059,6 +3122,7 @@ case OP_Savepoint: { } } }else{ + assert( p1==SAVEPOINT_RELEASE || p1==SAVEPOINT_ROLLBACK ); iSavepoint = 0; /* Find the named savepoint. If there is no such savepoint, then an @@ -3112,6 +3176,7 @@ case OP_Savepoint: { if( rc!=SQLITE_OK ) goto abort_due_to_error; } }else{ + assert( p1==SAVEPOINT_RELEASE ); isSchemaChange = 0; } for(ii=0; iinDb; ii++){ @@ -3148,6 +3213,7 @@ case OP_Savepoint: { db->nSavepoint--; } }else{ + assert( p1==SAVEPOINT_ROLLBACK ); db->nDeferredCons = pSavepoint->nDeferredCons; db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } @@ -3686,11 +3752,15 @@ case OP_OpenEphemeral: { if( pCx ){ /* If the ephermeral table is already open, erase all existing content ** so that the table is empty again, rather than creating a new table. */ - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + assert( pCx->isEphemeral ); + pCx->seqCount = 0; + pCx->cacheStatus = CACHE_STALE; + if( pCx->pBtx ){ + rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + } }else{ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; - pCx->nullRow = 1; pCx->isEphemeral = 1; rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, @@ -3726,6 +3796,7 @@ case OP_OpenEphemeral: { pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); } if( rc ) goto abort_due_to_error; + pCx->nullRow = 1; break; } @@ -3954,6 +4025,8 @@ case OP_SeekGT: { /* jump, in3, group */ pC->seekOp = pOp->opcode; #endif + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; if( pC->isTable ){ /* The BTREE_SEEK_EQ flag is only set on index cursors */ assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 @@ -3963,20 +4036,24 @@ case OP_SeekGT: { /* jump, in3, group */ ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so convert it. */ pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3, 0); } iKey = sqlite3VdbeIntValue(pIn3); /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ - if( (pIn3->flags & MEM_Int)==0 ){ + if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ if( (pIn3->flags & MEM_Real)==0 ){ - /* If the P3 value cannot be converted into any kind of a number, - ** then the seek is not possible, so jump to P2 */ - VdbeBranchTaken(1,2); goto jump_to_p2; - break; - } + if( (pIn3->flags & MEM_Null) || oc>=OP_SeekGE ){ + VdbeBranchTaken(1,2); goto jump_to_p2; + break; + }else{ + rc = sqlite3BtreeLast(pC->uc.pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + goto seek_not_found; + } + }else /* If the approximation iKey is larger than the actual real search ** term, substitute >= for > and < for <=. e.g. if the search term @@ -4000,7 +4077,7 @@ case OP_SeekGT: { /* jump, in3, group */ assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } - } + } rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res); pC->movetoTarget = iKey; /* Used by OP_Delete */ if( rc!=SQLITE_OK ){ @@ -4054,8 +4131,6 @@ case OP_SeekGT: { /* jump, in3, group */ goto seek_not_found; } } - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; #ifdef SQLITE_TEST sqlite3_search_count++; #endif @@ -4355,7 +4430,9 @@ case OP_SeekRowid: { /* jump, in3 */ u64 iKey; pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & MEM_Int)==0 ){ + testcase( pIn3->flags & MEM_Int ); + testcase( pIn3->flags & MEM_IntReal ); + if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ /* Make sure pIn3->u.i contains a valid integer representation of ** the key value, but do not change the datatype of the register, as ** other parts of the perpared statement might be depending on the @@ -4730,7 +4807,7 @@ case OP_Delete: { ** OP_Delete will have also set the pC->movetoTarget field to the rowid of ** the row that is being deleted */ i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor); - assert( pC->movetoTarget==iKey ); + assert( CORRUPT_DB || pC->movetoTarget==iKey ); } #endif diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 15a371d..17e057b 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -245,12 +245,12 @@ struct sqlite3_value { #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ -#define MEM_AffMask 0x001f /* Mask of affinity bits */ -#define MEM_FromBind 0x0020 /* Value originates from sqlite3_bind() */ -/* Available 0x0040 */ +#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */ +#define MEM_AffMask 0x003f /* Mask of affinity bits */ +#define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */ #define MEM_Undefined 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#define MEM_TypeMask 0xc1df /* Mask of type bits */ +#define MEM_TypeMask 0xc1bf /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 00eea75..83221d9 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -234,39 +234,86 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){ */ int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { - SQLITE_BLOB, /* 0x00 */ - SQLITE_NULL, /* 0x01 */ - SQLITE_TEXT, /* 0x02 */ - SQLITE_NULL, /* 0x03 */ - SQLITE_INTEGER, /* 0x04 */ - SQLITE_NULL, /* 0x05 */ - SQLITE_INTEGER, /* 0x06 */ - SQLITE_NULL, /* 0x07 */ - SQLITE_FLOAT, /* 0x08 */ - SQLITE_NULL, /* 0x09 */ - SQLITE_FLOAT, /* 0x0a */ - SQLITE_NULL, /* 0x0b */ - SQLITE_INTEGER, /* 0x0c */ - SQLITE_NULL, /* 0x0d */ - SQLITE_INTEGER, /* 0x0e */ - SQLITE_NULL, /* 0x0f */ - SQLITE_BLOB, /* 0x10 */ - SQLITE_NULL, /* 0x11 */ - SQLITE_TEXT, /* 0x12 */ - SQLITE_NULL, /* 0x13 */ - SQLITE_INTEGER, /* 0x14 */ - SQLITE_NULL, /* 0x15 */ - SQLITE_INTEGER, /* 0x16 */ - SQLITE_NULL, /* 0x17 */ - SQLITE_FLOAT, /* 0x18 */ - SQLITE_NULL, /* 0x19 */ - SQLITE_FLOAT, /* 0x1a */ - SQLITE_NULL, /* 0x1b */ - SQLITE_INTEGER, /* 0x1c */ - SQLITE_NULL, /* 0x1d */ - SQLITE_INTEGER, /* 0x1e */ - SQLITE_NULL, /* 0x1f */ + SQLITE_BLOB, /* 0x00 (not possible) */ + SQLITE_NULL, /* 0x01 NULL */ + SQLITE_TEXT, /* 0x02 TEXT */ + SQLITE_NULL, /* 0x03 (not possible) */ + SQLITE_INTEGER, /* 0x04 INTEGER */ + SQLITE_NULL, /* 0x05 (not possible) */ + SQLITE_INTEGER, /* 0x06 INTEGER + TEXT */ + SQLITE_NULL, /* 0x07 (not possible) */ + SQLITE_FLOAT, /* 0x08 FLOAT */ + SQLITE_NULL, /* 0x09 (not possible) */ + SQLITE_FLOAT, /* 0x0a FLOAT + TEXT */ + SQLITE_NULL, /* 0x0b (not possible) */ + SQLITE_INTEGER, /* 0x0c (not possible) */ + SQLITE_NULL, /* 0x0d (not possible) */ + SQLITE_INTEGER, /* 0x0e (not possible) */ + SQLITE_NULL, /* 0x0f (not possible) */ + SQLITE_BLOB, /* 0x10 BLOB */ + SQLITE_NULL, /* 0x11 (not possible) */ + SQLITE_TEXT, /* 0x12 (not possible) */ + SQLITE_NULL, /* 0x13 (not possible) */ + SQLITE_INTEGER, /* 0x14 INTEGER + BLOB */ + SQLITE_NULL, /* 0x15 (not possible) */ + SQLITE_INTEGER, /* 0x16 (not possible) */ + SQLITE_NULL, /* 0x17 (not possible) */ + SQLITE_FLOAT, /* 0x18 FLOAT + BLOB */ + SQLITE_NULL, /* 0x19 (not possible) */ + SQLITE_FLOAT, /* 0x1a (not possible) */ + SQLITE_NULL, /* 0x1b (not possible) */ + SQLITE_INTEGER, /* 0x1c (not possible) */ + SQLITE_NULL, /* 0x1d (not possible) */ + SQLITE_INTEGER, /* 0x1e (not possible) */ + SQLITE_NULL, /* 0x1f (not possible) */ + SQLITE_FLOAT, /* 0x20 INTREAL */ + SQLITE_NULL, /* 0x21 (not possible) */ + SQLITE_TEXT, /* 0x22 INTREAL + TEXT */ + SQLITE_NULL, /* 0x23 (not possible) */ + SQLITE_FLOAT, /* 0x24 (not possible) */ + SQLITE_NULL, /* 0x25 (not possible) */ + SQLITE_FLOAT, /* 0x26 (not possible) */ + SQLITE_NULL, /* 0x27 (not possible) */ + SQLITE_FLOAT, /* 0x28 (not possible) */ + SQLITE_NULL, /* 0x29 (not possible) */ + SQLITE_FLOAT, /* 0x2a (not possible) */ + SQLITE_NULL, /* 0x2b (not possible) */ + SQLITE_FLOAT, /* 0x2c (not possible) */ + SQLITE_NULL, /* 0x2d (not possible) */ + SQLITE_FLOAT, /* 0x2e (not possible) */ + SQLITE_NULL, /* 0x2f (not possible) */ + SQLITE_BLOB, /* 0x30 (not possible) */ + SQLITE_NULL, /* 0x31 (not possible) */ + SQLITE_TEXT, /* 0x32 (not possible) */ + SQLITE_NULL, /* 0x33 (not possible) */ + SQLITE_FLOAT, /* 0x34 (not possible) */ + SQLITE_NULL, /* 0x35 (not possible) */ + SQLITE_FLOAT, /* 0x36 (not possible) */ + SQLITE_NULL, /* 0x37 (not possible) */ + SQLITE_FLOAT, /* 0x38 (not possible) */ + SQLITE_NULL, /* 0x39 (not possible) */ + SQLITE_FLOAT, /* 0x3a (not possible) */ + SQLITE_NULL, /* 0x3b (not possible) */ + SQLITE_FLOAT, /* 0x3c (not possible) */ + SQLITE_NULL, /* 0x3d (not possible) */ + SQLITE_FLOAT, /* 0x3e (not possible) */ + SQLITE_NULL, /* 0x3f (not possible) */ }; +#ifdef SQLITE_DEBUG + { + int eType = SQLITE_BLOB; + if( pVal->flags & MEM_Null ){ + eType = SQLITE_NULL; + }else if( pVal->flags & (MEM_Real|MEM_IntReal) ){ + eType = SQLITE_FLOAT; + }else if( pVal->flags & MEM_Int ){ + eType = SQLITE_INTEGER; + }else if( pVal->flags & MEM_Str ){ + eType = SQLITE_TEXT; + } + assert( eType == aType[pVal->flags&MEM_AffMask] ); + } +#endif return aType[pVal->flags&MEM_AffMask]; } @@ -516,6 +563,21 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){ sqlite3OomFault(pCtx->pOut->db); } +#ifndef SQLITE_UNTESTABLE +/* Force the INT64 value currently stored as the result to be +** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL +** test-control. +*/ +void sqlite3ResultIntReal(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + if( pCtx->pOut->flags & MEM_Int ){ + pCtx->pOut->flags &= ~MEM_Int; + pCtx->pOut->flags |= MEM_IntReal; + } +} +#endif + + /* ** This function is called after a transaction has been committed. It ** invokes callbacks registered with sqlite3_wal_hook() as required. @@ -1802,7 +1864,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ }else if( iIdx>=p->pUnpacked->nField ){ *ppValue = (sqlite3_value *)columnNullValue(); }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ - if( pMem->flags & MEM_Int ){ + if( pMem->flags & (MEM_Int|MEM_IntReal) ){ + testcase( pMem->flags & MEM_Int ); + testcase( pMem->flags & MEM_IntReal ); sqlite3VdbeMemRealify(pMem); } } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 822c6fe..8dd2b42 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -629,6 +629,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int hasAbort = 0; int hasFkCounter = 0; int hasCreateTable = 0; + int hasCreateIndex = 0; int hasInitCoroutine = 0; Op *pOp; VdbeOpIter sIter; @@ -647,6 +648,14 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ break; } if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; + if( mayAbort ){ + /* hasCreateIndex may also be set for some DELETE statements that use + ** OP_Clear. So this routine may end up returning true in the case + ** where a "DELETE FROM tbl" has a statement-journal but does not + ** require one. This is not so bad - it is an inefficiency, not a bug. */ + if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1; + if( opcode==OP_Clear ) hasCreateIndex = 1; + } if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; #ifndef SQLITE_OMIT_FOREIGN_KEY if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ @@ -662,7 +671,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ ** true for this case to prevent the assert() in the callers frame ** from failing. */ return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter - || (hasCreateTable && hasInitCoroutine) ); + || (hasCreateTable && hasInitCoroutine) || hasCreateIndex + ); } #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ @@ -1534,7 +1544,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ Mem *pMem = pOp->p4.pMem; if( pMem->flags & MEM_Str ){ zP4 = pMem->z; - }else if( pMem->flags & MEM_Int ){ + }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ sqlite3_str_appendf(&x, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ sqlite3_str_appendf(&x, "%.16g", pMem->u.r); @@ -2896,7 +2906,7 @@ int sqlite3VdbeHalt(Vdbe *p){ } /* Check for immediate foreign key violations. */ - if( p->rc==SQLITE_OK ){ + if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ sqlite3VdbeCheckFk(p, 0); } @@ -3422,6 +3432,8 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ /* ** Return the serial-type for the value stored in pMem. +** +** This routine might convert a large MEM_IntReal value into MEM_Real. */ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ int flags = pMem->flags; @@ -3432,11 +3444,13 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ *pLen = 0; return 0; } - if( flags&MEM_Int ){ + if( flags&(MEM_Int|MEM_IntReal) ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; u64 u; + testcase( flags & MEM_Int ); + testcase( flags & MEM_IntReal ); if( i<0 ){ u = ~i; }else{ @@ -3456,6 +3470,15 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ if( u<=2147483647 ){ *pLen = 4; return 4; } if( u<=MAX_6BYTE ){ *pLen = 6; return 5; } *pLen = 8; + if( flags&MEM_IntReal ){ + /* If the value is IntReal and is going to take up 8 bytes to store + ** as an integer, then we might as well make it an 8-byte floating + ** point value */ + pMem->u.r = (double)pMem->u.i; + pMem->flags &= ~MEM_IntReal; + pMem->flags |= MEM_Real; + return 7; + } return 6; } if( flags&MEM_Real ){ @@ -3629,7 +3652,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ ** routine so that in most cases the overhead of moving the stack pointer ** is avoided. */ -static u32 SQLITE_NOINLINE serialGet( +static u32 serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ @@ -3661,7 +3684,7 @@ static u32 SQLITE_NOINLINE serialGet( assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); swapMixedEndianFloat(x); memcpy(&pMem->u.r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real; + pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; } return 8; } @@ -4111,8 +4134,13 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ /* At least one of the two values is a number */ - if( combined_flags&(MEM_Int|MEM_Real) ){ - if( (f1 & f2 & MEM_Int)!=0 ){ + if( combined_flags&(MEM_Int|MEM_Real|MEM_IntReal) ){ + testcase( combined_flags & MEM_Int ); + testcase( combined_flags & MEM_Real ); + testcase( combined_flags & MEM_IntReal ); + if( (f1 & f2 & (MEM_Int|MEM_IntReal))!=0 ){ + testcase( f1 & f2 & MEM_Int ); + testcase( f1 & f2 & MEM_IntReal ); if( pMem1->u.i < pMem2->u.i ) return -1; if( pMem1->u.i > pMem2->u.i ) return +1; return 0; @@ -4122,15 +4150,23 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ if( pMem1->u.r > pMem2->u.r ) return +1; return 0; } - if( (f1&MEM_Int)!=0 ){ + if( (f1&(MEM_Int|MEM_IntReal))!=0 ){ + testcase( f1 & MEM_Int ); + testcase( f1 & MEM_IntReal ); if( (f2&MEM_Real)!=0 ){ return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r); + }else if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return +1; + return 0; }else{ return -1; } } if( (f1&MEM_Real)!=0 ){ - if( (f2&MEM_Int)!=0 ){ + if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ + testcase( f2 & MEM_Int ); + testcase( f2 & MEM_IntReal ); return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r); }else{ return -1; @@ -4279,7 +4315,9 @@ int sqlite3VdbeRecordCompareWithSkip( u32 serial_type; /* RHS is an integer */ - if( pRhs->flags & MEM_Int ){ + if( pRhs->flags & (MEM_Int|MEM_IntReal) ){ + testcase( pRhs->flags & MEM_Int ); + testcase( pRhs->flags & MEM_IntReal ); serial_type = aKey1[idx1]; testcase( serial_type==12 ); if( serial_type>=10 ){ @@ -4624,7 +4662,9 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ testcase( flags & MEM_Real ); testcase( flags & MEM_Null ); testcase( flags & MEM_Blob ); - if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ + if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0 + && p->pKeyInfo->aColl[0]==0 + ){ assert( flags & MEM_Str ); return vdbeRecordCompareString; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 10c23ad..af6d41a 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -18,6 +18,11 @@ #include "sqliteInt.h" #include "vdbeInt.h" +/* True if X is a power of two. 0 is considered a power of two here. +** In other words, return true if X has at most one bit set. +*/ +#define ISPOWEROF2(X) (((X)&((X)-1))==0) + #ifdef SQLITE_DEBUG /* ** Check invariants on a Mem object. @@ -37,8 +42,8 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ ** That saves a few cycles in inner loops. */ assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); - /* Cannot be both MEM_Int and MEM_Real at the same time */ - assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + /* Cannot have more than one of MEM_Int, MEM_Real, or MEM_IntReal */ + assert( ISPOWEROF2(p->flags & (MEM_Int|MEM_Real|MEM_IntReal)) ); if( p->flags & MEM_Null ){ /* Cannot be both MEM_Null and some other type */ @@ -92,9 +97,31 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ } #endif +/* +** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal +** into a buffer. +*/ +static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ + StrAccum acc; + assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) ); + sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); + if( p->flags & MEM_Int ){ + sqlite3_str_appendf(&acc, "%lld", p->u.i); + }else if( p->flags & MEM_IntReal ){ + sqlite3_str_appendf(&acc, "%!.15g", (double)p->u.i); + }else{ + sqlite3_str_appendf(&acc, "%!.15g", p->u.r); + } + assert( acc.zText==zBuf && acc.mxAlloc<=0 ); + zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */ +} + #ifdef SQLITE_DEBUG /* -** Check that string value of pMem agrees with its integer or real value. +** Validity checks on pMem. pMem holds a string. +** +** (1) Check that string value of pMem agrees with its integer or real value. +** (2) Check that the string is correctly zero terminated ** ** A single int or real value always converts to the same strings. But ** many different strings can be converted into the same int or real. @@ -112,17 +139,24 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ ** ** This routine is for use inside of assert() statements only. */ -int sqlite3VdbeMemConsistentDualRep(Mem *p){ +int sqlite3VdbeMemValidStrRep(Mem *p){ char zBuf[100]; char *z; int i, j, incr; if( (p->flags & MEM_Str)==0 ) return 1; - if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1; - if( p->flags & MEM_Int ){ - sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i); - }else{ - sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r); + if( p->flags & MEM_Term ){ + /* Insure that the string is properly zero-terminated. Pay particular + ** attention to the case where p->n is odd */ + if( p->szMalloc>0 && p->z==p->zMalloc ){ + assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 ); + assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 ); + } + assert( p->z[p->n]==0 ); + assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 ); + assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 ); } + if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1; + vdbeMemRenderNum(sizeof(zBuf), zBuf, p); z = p->z; i = j = 0; incr = 1; @@ -234,8 +268,8 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ ** ** Any prior string or blob content in the pMem object may be discarded. ** The pMem->xDel destructor is called, if it exists. Though MEM_Str -** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null -** values are preserved. +** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal, +** and MEM_Null values are preserved. ** ** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM) ** if unable to complete the resizing. @@ -248,20 +282,26 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ } assert( (pMem->flags & MEM_Dyn)==0 ); pMem->z = pMem->zMalloc; - pMem->flags &= (MEM_Null|MEM_Int|MEM_Real); + pMem->flags &= (MEM_Null|MEM_Int|MEM_Real|MEM_IntReal); return SQLITE_OK; } /* ** It is already known that pMem contains an unterminated string. ** Add the zero terminator. +** +** Three bytes of zero are added. In this way, there is guaranteed +** to be a double-zero byte at an even byte boundary in order to +** terminate a UTF16 string, even if the initial size of the buffer +** is an odd number of bytes. */ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ return SQLITE_NOMEM_BKPT; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; + pMem->z[pMem->n+2] = 0; pMem->flags |= MEM_Term; return SQLITE_OK; } @@ -335,12 +375,12 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ } /* -** Add MEM_Str to the set of representations for the given Mem. Numbers -** are converted using sqlite3_snprintf(). Converting a BLOB to a string -** is a no-op. +** Add MEM_Str to the set of representations for the given Mem. This +** routine is only called if pMem is a number of some kind, not a NULL +** or a BLOB. ** -** Existing representations MEM_Int and MEM_Real are invalidated if -** bForce is true but are retained if bForce is false. +** Existing representations MEM_Int, MEM_Real, or MEM_IntReal are invalidated +** if bForce is true but are retained if bForce is false. ** ** A MEM_Null value will never be passed to this function. This function is ** used for converting values to text for returning to the user (i.e. via @@ -349,13 +389,12 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ ** user and the latter is an internal programming error. */ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ - int fg = pMem->flags; const int nByte = 32; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !(fg&MEM_Zero) ); - assert( !(fg&(MEM_Str|MEM_Blob)) ); - assert( fg&(MEM_Int|MEM_Real) ); + assert( !(pMem->flags&MEM_Zero) ); + assert( !(pMem->flags&(MEM_Str|MEM_Blob)) ); + assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) ); assert( !sqlite3VdbeMemIsRowSet(pMem) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); @@ -365,23 +404,12 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ return SQLITE_NOMEM_BKPT; } - /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 - ** string representation of the value. Then, if the required encoding - ** is UTF-16le or UTF-16be do a translation. - ** - ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. - */ - if( fg & MEM_Int ){ - sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); - }else{ - assert( fg & MEM_Real ); - sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); - } + vdbeMemRenderNum(nByte, pMem->z, pMem); assert( pMem->z!=0 ); pMem->n = sqlite3Strlen30NN(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; - if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); sqlite3VdbeChangeEncoding(pMem, enc); return SQLITE_OK; } @@ -555,7 +583,8 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); flags = pMem->flags; - if( flags & MEM_Int ){ + if( flags & (MEM_Int|MEM_IntReal) ){ + testcase( flags & MEM_IntReal ); return pMem->u.i; }else if( flags & MEM_Real ){ return doubleToInt64(pMem->u.r); @@ -584,7 +613,8 @@ double sqlite3VdbeRealValue(Mem *pMem){ assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( pMem->flags & MEM_Real ){ return pMem->u.r; - }else if( pMem->flags & MEM_Int ){ + }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ + testcase( pMem->flags & MEM_IntReal ); return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ return memRealValue(pMem); @@ -599,7 +629,8 @@ double sqlite3VdbeRealValue(Mem *pMem){ ** Return the value ifNull if pMem is NULL. */ int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ - if( pMem->flags & MEM_Int ) return pMem->u.i!=0; + testcase( pMem->flags & MEM_IntReal ); + if( pMem->flags & (MEM_Int|MEM_IntReal) ) return pMem->u.i!=0; if( pMem->flags & MEM_Null ) return ifNull; return sqlite3VdbeRealValue(pMem)!=0.0; } @@ -662,17 +693,21 @@ int sqlite3VdbeMemRealify(Mem *pMem){ /* Compare a floating point value to an integer. Return true if the two ** values are the same within the precision of the floating point value. ** +** This function assumes that i was obtained by assignment from r1. +** ** For some versions of GCC on 32-bit machines, if you do the more obvious ** comparison of "r1==(double)i" you sometimes get an answer of false even ** though the r1 and (double)i values are bit-for-bit the same. */ -static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ +int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ double r2 = (double)i; - return memcmp(&r1, &r2, sizeof(r1))==0; + return r1==0.0 + || (memcmp(&r1, &r2, sizeof(r1))==0 + && i >= -2251799813685248LL && i < 2251799813685248LL); } /* -** Convert pMem so that it has types MEM_Real or MEM_Int or both. +** Convert pMem so that it has type MEM_Real or MEM_Int. ** Invalidate any prior representations. ** ** Every effort is made to force the conversion, even if the input @@ -680,25 +715,26 @@ static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ ** as much of the string as we can and ignore the rest. */ int sqlite3VdbeMemNumerify(Mem *pMem){ - if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ + testcase( pMem->flags & MEM_Int ); + testcase( pMem->flags & MEM_Real ); + testcase( pMem->flags & MEM_IntReal ); + testcase( pMem->flags & MEM_Null ); + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){ int rc; + sqlite3_int64 ix; assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc); - if( rc==0 ){ + rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); + if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1) + || sqlite3RealSameAsInt(pMem->u.r, (ix = (i64)pMem->u.r)) + ){ + pMem->u.i = ix; MemSetTypeFlag(pMem, MEM_Int); }else{ - i64 i = pMem->u.i; - sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){ - pMem->u.i = i; - MemSetTypeFlag(pMem, MEM_Int); - }else{ - MemSetTypeFlag(pMem, MEM_Real); - } + MemSetTypeFlag(pMem, MEM_Real); } } - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))!=0 ); pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero); return SQLITE_OK; } @@ -741,7 +777,7 @@ void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ pMem->flags |= (pMem->flags&MEM_Blob)>>3; sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); + pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero); break; } } @@ -925,7 +961,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ ** dual type, are allowed, as long as the underlying value is the ** same. */ u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags; - assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i ); + assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i ); assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r ); assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) ); assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 ); @@ -1200,7 +1236,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 || pVal->db->mallocFailed ); if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ - assert( sqlite3VdbeMemConsistentDualRep(pVal) ); + assert( sqlite3VdbeMemValidStrRep(pVal) ); return pVal->z; }else{ return 0; @@ -1223,7 +1259,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); assert( !sqlite3VdbeMemIsRowSet(pVal) ); if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ - assert( sqlite3VdbeMemConsistentDualRep(pVal) ); + assert( sqlite3VdbeMemValidStrRep(pVal) ); return pVal->z; } if( pVal->flags&MEM_Null ){ @@ -1488,7 +1524,12 @@ static int valueFromExpr( }else{ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); } - if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str; + assert( (pVal->flags & MEM_IntReal)==0 ); + if( pVal->flags & (MEM_Int|MEM_IntReal|MEM_Real) ){ + testcase( pVal->flags & MEM_Int ); + testcase( pVal->flags & MEM_Real ); + pVal->flags &= ~MEM_Str; + } if( enc!=SQLITE_UTF8 ){ rc = sqlite3VdbeChangeEncoding(pVal, enc); } @@ -1511,7 +1552,7 @@ static int valueFromExpr( }else if( op==TK_NULL ){ pVal = valueNew(db, pCtx); if( pVal==0 ) goto no_mem; - sqlite3VdbeMemNumerify(pVal); + sqlite3VdbeMemSetNull(pVal); } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ diff --git a/src/vdbetrace.c b/src/vdbetrace.c index b6d9381..32c66af 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -130,7 +130,7 @@ char *sqlite3VdbeExpandSql( pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ sqlite3_str_append(&out, "NULL", 4); - }else if( pVar->flags & MEM_Int ){ + }else if( pVar->flags & (MEM_Int|MEM_IntReal) ){ sqlite3_str_appendf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); diff --git a/src/vtab.c b/src/vtab.c index 7806eb9..41e26ef 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -841,6 +841,7 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ p = vtabDisconnectAll(db, pTab); xDestroy = p->pMod->pModule->xDestroy; assert( xDestroy!=0 ); /* Checked before the virtual table is created */ + pTab->nTabRef++; rc = xDestroy(p->pVtab); /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ @@ -849,6 +850,7 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ pTab->pVTable = 0; sqlite3VtabUnlock(p); } + sqlite3DeleteTable(db, pTab); } return rc; diff --git a/src/wal.c b/src/wal.c index 845ac56..53a9e50 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2908,9 +2908,9 @@ int sqlite3WalFindFrame( } nCollide = HASHTABLE_NSLOT; for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ - u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero; - if( iFrame<=iLast && iFrame>=pWal->minFrame - && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){ + u32 iH = sLoc.aHash[iKey]; + u32 iFrame = iH + sLoc.iZero; + if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){ assert( iFrame>iRead || CORRUPT_DB ); iRead = iFrame; } diff --git a/src/where.c b/src/where.c index cd00fe9..f2ab125 100644 --- a/src/where.c +++ b/src/where.c @@ -562,17 +562,17 @@ static LogEst estLog(LogEst N){ ** opcodes into OP_Copy when the table is being accessed via co-routine ** instead of via table lookup. ** -** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on -** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero, -** then each OP_Rowid is transformed into an instruction to increment the -** value stored in its output register. +** If the iAutoidxCur is not zero, then any OP_Rowid instructions on +** cursor iTabCur are transformed into OP_Sequence opcode for the +** iAutoidxCur cursor, in order to generate unique rowids for the +** automatic index being generated. */ static void translateColumnToCopy( Parse *pParse, /* Parsing context */ int iStart, /* Translate from this opcode to the end */ int iTabCur, /* OP_Column/OP_Rowid references to this table */ int iRegister, /* The first column is in this register */ - int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */ + int iAutoidxCur /* If non-zero, cursor of autoindex being generated */ ){ Vdbe *v = pParse->pVdbe; VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); @@ -586,11 +586,9 @@ static void translateColumnToCopy( pOp->p2 = pOp->p3; pOp->p3 = 0; }else if( pOp->opcode==OP_Rowid ){ - if( bIncrRowid ){ - /* Increment the value stored in the P2 operand of the OP_Rowid. */ - pOp->opcode = OP_AddImm; - pOp->p1 = pOp->p2; - pOp->p2 = 1; + if( iAutoidxCur ){ + pOp->opcode = OP_Sequence; + pOp->p1 = iAutoidxCur; }else{ pOp->opcode = OP_Null; pOp->p1 = 0; @@ -737,7 +735,7 @@ static void constructAutomaticIndex( && (pTerm->wtFlags & TERM_VIRTUAL)==0 && !ExprHasProperty(pExpr, EP_FromJoin) && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ - pPartial = sqlite3ExprAnd(pParse->db, pPartial, + pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); } if( termCanDriveIndex(pTerm, pSrc, notReady) ){ @@ -864,8 +862,9 @@ static void constructAutomaticIndex( if( pTabItem->fg.viaCoroutine ){ sqlite3VdbeChangeP2(v, addrCounter, regBase+n); testcase( pParse->db->mallocFailed ); + assert( pLevel->iIdxCur>0 ); translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pTabItem->regResult, 1); + pTabItem->regResult, pLevel->iIdxCur); sqlite3VdbeGoto(v, addrTop); pTabItem->fg.viaCoroutine = 0; }else{ diff --git a/src/whereInt.h b/src/whereInt.h index 07876f4..090bbc2 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -14,6 +14,8 @@ ** planner logic in "where.c". These definitions are broken out into ** a separate source file for easier editing. */ +#ifndef SQLITE_WHEREINT_H +#define SQLITE_WHEREINT_H /* ** Trace output macros @@ -584,3 +586,5 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ + +#endif /* !defined(SQLITE_WHEREINT_H) */ diff --git a/src/wherecode.c b/src/wherecode.c index f710690..a625448 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -999,7 +999,7 @@ static void codeCursorHint( } /* If we survive all prior tests, that means this term is worth hinting */ - pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); + pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); } if( pExpr!=0 ){ sWalker.xExprCallback = codeCursorHintFixExpr; @@ -1964,7 +1964,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); - pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); + pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); } if( pAndExpr ){ /* The extra 0x10000 bit on the opcode is masked off and does not @@ -2115,7 +2115,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeGoto(v, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); - if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab); + if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); } if( !untestedTerms ) disableTerm(pLevel, pTerm); }else #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ diff --git a/src/whereexpr.c b/src/whereexpr.c index 961495c..9ac940c 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -262,27 +262,33 @@ static int isLikeOrGlob( zNew[iTo++] = zNew[iFrom]; } zNew[iTo] = 0; + assert( iTo>0 ); - /* If the RHS begins with a digit or a minus sign, then the LHS must be - ** an ordinary column (not a virtual table column) with TEXT affinity. - ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false - ** even though "lhs LIKE rhs" is true. But if the RHS does not start - ** with a digit or '-', then "lhs LIKE rhs" will always be false if - ** the LHS is numeric and so the optimization still works. + /* If the LHS is not an ordinary column with TEXT affinity, then the + ** pattern prefix boundaries (both the start and end boundaries) must + ** not look like a number. Otherwise the pattern might be treated as + ** a number, which will invalidate the LIKE optimization. ** - ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033 - ** The RHS pattern must not be '/%' because the termination condition - ** will then become "x<'0'" and if the affinity is numeric, will then - ** be converted into "x<0", which is incorrect. + ** Getting this right has been a persistent source of bugs in the + ** LIKE optimization. See, for example: + ** 2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1 + ** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28 + ** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07 + ** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975 */ - if( sqlite3Isdigit(zNew[0]) - || zNew[0]=='-' - || (zNew[0]+1=='0' && iTo==1) + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ){ - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ - ){ + int isNum; + double rDummy; + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); + if( isNum<=0 ){ + zNew[iTo-1]++; + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); + zNew[iTo-1]--; + } + if( isNum>0 ){ sqlite3ExprDelete(db, pPrefix); sqlite3ValueFree(pVal); return 0; diff --git a/src/window.c b/src/window.c index 4b5184d..dcd7107 100644 --- a/src/window.c +++ b/src/window.c @@ -736,6 +736,7 @@ struct WindowRewrite { Window *pWin; SrcList *pSrc; ExprList *pSub; + Table *pTab; Select *pSubSelect; /* Current sub-select, if any */ }; @@ -796,6 +797,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ pExpr->op = TK_COLUMN; pExpr->iColumn = p->pSub->nExpr-1; pExpr->iTable = p->pWin->iEphCsr; + pExpr->y.pTab = p->pTab; } break; @@ -839,6 +841,7 @@ static void selectWindowRewriteEList( Window *pWin, SrcList *pSrc, ExprList *pEList, /* Rewrite expressions in this list */ + Table *pTab, ExprList **ppSub /* IN/OUT: Sub-select expression-list */ ){ Walker sWalker; @@ -850,6 +853,7 @@ static void selectWindowRewriteEList( sRewrite.pSub = *ppSub; sRewrite.pWin = pWin; sRewrite.pSrc = pSrc; + sRewrite.pTab = pTab; sWalker.pParse = pParse; sWalker.xExprCallback = selectWindowRewriteExprCb; @@ -868,13 +872,18 @@ static void selectWindowRewriteEList( static ExprList *exprListAppendList( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to append. Might be NULL */ - ExprList *pAppend /* List of values to append. Might be NULL */ + ExprList *pAppend, /* List of values to append. Might be NULL */ + int bIntToNull ){ if( pAppend ){ int i; int nInit = pList ? pList->nExpr : 0; for(i=0; inExpr; i++){ Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0); + if( bIntToNull && pDup && pDup->op==TK_INTEGER ){ + pDup->op = TK_NULL; + pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); + } pList = sqlite3ExprListAppend(pParse, pList, pDup); if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; } @@ -904,17 +913,24 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ExprList *pSublist = 0; /* Expression list for sub-query */ Window *pMWin = p->pWin; /* Master window object */ Window *pWin; /* Window object iterator */ + Table *pTab; + + pTab = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTab==0 ){ + return SQLITE_NOMEM; + } p->pSrc = 0; p->pWhere = 0; p->pGroupBy = 0; p->pHaving = 0; + p->selFlags &= ~SF_Aggregate; /* Create the ORDER BY clause for the sub-select. This is the concatenation ** of the window PARTITION and ORDER BY clauses. Then, if this makes it ** redundant, remove the ORDER BY from the parent SELECT. */ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0); - pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy); + pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1); if( pSort && p->pOrderBy ){ if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ sqlite3ExprListDelete(db, p->pOrderBy); @@ -928,15 +944,15 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ pMWin->iEphCsr = pParse->nTab++; pParse->nTab += 3; - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist); - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist); + selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, pTab, &pSublist); + selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, pTab, &pSublist); pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); /* Append the PARTITION BY and ORDER BY expressions to the to the ** sub-select expression list. They are required to figure out where ** boundaries for partitions and sets of peer rows lie. */ - pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition); - pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy); + pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition, 0); + pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0); /* Append the arguments passed to each window function to the ** sub-select expression list. Also allocate two registers for each @@ -944,7 +960,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** results. */ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList); + pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList, 0); if( pWin->pFilter ){ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); @@ -971,16 +987,19 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ); p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); if( p->pSrc ){ + Table *pTab2; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); - if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){ + pSub->selFlags |= SF_Expanded; + pTab2 = sqlite3ResultSetOfSelect(pParse, pSub); + if( pTab2==0 ){ rc = SQLITE_NOMEM; }else{ - pSub->selFlags |= SF_Expanded; - p->selFlags &= ~SF_Aggregate; - sqlite3SelectPrep(pParse, pSub, 0); + memcpy(pTab, pTab2, sizeof(Table)); + pTab->tabFlags |= TF_Ephemeral; + p->pSrc->a[0].pTab = pTab; + pTab = pTab2; } - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr); sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr); @@ -989,6 +1008,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ sqlite3SelectDelete(db, pSub); } if( db->mallocFailed ) rc = SQLITE_NOMEM; + sqlite3DbFree(db, pTab); } return rc; diff --git a/test/altertab.test b/test/altertab.test index 4a12f0d..602f753 100644 --- a/test/altertab.test +++ b/test/altertab.test @@ -559,4 +559,39 @@ ifcapable fts3 { } } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 17.0 { + CREATE TABLE sqlite1234 (id integer); + ALTER TABLE sqlite1234 RENAME TO User; + SELECT name, sql FROM sqlite_master WHERE sql IS NOT NULL; +} { + User {CREATE TABLE "User" (id integer)} +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 18.1.0 { + CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)) WITHOUT ROWID; +} +breakpoint +do_execsql_test 18.1.1 { + ALTER TABLE t0 RENAME COLUMN c0 TO c1; +} +do_execsql_test 18.1.2 { + SELECT sql FROM sqlite_master; +} {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1)) WITHOUT ROWID}} + +reset_db +do_execsql_test 18.2.0 { + CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)); +} +do_execsql_test 18.2.1 { + ALTER TABLE t0 RENAME COLUMN c0 TO c1; +} +do_execsql_test 18.2.2 { + SELECT sql FROM sqlite_master; +} {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1))}} + finish_test + diff --git a/test/altertab2.test b/test/altertab2.test index 9fa40d0..f14dc13 100644 --- a/test/altertab2.test +++ b/test/altertab2.test @@ -338,15 +338,27 @@ do_execsql_test 8.3 { INSERT INTO t3 VALUES(4, 5, 6); } -do_execsql_test 8.1 { +do_execsql_test 8.4 { CREATE TABLE t4(a, b); CREATE VIEW v4 AS SELECT * FROM t4 WHERE (a=1 AND 0) OR b=2; } -do_execsql_test 8.2 { + +# Do not rename branches of an expression tree that is optimized out by +# the AND optimization. +# +do_execsql_test 8.5 { ALTER TABLE t4 RENAME a TO c; SELECT sql FROM sqlite_master WHERE name = 'v4' -} {{CREATE VIEW v4 AS SELECT * FROM t4 WHERE (c=1 AND 0) OR b=2}} +} {{CREATE VIEW v4 AS SELECT * FROM t4 WHERE (a=1 AND 0) OR b=2}} +# "a" is not renamed to "c" ---^ + +# 2019-06-10 https://www.sqlite.org/src/info/533010b8cacebe82 +reset_db +do_execsql_test 8.6 { + CREATE TABLE t0(c0); + CREATE INDEX i0 ON t0(LIKELIHOOD(1,2) AND 0); + ALTER TABLE t0 RENAME TO t1; + SELECT sql FROM sqlite_master WHERE name='i0'; +} {{CREATE INDEX i0 ON "t1"(LIKELIHOOD(1,2) AND 0)}} finish_test - - diff --git a/test/altertab3.test b/test/altertab3.test index 2bf6a9d..863da72 100644 --- a/test/altertab3.test +++ b/test/altertab3.test @@ -79,7 +79,7 @@ do_execsql_test 3.1 { do_execsql_test 3.2 { SELECT sql FROM sqlite_master WHERE name = 'v1' -} {{CREATE VIEW v1 AS SELECT * FROM t1 WHERE a=1 OR (bbb IN ())}} +} {{CREATE VIEW v1 AS SELECT * FROM t1 WHERE a=1 OR (b IN ())}} #------------------------------------------------------------------------- reset_db @@ -142,6 +142,100 @@ do_execsql_test 6.1 { ALTER TABLE Table0 RENAME Col0 TO Col0; } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 7.1.0 { + CREATE TABLE t1(a,b,c); + CREATE TRIGGER AFTER INSERT ON t1 BEGIN + SELECT a, rank() OVER w1 FROM t1 + WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1); + END; +} + +do_execsql_test 7.1.2 { + ALTER TABLE t1 RENAME TO t1x; + SELECT sql FROM sqlite_master; +} { + {CREATE TABLE "t1x"(a,b,c)} + {CREATE TRIGGER AFTER INSERT ON "t1x" BEGIN + SELECT a, rank() OVER w1 FROM "t1x" + WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1); + END} +} + +do_execsql_test 7.2.1 { + DROP TRIGGER after; + CREATE TRIGGER AFTER INSERT ON t1x BEGIN + SELECT a, rank() OVER w1 FROM t1x + WINDOW w1 AS (PARTITION BY b, percent_rank() OVER w1 ORDER BY d); + END; +} + +do_catchsql_test 7.2.2 { + ALTER TABLE t1x RENAME TO t1; +} {1 {error in trigger AFTER: no such column: d}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 8.0 { + CREATE TABLE t0(c0); + CREATE INDEX i0 ON t0('1' IN ()); +} +do_execsql_test 8.1 { + ALTER TABLE t0 RENAME TO t1; + SELECT sql FROM sqlite_master; +} { + {CREATE TABLE "t1"(c0)} + {CREATE INDEX i0 ON "t1"('1' IN ())} +} +do_execsql_test 8.2.1 { + CREATE TABLE t2 (c0); + CREATE INDEX i2 ON t2((LIKELIHOOD(c0, 100) IN ())); + ALTER TABLE t2 RENAME COLUMN c0 TO c1; +} +do_execsql_test 8.2.2 { + SELECT sql FROM sqlite_master WHERE tbl_name = 't2'; +} { + {CREATE TABLE t2 (c1)} + {CREATE INDEX i2 ON t2((LIKELIHOOD(c0, 100) IN ()))} +} +do_test 8.2.3 { + sqlite3 db2 test.db + db2 eval { INSERT INTO t2 VALUES (1), (2), (3) } + db close +} {} +db2 close + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 9.1 { + CREATE TABLE t1(a,b,c); + CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN + SELECT true WHERE (SELECT a, b FROM (t1)) IN (); + END; +} +do_execsql_test 9.2 { + ALTER TABLE t1 RENAME TO t1x; +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 10.1 { + CREATE TABLE t1(a, b, c); + CREATE TABLE t2(a, b, c); + CREATE VIEW v1 AS SELECT * FROM t1 WHERE ( + SELECT t1.a FROM t1, t2 + ) IN () OR t1.a=5; +} + +do_execsql_test 10.2 { + ALTER TABLE t2 RENAME TO t3; + SELECT sql FROM sqlite_master WHERE name='v1'; +} { + {CREATE VIEW v1 AS SELECT * FROM t1 WHERE ( + SELECT t1.a FROM t1, t2 + ) IN () OR t1.a=5} +} + + finish_test - - diff --git a/test/autoindex5.test b/test/autoindex5.test index eabdeae..94e2203 100644 --- a/test/autoindex5.test +++ b/test/autoindex5.test @@ -123,6 +123,20 @@ do_execsql_test 2.1 { SELECT sum(z) FROM vvv WHERE x='aaa' ) FROM one; } {8.0} +do_execsql_test 2.2 { + DROP TABLE t1; + CREATE TABLE t1(aaa); + INSERT INTO t1(aaa) VALUES(9); + SELECT ( + SELECT aaa FROM t1 GROUP BY ( + SELECT bbb FROM ( + SELECT ccc AS bbb FROM ( + SELECT 1 ccc + ) WHERE rowid IS NOT 1 + ) WHERE bbb = 1 + ) + ); +} {9} # Ticket https://www.sqlite.org/src/info/787fa716be3a7f65 # Segfault due to multiple uses of the same subquery where the diff --git a/test/between.test b/test/between.test index df4c679..e2b25ca 100644 --- a/test/between.test +++ b/test/between.test @@ -119,5 +119,25 @@ do_test between-1.5.3 { } } {4 2 25 27 sort t1 *} +#------------------------------------------------------------------------- +reset_db +do_execsql_test between-2.0 { + CREATE TABLE t1(x TEXT, y TEXT COLLATE nocase); + INSERT INTO t1 VALUES('0', 'abc'); +} + +foreach {tn expr res} { + 1 "x BETWEEN 1 AND '5'" 0 + 2 "x COLLATE binary BETWEEN 1 AND '5'" 0 + 3 "x COLLATE nocase BETWEEN 1 AND '5'" 0 + + 4 "y BETWEEN 'A' AND 'B'" 1 + 5 "y COLLATE nocase BETWEEN 'A' AND 'B'" 1 + 6 "y COLLATE binary BETWEEN 'A' AND 'B'" 0 + 7 "(y COLLATE binary) BETWEEN 'A' AND 'B'" 0 +} { + set sql "SELECT $expr FROM t1" + do_execsql_test between-2.1.$tn $sql $res +} finish_test diff --git a/test/cast.test b/test/cast.test index f43aa48..e6795ce 100644 --- a/test/cast.test +++ b/test/cast.test @@ -183,34 +183,34 @@ do_test cast-1.53 { execsql {SELECT CAST('123.5abc' AS integer)} } 123 -do_test case-1.60 { +do_test cast-1.60 { execsql {SELECT CAST(null AS REAL)} } {{}} -do_test case-1.61 { +do_test cast-1.61 { execsql {SELECT typeof(CAST(null AS REAL))} } {null} -do_test case-1.62 { +do_test cast-1.62 { execsql {SELECT CAST(1 AS REAL)} } {1.0} -do_test case-1.63 { +do_test cast-1.63 { execsql {SELECT typeof(CAST(1 AS REAL))} } {real} -do_test case-1.64 { +do_test cast-1.64 { execsql {SELECT CAST('1' AS REAL)} } {1.0} -do_test case-1.65 { +do_test cast-1.65 { execsql {SELECT typeof(CAST('1' AS REAL))} } {real} -do_test case-1.66 { +do_test cast-1.66 { execsql {SELECT CAST('abc' AS REAL)} } {0.0} -do_test case-1.67 { +do_test cast-1.67 { execsql {SELECT typeof(CAST('abc' AS REAL))} } {real} -do_test case-1.68 { +do_test cast-1.68 { execsql {SELECT CAST(x'31' AS REAL)} } {1.0} -do_test case-1.69 { +do_test cast-1.69 { execsql {SELECT typeof(CAST(x'31' AS REAL))} } {real} @@ -299,7 +299,7 @@ if {[db eval {PRAGMA encoding}]=="UTF-8"} { } 9223372036854774784 } } -do_test case-3.31 { +do_test cast-3.31 { execsql {SELECT CAST(NULL AS numeric)} } {{}} @@ -368,16 +368,17 @@ do_execsql_test cast-5.2 { # ignored because it is no part of the integer prefix. # EVIDENCE-OF: R-24225-46995 For example, "(CAST '123e+5' AS INTEGER)" # results in 123, not in 12300000. -do_execsql_test case-5.3 { +do_execsql_test cast-5.3 { SELECT CAST('123e+5' AS INTEGER); SELECT CAST('123e+5' AS NUMERIC); -} {123 12300000.0} + SELECT CAST('123e+5' AS REAL); +} {123 12300000 12300000.0} # The following does not have anything to do with the CAST operator, # but it does deal with affinity transformations. # -do_execsql_test case-6.1 { +do_execsql_test cast-6.1 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a NUMERIC); INSERT INTO t1 VALUES @@ -388,4 +389,78 @@ do_execsql_test case-6.1 { SELECT * FROM t1; } {9000000000000000001 9000000000000000001 9000000000000000001 9000000000000000001} +# 2019-06-07 +# https://www.sqlite.org/src/info/4c2d7639f076aa7c +do_execsql_test cast-7.1 { + SELECT CAST('-' AS NUMERIC); +} {0} +do_execsql_test cast-7.2 { + SELECT CAST('-0' AS NUMERIC); +} {0} +do_execsql_test cast-7.3 { + SELECT CAST('+' AS NUMERIC); +} {0} +do_execsql_test cast-7.4 { + SELECT CAST('/' AS NUMERIC); +} {0} + +# 2019-06-07 +# https://www.sqlite.org/src/info/e8bedb2a184001bb +do_execsql_test cast-7.10 { + SELECT '' - 2851427734582196970; +} {-2851427734582196970} +do_execsql_test cast-7.11 { + SELECT 0 - 2851427734582196970; +} {-2851427734582196970} +do_execsql_test cast-7.12 { + SELECT '' - 1; +} {-1} + +# 2019-06-10 +# https://www.sqlite.org/src/info/dd6bffbfb6e61db9 +# +# EVIDENCE-OF: R-55084-10555 Casting a TEXT or BLOB value into NUMERIC +# yields either an INTEGER or a REAL result. +# +do_execsql_test cast-7.20 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0 (c0 TEXT); + INSERT INTO t0(c0) VALUES ('1.0'); + SELECT CAST(c0 AS NUMERIC) FROM t0; +} {1} + +# 2019-06-10 +# https://sqlite.org/src/info/27de823723a41df45af3 +# +do_execsql_test cast-7.30 { + SELECT -'.'; +} 0 +do_execsql_test cast-7.31 { + SELECT '.'+0; +} 0 +do_execsql_test cast-7.32 { + SELECT CAST('.' AS numeric); +} 0 +do_execsql_test cast-7.33 { + SELECT -CAST('.' AS numeric); +} 0 + +# 2019-06-12 +# https://www.sqlite.org/src/info/674385aeba91c774 +# +do_execsql_test cast-7.40 { + SELECT CAST('-0.0' AS numeric); +} 0 +do_execsql_test cast-7.41 { + SELECT CAST('0.0' AS numeric); +} 0 +do_execsql_test cast-7.42 { + SELECT CAST('+0.0' AS numeric); +} 0 +do_execsql_test cast-7.43 { + SELECT CAST('-1.0' AS numeric); +} -1 + + + finish_test diff --git a/test/check.test b/test/check.test index a6dbaa6..dcd3c18 100644 --- a/test/check.test +++ b/test/check.test @@ -117,11 +117,13 @@ do_test check-1.17 { do_test check-2.1 { execsql { + PRAGMA writable_schema = 1; CREATE TABLE t2( x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ), y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) ); + PRAGMA writable_schema = 0; } } {} do_test check-2.2 { diff --git a/test/chunksize.test b/test/chunksize.test new file mode 100644 index 0000000..47d118d --- /dev/null +++ b/test/chunksize.test @@ -0,0 +1,41 @@ +# 2019 June 5 +# +# 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 chunksize + +if {$::tcl_platform(platform)!="unix"} { + finish_test + return +} + +foreach {tn jrnlmode} { + 1 delete + 2 wal +} { + reset_db + file_control_chunksize_test db main 32768 + do_execsql_test $tn.0 " PRAGMA journal_mode = $jrnlmode " $jrnlmode + do_execsql_test $tn.1 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2); + } + + execsql { PRAGMA wal_checkpoint } + + do_test $tn.2 { + file size test.db + } 32768 +} + +finish_test diff --git a/test/collate1.test b/test/collate1.test index 7cf5698..a1623f0 100644 --- a/test/collate1.test +++ b/test/collate1.test @@ -400,5 +400,21 @@ do_execsql_test 7.2 { ORDER BY 1 COLLATE binary COLLATE binary COLLATE binary COLLATE nocase; } {abc DEF} +# 2019-06-14 +# https://sqlite.org/src/info/f1580ba1b574e9e9 +# +do_execsql_test 8.0 { + SELECT ' ' > char(20) COLLATE rtrim; +} 0 +do_execsql_test 8.1 { + SELECT '' < char(20) COLLATE rtrim; +} 1 +do_execsql_test 8.2 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 COLLATE RTRIM, c1 BLOB UNIQUE, + PRIMARY KEY (c0, c1)) WITHOUT ROWID; + INSERT INTO t0 VALUES (123, 3), (' ', 1), (' ', 2), ('', 4); + SELECT * FROM t0 WHERE c1 = 1; +} {{ } 1} finish_test diff --git a/test/corruptL.test b/test/corruptL.test index 213af9d..53a68a0 100644 --- a/test/corruptL.test +++ b/test/corruptL.test @@ -838,4 +838,226 @@ do_catchsql_test 8.1 { INSERT INTO t3 SELECT * FROM t2; } {1 {database disk image is malformed}} +#------------------------------------------------------------------------- +reset_db +do_test 9.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 8192 pagesize 4096 filename crash-ab10597e4e1c32.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 01 0f d6 00 0f d6 00 00 ................ +| 4048: 00 00 00 00 00 00 28 01 06 17 11 11 01 3d 74 61 ......(......=ta +| 4064: 62 6c 65 74 31 74 31 02 43 52 45 41 54 45 20 54 blet1t1.CREATE T +| 4080: 41 42 4c 45 20 74 31 28 61 2c 62 2c 63 2c 64 29 ABLE t1(a,b,c,d) +| page 2 offset 4096 +| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| end crash-ab10597e4e1c32.db +}]} {} + +do_execsql_test 9.1 { + SAVEPOINT one; +} +do_catchsql_test 9.3 { + INSERT INTO t1(b,c) VALUES(5,6); +} {1 {database disk image is malformed}} +do_execsql_test 9.3 { + ROLLBACK TO one; +} + +#------------------------------------------------------------------------- +reset_db +do_test 10.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 180224 pagesize 4096 filename crash-41390d95d613b6.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 04 0e e2 00 0f 96 0f 44 ...............D +| 112: 0f 10 0e e2 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 3808: 00 00 2c 14 06 17 15 11 01 41 69 6e 64 65 78 74 ..,......Aindext +| 3824: 41 78 33 74 31 06 43 52 45 41 54 45 20 49 4e 44 Ax3t1.CREATE IND +| 3840: 45 58 20 74 31 78 32 20 4f 4e 20 74 31 28 62 29 EX t1x2 ON t1(b) +| 3856: 32 03 06 17 15 11 01 4d 69 6e 64 65 78 74 31 88 2......Mindext1. +| 3872: 31 74 31 05 43 52 45 41 54 45 20 49 4e 44 45 58 1t1.CREATE INDEX +| 3888: 20 74 31 78 31 20 4f 4e 20 74 31 28 67 2b 68 2c t1x1 ON t1(g+h, +| 3904: 6a 2d 6b 29 50 02 06 17 2b 2b 01 59 74 61 62 6c j-k)P...++.Ytabl +| 3920: 65 73 71 6c 69 74 65 5e 73 65 71 74 65 6e 63 65 esqlite^seqtence +| 3936: 73 71 6c 69 74 65 5f 73 65 71 75 65 6e 63 65 04 sqlite_sequence. +| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 73 71 6c CREATE TABLE sql +| 3968: 69 74 65 5f 73 65 71 75 65 6e 63 65 28 6e 61 6d ite_sequence(nam +| 3984: 65 2c 73 65 71 29 68 00 07 17 11 11 01 81 3b 74 e,seq)h.......;t +| 4000: 61 62 6c 65 74 31 74 31 03 43 52 45 41 54 45 20 ablet1t1.CREATE +| 4016: 54 41 42 4c 45 20 74 31 28 61 20 49 4e 54 45 47 TABLE t1(a INTEG +| 4032: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 20 41 ER PRIMARY KEY A +| 4048: 55 54 4f 49 4e 43 52 45 4d 45 4e 54 2c 0a 62 2c UTOINCREMENT,.b, +| 4064: 63 2c 64 2c 65 2c 66 2c 67 2c 68 2c 6a 2c 6b 2c c,d,e,f,g,h,j,k, +| 4080: 6c 2c 6d 2c 6e 2c 6f 2c 70 2c 71 2c 72 2c 73 29 l,m,n,o,p,q,r,s) +| page 2 offset 4096 +| 0: 01 00 00 00 00 01 00 00 10 00 01 00 00 00 00 01 ................ +| 16: 00 00 00 00 02 00 0f f0 00 15 00 00 00 03 02 00 ................ +| 32: 00 00 d9 05 00 00 00 03 02 00 00 00 00 05 00 00 ................ +| 48: 10 03 02 00 00 00 00 05 00 00 00 03 02 00 00 00 ................ +| 64: 00 05 00 00 00 02 62 00 00 00 00 05 00 00 00 03 ......b......... +| 80: 02 00 00 00 00 05 00 00 00 03 02 00 00 00 00 05 ................ +| 96: 00 00 00 03 02 00 00 00 00 05 00 00 00 03 05 00 ................ +| 112: 00 00 03 03 01 00 00 23 02 00 00 4f 00 02 00 00 .......#...O.... +| 128: 10 25 02 00 00 00 00 03 00 00 00 23 02 00 00 00 .%.........#.... +| 144: 00 03 00 00 00 23 02 00 00 00 00 03 00 00 00 23 .....#.........# +| 160: 05 00 08 90 06 05 00 00 00 06 01 ff 00 00 00 03 ................ +| 176: 00 00 00 06 02 00 00 00 00 02 ff 00 00 00 00 00 ................ +| page 3 offset 8192 +| 0: 05 00 00 00 09 0f d0 00 00 00 00 19 0f fb 0f f6 ................ +| 16: 0f f1 10 ec ec e7 0f e2 0f dc 0f d6 0f 00 00 00 ................ +| 1072: 00 97 4c 0a 24 00 ae 00 00 00 00 00 00 00 00 00 ..L.$........... +| 4048: 00 00 00 16 83 39 ff ff ff 14 81 16 00 00 00 12 .....9.......... +| 4064: 81 02 00 00 00 10 6e 00 00 00 0e 5a 00 00 00 0c ......n....Z.... +| 4080: 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F............... +| page 4 offset 12288 +| 1072: 97 4d 32 14 00 ae 00 00 00 00 00 00 00 00 00 00 .M2............. +| 4080: 00 00 00 00 00 00 00 07 01 03 11 02 74 31 00 bd ............t1.. +| page 5 offset 16384 +| 0: fa 0f 7c 00 0a 0f 74 00 0f f9 0f eb 0f dd 0f cf ..|...t......... +| 16: 0f c1 0f b3 0f a4 0e 94 0f 84 0f 74 0f 74 0f 74 ...........t.t.t +| 32: 0f 74 0f 64 0f 00 00 00 00 00 00 00 00 00 00 00 .t.d............ +| 3952: 00 00 00 00 07 05 00 00 00 02 00 be 0f 8c 10 07 ................ +| 3968: ff ff 00 00 07 05 00 00 00 02 00 aa 0f 9b f0 08 ................ +| 3984: c8 00 00 00 37 06 00 00 00 01 00 96 0f ac 00 08 ....7........... +| 4000: 00 00 00 b3 07 15 00 10 00 02 00 82 0f ba 00 07 ................ +| 4016: 00 00 00 06 05 00 00 00 01 6e 0f c8 00 07 00 00 .........n...... +| 4032: 00 06 05 00 00 00 01 5a 03 f6 00 07 00 00 00 06 .......Z........ +| 4048: 05 00 00 00 01 46 0f e4 00 07 00 00 10 06 05 00 .....F.......... +| 4064: 00 00 01 32 10 02 00 07 00 00 00 07 05 00 00 00 ...2............ +| 4080: 01 1d ff ff ff 07 10 00 00 06 05 00 00 00 01 0a ................ +| page 6 offset 20480 +| 624: 00 00 00 00 00 21 97 00 00 00 00 00 00 00 00 00 .....!.......... +| 1120: 00 00 00 00 00 24 57 3e 00 00 00 00 00 00 00 00 .....$W>........ +| 1616: 00 00 00 00 1f 97 00 00 00 00 00 00 00 00 00 00 ................ +| 2112: 00 00 00 1e 97 3d 00 00 00 00 00 00 00 00 00 00 .....=.......... +| 2608: 00 1d 97 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| page 8 offset 28672 +| 1184: 00 00 00 00 00 00 00 00 00 97 4d 1e 13 ff ae 7c ..........M....| +| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 ................ +| page 9 offset 32768 +| 256: 0d 01 c0 00 01 04 30 00 04 30 00 00 00 00 00 00 ......0..0...... +| page 10 offset 36864 +| 0: 0d 00 22 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 ................ +| page 12 offset 45056 +| 0: 0d 00 00 00 01 04 30 00 00 00 00 00 00 00 00 00 ......0......... +| page 14 offset 53248 +| 0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00 ......0..0...... +| 1072: 96 4d 5a 14 00 00 00 00 00 00 00 00 00 00 00 00 .MZ............. +| page 16 offset 61440 +| 0: 0d 00 00 00 01 04 30 00 04 30 00 00 00 00 00 00 ......0..0...... +| 1072: 97 4d 6e 14 00 ae 7b ff ff ff ff 00 00 00 00 00 .Mn............. +| page 18 offset 69632 +| 1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................ +| 1072: 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 M............... +| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d ................ +| page 20 offset 77824 +| 1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................ +| 1072: 4d 81 16 14 00 ae 00 00 00 00 00 00 00 00 00 00 M............... +| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f ................ +| page 22 offset 86016 +| 0: 0d 00 00 00 01 04 2f 00 04 2f 01 00 00 00 00 00 ....../../...... +| 1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................ +| 1072: 4d 81 2a 14 00 00 00 00 00 00 00 00 00 00 00 00 M.*............. +| page 24 offset 94208 +| 1072: 00 97 4c 0a 14 00 ae 7c 00 00 00 00 00 00 00 00 ..L....|........ +| page 25 offset 98304 +| 1056: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 97 ................ +| 1072: 4d 81 3e 14 00 ae 7c 00 00 18 ff 00 00 00 00 00 M.>...|......... +| page 27 offset 106496 +| 0: 00 00 00 00 00 00 00 12 00 00 00 07 00 00 00 1d ................ +| 16: 00 00 00 09 00 00 00 1f 00 00 00 0b 00 00 00 21 ...............! +| 32: 00 00 00 0d 00 10 00 25 00 00 00 0f 00 00 00 27 .......%.......' +| 48: 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| page 32 offset 126976 +| 2512: 00 00 00 00 00 00 00 45 21 00 00 00 00 00 00 00 .......E!....... +| page 35 offset 139264 +| 0: 00 0a 08 44 00 05 02 77 00 0e 11 0a 92 00 00 00 ...D...w........ +| 1120: 00 00 00 00 00 20 97 00 00 00 00 00 00 00 00 00 ..... .......... +| 1616: 00 00 00 00 22 00 00 00 00 00 00 00 00 00 00 00 ................ +| 2608: 00 00 00 97 3d 04 00 00 00 00 00 00 00 00 00 00 ....=........... +| 3104: 00 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 3600: 00 97 3d 04 ae 7c 00 00 00 00 00 00 00 00 00 00 ..=..|.......... +| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1a ................ +| page 36 offset 143360 +| 0: 0a 08 44 00 04 02 00 00 00 00 00 00 00 00 00 00 ..D............. +| 1120: 00 00 00 00 00 2a 97 3e 04 00 00 00 00 00 00 00 .....*.>........ +| 1616: 00 00 00 00 2c 97 3e 00 00 00 00 00 00 00 00 00 ....,.>......... +| 2112: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 38 ...............8 +| 2128: 00 00 05 cd 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 3600: 00 97 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| page 38 offset 151552 +| 2464: 00 00 00 00 00 00 00 00 00 6e 00 00 00 00 00 00 .........n...... +| page 40 offset 159744 +| 2512: 00 00 00 00 00 00 00 00 82 00 00 00 00 00 00 00 ................ +| page 42 offset 167936 +| 2512: 00 00 00 00 00 00 00 96 00 00 00 00 00 00 00 00 ................ +| page 44 offset 176128 +| 2512: 00 00 00 00 00 00 00 00 aa 00 00 00 00 00 00 00 ................ +| end crash-41390d95d613b6.db +}]} {} + +do_catchsql_test 10.1 { + SELECT * FROM t1 WHERE a<='2019-05-09' ORDER BY a DESC; +} {1 {database disk image is malformed}} + + +#------------------------------------------------------------------------- +reset_db +do_test 11.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 595 pagesize 512 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: 02 00 00 01 00 40 20 20 00 01 00 0c 00 00 00 07 .....@ ........ +| 32: 00 00 00 05 07 a1 1f fa 00 00 00 08 00 00 00 04 ................ +| 48: 00 00 01 00 00 49 00 00 00 00 00 05 00 00 00 00 .....I.......... +| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1c ................ +| 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 62 00 00 00 00 00 .V...*....b..... +| 128: 00 ed e2 78 74 64 33 ff 43 52 45 41 54 45 20 49 ...xtd3.CREATE I +| 144: 4e 44 45 58 20 74 33 78 20 4f 4e 20 74 33 28 38 NDEX t3x ON t3(8 +| 160: 29 2e 04 06 17 15 11 01 45 69 6e 64 65 68 74 32 ).......Eindeht2 +| 176: 63 64 74 31 e5 43 52 45 41 54 45 20 49 4e 44 45 cdt1.CREATE INDE +| 192: 58 20 74 32 63 c4 20 4f 4e 20 74 32 28 63 2c 64 X t2c. ON t2(c,d +| 208: 29 28 05 06 17 01 11 11 3d 74 61 6c 36 74 62 74 )(......=tal6tbt +| 224: 65 32 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 e2.CREATE TABLE +| 240: 74 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 t............... +| 256: 00 00 00 00 00 00 22 07 06 17 11 11 01 30 e8 03 .............0.. +| 272: 62 6c 65 74 34 74 35 02 43 52 45 41 54 45 20 54 blet4t5.CREATE T +| 288: 41 42 4c 45 20 74 34 28 94 29 2a 06 06 17 13 11 ABLE t4(.)*..... +| 304: 01 3f 69 33 74 6e 65 78 78 74 64 33 ff 43 52 45 .?i3tnexxtd3.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 31 28 38 29 2e 04 06 17 15 11 01 45 69 6e t1(8).......Ein +| 352: 64 65 68 74 32 63 64 74 31 e5 43 52 45 41 54 45 deht2cdt1.CREATE +| 368: 20 49 4e 44 45 58 20 74 32 63 c4 20 4f 4e 20 74 INDEX t2c. ON t +| 384: 32 28 63 2c 64 29 28 05 06 17 01 11 11 3d 74 61 2(c,d)(......=ta +| 400: 6c 32 74 62 74 65 32 04 43 52 45 41 54 45 20 54 l2tbte2.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 9e 93 65 74 32 74 (......=ta..et2t +| 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 55 61 62 6c 88 74 31 74 31 02 43 52 45 41 .5Uabl.t1t1.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 0d 25 00 01 cf 00 01 fa 01 f3 01 de .....%.......... +| 16: 01 00 00 00 fd 00 00 0d 00 00 00 00 45 20 54 41 ............E TA +| 32: 42 4c 45 20 74 34 28 94 29 2a 06 06 17 13 11 01 BLE t4(.)*...... +| 48: 3f 69 33 74 6e 65 78 78 74 64 33 ff 43 52 45 a0 ?i3tnexxtd3.CRE. +| 64: a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 74 13 11 01 ............t... +| 80: 49 45 74 00 00 00 00 00 00 00 00 00 00 00 00 00 IEt............. +| end x.db +}]} {} + +do_catchsql_test 11.1 { + DELETE FROM t3 WHERE x IN (SELECT x FROM t4); +} {1 {database disk image is malformed}} + finish_test diff --git a/test/countofview.test b/test/countofview.test index 5f892ee..0ee511f 100644 --- a/test/countofview.test +++ b/test/countofview.test @@ -40,4 +40,17 @@ do_execsql_test 1.3 { ) } {3} +# 2019-05-15 +do_execsql_test 2.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1),(99),('abc'); + CREATE VIEW v1(x,y) AS SELECT x,1 FROM t1 UNION ALL SELECT x,2 FROM t1; + SELECT count(*) FROM v1 WHERE x<>1; +} {4} +do_execsql_test 2.1 { + SELECT count(*) FROM v1 GROUP BY y; +} {3 3} + + + finish_test diff --git a/test/dbdata.test b/test/dbdata.test new file mode 100644 index 0000000..5b1150c --- /dev/null +++ b/test/dbdata.test @@ -0,0 +1,115 @@ +# 2019-04-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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is testing the sqlite_dbpage virtual table. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix dbdata + +ifcapable !vtab||!compound { + finish_test + return +} +if { [catch { db enable_load_extension 1 }] + || [catch { db eval { SELECT load_extension('../dbdata') } }] +} { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE T1(a, b); + INSERT INTO t1(rowid, a ,b) VALUES(5, 'v', 'five'); + INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten'); +} + +do_execsql_test 1.1 { + SELECT pgno, cell, field, quote(value) FROM sqlite_dbdata WHERE pgno=2; +} { + 2 0 -1 5 + 2 0 0 'v' + 2 0 1 'five' + 2 1 -1 10 + 2 1 0 'x' + 2 1 1 'ten' +} + +breakpoint +do_execsql_test 1.2 { + SELECT pgno, cell, field, quote(value) FROM sqlite_dbdata; +} { + 1 0 -1 1 + 1 0 0 'table' + 1 0 1 'T1' + 1 0 2 'T1' + 1 0 3 2 + 1 0 4 {'CREATE TABLE T1(a, b)'} + 2 0 -1 5 + 2 0 0 'v' + 2 0 1 'five' + 2 1 -1 10 + 2 1 0 'x' + 2 1 1 'ten' +} + +set big [string repeat big 2000] +do_execsql_test 1.3 { + INSERT INTO t1 VALUES(NULL, $big); + SELECT value FROM sqlite_dbdata WHERE pgno=2 AND cell=2 AND field=1; +} $big + +do_execsql_test 1.4 { + DELETE FROM t1; + INSERT INTO t1 VALUES(NULL, randomblob(5050)); +} +do_test 1.5 { + execsql { + SELECT quote(value) FROM sqlite_dbdata WHERE pgno=2 AND cell=0 AND field=1; + } +} [db one {SELECT quote(b) FROM t1}] + +#------------------------------------------------------------------------- +reset_db +db enable_load_extension 1 +db eval { SELECT load_extension('../dbdata') } + +do_execsql_test 2.0 { + CREATE TABLE t1(a); + CREATE INDEX i1 ON t1(a); + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 + ) + INSERT INTO t1 SELECT randomblob(900) FROM s; +} + +do_execsql_test 2.1 { + SELECT * FROM sqlite_dbptr WHERE pgno=2; +} { + 2 25 2 6 2 7 2 9 2 11 2 13 2 15 2 17 2 19 2 21 +} + +do_execsql_test 2.2 { + SELECT * FROM sqlite_dbptr WHERE pgno=3; +} { + 3 24 3 23 +} + +do_execsql_test 2.3 { + SELECT * FROM sqlite_dbptr +} { + 2 25 2 6 2 7 2 9 2 11 2 13 2 15 2 17 2 19 2 21 + 3 24 3 23 +} + + +finish_test diff --git a/test/dbfuzz2.c b/test/dbfuzz2.c index 3e277c9..025204d 100644 --- a/test/dbfuzz2.c +++ b/test/dbfuzz2.c @@ -377,6 +377,7 @@ int main(int argc, char **argv){ free(pIn); } } +#ifdef RUSAGE_SELF if( eVerbosity>0 ){ struct rusage x; printf("SQLite %s\n", sqlite3_sourceid()); @@ -385,6 +386,7 @@ int main(int argc, char **argv){ printf("Maximum RSS = %ld KB\n", x.ru_maxrss); } } +#endif return 0; } #endif /*STANDALONE*/ diff --git a/test/e_expr.test b/test/e_expr.test index 1cac319..b8445c2 100644 --- a/test/e_expr.test +++ b/test/e_expr.test @@ -1013,13 +1013,18 @@ sqlite3 db test.db # EVIDENCE-OF: R-22868-25880 The LIKE operator can be made case # sensitive using the case_sensitive_like pragma. # -do_execsql_test e_expr-16.1.1 { SELECT 'abcxyz' LIKE 'ABC%' } 1 -do_execsql_test e_expr-16.1.2 { PRAGMA case_sensitive_like = 1 } {} -do_execsql_test e_expr-16.1.3 { SELECT 'abcxyz' LIKE 'ABC%' } 0 -do_execsql_test e_expr-16.1.4 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 -do_execsql_test e_expr-16.1.5 { PRAGMA case_sensitive_like = 0 } {} -do_execsql_test e_expr-16.1.6 { SELECT 'abcxyz' LIKE 'ABC%' } 1 -do_execsql_test e_expr-16.1.7 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 +do_execsql_test e_expr-16.1.1 { SELECT 'abcxyz' LIKE 'ABC%' } 1 +do_execsql_test e_expr-16.1.1b { SELECT 'abc%xyz' LIKE 'ABC\%x%' ESCAPE '\' } 1 +do_execsql_test e_expr-16.1.2 { PRAGMA case_sensitive_like = 1 } {} +do_execsql_test e_expr-16.1.3 { SELECT 'abcxyz' LIKE 'ABC%' } 0 +do_execsql_test e_expr-16.1.3b { SELECT 'abc%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 0 +do_execsql_test e_expr-16.1.4 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 +do_execsql_test e_expr-16.1.4b { SELECT 'ABC%xyz' LIKE 'ABC\%x%' ESCAPE '\' } 1 +do_execsql_test e_expr-16.1.5 { PRAGMA case_sensitive_like = 0 } {} +do_execsql_test e_expr-16.1.6 { SELECT 'abcxyz' LIKE 'ABC%' } 1 +do_execsql_test e_expr-16.1.6b { SELECT 'abc%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 1 +do_execsql_test e_expr-16.1.7 { SELECT 'ABCxyz' LIKE 'ABC%' } 1 +do_execsql_test e_expr-16.1.7b { SELECT 'ABC%xyz' LIKE 'ABC\%X%' ESCAPE '\' } 1 # EVIDENCE-OF: R-52087-12043 The GLOB operator is similar to LIKE but # uses the Unix file globbing syntax for its wildcards. @@ -1639,16 +1644,40 @@ do_expr_test e_expr-31.2.4 { } integer 9223372036854775807 -# EVIDENCE-OF: R-09295-61337 Casting a TEXT or BLOB value into NUMERIC -# first does a forced conversion into REAL but then further converts the -# result into INTEGER if and only if the conversion from REAL to INTEGER -# is lossless and reversible. +# EVIDENCE-OF: R-55084-10555 Casting a TEXT or BLOB value into NUMERIC +# yields either an INTEGER or a REAL result. +# +# EVIDENCE-OF: R-48945-04866 If the input text looks like an integer +# (there is no decimal point nor exponent) and the value is small enough +# to fit in a 64-bit signed integer, then the result will be INTEGER. +# +# EVIDENCE-OF: R-47045-23194 Input text that looks like floating point +# (there is a decimal point and/or an exponent) and the text describes a +# value that can be losslessly converted back and forth between IEEE 754 +# 64-bit float and a 51-bit signed integer, then the result is INTEGER. # do_expr_test e_expr-32.1.1 { CAST('45' AS NUMERIC) } integer 45 do_expr_test e_expr-32.1.2 { CAST('45.0' AS NUMERIC) } integer 45 do_expr_test e_expr-32.1.3 { CAST('45.2' AS NUMERIC) } real 45.2 do_expr_test e_expr-32.1.4 { CAST('11abc' AS NUMERIC) } integer 11 do_expr_test e_expr-32.1.5 { CAST('11.1abc' AS NUMERIC) } real 11.1 +do_expr_test e_expr-32.1.6 {CAST( '9.223372036e14' AS NUMERIC)} integer 922337203600000 +do_expr_test e_expr-32.1.7 {CAST('-9.223372036e14' AS NUMERIC)} integer -922337203600000 +do_expr_test e_expr-32.1.8 {CAST( '9.223372036e15' AS NUMERIC)} real 9223372036000000.0 +do_expr_test e_expr-32.1.9 {CAST('-9.223372036e15' AS NUMERIC)} real -9223372036000000.0 + + +# EVIDENCE-OF: R-50300-26941 Any text input that describes a value +# outside the range of a 64-bit signed integer yields a REAL result. +# +do_expr_test e_expr-32.1.20 { CAST('9223372036854775807' AS numeric) } \ + integer 9223372036854775807 +do_expr_test e_expr-32.1.21 { CAST('9223372036854775808' AS numeric) } \ + real 9.22337203685478e+18 +do_expr_test e_expr-32.1.22 { CAST('-9223372036854775808' AS numeric) } \ + integer -9223372036854775808 +do_expr_test e_expr-32.1.23 { CAST('-9223372036854775809' AS numeric) } \ + real -9.22337203685478e+18 # EVIDENCE-OF: R-30347-18702 Casting a REAL or INTEGER value to NUMERIC # is a no-op, even if a real value could be losslessly converted to an @@ -1696,14 +1725,14 @@ do_execsql_test e_expr-32.2.8 { integer 9000000000000000001 \ integer 9000000000000000001 \ integer 9000000000000000001 \ - integer 9000000000000000001 \ + real 9.0e+18 \ integer 9223372036854775807 \ integer 9223372036854775807 \ integer 9223372036854775807 \ real 9.22337203685478e+18 \ real 9.22337203685478e+18 \ - integer 9223372036854775807 \ - integer 9223372036854775807 \ + real 9.22337203685478e+18 \ + real 9.22337203685478e+18 \ integer -5 \ integer -5 \ ] diff --git a/test/expr2.test b/test/expr2.test new file mode 100644 index 0000000..3dfbadc --- /dev/null +++ b/test/expr2.test @@ -0,0 +1,54 @@ +# 2019 May 20 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is testing expressions. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix expr2 + +do_execsql_test 1.0 { + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES ('val'); +} + +do_execsql_test 1.1 { + SELECT * FROM t0 WHERE ( + ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) IS 0 + ) +} {val} + +do_execsql_test 1.2.1 { + SELECT + ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) IS 0 + FROM t0 +} {1} + +do_execsql_test 1.2.2 { + SELECT + ( (0 IS NOT FALSE) OR NOT (0 IS 0 OR (t0.c0 = 1)) ) IS 0 + FROM t0 +} {1} + +do_execsql_test 1.3 { + SELECT ( (0 IS NOT FALSE) OR NOT (0 IS FALSE OR (t0.c0 = 1)) ) FROM t0 +} {0} + +do_execsql_test 1.4.1 { + SELECT (0 IS NOT FALSE) FROM t0 +} {0} +do_execsql_test 1.4.2 { + SELECT NOT (0 IS FALSE OR (t0.c0 = 1)) FROM t0 +} {0} + + +finish_test diff --git a/test/fkey7.test b/test/fkey7.test index e86fc5c..77870a7 100644 --- a/test/fkey7.test +++ b/test/fkey7.test @@ -82,4 +82,40 @@ ifcapable stat4 { } } + +do_execsql_test 4.0 { + PRAGMA foreign_keys = true; + CREATE TABLE parent( + p PRIMARY KEY + ); + CREATE TABLE child( + c UNIQUE REFERENCES parent(p) + ); +} + +do_catchsql_test 4.1 { + INSERT OR FAIL INTO child VALUES(123), (123); +} {1 {FOREIGN KEY constraint failed}} + +do_execsql_test 4.2 { + SELECT * FROM child; +} {} + +do_execsql_test 4.3 { + PRAGMA foreign_key_check; +} {} + +do_catchsql_test 4.4 { + INSERT INTO parent VALUES(123); + INSERT OR FAIL INTO child VALUES(123), (123); +} {1 {UNIQUE constraint failed: child.c}} + +do_execsql_test 4.5 { + SELECT * FROM child; +} {123} + +do_execsql_test 4.6 { + PRAGMA foreign_key_check; +} {} + finish_test diff --git a/test/fkey8.test b/test/fkey8.test index f38e835..42f997f 100644 --- a/test/fkey8.test +++ b/test/fkey8.test @@ -197,5 +197,36 @@ do_execsql_test 4.2 { INSERT OR REPLACE INTO t1 VALUES(20000, 20000); } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + PRAGMA foreign_keys = true; + CREATE TABLE parent( + p TEXT PRIMARY KEY + ); + CREATE TABLE child( + c INTEGER UNIQUE, + FOREIGN KEY(c) REFERENCES parent(p) DEFERRABLE INITIALLY DEFERRED + ); + BEGIN; + INSERT INTO child VALUES(123); + INSERT INTO parent VALUES('123'); + COMMIT; +} +do_execsql_test 5.1 { + PRAGMA integrity_check; +} {ok} + +do_execsql_test 5.2 { + INSERT INTO parent VALUES(1200); + BEGIN; + INSERT INTO child VALUES(456); + UPDATE parent SET p = '456' WHERE p=1200; + COMMIT; +} +do_execsql_test 5.3 { + PRAGMA integrity_check; +} {ok} + finish_test diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test index 12a3dfa..8c1a14a 100644 --- a/test/fts3corrupt4.test +++ b/test/fts3corrupt4.test @@ -1946,7 +1946,7 @@ do_test 13.0 { do_catchsql_test 13.1 { SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*'; -} {0 {0 0}} +} {0 {}} #------------------------------------------------------------------------- reset_db @@ -2826,7 +2826,7 @@ do_test 18.0 { do_catchsql_test 18.1 { SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*'; -} {0 0} +} {0 {}} #------------------------------------------------------------------------- reset_db @@ -3915,5 +3915,1184 @@ do_catchsql_test 23.1 { SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j'; } {1 {database disk image is malformed}} +#------------------------------------------------------------------------- +reset_db +do_test 24.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-369d042958c29b.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 03 10 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 67 64 69 72 egdir_1t1_segdir +| 3760: 06 0f c7 00 08 00 10 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: 64 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52 dst1_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 4f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1Ocontentt1_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 39 4d cid INTEGER PR9M +| 3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20 ARY KEY, 'c0a', +| 3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06 'c1b', '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 26 0b 48 0e 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 0e 94 03 28 0d 4f 0d 35 0d 1b 05 0b .......(.O.5.... +| 64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a .......x.W.>.$.. +| 2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00 .........?%..r.. +| 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 55 42 4.0 20160609 DUB +| 2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54 UG ENA.|E DBSTAT +| 2944: e4 d1 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53 ..TAB 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: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59 BTREE MAX MEMORY +| 3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c =50000000 OLIT L +| 3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48 OAC 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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22 DSAKu=0XMOCASE.. +| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d ..%..THREADSAFF= +| 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 52 49 4f IT LOAD EXTENRIO +| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O +| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000 +| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 +| 3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MB. 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 0d a5 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 1c 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 14 05 01 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 12 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN.BLE JSON1XB +| 3536: 49 4e 41 52 59 18 14 05 00 25 09 d9 45 4e 41 42 INARY....%..ENAB +| 3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17 LE JSO>1XNOCASE. +| 3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f ...%..EN@BLE JSO +| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c NARY....)..FNABL +| 3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45 H.GEOPOLYXNtCASE +| 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 30 46 54 53 35 58 42 49 ..ENABLE0FTS5XBI +| 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 0e 05 E FTS5XNOCASE... +| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X +| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB +| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY.. +| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4 +| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM. +| 3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53 ...1..ENBBLE 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 4a 4d 11 06 TAT VTABXRTRJM.. +| 3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR +| 3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 16 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 06 00 43 0f 17 43 9XNOCASE&...C..C +| 4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e OMPIKER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d 0 201606@9X)TRIM +| page 4 offset 12288 +| 0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 01 00 00 ................ +| 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 6e 6f 72 79 ..max.%....enory +| 3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04 .%.....ysM.%.... +| 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 0e 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 09 ................ +| 3280: 51 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07 Q....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 02 f1 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 6d 70 69 ...........compi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67 ler............g +| 3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 .stat........... +| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug........... +| 3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02 .eno.le?........ +| 3488: b0 01 02 00 01 02 00 11 02 00 01 02 00 01 02 00 ................ +| 3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01 ................ +| 3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02 ..Q............. +| 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 00 04 00 00 04 66 74 73 n............fts +| 3568: 34 09 0a 03 00 01 03 00 01 03 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 00 01 03 00 01 06 65 6f 70 73 6c 79 09 .........eopsly. +| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31 ...........json1 +| 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 12 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 03 ff ff 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 07 30 01 01 01 02 00 01 01 ........0....... +| 3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 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 01 ff 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 09 c2 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 0e f4 0f e9 10 d6 0f c7 ................ +| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =1.............. +| end crash-369d042958c29b.db +}]} {} + +do_catchsql_test 24.1 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT '4hE'+x FROM c WHERE x<72) + INSERT INTO t1(a) SELECT randomblob(2829) FROM c; +} {0 {}} + +do_catchsql_test 24.2 { + UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h'; +} {0 {}} + +do_catchsql_test 24.3 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72) + INSERT INTO t1(a) SELECT randomblob(2829) FROM c; +} {0 {}} + +do_catchsql_test 24.4 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT null<.$.. +| 2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00 .........?%..r.. +| 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 55 42 4.0 20160609 DUB +| 2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54 UG ENA.|E DBSTAT +| 2944: e4 46 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53 .FTAB 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: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59 BTREE MAX MEMORY +| 3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c =50000000 OLIT L +| 3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48 OAC 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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22 DSAKu=0XMOCASE.. +| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d ..%..THREADSAFF= +| 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 52 49 4f IT LOAD EXTENRIO +| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O +| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000 +| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 +| 3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MB. 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 0d a5 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 1c 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 14 05 01 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 12 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN.BLE JSON1XB +| 3536: 49 4e 41 52 59 18 14 05 00 25 09 d9 45 4e 41 42 INARY....%..ENAB +| 3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17 LE JSO>1XNOCASE. +| 3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f ...%..EN@BLE JSO +| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c NARY....)..FNABL +| 3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45 H.GEOPOLYXNtCASE +| 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 30 46 54 53 35 58 42 49 ..ENABLE0FTS5XBI +| 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 0e 05 E FTS5XNOCASE... +| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X +| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB +| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY.. +| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4 +| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM. +| 3824: 09 05 00 31 0f 19 45 4e 42 42 4c 45 20 44 42 53 ...1..ENBBLE 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 4a 4d 11 06 TAT VTABXRTRJM.. +| 3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR +| 3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 16 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 06 00 43 0f 17 43 9XNOCASE&...C..C +| 4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e OMPIKER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d 0 201606@9X)TRIM +| page 4 offset 12288 +| 0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 01 00 00 ................ +| 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 6e 6f 72 79 ..max.%....enory +| 3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04 .%.....ysM.%.... +| 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 0e 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 09 ................ +| 3280: 51 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07 Q....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 02 f1 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 6d 70 69 ...........compi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67 ler............g +| 3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 .stat........... +| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug........... +| 3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02 .eno.le?........ +| 3488: b0 01 02 00 01 02 00 11 02 00 01 02 00 01 02 00 ................ +| 3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01 ................ +| 3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02 ..Q............. +| 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 00 04 00 00 04 66 74 73 n............fts +| 3568: 34 09 0a 03 00 01 03 00 01 03 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 00 01 03 00 01 06 65 6f 70 73 6c 79 09 .........eopsly. +| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31 ...........json1 +| 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 12 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: 0e 9f 6d 69 74 09 1f 02 00 01 02 00 01 02 00 00 ..mit........... +| 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 07 30 01 01 01 02 00 01 01 ........0....... +| 3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 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 01 ff 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 0e f4 0f e9 10 d6 0f c7 ................ +| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =1.............. +| end crash-dde9e76ed8ab2d.db +}]} {} + +do_catchsql_test 25.1 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237) + INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ; +} {0 {}} + +do_catchsql_test 25.2 { + UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h*'; +} {0 {}} + +do_catchsql_test 25.3 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x +x FROM c WHERE 721XNOCASE. +| 3568: 13 05 00 25 0f 17 45 4e 40 42 4c 45 20 4a 53 4f ...%..EN@BLE JSO +| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 29 0f 19 45 N1XRTRIM....)..E +| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4d 59 58 42 49 NABLE GEOPOMYXBI +| 3616: 4e 41 52 59 1a 11 05 c9 29 e8 19 46 4e 41 42 4c NARY....)..FNABL +| 3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45 H.GEOPOLYXNtCASE +| 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 30 46 54 53 35 58 42 49 ..ENABLE0FTS5XBI +| 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 4a e1 53 45 16 0e 05 E FTS5XNOJ.SE... +| 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 55 4e XNOCASE....#..UN +| 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 42 42 4c 45 20 44 42 53 ...1..ENBBLE 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 4a 4d 11 06 TAT VTABXRTRJM.. +| 3920: 05 f0 17 0f 29 44 45 42 55 47 58 42 49 4e 41 52 ....)DEBUGXBINAR +| 3936: 59 11 05 05 00 17 0e 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 16 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 06 00 43 0f 17 43 9XNOCASE&...C..C +| 4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e OMPIKER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d 0 201606@9X)TRIM +| page 4 offset 12288 +| 0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 00 00 00 ................ +| 16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 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 7c 65 09 25 09 g.%....enab|e.%. +| 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 6e 6f 72 79 ..max.%....enory +| 3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04 .%.....ysM.%.... +| 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 0e 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 02 f1 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 01 f2 00 03 01 02 02 00 00 08 63 6f 6d 70 69 ...........compi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67 ler............g +| 3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 .stat........... +| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug........... +| 3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02 .eno.le?........ +| 3488: b0 01 02 00 01 02 00 11 0a f0 01 02 00 01 02 00 ................ +| 3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 02 ................ +| 3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02 ..Q............. +| 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 00 04 00 00 04 66 74 73 n............fts +| 3568: 34 09 0a 03 00 01 03 00 01 03 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 00 01 03 00 01 06 65 6f 70 73 6c 79 09 .........eopsly. +| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31 ...........json1 +| 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 12 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 01 e3 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 01 f0 01 01 01 07 30 01 01 01 02 00 01 01 ........0....... +| 3968: 01 02 00 ea 01 01 02 00 01 01 01 02 00 11 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 01 ff 01 01 01 02 00 01 01 01 02 00 01 ................ +| 4032: 01 01 02 00 01 11 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 01 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 0e f4 0f e9 10 d6 0f c7 ................ +| 4016: 00 00 00 00 00 00 00 00 0f 85 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =1.............. +| end crash-23ddd777a03bfd.db +}]} {} + +do_catchsql_test 27.2 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x GLOB 2.16770 FROM x) + INSERT INTO t1(a) SELECT randomblob(3000) FROM t2 ; +} {0 {}} +do_catchsql_test 27.3 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<2.653) + INSERT INTO t1(a) SELECT randomblob(-current_time) FROM c; +} {0 {}} +do_catchsql_test 27.4 { + UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h*h*'; +} {0 {}} +do_catchsql_test 27.5 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<2.653) + INSERT INTO t1(a) SELECT randomblob(-current_time) FROM c; +} {0 {}} +do_catchsql_test 27.5 { + INSERT INTO t1(t1) SELECT x FROM t2; +} {0 {}} +do_catchsql_test 27.6 { + INSERT INTO t1(t1) SELECT x FROM t2; +} {0 {}} + +#------------------------------------------------------------------------- +reset_db +do_test 28.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-159ac1ca51ed55.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 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 67 64 69 72 egdir_1t1_segdir +| 3760: 06 0f c7 00 08 00 10 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: 64 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52 dst1_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 4f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1Ocontentt1_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 43 a5 52 20 50 52 39 4d cid INTEC.R PR9M +| 3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20 ARY KEY, 'c0a', +| 3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06 'c1b', '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 26 0b 48 00 00 00 00 00 00 00 00 00 ....&.H......... +| 2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00 .........?%..r.. +| 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 55 42 4.0 20160609 DUB +| 2928: 55 47 20 45 4e 41 e4 7c 45 20 44 42 53 54 41 54 UG ENA.|E DBSTAT +| 2944: e4 46 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53 .FTAB 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 1f 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41 AB.E 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: 42 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59 BTREE MAX MEMORY +| 3040: 3d 35 30 30 30 30 30 30 30 20 4f 4c 49 54 20 4c =50000000 OLIT L +| 3056: 4f 41 43 20 45 58 54 45 4e 53 49 4f 4e 21 54 48 OAC EXTENSION!TH +| 3072: 52 45 41 44 53 41 46 45 3d 2f 18 24 05 00 25 0f READSAFE=/.$..%. +| 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 4b 75 3d 30 58 4d 4f 43 41 53 45 17 22 DSAKu=0XMOCASE.. +| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 46 3d ..%..THREADSAFF= +| 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 52 49 4f IT LOAD EXTENRIO +| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O +| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000 +| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 +| 3328: 0f 17 4d 42 b8 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MB. MEMORY=500 +| 3344: 30 30 30 30 30 58 52 54 52 4a 4d 18 1b 05 00 25 00000XRTRJM....% +| 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 0d a5 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 1c 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 14 05 01 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 12 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN.BLE JSON1XB +| 3536: 49 4e 41 52 59 18 14 05 00 25 09 d9 45 4e 41 42 INARY....%..ENAB +| 3552: 4c 45 20 4a 53 4f 3e 31 58 4e 4f 43 41 53 45 17 LE JSO>1XNOCASE. +| 3568: 13 05 00 25 0f 17 44 4e 40 42 4c 45 20 4a 53 4f ...%..DN@BLE JSO +| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 82 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 c9 29 e8 19 46 4e 41 42 4c NARY....)..FNABL +| 3632: 48 c0 47 45 4f 50 4f 4c 59 58 4e 74 43 41 53 45 H.GEOPOLYXNtCASE +| 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 30 46 54 53 35 58 42 49 ..ENABLE0FTS5XBI +| 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 0e 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: 04 ff 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 42 42 4c 45 20 44 42 53 ...1..ENBBLE 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 4a 4d 11 06 TAT VTABXRTRJM.. +| 3920: 05 f0 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR +| 3936: 59 11 05 09 b0 17 0e 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 16 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 4d 67 ...C..COMPILERMg +| 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 06 00 43 0f 17 43 9XNOCASE&...C..C +| 4064: 4f 4d 50 49 4b 45 52 3d 67 63 63 2d 35 2e 34 2e OMPIKER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 40 39 58 29 54 52 49 4d 0 201606@9X)TRIM +| page 4 offset 12288 +| 0: 0d 00 10 00 00 10 00 00 00 00 00 00 00 00 00 00 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 02 0b a0 00 00 00 00 00 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 4d 07 30 30 30 30 30 30 30 03 25 1a .%..M.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 10 ff ff f5 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 71 78 03 25 18 00 01 05 65 6e 6f 72 79 ..mqx.%....enory +| 3184: 03 25 19 00 03 04 ce 79 73 4d 03 25 15 00 00 04 .%.....ysM.%.... +| 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 7f 08 72 65 61 64 73 61 66 65 03 %......readsafe. +| 3232: 25 0e 00 00 04 76 75 61 62 03 25 0b 00 86 50 01 %....vuab.%...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 09 ................ +| 3280: 51 03 00 00 09 32 30 31 36 30 36 30 39 09 01 07 Q....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 03 ff 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 02 f1 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 6d 70 69 ...........compi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 67 ler............g +| 3440: d2 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 .stat........... +| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug........... +| 3472: 06 65 6e 6f 82 6c 65 3f 07 02 00 01 02 00 01 02 .eno.le?........ +| 3488: b0 01 02 00 00 f2 00 11 02 00 01 02 00 01 02 00 ................ +| 3504: 01 02 00 01 02 00 01 02 00 01 a6 00 01 02 00 01 ................ +| 3520: 02 05 51 02 00 01 02 00 01 02 00 01 02 00 01 02 ..Q............. +| 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 00 04 00 00 04 66 74 73 n............fts +| 3568: 34 09 0a 03 00 01 03 00 01 03 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 00 01 03 00 01 06 65 6f 70 73 6c 79 09 .........eopsly. +| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31 ...........json1 +| 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 12 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: 0f 71 02 02 00 03 01 02 02 00 03 6f 02 02 00 00 .q.........o.... +| 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 07 30 01 01 01 02 00 01 01 ........0....... +| 3968: 01 02 00 11 01 01 02 00 01 01 01 02 00 11 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 01 ff 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 00 00 00 00 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 0e f4 0f e9 10 d6 0f c7 ................ +| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =1.............. +| end crash-159ac1ca51ed55.db +}]} {} + +do_catchsql_test 28.1 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72) + INSERT INTO t1(a) SELECT randomblob(2829) FROM c; +} {0 {}} + +do_catchsql_test 28.1 { + UPDATE t1 SET b=quote((true) ) WHERE t1 MATCH 'h'; +} {0 {}} + +do_catchsql_test 28.1 { + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72) + INSERT INTO t1(a) SELECT randomblob(2829) FROM c; +} {0 {}} + +do_catchsql_test 28.1 { + WITH c(x) AS (VALUES(1) UNION ALL SELECT 3<&3(Qh;#xXAVQK;>5ve}QltbM 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

9mc%q2_)bu4cY#zDZblXib? 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%0D-SdE(d(b5q=i zUy1uo`P;^Bo>-s^Zwc(mzzmPY)z2@V@uW)k3+ntkGykM)&y!z^dli?u*hg9sikHC; zXyVJ1L=P#CYW9c(OGk}_9EQot;vQwmo2R7SOo6VJci=3+0O9DJDAqXk&Iy^m);}Wa z*`Xdisv>6qCayC*Sd`(PDU`_ca(``aQf=j$_Sg%5}CssE5EtMX(8ofF{uVpeQHgP8bceCJq5m3hSH}7D8z$O#` zy$#FcyX&`L{RhR5Ed&S-iYQ)>cy{7ad~|FdkXIPIqp*^IQMH1 zzzvy(tzuesWu_&$YW{x1c&(T=O)Hu`&})m|sc25Oe`sWh5}#G+>!Q5Ps+ZS*2TiL# zz~xCFObr&wQM3&(!Bgx=VYAQ23DuCLsL;4~mik(-vV{MAscOsgA^AIIc79OW11aq@ zV`|j?U(#L;=7*_G54LT~W&uwRmFXK)mi(}m;;K+Wrq2-ar^E<&g_k@QKU=J?5U9$sV9ajpv?r)c zy?uL%-psS#{QkI%m&}UqB1snJd0W|z;y)*`-f3AMQ~WG7)VER=$4^sQHzj*o^PymDk(yo1?t{hWH~gQW87`jnKc;{H=oct{UifffPGct9Q7UdO%;P-9c^Ej6LW=p6!>~FM)N9~XQN(O_rCei`$3;>{p8hOT2J#Z3B&l8z1y)MLXo9;!^eq2MxiCo0o!TeVDicOWmjO zHri;4{qY#$okcYB?>in6tu($sC3R+bt6qxRP}Blw-%P{fNQ&VpxX$|hIqPGXhZ;A3p|_c4-A zH2oe}ul-fHwm{|oX4qZ+;H4?;Qy{fn6RKeC8`$4q_nO(2?6=b=AWNTI)Qvyi&^}Zx z^?OK!2tpxdi^kcX?1S z^KWq|wA(aZHq4#}M<@O5ZT%YbkTCn7GCb|h3X?X1Zrslvz!L}BSIWpLq;LcrU7ThQ z60|Y^ozHz`46cr#t~KO} zQTBCko66kj_M@7y>ykW!1*s*w&8^btGZb1@zZmGQ?4WDrJ=qYTS0QV06C{q*m=4^XA=}~q% z$u<$^s#9@dSk1z4N|^z@C~SIJtmvnN0W?cL7qisAI=q&UMc|YkHbQ5jrX|A;Wb>}e z?5AX~sd#9E3J1e1`>Qyq6xdf#>!%S21Rp}@?T_-*i1G+XrYe%A*FBhQi+z#!kY~M? zU}{z+o#~7gz}M`vFOmB+*zjLOZ!}3 zK-+N;YjoKDJ><&NOK|qB3gYWVJ+}zR0oj+3y=iYFa7%zNoCFxDUwmi`nVMj#v2W zrS=XuTzgynL5V=svNBP!aZwT$f1Dru#17BB%c|A>rK|RyVxV?mvhs)3J|JPWoT

  • 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 ?42x$B$=a57h}hVHf2 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

    3mHt6?|!K0 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 BgH!+j delta 443320 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­<2#_8k-W)lqfbNd;|7Jp=NIQ2Yat$g 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

    9f2(8O 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

    H!3v}LLmhDdQ~jel~q-?B)*l0CO&r6*f(v-^DN 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

    RR1<8BMXEhm?z~|i+iwyhUw4rA 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

    p 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 H$M*jK^XCBL diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 929cdfefed3a873a16b25589b689241b389f623b..4452d295b8f141d6fc93bee6249dc969fc1467af 100644 GIT binary patch delta 42242 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 delta 18102 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 +do_execsql_test 7.0 { + CREATE TABLE IF NOT EXISTS t0(c0); + INSERT INTO t0(c0) VALUES (-9223372036854775808); + BEGIN; +} +do_catchsql_test 7.1 { + CREATE INDEX i0 ON t0(ABS(c0)); +} {1 {integer overflow}} +do_execsql_test 7.2 { + COMMIT; + SELECT sql FROM sqlite_master WHERE tbl_name = 't0'; + CREATE INDEX i0 ON t0(c0); +} {{CREATE TABLE t0(c0)}} +do_execsql_test 7.3 { + REINDEX; +} {} + + finish_test diff --git a/test/intreal.test b/test/intreal.test new file mode 100644 index 0000000..cf2c3b7 --- /dev/null +++ b/test/intreal.test @@ -0,0 +1,86 @@ +# 2019-05-03 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# Tests to exercise the MEM_IntReal representation of Mem objects. +# +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix intreal + +sqlite3_create_function db +do_execsql_test 100 { + SELECT intreal(5); +} {5.0} +do_execsql_test 110 { + SELECT intreal(5)=5, 6=intreal(6); +} {1 1} +do_execsql_test 120 { + SELECT intreal(7)=7.0, 8.0=intreal(8); +} {1 1} +do_execsql_test 130 { + SELECT typeof(intreal(9)); +} {real} +do_execsql_test 140 { + SELECT 'a'||intreal(11)||'z'; +} {a11.0z} + +do_execsql_test 150 { + SELECT max(1.0,intreal(2),3.0), max(1,intreal(2),3); +} {3.0 3} +do_execsql_test 160 { + SELECT max(1.0,intreal(4),3.0), max(1,intreal(4),3); +} {4.0 4.0} +do_execsql_test 170 { + SELECT max(1.0,intreal(2),intreal(3),4.0), + max(1,intreal(2),intreal(3),4); +} {4.0 4} +do_execsql_test 180 { + SELECT max(1.0,intreal(5),intreal(3),4.0), + max(1,intreal(5),intreal(3),4); +} {5.0 5.0} + +#------------------------------------------------------------------------- +do_execsql_test 2.1 { + CREATE TABLE t2(a REAL); + INSERT INTO t2 VALUES( 836627109860825358 ); + SELECT substr(a,1,4) FROM t2 WHERE a = CAST(836627109860825358 AS REAL); +} {8.36} + +do_execsql_test 2.2 { + CREATE INDEX i2 ON t2(a); + SELECT substr(a,1,4) FROM t2 WHERE a = CAST(836627109860825358 AS REAL); +} {8.36} + +do_execsql_test 2.3 { + CREATE TABLE t0 (c0); + CREATE TABLE t1 (c1 REAL); + INSERT INTO t1(c1) VALUES (8366271098608253588); + INSERT INTO t0(c0) VALUES ('a'); +} +set D [db one {SELECT c1 FROM t1}] + +do_execsql_test 2.4 { + SELECT * FROM t1 WHERE (t1.c1 = CAST(8366271098608253588 AS REAL)); +} $D + +do_execsql_test 2.5 { + SELECT * FROM t0, t1 WHERE (t1.c1 = CAST(8366271098608253588 AS REAL)); +} [list a $D] + +do_execsql_test 2.6 { + SELECT * FROM t0, t1 + WHERE ( + t1.c1 >= CAST(8366271098608253588 AS REAL) + AND t1.c1 <= CAST(8366271098608253588 AS REAL) + ); +} [list a $D] + + +finish_test diff --git a/test/istrue.test b/test/istrue.test index 14c013f..d2768b3 100644 --- a/test/istrue.test +++ b/test/istrue.test @@ -158,4 +158,18 @@ do_execsql_test istrue-700 { SELECT *,'x' FROM t7 ORDER BY a; } {1 0 1 0 1 x 2 1 0 0 1 x 3 1 0 0 1 x 4 0 1 1 0 x} +do_execsql_test istrue-710 { + SELECT 0.5 IS TRUE COLLATE NOCASE; + SELECT 0.5 IS TRUE COLLATE RTRIM; + SELECT 0.5 IS TRUE COLLATE BINARY; + + SELECT 0.5 IS TRUE; + SELECT 0.5 COLLATE NOCASE IS TRUE; + SELECT 0.0 IS FALSE; + + SELECT 0.0 IS FALSE COLLATE NOCASE; + SELECT 0.0 IS FALSE COLLATE RTRIM; + SELECT 0.0 IS FALSE COLLATE BINARY; +} {1 1 1 1 1 1 1 1 1} + finish_test diff --git a/test/join5.test b/test/join5.test index f4ded79..6724419 100644 --- a/test/join5.test +++ b/test/join5.test @@ -306,4 +306,25 @@ do_eqp_test 7.4 { `--SEARCH TABLE t4 USING INDEX t4xz (x=?) } +reset_db +do_execsql_test 8.0 { + CREATE TABLE t0 (c0, c1, PRIMARY KEY (c0, c1)); + CREATE TABLE t1 (c0); + + INSERT INTO t1 VALUES (2); + + INSERT INTO t0 VALUES(0, 10); + INSERT INTO t0 VALUES(1, 10); + INSERT INTO t0 VALUES(2, 10); + INSERT INTO t0 VALUES(3, 10); +} + +do_execsql_test 8.1 { + SELECT * FROM t0, t1 + WHERE (t0.c1 >= 1 OR t0.c1 < 1) AND t0.c0 IN (1, t1.c0) ORDER BY 1; +} { + 1 10 2 + 2 10 2 +} + finish_test diff --git a/test/jrnlmode.test b/test/jrnlmode.test index 3112f61..99823a8 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -65,7 +65,16 @@ do_test jrnlmode-1.2 { PRAGMA temp.journal_mode; } } [list persist persist [temp_journal_mode persist]] -do_test jrnlmode-1.4 { +do_test jrnlmode-1.4a { + # When defensive is on, unable to set journal_mode to OFF + sqlite3_db_config db DEFENSIVE 1 + execsql { + PRAGMA journal_mode = off; + } +} {persist} +do_test jrnlmode-1.4b { + # When defensive is on, unable to set journal_mode to OFF + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA journal_mode = off; } diff --git a/test/json104.test b/test/json104.test index b5313f0..23864d5 100644 --- a/test/json104.test +++ b/test/json104.test @@ -13,6 +13,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix json104 ifcapable !json1 { finish_test @@ -125,6 +126,32 @@ do_execsql_test json104-314 { SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}'); } {{{"a":{"bb":{}}}}} +#------------------------------------------------------------------------- + +do_execsql_test 401 { + CREATE TABLE obj(x); + INSERT INTO obj VALUES('{"a":1,"b":2}'); + SELECT * FROM obj; +} {{{"a":1,"b":2}}} +do_execsql_test 402 { + UPDATE obj SET x = json_insert(x, '$.c', 3); + SELECT * FROM obj; +} {{{"a":1,"b":2,"c":3}}} +do_execsql_test 403 { + SELECT json_extract(x, '$.b') FROM obj; + SELECT json_extract(x, '$."b"') FROM obj; +} {2 2} +do_execsql_test 404 { + UPDATE obj SET x = json_set(x, '$."b"', 555); + SELECT json_extract(x, '$.b') FROM obj; + SELECT json_extract(x, '$."b"') FROM obj; +} {555 555} +do_execsql_test 405 { + UPDATE obj SET x = json_set(x, '$."d"', 4); + SELECT json_extract(x, '$."d"') FROM obj; +} {4} finish_test + + diff --git a/test/like.test b/test/like.test index e5324ae..75ddf9c 100644 --- a/test/like.test +++ b/test/like.test @@ -17,6 +17,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix like # Create some sample data to work with. # @@ -1095,4 +1096,22 @@ do_execsql_test like-15.121 { } {/SEARCH/} } +#------------------------------------------------------------------------- +# Tests for ticket [b1d8c79314]. +# +reset_db +do_execsql_test 16.0 { + CREATE TABLE t1(a INTEGER COLLATE NOCASE); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES(' 1x'); + INSERT INTO t1 VALUES(' 1-'); +} +do_execsql_test 16.1 { + SELECT * FROM t1 WHERE a LIKE ' 1%'; +} {{ 1x} { 1-}} +do_execsql_test 16.2 { + SELECT * FROM t1 WHERE a LIKE ' 1-'; +} {{ 1-}} + finish_test + diff --git a/test/like3.test b/test/like3.test index 622f833..f64fb63 100644 --- a/test/like3.test +++ b/test/like3.test @@ -178,10 +178,41 @@ do_eqp_test like3-5.211 { `--SEARCH TABLE t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x? AND path$ans { + set x [db one "SELECT round(${r}4,$n)"] + } $ans + set x4 [string range [format %09d [expr {$x2+1}]] [expr {9-$n}] end] + if {[string trim $x3 9]==""} {incr x1} + set r2 $x1.$x4 + set ans [string trimright $r2 0] + if {[string match *. $ans]} {set ans ${ans}0} + do_test $iTest/$n/${r}5=>$ans { + set x [db one "SELECT round(${r}5,$n)"] + } $ans +} + +finish_test diff --git a/test/rowid.test b/test/rowid.test index 5633645..f4fa1ce 100644 --- a/test/rowid.test +++ b/test/rowid.test @@ -659,6 +659,32 @@ do_test rowid-11.4 { execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc'} } {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8} +do_test rowid-11.asc.1 { + execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc' ORDER BY 1 ASC} +} {} +do_test rowid-11.asc.2 { + execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc' ORDER BY 1 ASC} +} {} +do_test rowid-11.asc.3 { + execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc' ORDER BY 1 ASC} +} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8} +do_test rowid-11.asc.4 { + execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc' ORDER BY 1 ASC} +} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8} + +do_test rowid-11.desc.1 { + execsql {SELECT rowid, a FROM t5 WHERE rowid>'abc' ORDER BY 1 DESC} +} {} +do_test rowid-11.desc.2 { + execsql {SELECT rowid, a FROM t5 WHERE rowid>='abc' ORDER BY 1 DESC} +} {} +do_test rowid-11.desc.3 { + execsql {SELECT rowid, a FROM t5 WHERE rowid<'abc' ORDER BY 1 DESC} +} {8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1} +do_test rowid-11.desc.4 { + execsql {SELECT rowid, a FROM t5 WHERE rowid<='abc' ORDER BY 1 DESC} +} {8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1} + # Test the automatic generation of rowids when the table already contains # a rowid with the maximum value. # @@ -719,4 +745,46 @@ do_execsql_test rowid-13.1 { SELECT last_insert_rowid(); } {1234 5 2234 | 2234 4990756 3234 | 3234 10458756 4234 | 4234} +#------------------------------------------------------------------------- +do_execsql_test rowid-14.0 { + CREATE TABLE t14(x INTEGER PRIMARY KEY); + INSERT INTO t14(x) VALUES (100); +} +do_execsql_test rowid-14.1 { + SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid ASC; +} {100} +do_execsql_test rowid-14.2 { + SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid DESC; +} {100} + +do_execsql_test rowid-14.3 { + DELETE FROM t14; + SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid ASC; +} {} +do_execsql_test rowid-14.4 { + SELECT * FROM t14 WHERE x < 'a' ORDER BY rowid DESC; +} {} + +reset_db +do_execsql_test rowid-15.0 { + PRAGMA reverse_unordered_selects=true; + CREATE TABLE t1 (c0, c1); + CREATE TABLE t2 (c0 INT UNIQUE); + INSERT INTO t1(c0, c1) VALUES (0, 0), (0, NULL); + INSERT INTO t2(c0) VALUES (1); +} + +do_execsql_test rowid-15.1 { + SELECT t2.c0, t1.c1 FROM t1, t2 + WHERE (t2.rowid <= 'a') OR (t1.c0 <= t2.c0) LIMIT 100 +} {1 {} 1 0} + +do_execsql_test rowid-15.2 { + SELECT 1, NULL INTERSECT SELECT * FROM ( + SELECT t2.c0, t1.c1 FROM t1, t2 + WHERE ((t2.rowid <= 'a')) OR (t1.c0 <= t2.c0) ORDER BY 'a' DESC LIMIT 100 + ); +} {1 {}} + + finish_test diff --git a/test/select3.test b/test/select3.test index b5dbef5..e15464f 100644 --- a/test/select3.test +++ b/test/select3.test @@ -261,4 +261,49 @@ do_test select3-8.2 { } } {real} +# 2019-05-09 ticket https://www.sqlite.org/src/tktview/6c1d3febc00b22d457c7 +# +unset -nocomplain x +foreach {id x} { + 100 127 + 101 128 + 102 -127 + 103 -128 + 104 -129 + 110 32767 + 111 32768 + 112 -32767 + 113 -32768 + 114 -32769 + 120 2147483647 + 121 2147483648 + 122 -2147483647 + 123 -2147483648 + 124 -2147483649 + 130 140737488355327 + 131 140737488355328 + 132 -140737488355327 + 133 -140737488355328 + 134 -140737488355329 + 140 9223372036854775807 + 141 -9223372036854775807 + 142 -9223372036854775808 + 143 9223372036854775806 + 144 9223372036854775805 + 145 -9223372036854775806 + 146 -9223372036854775805 + +} { + set x [expr {$x+0}] + do_execsql_test select3-8.$id { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1 (c0, c1 REAL PRIMARY KEY); + INSERT INTO t1(c0, c1) VALUES (0, $x), (0, 0); + UPDATE t1 SET c0 = NULL; + UPDATE OR REPLACE t1 SET c1 = 1; + SELECT DISTINCT * FROM t1 WHERE (t1.c0 IS NULL); + PRAGMA integrity_check; + } {{} 1.0 ok} +} + finish_test diff --git a/test/select6.test b/test/select6.test index 590512a..ef5c5b2 100644 --- a/test/select6.test +++ b/test/select6.test @@ -12,7 +12,6 @@ # focus of this file is testing SELECT statements that contain # subqueries in their FROM clause. # -# $Id: select6.test,v 1.29 2009/01/09 01:12:28 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -613,5 +612,21 @@ do_execsql_test 11.100 { FROM ( SELECT count(*) AS cnt FROM t1 ); } {{}} +# 2019-05-29 ticket https://www.sqlite.org/src/info/c41afac34f15781f +# A LIMIT clause in a subquery is incorrectly applied to a subquery. +# +do_execsql_test 12.100 { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(a); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + CREATE TABLE t2(b); + INSERT INTO t2 VALUES(3); + SELECT * FROM ( + SELECT * FROM (SELECT * FROM t1 LIMIT 1) + UNION ALL + SELECT * from t2); +} {1 3} finish_test diff --git a/test/speedtest1.c b/test/speedtest1.c index cf03c53..ccb8a44 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -1191,6 +1191,19 @@ void testset_fp(void){ speedtest1_run(); } speedtest1_end_test(); + + n = g.szTest*5000; + speedtest1_begin_test(140, "%d calls to round()", n); + speedtest1_exec("SELECT sum(round(a,2)+round(b,4)) FROM t1;"); + speedtest1_end_test(); + + + speedtest1_begin_test(150, "%d printf() calls", n*4); + speedtest1_exec( + "WITH c(fmt) AS (VALUES('%%g'),('%%e'),('%%!g'),('%%.20f'))" + "SELECT sum(printf(fmt,a)) FROM t1, c" + ); + speedtest1_end_test(); } #ifdef SQLITE_ENABLE_RTREE diff --git a/test/subquery2.test b/test/subquery2.test index 8ccd229..0c1bdc6 100644 --- a/test/subquery2.test +++ b/test/subquery2.test @@ -197,5 +197,22 @@ foreach {tn sql} { }] } +#------------------------------------------------------------------------- +# Test that ticket [9cdc5c46] is fixed. +# +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('ALFKI'); + INSERT INTO t1 VALUES('ANATR'); + + CREATE TABLE t2(y, z); + CREATE INDEX t2y ON t2 (y); + INSERT INTO t2 VALUES('ANATR', '1997-08-08 00:00:00'); + INSERT INTO t2 VALUES('ALFKI', '1997-08-25 00:00:00'); +} +do_execsql_test 5.1 { + SELECT ( SELECT y FROM t2 WHERE x = y ORDER BY y, z) FROM t1; +} {ALFKI ANATR} finish_test diff --git a/test/tkt-78e04e52ea.test b/test/tkt-78e04e52ea.test index 47a1093..a432e6c 100644 --- a/test/tkt-78e04e52ea.test +++ b/test/tkt-78e04e52ea.test @@ -41,7 +41,7 @@ do_test tkt-78e04-1.3 { } } {} do_test tkt-78e04-1.4 { - db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';} + db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1e5%';} } {/*SCAN TABLE USING COVERING INDEX i1*/} do_test tkt-78e04-1.5 { execsql { diff --git a/test/tkt-a8a0d2996a.test b/test/tkt-a8a0d2996a.test index 03c2ee9..2644937 100644 --- a/test/tkt-a8a0d2996a.test +++ b/test/tkt-a8a0d2996a.test @@ -84,12 +84,12 @@ do_execsql_test 4.3 { } {104.5} do_execsql_test 4.4 { SELECT '-9223372036854775807x'-'1x'; -} {-9.22337203685478e+18} +} {-9223372036854775808} do_execsql_test 4.5 { SELECT '9223372036854775806x'+'1x'; -} {9.22337203685478e+18} +} {9223372036854775807} do_execsql_test 4.6 { - SELECT '1234x'/'10y'; -} {123.4} + SELECT '1234x'/'10y', '1234x'/'10.y', '1234x'/'1e1y'; +} {123 123.4 123.4} finish_test diff --git a/test/view.test b/test/view.test index 59ff55c..8a60f86 100644 --- a/test/view.test +++ b/test/view.test @@ -701,4 +701,27 @@ do_test view-25.2 { set log } $res +#------------------------------------------------------------------------- +do_execsql_test view-26.0 { + CREATE TABLE t16(a, b, c UNIQUE); + INSERT INTO t16 VALUES(1, 1, 1); + INSERT INTO t16 VALUES(2, 2, 2); + INSERT INTO t16 VALUES(3, 3, 3); + CREATE VIEW v16 AS SELECT max(a) AS mx, min(b) AS mn FROM t16 GROUP BY c; + + SELECT * FROM v16 AS one, v16 AS two WHERE one.mx=1; +} { + 1 1 1 1 + 1 1 2 2 + 1 1 3 3 +} +do_execsql_test view-26.1 { + WITH v17(x,y) AS (SELECT max(a), min(b) FROM t16 GROUP BY c) + SELECT * FROM v17 AS one, v17 AS two WHERE one.x=1; +} { + 1 1 1 1 + 1 1 2 2 + 1 1 3 3 +} + finish_test diff --git a/test/vtab1.test b/test/vtab1.test index 193a53a..8280715 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -1311,10 +1311,13 @@ foreach {tn sql res filter} { {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%} 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%} + + 1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} } { set echo_module {} do_execsql_test 18.$tn.1 $sql $res @@ -1323,11 +1326,14 @@ foreach {tn sql res filter} { do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON } foreach {tn sql res filter} { - 2.1 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%} + 2.1 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} 2.2 "SELECT a FROM e6 WHERE b LIKE '8j%'" {} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8j 8k 8j%} + + 2.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8K 8J%} } { set echo_module {} do_execsql_test 18.$tn.1 $sql $res diff --git a/test/vtabH.test b/test/vtabH.test index 56c1254..78b156c 100644 --- a/test/vtabH.test +++ b/test/vtabH.test @@ -32,13 +32,27 @@ do_execsql_test 1.0 { foreach {tn sql expect} { 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { - xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8abc + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + 8ABC 8abd 8abc } 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + 8abc 8abd 8abc + } + 3 "SELECT * FROM e6 WHERE b LIKE '8e/'" { + xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} + xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/ + } + 4 "SELECT * FROM e6 WHERE b GLOB '8e/'" { xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8abc + xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/ } } { do_test 1.$tn { diff --git a/test/wapptest.tcl b/test/wapptest.tcl index d12d8e7..65bf988 100755 --- a/test/wapptest.tcl +++ b/test/wapptest.tcl @@ -20,16 +20,20 @@ source [file join [file dirname [info script]] releasetest_data.tcl] # set G(platform) $::tcl_platform(os)-$::tcl_platform(machine) set G(test) Normal -set G(keep) 0 +set G(keep) 1 set G(msvc) 0 set G(tcl) [::tcl::pkgconfig get libdir,install] set G(jobs) 3 set G(debug) 0 +set G(noui) 0 +set G(stdout) 0 + + proc wapptest_init {} { global G - set lSave [list platform test keep msvc tcl jobs debug] + set lSave [list platform test keep msvc tcl jobs debug noui stdout] foreach k $lSave { set A($k) $G($k) } array unset G foreach k $lSave { set G($k) $A($k) } @@ -37,9 +41,6 @@ proc wapptest_init {} { # The root of the SQLite source tree. set G(srcdir) [file dirname [file dirname [info script]]] - # releasetest.tcl script - set G(releaseTest) [file join [file dirname [info script]] releasetest.tcl] - set G(sqlite_version) "unknown" # Either "config", "running" or "stopped": @@ -52,28 +53,36 @@ proc wapptest_init {} { append G(host) " $::tcl_platform(machine) $::tcl_platform(byteOrder)" } -# Check to see if there are uncommitted changes in the SQLite source -# directory. Return true if there are, or false otherwise. -# -proc check_uncommitted {} { +proc wapptest_run {} { global G - set ret 0 - set pwd [pwd] - cd $G(srcdir) - if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} { - set ret 1 + set_test_array + set G(state) "running" + + wapptest_openlog + + wapptest_output "Running the following for $G(platform). $G(jobs) jobs." + foreach t $G(test_array) { + set config [dict get $t config] + set target [dict get $t target] + wapptest_output [format " %-25s%s" $config $target] } - cd $pwd - return $ret + wapptest_output [string repeat * 70] } +# Generate the text for the box at the top of the UI. The current SQLite +# version, according to fossil, along with a warning if there are +# uncommitted changes in the checkout. +# proc generate_fossil_info {} { global G set pwd [pwd] cd $G(srcdir) - if {[catch {exec fossil info} r1]} return - if {[catch {exec fossil changes} r2]} return + set rc [catch { + set r1 [exec fossil info] + set r2 [exec fossil changes] + }] cd $pwd + if {$rc} return foreach line [split $r1 "\n"] { if {[regexp {^checkout: *(.*)$} $line -> co]} { @@ -208,6 +217,35 @@ proc count_tests_and_errors {name logfile} { } } +proc wapptest_output {str} { + global G + if {$G(stdout)} { puts $str } + if {[info exists G(log)]} { + puts $G(log) $str + flush $G(log) + } +} +proc wapptest_openlog {} { + global G + set G(log) [open wapptest-out.txt w+] +} +proc wapptest_closelog {} { + global G + close $G(log) + unset G(log) +} + +proc format_seconds {seconds} { + set min [format %.2d [expr ($seconds / 60) % 60]] + set hr [format %.2d [expr $seconds / 3600]] + set sec [format %.2d [expr $seconds % 60]] + return "$hr:$min:$sec" +} + +# This command is invoked once a slave process has finished running its +# tests, successfully or otherwise. Parameter $name is the name of the +# test, $rc the exit code returned by the slave process. +# proc slave_test_done {name rc} { global G set G(test.$name.done) [clock seconds] @@ -220,8 +258,43 @@ proc slave_test_done {name rc} { if {[file exists $G(test.$name.log)]} { count_tests_and_errors $name $G(test.$name.log) } + + # If the "keep files" checkbox is clear, delete all files except for + # the executables and test logs. And any core file that is present. + if {$G(keep)==0} { + set keeplist { + testfixture testfixture.exe + sqlite3 sqlite3.exe + test.log test-out.txt + core + wapptest_make.sh + wapptest_configure.sh + wapptest_run.tcl + } + foreach f [glob -nocomplain [file join $G(test.$name.dir) *]] { + set t [file tail $f] + if {[lsearch $keeplist $t]<0} { + catch { file delete -force $f } + } + } + } + + # Format a message regarding the success or failure of hte test. + set t [format_seconds [expr $G(test.$name.done) - $G(test.$name.start)]] + set res "OK" + if {$G(test.$name.nError)} { set res "FAILED" } + set dots [string repeat . [expr 60 - [string length $name]]] + set msg "$name $dots $res ($t)" + + wapptest_output $msg + if {[info exists G(test.$name.errmsg)] && $G(test.$name.errmsg)!=""} { + wapptest_output " $G(test.$name.errmsg)" + } } +# This is a fileevent callback invoked each time a file-descriptor that +# connects this process to a slave process is readable. +# proc slave_fileevent {name} { global G set fd $G(test.$name.channel) @@ -239,6 +312,99 @@ proc slave_fileevent {name} { do_some_stuff } +# Return the contents of the "slave script" - the script run by slave +# processes to actually perform the test. It does two things: +# +# 1. Reads and [exec]s the contents of file wapptest_configure.sh. +# 2. Reads and [exec]s the contents of file wapptest_make.sh. +# +# Step 1 is omitted if the test uses MSVC (which does not use configure). +# +proc wapptest_slave_script {} { + global G + set res { + proc readfile {filename} { + set fd [open $filename] + set data [read $fd] + close $fd + return $data + } + } + + if {$G(msvc)==0} { + append res { + set cfg [readfile wapptest_configure.sh] + set rc [catch { exec {*}$cfg >& test.log } msg] + if {$rc==0} { + set make [readfile wapptest_make.sh] + set rc [catch { exec {*}$make >>& test.log }] + } + } + } else { + append res { + set make [readfile wapptest_make.sh] + set rc [catch { exec {*}$make >>& test.log }] + } + } + + append res { exit $rc } + + set res +} + + +# Launch a slave process to run a test. +# +proc slave_launch { + name wtcl title dir configOpts testtarget makeOpts cflags opts +} { + global G + + catch { file mkdir $dir } msg + foreach f [glob -nocomplain [file join $dir *]] { + catch { file delete -force $f } + } + set G(test.$name.dir) $dir + + # Write the configure command to wapptest_configure.sh. This file + # is empty if using MSVC - MSVC does not use configure. + # + set fd1 [open [file join $dir wapptest_configure.sh] w] + if {$G(msvc)==0} { + puts $fd1 "[file join .. $G(srcdir) configure] $wtcl $configOpts" + } + close $fd1 + + # Write the make command to wapptest_make.sh. Using nmake for MSVC and + # make for all other systems. + # + set makecmd "make" + if {$G(msvc)} { + set nativedir [file nativename $G(srcdir)] + set nativedir [string map [list "\\" "\\\\"] $nativedir] + set makecmd "nmake /f [file join $nativedir Makefile.msc] TOP=$nativedir" + } + set fd2 [open [file join $dir wapptest_make.sh] w] + puts $fd2 "$makecmd $makeOpts $testtarget \"CFLAGS=$cflags\" \"OPTS=$opts\"" + close $fd2 + + # Write the wapptest_run.tcl script to the test directory. To run the + # commands in the other two files. + # + set fd3 [open [file join $dir wapptest_run.tcl] w] + puts $fd3 [wapptest_slave_script] + close $fd3 + + set pwd [pwd] + cd $dir + set fd [open "|[info nameofexecutable] wapptest_run.tcl" r+] + cd $pwd + + set G(test.$name.channel) $fd + fconfigure $fd -blocking 0 + fileevent $fd readable [list slave_fileevent $name] +} + proc do_some_stuff {} { global G @@ -263,10 +429,15 @@ proc do_some_stuff {} { incr nConfig } set G(result) "$nError errors from $nTest tests in $nConfig configurations." + wapptest_output [string repeat * 70] + wapptest_output $G(result) catch { append G(result) " SQLite version $G(sqlite_version)" + wapptest_output " SQLite version $G(sqlite_version)" } set G(state) "stopped" + wapptest_closelog + if {$G(noui)} { exit 0 } } else { set nLaunch [expr $G(jobs) - $nRunning] foreach j $G(test_array) { @@ -275,15 +446,9 @@ proc do_some_stuff {} { if { ![info exists G(test.$name.channel)] && ![info exists G(test.$name.done)] } { + set target [dict get $j target] set G(test.$name.start) [clock seconds] - set fd [open "|[info nameofexecutable] $G(releaseTest) --slave" r+] - set G(test.$name.channel) $fd - fconfigure $fd -blocking 0 - fileevent $fd readable [list slave_fileevent $name] - - puts $fd [list 0 $G(msvc) 0 $G(keep)] - set wtcl "" if {$G(tcl)!=""} { set wtcl "--with-tcl=$G(tcl)" } @@ -303,8 +468,9 @@ proc do_some_stuff {} { } set L [make_test_suite $G(msvc) $wtcl $name $target $opts] - puts $fd $L - flush $fd + set G(test.$name.log) [file join [lindex $L 1] test.log] + slave_launch $name $wtcl {*}$L + set G(test.$name.log) [file join [lindex $L 1] test.log] incr nLaunch -1 } @@ -439,11 +605,7 @@ proc wapp-page-tests {} { } set seconds [expr $G(test.$config.done) - $G(test.$config.start)] } - - set min [format %.2d [expr ($seconds / 60) % 60]] - set hr [format %.2d [expr $seconds / 3600]] - set sec [format %.2d [expr $seconds % 60]] - set seconds "$hr:$min:$sec" + set seconds [format_seconds $seconds] } wapp-trim { @@ -502,8 +664,7 @@ proc wapp-page-control {} { if {[wapp-param-exists control_run]} { # This is a "run test" command. - set_test_array - set ::G(state) "running" + wapptest_run } if {[wapp-param-exists control_stop]} { @@ -518,6 +679,7 @@ proc wapp-page-control {} { slave_test_done $name 1 } } + wapptest_closelog } if {[wapp-param-exists control_reset]} { @@ -669,6 +831,118 @@ proc wapp-page-log {} { } } -wapptest_init -wapp-start $argv +# Print out a usage message. Then do [exit 1]. +# +proc wapptest_usage {} { + puts stderr { +This Tcl script is used to test various configurations of SQLite. By +default it uses "wapp" to provide an interactive interface. Supported +command line options (all optional) are: + + --platform PLATFORM (which tests to run) + --smoketest (run "make smoketest" only) + --veryquick (run veryquick.test only) + --buildonly (build executables, do not run tests) + --jobs N (number of concurrent jobs) + --tcl DIR (where to find tclConfig.sh) + --deletefiles (delete extra files after each test) + --msvc (Use MS Visual C) + --debug (Also run [n]debugging versions of tests) + --noui (do not use wapp) + } + exit 1 +} + +# Sort command line arguments into two groups: those that belong to wapp, +# and those that belong to the application. +set WAPPARG(-server) 1 +set WAPPARG(-local) 1 +set WAPPARG(-scgi) 1 +set WAPPARG(-remote-scgi) 1 +set WAPPARG(-fromip) 1 +set WAPPARG(-nowait) 0 +set WAPPARG(-cgi) 0 +set lWappArg [list] +set lTestArg [list] +for {set i 0} {$i < [llength $argv]} {incr i} { + set arg [lindex $argv $i] + if {[string range $arg 0 1]=="--"} { + set arg [string range $arg 1 end] + } + if {[info exists WAPPARG($arg)]} { + lappend lWappArg $arg + if {$WAPPARG($arg)} { + incr i + lappend lWappArg [lindex $argv $i] + } + } else { + lappend lTestArg $arg + } +} + +for {set i 0} {$i < [llength $lTestArg]} {incr i} { + switch -- [lindex $lTestArg $i] { + -platform { + if {$i==[llength $lTestArg]-1} { wapptest_usage } + incr i + set arg [lindex $lTestArg $i] + set lPlatform [array names ::Platforms] + if {[lsearch $lPlatform $arg]<0} { + puts stderr "No such platform: $arg. Platforms are: $lPlatform" + exit -1 + } + set G(platform) $arg + } + + -smoketest { set G(test) Smoketest } + -veryquick { set G(test) Veryquick } + -buildonly { set G(test) Build-Only } + -jobs { + if {$i==[llength $lTestArg]-1} { wapptest_usage } + incr i + set G(jobs) [lindex $lTestArg $i] + } + + -tcl { + if {$i==[llength $lTestArg]-1} { wapptest_usage } + incr i + set G(tcl) [lindex $lTestArg $i] + } + + -deletefiles { + set G(keep) 0 + } + + -msvc { + set G(msvc) 1 + } + + -debug { + set G(debug) 1 + } + + -noui { + set G(noui) 1 + set G(stdout) 1 + } + + -stdout { + set G(stdout) 1 + } + + default { + puts stderr "Unrecognized option: [lindex $lTestArg $i]" + wapptest_usage + } + } +} + +wapptest_init +if {$G(noui)==0} { + wapp-start $lWappArg +} else { + wapptest_run + do_some_stuff + vwait forever +} diff --git a/test/window2.tcl b/test/window2.tcl index 48fcdae..093d693 100644 --- a/test/window2.tcl +++ b/test/window2.tcl @@ -417,6 +417,13 @@ execsql_test 4.8.4 { ) FROM t2 ORDER BY 1, 2; } +execsql_float_test 4.9 { + SELECT + rank() OVER win AS rank, + cume_dist() OVER win AS cume_dist FROM t1 + WINDOW win AS (ORDER BY 1); +} + finish_test diff --git a/test/window2.test b/test/window2.test index 086e566..4bed0cd 100644 --- a/test/window2.test +++ b/test/window2.test @@ -326,7 +326,32 @@ do_execsql_test 4.1 { PARTITION BY (b%10) ORDER BY b ) FROM t2 ORDER BY a; -} {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 140 754 141 133 142 340 143 535 144 46 145 250 146 132 147 132 148 354 149 500 150 770 151 276 152 360 153 354 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 190 250 191 266 192 360 193 120 194 128 195 178 196 770 197 92 198 634 199 38 200 21} +} {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 + 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 + 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 + 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 + 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 + 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 + 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 + 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 + 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 + 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 + 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 + 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 + 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 + 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 + 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 + 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 + 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 + 140 754 141 133 142 340 143 535 144 46 145 250 146 132 + 147 132 148 354 149 500 150 770 151 276 152 360 153 354 + 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 + 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 + 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 + 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 + 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 + 190 250 191 266 192 360 193 120 194 128 195 178 196 770 + 197 92 198 634 199 38 200 21} do_execsql_test 4.2 { SELECT a, sum(b) OVER ( @@ -334,101 +359,538 @@ do_execsql_test 4.2 { ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY a; -} {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 140 754 141 133 142 340 143 535 144 46 145 250 146 132 147 132 148 354 149 500 150 770 151 276 152 360 153 354 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 190 250 191 266 192 360 193 120 194 128 195 178 196 770 197 92 198 634 199 38 200 21} +} {1 0 2 754 3 251 4 754 5 101 6 1247 7 132 8 266 9 6 10 950 + 11 667 12 1052 13 535 14 128 15 428 16 250 17 336 18 1122 + 19 368 20 6 21 1247 22 1000 23 92 24 368 25 584 26 320 + 27 1000 28 24 29 478 30 133 31 1049 32 1090 33 632 34 101 + 35 54 36 54 37 1049 38 450 39 145 40 354 41 21 42 764 + 43 754 44 424 45 1122 46 930 47 42 48 930 49 352 50 535 + 51 42 52 118 53 536 54 6 55 1122 56 86 57 770 58 255 59 50 + 60 52 61 950 62 75 63 354 64 2 65 536 66 160 67 352 68 536 + 69 54 70 675 71 276 72 950 73 868 74 678 75 667 76 4 + 77 1184 78 160 79 120 80 584 81 266 82 133 83 405 84 468 + 85 6 86 806 87 166 88 500 89 1090 90 552 91 251 92 27 + 93 424 94 687 95 1215 96 450 97 32 98 360 99 1052 100 868 + 101 2 102 66 103 754 104 450 105 145 106 5 107 687 108 24 + 109 302 110 806 111 251 112 42 113 24 114 30 115 128 116 128 + 117 50 118 1215 119 86 120 687 121 683 122 672 123 178 124 24 + 125 24 126 299 127 178 128 770 129 535 130 1052 131 270 + 132 255 133 675 134 632 135 266 136 6 137 21 138 930 139 411 + 140 754 141 133 142 340 143 535 144 46 145 250 146 132 + 147 132 148 354 149 500 150 770 151 276 152 360 153 354 + 154 27 155 552 156 552 157 602 158 266 159 1049 160 675 + 161 384 162 667 163 27 164 101 165 166 166 32 167 42 168 18 + 169 336 170 1122 171 276 172 1122 173 266 174 50 175 178 + 176 276 177 1247 178 6 179 1215 180 604 181 360 182 212 + 183 120 184 210 185 1090 186 10 187 1090 188 266 189 66 + 190 250 191 266 192 360 193 120 194 128 195 178 196 770 + 197 92 198 634 199 38 200 21} do_execsql_test 4.3 { SELECT b, sum(b) OVER ( ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY b; -} {0 0 1 1 1 2 2 4 2 6 2 8 3 11 3 14 4 18 5 23 6 29 7 36 7 43 7 50 8 58 8 66 8 74 9 83 9 92 9 101 10 111 11 122 11 133 12 145 12 157 12 169 13 182 13 195 14 209 15 224 15 239 15 254 16 270 16 286 16 302 17 319 19 338 20 358 21 379 21 400 22 422 22 444 23 467 23 490 23 513 24 537 25 562 26 588 26 614 26 640 27 667 27 694 28 722 29 751 29 780 29 809 30 839 30 869 30 899 31 930 31 961 32 993 33 1026 33 1059 33 1092 33 1125 33 1158 34 1192 34 1226 34 1260 34 1294 35 1329 35 1364 36 1400 36 1436 36 1472 36 1508 37 1545 37 1582 38 1620 38 1658 39 1697 39 1736 39 1775 40 1815 41 1856 41 1897 41 1938 42 1980 43 2023 43 2066 44 2110 44 2154 46 2200 46 2246 47 2293 47 2340 47 2387 47 2434 49 2483 50 2533 51 2584 52 2636 53 2689 54 2743 55 2798 55 2853 56 2909 56 2965 56 3021 57 3078 58 3136 58 3194 58 3252 58 3310 59 3369 59 3428 59 3487 59 3546 60 3606 61 3667 61 3728 62 3790 62 3852 63 3915 64 3979 65 4044 65 4109 65 4174 66 4240 67 4307 68 4375 69 4444 70 4514 72 4586 72 4658 72 4730 73 4803 73 4876 73 4949 74 5023 74 5097 74 5171 74 5245 74 5319 75 5394 75 5469 75 5544 76 5620 77 5697 77 5774 78 5852 78 5930 79 6009 80 6089 80 6169 81 6250 81 6331 81 6412 82 6494 83 6577 84 6661 84 6745 84 6829 84 6913 85 6998 85 7083 85 7168 86 7254 87 7341 87 7428 88 7516 89 7605 89 7694 89 7783 90 7873 90 7963 90 8053 91 8144 91 8235 91 8326 91 8417 91 8508 93 8601 93 8694 93 8787 94 8881 95 8976 95 9071 95 9166 96 9262 96 9358 96 9454 97 9551 97 9648 98 9746 98 9844 99 9943 99 10042 99 10141} +} {0 0 1 1 1 2 2 4 2 6 2 8 3 11 3 14 4 18 5 23 6 29 7 36 + 7 43 7 50 8 58 8 66 8 74 9 83 9 92 9 101 10 111 11 122 + 11 133 12 145 12 157 12 169 13 182 13 195 14 209 15 224 + 15 239 15 254 16 270 16 286 16 302 17 319 19 338 20 358 + 21 379 21 400 22 422 22 444 23 467 23 490 23 513 24 537 + 25 562 26 588 26 614 26 640 27 667 27 694 28 722 29 751 + 29 780 29 809 30 839 30 869 30 899 31 930 31 961 32 993 + 33 1026 33 1059 33 1092 33 1125 33 1158 34 1192 34 1226 + 34 1260 34 1294 35 1329 35 1364 36 1400 36 1436 36 1472 + 36 1508 37 1545 37 1582 38 1620 38 1658 39 1697 39 1736 + 39 1775 40 1815 41 1856 41 1897 41 1938 42 1980 43 2023 + 43 2066 44 2110 44 2154 46 2200 46 2246 47 2293 47 2340 + 47 2387 47 2434 49 2483 50 2533 51 2584 52 2636 53 2689 + 54 2743 55 2798 55 2853 56 2909 56 2965 56 3021 57 3078 + 58 3136 58 3194 58 3252 58 3310 59 3369 59 3428 59 3487 + 59 3546 60 3606 61 3667 61 3728 62 3790 62 3852 63 3915 + 64 3979 65 4044 65 4109 65 4174 66 4240 67 4307 68 4375 + 69 4444 70 4514 72 4586 72 4658 72 4730 73 4803 73 4876 + 73 4949 74 5023 74 5097 74 5171 74 5245 74 5319 75 5394 + 75 5469 75 5544 76 5620 77 5697 77 5774 78 5852 78 5930 + 79 6009 80 6089 80 6169 81 6250 81 6331 81 6412 82 6494 + 83 6577 84 6661 84 6745 84 6829 84 6913 85 6998 85 7083 + 85 7168 86 7254 87 7341 87 7428 88 7516 89 7605 89 7694 + 89 7783 90 7873 90 7963 90 8053 91 8144 91 8235 91 8326 + 91 8417 91 8508 93 8601 93 8694 93 8787 94 8881 95 8976 + 95 9071 95 9166 96 9262 96 9358 96 9454 97 9551 97 9648 + 98 9746 98 9844 99 9943 99 10042 99 10141} do_execsql_test 4.4 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.5 { SELECT b, sum(b) OVER ( ORDER BY b RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; -} {0 0 1 2 1 2 2 6 2 6 2 6 3 6 3 6 4 4 5 5 6 6 7 21 7 21 7 21 8 24 8 24 8 24 9 27 9 27 9 27 10 10 11 22 11 22 12 36 12 36 12 36 13 26 13 26 14 14 15 45 15 45 15 45 16 48 16 48 16 48 17 17 19 19 20 20 21 42 21 42 22 44 22 44 23 69 23 69 23 69 24 24 25 25 26 78 26 78 26 78 27 54 27 54 28 28 29 87 29 87 29 87 30 90 30 90 30 90 31 62 31 62 32 32 33 165 33 165 33 165 33 165 33 165 34 136 34 136 34 136 34 136 35 70 35 70 36 144 36 144 36 144 36 144 37 74 37 74 38 76 38 76 39 117 39 117 39 117 40 40 41 123 41 123 41 123 42 42 43 86 43 86 44 88 44 88 46 92 46 92 47 188 47 188 47 188 47 188 49 49 50 50 51 51 52 52 53 53 54 54 55 110 55 110 56 168 56 168 56 168 57 57 58 232 58 232 58 232 58 232 59 236 59 236 59 236 59 236 60 60 61 122 61 122 62 124 62 124 63 63 64 64 65 195 65 195 65 195 66 66 67 67 68 68 69 69 70 70 72 216 72 216 72 216 73 219 73 219 73 219 74 370 74 370 74 370 74 370 74 370 75 225 75 225 75 225 76 76 77 154 77 154 78 156 78 156 79 79 80 160 80 160 81 243 81 243 81 243 82 82 83 83 84 336 84 336 84 336 84 336 85 255 85 255 85 255 86 86 87 174 87 174 88 88 89 267 89 267 89 267 90 270 90 270 90 270 91 455 91 455 91 455 91 455 91 455 93 279 93 279 93 279 94 94 95 285 95 285 95 285 96 288 96 288 96 288 97 194 97 194 98 196 98 196 99 297 99 297 99 297} +} {0 0 1 2 1 2 2 6 2 6 2 6 3 6 3 6 4 4 5 5 6 6 7 21 + 7 21 7 21 8 24 8 24 8 24 9 27 9 27 9 27 10 10 11 22 + 11 22 12 36 12 36 12 36 13 26 13 26 14 14 15 45 15 45 + 15 45 16 48 16 48 16 48 17 17 19 19 20 20 21 42 21 42 + 22 44 22 44 23 69 23 69 23 69 24 24 25 25 26 78 26 78 + 26 78 27 54 27 54 28 28 29 87 29 87 29 87 30 90 30 90 + 30 90 31 62 31 62 32 32 33 165 33 165 33 165 33 165 33 165 + 34 136 34 136 34 136 34 136 35 70 35 70 36 144 36 144 + 36 144 36 144 37 74 37 74 38 76 38 76 39 117 39 117 39 117 + 40 40 41 123 41 123 41 123 42 42 43 86 43 86 44 88 44 88 + 46 92 46 92 47 188 47 188 47 188 47 188 49 49 50 50 51 51 + 52 52 53 53 54 54 55 110 55 110 56 168 56 168 56 168 57 57 + 58 232 58 232 58 232 58 232 59 236 59 236 59 236 59 236 + 60 60 61 122 61 122 62 124 62 124 63 63 64 64 65 195 65 195 + 65 195 66 66 67 67 68 68 69 69 70 70 72 216 72 216 72 216 + 73 219 73 219 73 219 74 370 74 370 74 370 74 370 74 370 + 75 225 75 225 75 225 76 76 77 154 77 154 78 156 78 156 + 79 79 80 160 80 160 81 243 81 243 81 243 82 82 83 83 84 336 + 84 336 84 336 84 336 85 255 85 255 85 255 86 86 87 174 + 87 174 88 88 89 267 89 267 89 267 90 270 90 270 90 270 + 91 455 91 455 91 455 91 455 91 455 93 279 93 279 93 279 + 94 94 95 285 95 285 95 285 96 288 96 288 96 288 97 194 + 97 194 98 196 98 196 99 297 99 297 99 297} do_execsql_test 4.6.1 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY b; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.2 { SELECT b, sum(b) OVER () FROM t2 ORDER BY b; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.3 { SELECT b, sum(b) OVER ( RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.6.4 { SELECT b, sum(b) OVER ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY b; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.7.1 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; -} {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 98 98 98 98 99 99 99 99 99 99} +} {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 + 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 + 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 + 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 + 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 + 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 + 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 + 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 + 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 + 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 + 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 + 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 + 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 + 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 + 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 + 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 + 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 + 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 + 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 + 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 + 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 + 98 98 98 98 99 99 99 99 99 99} do_execsql_test 4.7.2 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; -} {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 98 3888 98 5442 99 311 99 1146 99 9093} +} {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 + 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 + 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 + 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 + 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 + 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 + 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 + 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 + 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 + 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 + 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 + 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 + 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 + 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 + 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 + 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 + 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 + 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 + 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 + 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 + 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 + 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 + 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 + 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 + 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 + 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 + 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 + 98 3888 98 5442 99 311 99 1146 99 9093} do_execsql_test 4.7.3 { SELECT b, sum(b) OVER ( ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.7.4 { SELECT b, sum(b) OVER ( ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; -} {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} +} {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 + 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 + 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 + 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 + 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 + 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 + 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 + 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 + 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 + 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 + 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 + 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 + 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 + 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 + 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 + 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 + 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 + 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 + 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 + 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 + 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 + 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 + 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 + 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 + 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 + 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 + 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} do_execsql_test 4.8.1 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; -} {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 98 98 98 98 99 99 99 99 99 99} +} {0 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 4 4 5 5 6 6 7 7 7 7 + 7 7 8 8 8 8 8 8 9 9 9 9 9 9 10 10 11 11 11 11 12 12 + 12 12 12 12 13 13 13 13 14 14 15 15 15 15 15 15 16 16 + 16 16 16 16 17 17 19 19 20 20 21 21 21 21 22 22 22 22 + 23 23 23 23 23 23 24 24 25 25 26 26 26 26 26 26 27 27 + 27 27 28 28 29 29 29 29 29 29 30 30 30 30 30 30 31 31 + 31 31 32 32 33 33 33 33 33 33 33 33 33 33 34 34 34 34 + 34 34 34 34 35 35 35 35 36 36 36 36 36 36 36 36 37 37 + 37 37 38 38 38 38 39 39 39 39 39 39 40 40 41 41 41 41 + 41 41 42 42 43 43 43 43 44 44 44 44 46 46 46 46 47 47 + 47 47 47 47 47 47 49 49 50 50 51 51 52 52 53 53 54 54 + 55 55 55 55 56 56 56 56 56 56 57 57 58 58 58 58 58 58 + 58 58 59 59 59 59 59 59 59 59 60 60 61 61 61 61 62 62 + 62 62 63 63 64 64 65 65 65 65 65 65 66 66 67 67 68 68 + 69 69 70 70 72 72 72 72 72 72 73 73 73 73 73 73 74 74 + 74 74 74 74 74 74 74 74 75 75 75 75 75 75 76 76 77 77 + 77 77 78 78 78 78 79 79 80 80 80 80 81 81 81 81 81 81 + 82 82 83 83 84 84 84 84 84 84 84 84 85 85 85 85 85 85 + 86 86 87 87 87 87 88 88 89 89 89 89 89 89 90 90 90 90 + 90 90 91 91 91 91 91 91 91 91 91 91 93 93 93 93 93 93 + 94 94 95 95 95 95 95 95 96 96 96 96 96 96 97 97 97 97 + 98 98 98 98 99 99 99 99 99 99} do_execsql_test 4.8.2 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM t2 ORDER BY 1, 2; -} {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 98 3888 98 5442 99 311 99 1146 99 9093} +} {0 0 1 3379 1 5443 2 372 2 4473 2 7074 3 2916 3 9096 4 4049 + 5 5643 6 1047 7 2205 7 7081 7 10141 8 1553 8 5926 8 6422 + 9 4883 9 7932 9 8497 10 9544 11 5727 11 6433 12 2825 12 5918 + 12 8582 13 5190 13 8570 14 8596 15 3189 15 6023 15 8924 + 16 1942 16 1958 16 3590 17 10134 19 7474 20 5946 21 5464 + 21 9682 22 3029 22 6140 23 212 23 1926 23 8520 24 2626 + 25 3331 26 337 26 7539 26 7565 27 1270 27 10035 28 3217 + 29 1649 29 4355 29 7326 30 4215 30 9400 30 9853 31 5977 + 31 6008 32 2857 33 370 33 4326 33 8175 33 8909 33 9661 + 34 6414 34 6516 34 8958 34 9925 35 2151 35 5638 36 3701 + 36 7818 36 8785 36 8994 37 4597 37 8557 38 735 38 9891 39 842 + 39 7513 39 9721 40 3475 41 115 41 4874 41 5906 42 4185 + 43 2754 43 3518 44 7072 44 9765 46 1041 46 1316 47 2198 + 47 3378 47 7612 47 7923 49 6482 50 9450 51 5778 52 9370 + 53 4408 54 1448 55 3174 55 6876 56 2913 56 3435 56 3574 + 57 7223 58 5248 58 7876 58 9318 58 9823 59 697 59 2813 + 59 6665 59 7455 60 6821 61 2426 61 4944 62 904 62 8658 + 63 4471 64 8407 65 2116 65 5177 65 5603 66 8142 67 1620 + 68 803 69 9260 70 7396 72 4833 72 8004 72 8076 73 5017 + 73 5716 73 6213 74 74 74 189 74 2365 74 5538 74 7297 75 3665 + 75 6951 75 8343 76 3964 77 1903 77 7028 78 1394 78 4293 + 79 6292 80 4677 80 7692 81 542 81 4045 81 8488 82 10117 + 83 10008 84 1826 84 4761 84 9534 84 9628 85 2602 85 2711 + 85 7166 86 2291 87 4560 87 5865 88 6380 89 461 89 3306 + 89 3790 90 3119 90 6606 90 7782 91 995 91 2517 91 3007 + 91 8749 91 8876 93 1742 93 2051 93 8268 94 4143 95 5112 + 95 6118 95 9191 96 638 96 5344 96 6761 97 1243 97 1545 + 98 3888 98 5442 99 311 99 1146 99 9093} do_execsql_test 4.8.3 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; -} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 98 10141 99 10141 99 10141 99 10141} +} {0 10141 1 10141 1 10141 2 10141 2 10141 2 10141 3 10141 + 3 10141 4 10141 5 10141 6 10141 7 10141 7 10141 7 10141 + 8 10141 8 10141 8 10141 9 10141 9 10141 9 10141 10 10141 + 11 10141 11 10141 12 10141 12 10141 12 10141 13 10141 13 10141 + 14 10141 15 10141 15 10141 15 10141 16 10141 16 10141 16 10141 + 17 10141 19 10141 20 10141 21 10141 21 10141 22 10141 22 10141 + 23 10141 23 10141 23 10141 24 10141 25 10141 26 10141 26 10141 + 26 10141 27 10141 27 10141 28 10141 29 10141 29 10141 29 10141 + 30 10141 30 10141 30 10141 31 10141 31 10141 32 10141 33 10141 + 33 10141 33 10141 33 10141 33 10141 34 10141 34 10141 34 10141 + 34 10141 35 10141 35 10141 36 10141 36 10141 36 10141 36 10141 + 37 10141 37 10141 38 10141 38 10141 39 10141 39 10141 39 10141 + 40 10141 41 10141 41 10141 41 10141 42 10141 43 10141 43 10141 + 44 10141 44 10141 46 10141 46 10141 47 10141 47 10141 47 10141 + 47 10141 49 10141 50 10141 51 10141 52 10141 53 10141 54 10141 + 55 10141 55 10141 56 10141 56 10141 56 10141 57 10141 58 10141 + 58 10141 58 10141 58 10141 59 10141 59 10141 59 10141 59 10141 + 60 10141 61 10141 61 10141 62 10141 62 10141 63 10141 64 10141 + 65 10141 65 10141 65 10141 66 10141 67 10141 68 10141 69 10141 + 70 10141 72 10141 72 10141 72 10141 73 10141 73 10141 73 10141 + 74 10141 74 10141 74 10141 74 10141 74 10141 75 10141 75 10141 + 75 10141 76 10141 77 10141 77 10141 78 10141 78 10141 79 10141 + 80 10141 80 10141 81 10141 81 10141 81 10141 82 10141 83 10141 + 84 10141 84 10141 84 10141 84 10141 85 10141 85 10141 85 10141 + 86 10141 87 10141 87 10141 88 10141 89 10141 89 10141 89 10141 + 90 10141 90 10141 90 10141 91 10141 91 10141 91 10141 91 10141 + 91 10141 93 10141 93 10141 93 10141 94 10141 95 10141 95 10141 + 95 10141 96 10141 96 10141 96 10141 97 10141 97 10141 98 10141 + 98 10141 99 10141 99 10141 99 10141} do_execsql_test 4.8.4 { SELECT b, sum(b) OVER ( ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) FROM t2 ORDER BY 1, 2; -} {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} +} {0 10141 1 4699 1 6763 2 3069 2 5670 2 9771 3 1048 3 7228 + 4 6096 5 4503 6 9100 7 7 7 3067 7 7943 8 3727 8 4223 8 8596 + 9 1653 9 2218 9 5267 10 607 11 3719 11 4425 12 1571 12 4235 + 12 7328 13 1584 13 4964 14 1559 15 1232 15 4133 15 6967 + 16 6567 16 8199 16 8215 17 24 19 2686 20 4215 21 480 21 4698 + 22 4023 22 7134 23 1644 23 8238 23 9952 24 7539 25 6835 + 26 2602 26 2628 26 9830 27 133 27 8898 28 6952 29 2844 + 29 5815 29 8521 30 318 30 771 30 5956 31 4164 31 4195 32 7316 + 33 513 33 1265 33 1999 33 5848 33 9804 34 250 34 1217 34 3659 + 34 3761 35 4538 35 8025 36 1183 36 1392 36 2359 36 6476 + 37 1621 37 5581 38 288 38 9444 39 459 39 2667 39 9338 40 6706 + 41 4276 41 5308 41 10067 42 5998 43 6666 43 7430 44 420 + 44 3113 46 8871 46 9146 47 2265 47 2576 47 6810 47 7990 + 49 3708 50 741 51 4414 52 823 53 5786 54 8747 55 3320 55 7022 + 56 6623 56 6762 56 7284 57 2975 58 376 58 881 58 2323 58 4951 + 59 2745 59 3535 59 7387 59 9503 60 3380 61 5258 61 7776 + 62 1545 62 9299 63 5733 64 1798 65 4603 65 5029 65 8090 + 66 2065 67 8588 68 9406 69 950 70 2815 72 2137 72 2209 + 72 5380 73 4001 73 4498 73 5197 74 2918 74 4677 74 7850 + 74 10026 74 10141 75 1873 75 3265 75 6551 76 6253 77 3190 + 77 8315 78 5926 78 8825 79 3928 80 2529 80 5544 81 1734 + 81 6177 81 9680 82 106 83 216 84 597 84 691 84 5464 84 8399 + 85 3060 85 7515 85 7624 86 7936 87 4363 87 5668 88 3849 + 89 6440 89 6924 89 9769 90 2449 90 3625 90 7112 91 1356 + 91 1483 91 7225 91 7715 91 9237 93 1966 93 8183 93 8492 + 94 6092 95 1045 95 4118 95 5124 96 3476 96 4893 96 9599 + 97 8693 97 8995 98 4797 98 6351 99 1147 99 9094 99 9929} + + +do_test 4.9 { + set myres {} + foreach r [db eval {SELECT + rank() OVER win AS rank, + cume_dist() OVER win AS cume_dist FROM t1 + WINDOW win AS (ORDER BY 1);}] { + lappend myres [format %.4f [set r]] + } + set res2 {1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000} + set i 0 + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + incr i + } + set {} {} +} {} finish_test diff --git a/test/window9.test b/test/window9.test new file mode 100644 index 0000000..5a32a75 --- /dev/null +++ b/test/window9.test @@ -0,0 +1,102 @@ +# 2019 June 8 +# +# 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 window9 + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE fruits( + name TEXT COLLATE NOCASE, + color TEXT COLLATE NOCASE + ); +} + +do_execsql_test 1.1 { + INSERT INTO fruits (name, color) VALUES ('apple', 'RED'); + INSERT INTO fruits (name, color) VALUES ('APPLE', 'yellow'); + INSERT INTO fruits (name, color) VALUES ('pear', 'YELLOW'); + INSERT INTO fruits (name, color) VALUES ('PEAR', 'green'); +} + +do_execsql_test 1.2 { + SELECT name, color, dense_rank() OVER (ORDER BY name) FROM fruits; +} { + apple RED 1 + APPLE yellow 1 + pear YELLOW 2 + PEAR green 2 +} + +do_execsql_test 1.3 { + SELECT name, color, + dense_rank() OVER (PARTITION BY name ORDER BY color) + FROM fruits; +} { + apple RED 1 + APPLE yellow 2 + PEAR green 1 + pear YELLOW 2 +} + +do_execsql_test 1.4 { + SELECT name, color, + dense_rank() OVER (ORDER BY name), + dense_rank() OVER (PARTITION BY name ORDER BY color) + FROM fruits; +} { + apple RED 1 1 + APPLE yellow 1 2 + PEAR green 2 1 + pear YELLOW 2 2 +} + +do_execsql_test 1.5 { + SELECT name, color, + dense_rank() OVER (ORDER BY name), + dense_rank() OVER (PARTITION BY name ORDER BY color) + FROM fruits ORDER BY color; +} { + PEAR green 2 1 + apple RED 1 1 + APPLE yellow 1 2 + pear YELLOW 2 2 +} + +do_execsql_test 2.0 { + CREATE TABLE t1(a BLOB, b INTEGER, c COLLATE nocase); + INSERT INTO t1 VALUES(1, 2, 'abc'); + INSERT INTO t1 VALUES(3, 4, 'ABC'); +} + +do_execsql_test 2.1.1 { + SELECT c=='Abc' FROM t1 +} {1 1} +do_execsql_test 2.1.2 { + SELECT c=='Abc', rank() OVER (ORDER BY b) FROM t1 +} {1 1 1 2} + +do_execsql_test 2.2.1 { + SELECT b=='2' FROM t1 +} {1 0} +do_execsql_test 2.2.2 { + SELECT b=='2', rank() OVER (ORDER BY a) FROM t1 +} {1 1 0 2} + +finish_test + diff --git a/test/windowfault.test b/test/windowfault.test index 6c2554a..41c4bb6 100644 --- a/test/windowfault.test +++ b/test/windowfault.test @@ -209,6 +209,7 @@ proc tmpread_injectstop {} { return $ret } +set L [db eval {SELECT 0.0 FROM t}] do_faultsim_test 9 -end 25 -faults tmpread -body { execsql { SELECT sum(y) OVER win FROM t @@ -217,7 +218,7 @@ do_faultsim_test 9 -end 25 -faults tmpread -body { ) } } -test { - faultsim_test_result {0 {}} + faultsim_test_result [list 0 $::L] } catch {db close} diff --git a/test/with1.test b/test/with1.test index aecf0d1..5631bfb 100644 --- a/test/with1.test +++ b/test/with1.test @@ -1091,4 +1091,53 @@ do_catchsql_test 22.1 { SELECT 4 FROM c,c,c,c,c,c,c,c,c; } {1 {too many FROM clause terms, max: 200}} +# 2019-05-22 +# ticket https://www.sqlite.org/src/tktview/ce823231949d3abf42453c8f20 +# +sqlite3 db :memory: +do_execsql_test 23.1 { + CREATE TABLE t1(id INTEGER NULL PRIMARY KEY, name Text); + INSERT INTO t1 VALUES (1, 'john'); + INSERT INTO t1 VALUES (2, 'james'); + INSERT INTO t1 VALUES (3, 'jingle'); + INSERT INTO t1 VALUES (4, 'himer'); + INSERT INTO t1 VALUES (5, 'smith'); + CREATE VIEW v2 AS + WITH t4(Name) AS (VALUES ('A'), ('B')) + SELECT Name Name FROM t4; + CREATE VIEW v3 AS + WITH t4(Att, Val, Act) AS (VALUES + ('C', 'D', 'E'), + ('F', 'G', 'H') + ) + SELECT D.Id Id, P.Name Protocol, T.Att Att, T.Val Val, T.Act Act + FROM t1 D + CROSS JOIN v2 P + CROSS JOIN t4 T; + SELECT * FROM v3; +} {1 A C D E 1 A F G H 1 B C D E 1 B F G H 2 A C D E 2 A F G H 2 B C D E 2 B F G H 3 A C D E 3 A F G H 3 B C D E 3 B F G H 4 A C D E 4 A F G H 4 B C D E 4 B F G H 5 A C D E 5 A F G H 5 B C D E 5 B F G H} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 24.1 { + CREATE TABLE t1(a, b, c); + CREATE VIEW v1 AS SELECT max(a), min(b) FROM t1 GROUP BY c; +} +do_test 24.1 { + set program [db eval {EXPLAIN SELECT 1 FROM v1,v1,v1}] + expr [lsearch $program OpenDup]>0 +} {1} +do_execsql_test 24.2 { + ATTACH "" AS aux; + CREATE VIEW aux.v3 AS VALUES(1); + CREATE VIEW main.v3 AS VALUES(3); + + CREATE VIEW aux.v2 AS SELECT * FROM v3; + CREATE VIEW main.v2 AS SELECT * FROM v3; + + SELECT * FROM main.v2 AS a, aux.v2 AS b, aux.v2 AS c, main.v2 AS d; +} { + 3 1 1 3 +} + finish_test diff --git a/test/with3.test b/test/with3.test index 0f49f06..360d37f 100644 --- a/test/with3.test +++ b/test/with3.test @@ -130,4 +130,40 @@ do_eqp_test 3.2.2 { `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?) } +do_execsql_test 4.0 { + WITH t5(t5col1) AS ( + SELECT ( + WITH t3(t3col1) AS ( + WITH t2 AS ( + WITH t1 AS (SELECT 1 AS c1 GROUP BY 1) + SELECT a.c1 FROM t1 AS a, t1 AS b + WHERE anoncol1 = 1 + ) + SELECT (SELECT 1 FROM t2) FROM t2 + ) + SELECT t3col1 FROM t3 WHERE t3col1 + ) FROM (SELECT 1 AS anoncol1) + ) + SELECT t5col1, t5col1 FROM t5 +} {1 1} +do_execsql_test 4.1 { + SELECT EXISTS ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0(Col0) AS (SELECT ALL 1 ) + SELECT ALL ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0 AS (SELECT DISTINCT 1 GROUP BY 1 ) + SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 + WHERE Col0 = 1 + ) + SELECT ALL (SELECT DISTINCT * FROM Table0) FROM Table0 WHERE Col0 = 1 + ) + SELECT ALL * FROM Table0 NATURAL INNER JOIN Table0 + ) FROM Table0 ) + SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 + ); +} {1} + + finish_test diff --git a/test/without_rowid1.test b/test/without_rowid1.test index c8f0187..3832239 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -391,5 +391,23 @@ do_execsql_test 10.6 { SELECT * FROM t1; } {b a 3 b b 4} +# 2019-04-29 ticket https://www.sqlite.org/src/info/3182d3879020ef3 +do_execsql_test 11.1 { + CREATE TABLE t11(a TEXT PRIMARY KEY, b INT) WITHOUT ROWID; + CREATE INDEX t11a ON t11(a COLLATE NOCASE); + INSERT INTO t11(a,b) VALUES ('A',1),('a',2); + PRAGMA integrity_check; + SELECT a FROM t11 ORDER BY a COLLATE binary; +} {ok A a} + +# 2019-05-13 ticket https://www.sqlite.org/src/info/bba7b69f9849b5b +do_execsql_test 12.1 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0 (c0 INTEGER PRIMARY KEY DESC, c1 UNIQUE DEFAULT NULL) WITHOUT ROWID; + INSERT INTO t0(c0) VALUES (1), (2), (3), (4), (5); + REINDEX; + PRAGMA integrity_check; +} {ok} + finish_test diff --git a/tool/lemon.c b/tool/lemon.c index 7ef99fd..4416f67 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -48,6 +48,7 @@ extern int access(const char *path, int mode); #define MAXRHS 1000 #endif +extern void memory_error(); static int showPrecedenceConflict = 0; static char *msort(char*,char**,int(*)(const char*,const char*)); @@ -483,22 +484,22 @@ void Configtable_clear(int(*)(struct config *)); /* Allocate a new parser action */ static struct action *Action_new(void){ - static struct action *freelist = 0; + static struct action *actionfreelist = 0; struct action *newaction; - if( freelist==0 ){ + if( actionfreelist==0 ){ int i; int amt = 100; - freelist = (struct action *)calloc(amt, sizeof(struct action)); - if( freelist==0 ){ + actionfreelist = (struct action *)calloc(amt, sizeof(struct action)); + if( actionfreelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new parser action."); exit(1); } - for(i=0; inext; + newaction = actionfreelist; + actionfreelist = actionfreelist->next; return newaction; } @@ -1907,7 +1908,7 @@ static char *msort( return ep; } /************************ From the file "option.c" **************************/ -static char **argv; +static char **g_argv; static struct s_options *op; static FILE *errstream; @@ -1920,14 +1921,14 @@ static FILE *errstream; static void errline(int n, int k, FILE *err) { int spcnt, i; - if( argv[0] ) fprintf(err,"%s",argv[0]); - spcnt = lemonStrlen(argv[0]) + 1; - for(i=1; i=0 ? argv[i] : 0; + return i>=0 ? g_argv[i] : 0; } void OptErr(int n) @@ -2728,7 +2729,7 @@ to follow the previous rule."); case WAITING_FOR_CLASS_ID: if( !ISLOWER(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, - "%%token_class must be followed by an identifier: ", x); + "%%token_class must be followed by an identifier: %s", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else if( Symbol_find(x) ){ @@ -3848,7 +3849,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ ErrorMsg(lemp->filename,rp->ruleline, "%s(%s) has the same label as the LHS but is not the left-most " "symbol on the RHS.", - rp->rhs[i]->name, rp->rhsalias); + rp->rhs[i]->name, rp->rhsalias[i]); lemp->errorcnt++; } for(j=0; jg.mxPage ) return; a = fileRead((pgno-1)*g.pagesize, g.pagesize); switch( a[hdr] ){ + case 0: { + if( allZero(a, g.pagesize) ){ + zType = "zeroed page"; + }else if( parent<0 ){ + return; + }else{ + zType = "corrupt node"; + } + break; + } case 2: zType = "interior node of index"; break; case 5: zType = "interior node of table"; break; case 10: zType = "leaf of index"; break; case 13: zType = "leaf of table"; break; - } - if( parent ){ - page_usage_msg(pgno, "%s [%s], child %d of page %d", - zType, zName, idx, parent); - }else{ - page_usage_msg(pgno, "root %s [%s]", zType, zName); + default: { + if( parent<0 ) return; + zType = "corrupt node"; + } } nCell = a[hdr+3]*256 + a[hdr+4]; + if( nCell==1 ){ + sqlite3_snprintf(sizeof(zEntry),zEntry,"1 row"); + }else{ + sqlite3_snprintf(sizeof(zEntry),zEntry,"%d rows", nCell); + } + if( parent>0 ){ + page_usage_msg(pgno, "%s [%s], child %d of page %d, %s", + zType, zName, idx, parent, zEntry); + }else if( parent==0 ){ + page_usage_msg(pgno, "root %s [%s], %s", zType, zName, zEntry); + }else{ + page_usage_msg(pgno, "orphaned %s, %s", zType, zEntry); + } if( a[hdr]==2 || a[hdr]==5 ){ int cellstart = hdr+12; unsigned int child; @@ -988,6 +1021,7 @@ static void page_usage_report(const char *zPrg, const char *zDbName){ /* Print the report and free memory used */ for(i=1; i<=g.mxPage; i++){ + if( zPageUse[i]==0 ) page_usage_btree(i, -1, 0, 0); printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???"); sqlite3_free(zPageUse[i]); } From 2f8202bf5102d7834f365bddb68a4ddf6cf6c49c Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 25 Sep 2019 13:36:22 -0400 Subject: [PATCH 09/24] update tests to expect "ok" from PRAGMA key --- test/sqlcipher-compatibility.test | 80 ++++++++++++++-------------- test/sqlcipher-core.test | 34 ++++++------ test/sqlcipher-integrity.test | 20 +++---- test/sqlcipher-plaintext-header.test | 31 ++++++----- test/sqlcipher-pragmas.test | 48 ++++++++--------- test/sqlcipher-rekey.test | 22 ++++---- test/sqlcipher.test | 1 - 7 files changed, 120 insertions(+), 116 deletions(-) diff --git a/test/sqlcipher-compatibility.test b/test/sqlcipher-compatibility.test index 7958d76..090e05e 100644 --- a/test/sqlcipher-compatibility.test +++ b/test/sqlcipher-compatibility.test @@ -68,7 +68,7 @@ do_test unencrypted-attach { PRAGMA key='testkey'; SELECT count(*) FROM t1; } db2 -} {1000} +} {ok 1000} db2 close file delete -force test.db file delete -force test2.db @@ -102,7 +102,7 @@ do_test unencrypted-attach-raw-key { PRAGMA key="x'10483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'"; SELECT count(*) FROM t1; } db2 -} {1000} +} {ok 1000} db2 close file delete -force test.db file delete -force test2.db @@ -115,7 +115,7 @@ do_test compat-open-4.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} db close # create an encrypted database, attach an default-key encrypted volume @@ -148,7 +148,7 @@ do_test encrypted-attach-default-key { PRAGMA key='testkey'; SELECT count(*) FROM t1; } db2 -} {1000} +} {ok 1000} db close db2 close file delete -force test.db @@ -257,7 +257,7 @@ do_test unencrypted-corrupt-to-encrypted-export { SELECT count(*) FROM sqlite_master; SELECT count(*) FROM t1; } -} {1 2} +} {ok 1 2} db close file delete -force test.db file delete -force test2.db @@ -299,7 +299,7 @@ do_test unencrypted-to-encrypted-import { PRAGMA key = 'testkey2'; SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close file delete -force test.db file delete -force test2.db @@ -354,7 +354,7 @@ do_test open-1.1.8-database { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {75709 1 1 one one 1 2 one two 1 2} +} {ok 75709 1 1 one one 1 2 one two 1 2} db close file delete -force test.db @@ -381,7 +381,7 @@ do_test attach-and-copy-1.1.8 { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {75709 1 1 one one 1 2 one two 1 2} +} {ok 75709 1 1 one one 1 2 one two 1 2} db close file delete -force test.db @@ -424,7 +424,7 @@ do_test attached-database-pragmas { PRAGMA cipher_use_hmac = OFF; SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close file delete -force test.db file delete -force test2.db @@ -505,7 +505,7 @@ do_test export-database { SELECT seq FROM sqlite_sequence WHERE name = 't1'; -- verify that autoincrement worked SELECT a FROM fts WHERE b MATCH '1000000'; } -} {1000 1000 1 1000 1001 1001 1000000} +} {ok 1000 1000 1 1000 1001 1001 1000000} db close file delete -force test.db file delete -force test2.db @@ -578,7 +578,7 @@ do_test export-attached-database { SELECT a FROM fts WHERE b MATCH '1000000'; SELECT count(*) FROM t3; } -} {1000 1000 2 1000 1001 1001 1000000 2} +} {ok 1000 1000 2 1000 1001 1001 1000000 2} db close file delete -force test.db file delete -force test2.db @@ -644,7 +644,7 @@ do_test vacuum { SELECT count(*) FROM t1; }] -} {10000 true true 5000 5000} +} {10000 true true {ok 5000} {ok 5000}} db close file delete -force test.db file delete -force test-vacuum.db @@ -671,7 +671,7 @@ do_test default-hmac-kdf-attach { PRAGMA cipher_default_page_size = 4096; PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA512; } -} {75709 75709} +} {ok 75709 75709} db close file delete -force test.db file delete -force sqlcipher-1.1.8-testkey.db @@ -722,7 +722,7 @@ do_test change-default-hmac-kdf-attach { PRAGMA cipher_default_page_size = 4096; PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA512; } -} {1 75709} +} {ok 1 75709} db close file delete -force test.db file delete -force sqlcipher-1.1.8-testkey.db @@ -818,7 +818,7 @@ do_test multipage-schema { SELECT count(*) FROM sqlite_master where type = 'table'; } db -} {300} +} {ok 300} db close file delete -force test.db @@ -852,7 +852,7 @@ do_test multipage-schema-autovacuum-shortread { SELECT count(*) FROM sqlite_master where type = 'table'; } db -} {300} +} {ok 300} db close file delete -force test.db @@ -882,7 +882,7 @@ do_test multipage-schema-autovacuum-shortread-wal { PRAGMA key = 'testkey'; SELECT count(*) FROM sqlite_master where type = 'table'; } db -} {300} +} {ok 300} db close file delete -force test.db @@ -899,7 +899,7 @@ do_test open-3.0-le-database { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {78536 1 1 one one 1 2 one two} +} {ok 78536 1 1 one one 1 2 one two} db close # open a 2.0 database with little endian hmac page numbers (default) @@ -915,7 +915,7 @@ do_test open-2.0-le-database { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {78536 1 1 one one 1 2 one two} +} {ok 78536 1 1 one one 1 2 one two} db close # open a 2.0 database with big-endian hmac page numbers @@ -932,7 +932,7 @@ do_test open-2.0-be-database { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {{PRAGMA cipher_hmac_pgno is deprecated, please remove from use} 78536 1 1 one one 1 2 one two} +} {ok {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} 78536 1 1 one one 1 2 one two} db close # open a 2.0 database with big-endian hmac page numbers @@ -962,7 +962,7 @@ do_test be-to-le-migration { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {78536 1 1 one one 1 2 one two} +} {ok 78536 1 1 one one 1 2 one two} db close file delete -force test.db @@ -984,7 +984,7 @@ do_test open-2.0-beta-database { SELECT count(*) FROM t1; SELECT distinct * FROM t1; } -} {{PRAGMA fast_kdf_iter is deprecated, please remove from use} {PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use} 38768 test-0-0 test-0-1 test-1-0 test-1-1} +} {ok {PRAGMA fast_kdf_iter is deprecated, please remove from use} {PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use} 38768 test-0-0 test-0-1 test-1-0 test-1-1} db close # open a 2.0 beta database @@ -1018,7 +1018,7 @@ do_test 2.0-beta-to-2.0-migration { PRAGMA key = 'testkey'; SELECT distinct * FROM t1; } -} {test-0-0 test-0-1 test-1-0 test-1-1} +} {ok test-0-0 test-0-1 test-1-0 test-1-1} db close file delete -force test.db @@ -1036,7 +1036,7 @@ do_test migrate-1.1.8-database-to-current-format { PRAGMA key = 'testkey'; SELECT count(*) FROM sqlite_master; } -} {1} +} {ok 1} db close file delete -force test.db test.db-migrated test.db-journal @@ -1054,7 +1054,7 @@ do_test migrate-2-0-le-database-to-current-format { PRAGMA key = 'testkey'; SELECT count(*) FROM sqlite_master; } -} {1} +} {ok 1} db close file delete -force test.db test.db-migrated test.db-journal @@ -1073,7 +1073,7 @@ do_test migrate-3-0-database-to-current-format { SELECT count(*) FROM sqlite_master; PRAGMA journal_mode; } -} {1 delete} +} {ok 1 delete} db close file delete -force test.db @@ -1103,7 +1103,7 @@ do_test migrate-wal-database-to-current { SELECT count(*) FROM sqlite_master; PRAGMA journal_mode; }] -} {wal {0 wal} {1 wal}} +} {{ok wal} {ok 0 wal} {ok 1 wal}} db close file delete -force test.db @@ -1124,7 +1124,7 @@ do_test key-database-by-name { pragma key = 'foo'; select * from t1; } -} {foo bar} +} {ok foo bar} db close file delete -force test.db file delete -force new.db @@ -1150,7 +1150,7 @@ do_test key-multiple-databases-with-different-keys-using-pragma { select * from t1; select * from test.t1; } -} {foo bar baz qux} +} {ok foo bar baz qux} db close file delete -force test.db file delete -force new.db @@ -1213,7 +1213,7 @@ do_test can-migrate-with-keys-longer-than-64-characters { PRAGMA key = "012345678901234567890123456789012345678901234567890123456789012345"; PRAGMA user_version; } -} {5} +} {ok 5} db close file delete -force test.db @@ -1240,7 +1240,7 @@ do_test can-migrate-with-raw-hex-key { PRAGMA user_version; } -} {5} +} {ok 5} db close file delete -force test.db @@ -1263,7 +1263,7 @@ do_test attach_database_with_non_default_page_size { SELECT count(*) FROM test2.t1; PRAGMA cipher_default_page_size = 4096; } -} {2} +} {ok 2} db close file delete -force test.db test2.db @@ -1296,7 +1296,7 @@ do_test compat-open-1.1.8-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 75709} +} {ok ok 75709} db close # open a 2.0 database using cipher_compatibility @@ -1308,7 +1308,7 @@ do_test compat-open-2.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} db close # open a 3.0 database using cipher_compatibility @@ -1320,7 +1320,7 @@ do_test compat-open-3.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} db close # open a 4.0 database using cipher_compatibility @@ -1332,7 +1332,7 @@ do_test compat-open-4.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} db close # open a 1.1.8 database using cipher_default_compatibility @@ -1344,7 +1344,7 @@ do_test default-compat-open-1.1.8-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 75709} +} {ok ok 75709} db close # open a 2.0 database using cipher_default_compatibility @@ -1356,7 +1356,7 @@ do_test default-compat-open-2.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} # open a 3.0 database using cipher_default_compatibility do_test default-compat-open-3.0-database { @@ -1367,7 +1367,7 @@ do_test default-compat-open-3.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} # re-open a 4.0 database using cipher_default_compatibility do_test default-compat-open-4.0-database { @@ -1378,7 +1378,7 @@ do_test default-compat-open-4.0-database { PRAGMA integrity_check; SELECT count(*) FROM t1; } -} {ok 78536} +} {ok ok 78536} sqlite3_test_control_pending_byte $old_pending_byte diff --git a/test/sqlcipher-core.test b/test/sqlcipher-core.test index f7c9403..211b76c 100644 --- a/test/sqlcipher-core.test +++ b/test/sqlcipher-core.test @@ -52,7 +52,7 @@ do_test will-open-with-correct-raw-key { SELECT name FROM sqlite_master WHERE type='table'; SELECT * from t1; } -} {t1 test1 test2} +} {ok t1 test1 test2} db close file delete -force test.db @@ -70,7 +70,7 @@ do_test will-open-with-correct-derived-key { SELECT name FROM sqlite_master WHERE type='table'; SELECT * from t1; } -} {t1 test1 test2} +} {ok t1 test1 test2} db close file delete -force test.db @@ -87,7 +87,7 @@ do_test test-temp-master { SELECT name FROM sqlite_temp_master WHERE type='table'; SELECT * from temp_t1; } -} {temp_t1 test1 test2} +} {ok temp_t1 test1 test2} db close file delete -force test.db @@ -236,7 +236,7 @@ do_test attach-empty-database-with-default-key { SELECT count(*) FROM t1; } db2] lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]] -} {2 1} +} {{ok 2} 1} db close db2 close file delete -force test.db @@ -267,7 +267,7 @@ do_test attach-empty-database-with-default-key-first-op { } db2] lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]] -} {1 0} +} {{ok 1} 0} db close db2 close file delete -force test.db @@ -298,7 +298,7 @@ do_test attach-empty-database-with-cipher-store-pass { SELECT count(*) FROM t1; } db2] lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]] -} {2 0} +} {{ok 2} 0} db close db2 close file delete -force test.db @@ -341,7 +341,7 @@ do_test attach-database-with-default-key-using-cipher-store-pass { SELECT * FROM t1; } db2 -} {foo bar} +} {ok foo bar} db2 close file delete -force test.db file delete -force test2.db @@ -451,7 +451,7 @@ do_test alter-schema { SELECT * FROM t1a; } -} {3 2 teststring} +} {ok 3 2 teststring} db close file delete -force test.db @@ -465,7 +465,7 @@ do_test verify-errors-for-rekey-kdf-and-cipher-changes { PRAGMA rekey_kdf_iter = 1000; PRAGMA rekey_cipher = 'aes-256-ecb'; } -} {{PRAGMA rekey_kdf_iter is no longer supported.} {PRAGMA rekey_cipher is no longer supported.}} +} {ok {PRAGMA rekey_kdf_iter is no longer supported.} {PRAGMA rekey_cipher is no longer supported.}} db close file delete -force test.db @@ -477,7 +477,7 @@ do_test verify-errors-for-cipher-change { PRAGMA key = 'testkey'; PRAGMA cipher = 'aes-256-ecb'; } -} {{PRAGMA cipher is no longer supported.}} +} {ok {PRAGMA cipher is no longer supported.}} db close file delete -force test.db @@ -516,7 +516,7 @@ do_test custom-pagesize { SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close # open the database with the default page size @@ -565,7 +565,7 @@ do_test journal-mode-wal { PRAGMA journal_mode; } -} {1000 wal} +} {ok 1000 wal} db close file delete -force test.db @@ -577,7 +577,7 @@ do_test multiple-key-calls-safe-1 { PRAGMA cache_size = 0; SELECT name FROM sqlite_master WHERE type='table'; } -} {t1} +} {ok t1} do_test multiple-key-calls-safe-2 { catchsql { @@ -591,7 +591,7 @@ do_test multiple-key-calls-safe-3 { PRAGMA key = 'testkey'; SELECT name FROM sqlite_master WHERE type='table'; } -} {t1} +} {ok t1} db close file delete -force test.db @@ -630,7 +630,7 @@ do_test custom-hmac-kdf-iter { SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close # open the database with the default hmac @@ -698,7 +698,7 @@ do_test auto-vacuum { SELECT count(*) FROM t1; }] -} {10000 true 5000} +} {10000 true {ok 5000}} db close file delete -force test.db @@ -725,7 +725,7 @@ do_test cipher-options-before-keys { SELECT count(*) FROM t1; } -} {1} +} {ok 1} db close file delete -force test.db diff --git a/test/sqlcipher-integrity.test b/test/sqlcipher-integrity.test index 098c162..b1ad3d7 100644 --- a/test/sqlcipher-integrity.test +++ b/test/sqlcipher-integrity.test @@ -113,7 +113,7 @@ do_test nohmac-not-tamper-resistent { SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close file delete -force test.db @@ -165,7 +165,7 @@ do_test memory-integrity-check-should-fail { INSERT INTO t1(a,b) values (1,2); PRAGMA cipher_integrity_check; } -} {{database file is undefined}} +} {ok {database file is undefined}} db close # try cipher_integrity_check on a valid 1.1.8 database @@ -178,7 +178,7 @@ do_test version-1-integrity-check-fail-no-hmac { PRAGMA cipher_compatibility = 1; PRAGMA cipher_integrity_check; } -} {{HMAC is not enabled, unable to integrity check}} +} {ok {HMAC is not enabled, unable to integrity check}} db close file delete -force test.db @@ -191,7 +191,7 @@ do_test version-2-integrity-check-valid { PRAGMA cipher_compatibility = 2; PRAGMA cipher_integrity_check; } -} {} +} {ok} db close file delete -force test.db @@ -206,7 +206,7 @@ do_test version-2-integrity-check-invalid { PRAGMA cipher_compatibility = 2; PRAGMA cipher_integrity_check; } -} {{HMAC verification failed for page 9} {HMAC verification failed for page 11}} +} {ok {HMAC verification failed for page 9} {HMAC verification failed for page 11}} db close file delete -force test.db @@ -219,7 +219,7 @@ do_test version-3-integrity-check-valid { PRAGMA cipher_compatibility = 3; PRAGMA cipher_integrity_check; } -} {} +} {ok} db close file delete -force test.db @@ -234,7 +234,7 @@ do_test version-3-integrity-check-invalid { PRAGMA cipher_compatibility = 3; PRAGMA cipher_integrity_check; } -} {{HMAC verification failed for page 9} {HMAC verification failed for page 11}} +} {ok {HMAC verification failed for page 9} {HMAC verification failed for page 11}} db close file delete -force test.db @@ -246,7 +246,7 @@ do_test version-4-integrity-check-valid { PRAGMA key = 'testkey'; PRAGMA cipher_integrity_check; } -} {} +} {ok} db close file delete -force test.db @@ -264,7 +264,7 @@ do_test version-4-integrity-check-invalid { PRAGMA key = 'testkey'; PRAGMA cipher_integrity_check; } -} {{HMAC verification failed for page 2} {HMAC verification failed for page 3} {HMAC verification failed for page 4}} +} {ok {HMAC verification failed for page 2} {HMAC verification failed for page 3} {HMAC verification failed for page 4}} db close file delete -force test.db @@ -277,7 +277,7 @@ do_test version-4-integrity-check-invalid-last-page { PRAGMA key = 'testkey'; PRAGMA cipher_integrity_check; } -} {{page 240 has an invalid size of 2 bytes}} +} {ok {page 240 has an invalid size of 2 bytes}} db close file delete -force test.db diff --git a/test/sqlcipher-plaintext-header.test b/test/sqlcipher-plaintext-header.test index f9f12a8..54279b5 100644 --- a/test/sqlcipher-plaintext-header.test +++ b/test/sqlcipher-plaintext-header.test @@ -44,8 +44,8 @@ set hexkeyspec "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483 # of an existing database do_test test-pragma-salt-get { sqlite_orig db test.db + execsql { PRAGMA key = 'test'; } set salt [execsql { - PRAGMA key = 'test'; CREATE TABLE t1(a,b); PRAGMA cipher_salt; }] @@ -75,7 +75,7 @@ do_test test-pragma-salt-set { PRAGMA cipher_salt; "] -} {01010101010101010101010101010101 {1 01010101010101010101010101010101}} +} {01010101010101010101010101010101 {ok 1 01010101010101010101010101010101}} file delete -force test.db @@ -101,7 +101,7 @@ do_test test-raw-key-with-salt-spec { SELECT count(*) FROM t1; PRAGMA cipher_salt; "] -} {01010101010101010101010101010101 {1 01010101010101010101010101010101}} +} {01010101010101010101010101010101 {ok 1 01010101010101010101010101010101}} db close file delete -force test.db @@ -145,7 +145,7 @@ do_test test-raw-key-with-invalid-salt-spec-no-hmac { PRAGMA cipher_use_hmac = OFF; SELECT count(*) FROM t1; } -} {1} +} {ok 1} db close file delete -force test.db @@ -201,7 +201,7 @@ do_test test-valid-plaintext-header-size { SELECT count(*) FROM t1; PRAGMA cipher_plaintext_header_size; "] -} {53514C69746520666F726D6174203300 {1 16}} +} {53514C69746520666F726D6174203300 {ok 1 16}} db close file delete -force test.db @@ -247,9 +247,12 @@ file delete -force test.db do_test test-valid-default-plaintext-header-size { set rc {} sqlite_orig db test.db - set salt [execsql { + execsql { PRAGMA cipher_default_plaintext_header_size = 16; PRAGMA key = 'test'; + } + + set salt [execsql { CREATE TABLE t1(a,b); INSERT INTO t1(a,b) VALUES (1,2); PRAGMA cipher_salt; @@ -259,8 +262,8 @@ do_test test-valid-default-plaintext-header-size { lappend rc [hexio_read test.db 0 16] sqlite_orig db test.db + execsql { PRAGMA key = 'test'; } lappend rc [execsql " - PRAGMA key = 'test'; PRAGMA cipher_salt = \"x'$salt'\"; SELECT count(*) FROM t1; PRAGMA cipher_plaintext_header_size; @@ -280,9 +283,11 @@ file delete -force test.db do_test test-valid-default-plaintext-header-size-attach { set rc {} sqlite_orig db test.db - set salt [execsql { + execsql { PRAGMA cipher_default_plaintext_header_size = 16; PRAGMA key = 'test'; + } + set salt [execsql { CREATE TABLE temp(a); ATTACH DATABASE 'test2.db' as db2; CREATE TABLE db2.t2(a,b); @@ -294,8 +299,8 @@ do_test test-valid-default-plaintext-header-size-attach { lappend rc [hexio_read test2.db 0 16] sqlite_orig db test2.db + execsql { PRAGMA key = 'test'; } lappend rc [execsql " - PRAGMA key = 'test'; PRAGMA cipher_salt = \"x'$salt'\"; SELECT count(*) FROM t2; PRAGMA cipher_plaintext_header_size; @@ -343,7 +348,7 @@ do_test test-plaintext-header-migrate-journal-delete { SELECT count(*) FROM t1; "] -} {01010101010101010101010101010101 53514C69746520666F726D61742033001000010150 1} +} {01010101010101010101010101010101 53514C69746520666F726D61742033001000010150 {ok 1}} db close file delete -force test.db @@ -383,7 +388,7 @@ do_test test-plaintext-header-migrate-journal-wal { PRAGMA journal_mode; "] -} {01010101010101010101010101010101 {1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {1 wal}} +} {01010101010101010101010101010101 {ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}} db close file delete -force test.db @@ -426,7 +431,7 @@ do_test test-plaintext-header-migrate-journal-wal-string-key-random-salt { "] -} {{1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {1 wal}} +} {{ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}} db close file delete -force test.db @@ -436,8 +441,8 @@ file delete -force test.db do_test plaintext-header-size-salt-first-op { set rc {} sqlite_orig db test.db + execsql { PRAGMA key = 'test'; } set salt1 [execsql { - PRAGMA key = 'test'; PRAGMA cipher_plaintext_header_size = 16; PRAGMA cipher_salt; }] diff --git a/test/sqlcipher-pragmas.test b/test/sqlcipher-pragmas.test index 31c99fe..8d13b21 100644 --- a/test/sqlcipher-pragmas.test +++ b/test/sqlcipher-pragmas.test @@ -58,7 +58,7 @@ do_test verify-pragma-cipher-use-hmac-default { PRAGMA key = 'test'; PRAGMA cipher_use_hmac; } -} {1} +} {ok 1} db close file delete -force test.db @@ -71,7 +71,7 @@ do_test verify-pragma-cipher-use-hmac-off { PRAGMA cipher_use_hmac = off; PRAGMA cipher_use_hmac; } -} {0} +} {ok 0} db close file delete -force test.db @@ -135,7 +135,7 @@ do_test verify-pragma-kdf-iter-reports-default { PRAGMA key = 'test'; PRAGMA kdf_iter; } -} {256000} +} {ok 256000} db close file delete -force test.db @@ -148,7 +148,7 @@ do_test verify-pragma-kdf-iter-reports-value-changed { PRAGMA kdf_iter = 8000; PRAGMA kdf_iter; } - } {8000} + } {ok 8000} db close file delete -force test.db @@ -160,7 +160,7 @@ do_test verify-pragma-fast-kdf-iter-reports-default { PRAGMA key = 'test'; PRAGMA fast_kdf_iter; } -} {2} +} {ok 2} db close file delete -force test.db @@ -173,7 +173,7 @@ do_test verify-pragma-kdf-iter-reports-value-changed { PRAGMA fast_kdf_iter = 4000; PRAGMA fast_kdf_iter; } -} {{PRAGMA fast_kdf_iter is deprecated, please remove from use} 4000} +} {ok {PRAGMA fast_kdf_iter is deprecated, please remove from use} 4000} db close file delete -force test.db @@ -185,7 +185,7 @@ do_test verify-pragma-cipher-page-size-default { PRAGMA key = 'test'; PRAGMA cipher_page_size; } -} {4096} +} {ok 4096} db close file delete -force test.db @@ -198,7 +198,7 @@ do_test verify-pragma-cipher-page-size-changed { PRAGMA cipher_page_size = 8192; PRAGMA cipher_page_size; } -} {8192} +} {ok 8192} db close file delete -force test.db @@ -210,7 +210,7 @@ do_test verify-cipher-store-pass-before-key-does-not-segfault { PRAGMA cipher_store_pass = 1; PRAGMA key = 'test'; } -} {} +} {ok} db close file delete -force test.db @@ -222,7 +222,7 @@ if_built_with_openssl verify-pragma-cipher-default { PRAGMA key = 'test'; PRAGMA cipher; } -} {AES-256-CBC} +} {ok AES-256-CBC} db close file delete -force test.db @@ -233,7 +233,7 @@ do_test verify-pragma-hmac-salt-mask-reports-default { PRAGMA key = 'test'; PRAGMA cipher_hmac_salt_mask; } -} {3a} +} {ok 3a} db close file delete -force test.db @@ -247,7 +247,7 @@ do_test verify-pragma-hmac-salt-mask-reports-value-changed { PRAGMA cipher_hmac_salt_mask; PRAGMA cipher_hmac_salt_mask = "x'3a'"; } -} {{PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use} 11 {PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use}} +} {ok {PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use} 11 {PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use}} db close file delete -force test.db @@ -258,7 +258,7 @@ do_test verify-pragma-hmac-pgno-reports-default { PRAGMA key = 'test'; PRAGMA cipher_hmac_pgno; } -} {le} +} {ok le} db close file delete -force test.db @@ -275,7 +275,7 @@ do_test verify-pragma-hmac-pgno-reports-value-changed { PRAGMA cipher_hmac_pgno = le; PRAGMA cipher_hmac_pgno; } -} {{PRAGMA cipher_hmac_pgno is deprecated, please remove from use} be {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} native {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} le} +} {ok {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} be {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} native {PRAGMA cipher_hmac_pgno is deprecated, please remove from use} le} db close file delete -force test.db @@ -286,7 +286,7 @@ do_test verify-pragma-cipher-hmac-algorithm-reports-default { PRAGMA key = 'test'; PRAGMA cipher_hmac_algorithm; } -} {HMAC_SHA512} +} {ok HMAC_SHA512} db close file delete -force test.db @@ -297,7 +297,7 @@ do_test verify-pragma-cipher-hmac-algorithm-reports-value-changed { PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_hmac_algorithm; } -} {HMAC_SHA1} +} {ok HMAC_SHA1} db close file delete -force test.db @@ -320,7 +320,7 @@ do_test verify-pragma-cipher-kdf-algorithm-reports-default { PRAGMA key = 'test'; PRAGMA cipher_kdf_algorithm; } -} {PBKDF2_HMAC_SHA512} +} {ok PBKDF2_HMAC_SHA512} db close file delete -force test.db @@ -331,7 +331,7 @@ do_test verify-pragma-cipher-kdf-algorithm-reports-value-changed { PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1; PRAGMA cipher_kdf_algorithm; } -} {PBKDF2_HMAC_SHA1} +} {ok PBKDF2_HMAC_SHA1} db close file delete -force test.db @@ -353,7 +353,7 @@ if_built_with_openssl verify-default-cipher { PRAGMA key='test'; PRAGMA cipher; } -} {AES-256-CBC} +} {ok AES-256-CBC} db close file delete -force test.db @@ -363,7 +363,7 @@ if_built_with_libtomcrypt verify-default-cipher { PRAGMA key='test'; PRAGMA cipher; } -} {aes-256-cbc} +} {ok aes-256-cbc} db close file delete -force test.db @@ -373,7 +373,7 @@ if_built_with_commoncrypto verify-default-cipher { PRAGMA key='test'; PRAGMA cipher; } -} {aes-256-cbc} +} {ok aes-256-cbc} db close file delete -force test.db @@ -383,7 +383,7 @@ if_built_with_nss verify-default-cipher { PRAGMA key='test'; PRAGMA cipher; } -} {aes-256-cbc} +} {ok aes-256-cbc} db close file delete -force test.db @@ -393,7 +393,7 @@ do_test verify-cipher_settings_default { PRAGMA key = 'test'; PRAGMA cipher_settings; } -} {{PRAGMA kdf_iter = 256000;} {PRAGMA cipher_page_size = 4096;} {PRAGMA cipher_use_hmac = 1;} {PRAGMA cipher_plaintext_header_size = 0;} {PRAGMA cipher_hmac_algorithm = HMAC_SHA512;} {PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;}} +} {ok {PRAGMA kdf_iter = 256000;} {PRAGMA cipher_page_size = 4096;} {PRAGMA cipher_use_hmac = 1;} {PRAGMA cipher_plaintext_header_size = 0;} {PRAGMA cipher_hmac_algorithm = HMAC_SHA512;} {PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;}} db close file delete -force test.db @@ -404,7 +404,7 @@ do_test verify-cipher_settings_v1 { PRAGMA cipher_compatibility = 1; PRAGMA cipher_settings; } -} {{PRAGMA kdf_iter = 4000;} {PRAGMA cipher_page_size = 1024;} {PRAGMA cipher_use_hmac = 0;} {PRAGMA cipher_plaintext_header_size = 0;} {PRAGMA cipher_hmac_algorithm = HMAC_SHA1;} {PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;}} +} {ok {PRAGMA kdf_iter = 4000;} {PRAGMA cipher_page_size = 1024;} {PRAGMA cipher_use_hmac = 0;} {PRAGMA cipher_plaintext_header_size = 0;} {PRAGMA cipher_hmac_algorithm = HMAC_SHA1;} {PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;}} db close file delete -force test.db diff --git a/test/sqlcipher-rekey.test b/test/sqlcipher-rekey.test index b2ce2f5..89f7462 100644 --- a/test/sqlcipher-rekey.test +++ b/test/sqlcipher-rekey.test @@ -65,7 +65,7 @@ do_test rekey-as-first-op { SELECT count(*) FROM t1; } -} {100} +} {ok 100} db close file delete -force test.db @@ -98,7 +98,7 @@ do_test rekey-then-key-as-first-ops { SELECT count(*) FROM t1; } -} {100} +} {ok ok 100} db close file delete -force test.db @@ -120,7 +120,7 @@ do_test rekey-as-first-operation { PRAGMA key = 'testkeynew'; SELECT name FROM sqlite_master WHERE type='table'; } -} {t1} +} {ok t1} db close file delete -force test.db @@ -146,7 +146,7 @@ do_test rekey-same-passkey { PRAGMA rekey = 'test123'; SELECT count(*) FROM t1; } -} {1000 1000} +} {1000 ok 1000} db close file delete -force test.db @@ -174,7 +174,7 @@ do_test rekey-and-query-1 { PRAGMA rekey = 'test321'; SELECT count(*) FROM t1; } -} {1000 1000} +} {1000 ok 1000} db close @@ -184,7 +184,7 @@ do_test rekey-and-query-2 { PRAGMA key = 'test321'; SELECT count(*) FROM t1; } -} {1000} +} {ok 1000} db close file delete -force test.db @@ -235,7 +235,7 @@ do_test rekey-delete-and-query-2 { SELECT count(*) > 1 FROM t1; PRAGMA integrity_check; } -} {1 ok} +} {ok ok 1 ok} db close do_test rekey-delete-and-query-3 { @@ -244,7 +244,7 @@ do_test rekey-delete-and-query-3 { PRAGMA key = 'test321'; SELECT count(*) > 1 FROM t1; } -} {1} +} {ok 1} db close file delete -force test.db @@ -290,7 +290,7 @@ do_test rekey-delete-and-query-wal-2 { SELECT count(*) > 1 FROM t1; PRAGMA integrity_check; } -} {wal 1 ok} +} {ok wal ok 1 ok} db close do_test rekey-delete-and-query-wal-3 { @@ -300,7 +300,7 @@ do_test rekey-delete-and-query-wal-3 { PRAGMA journal_mode = WAL; SELECT count(*) > 1 FROM t1; } -} {wal 1} +} {ok wal 1} db close file delete -force test.db @@ -321,7 +321,7 @@ do_test rekey-database-by-name { pragma key = 'bar'; select * from t1; } -} {foo bar} +} {ok foo bar} db close file delete -force test.db file delete -force new.db diff --git a/test/sqlcipher.test b/test/sqlcipher.test index 200564c..eed7365 100644 --- a/test/sqlcipher.test +++ b/test/sqlcipher.test @@ -46,7 +46,6 @@ slave_test_file $testdir/sqlcipher-core.test slave_test_file $testdir/sqlcipher-compatibility.test slave_test_file $testdir/sqlcipher-rekey.test slave_test_file $testdir/sqlcipher-plaintext-header.test -slave_test_file $testdir/sqlcipher-rekey.test slave_test_file $testdir/sqlcipher-pragmas.test slave_test_file $testdir/sqlcipher-integrity.test From 37b0143ac7cf7029eecbdaadefba2af7f5a81dc7 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Fri, 27 Sep 2019 15:35:01 -0400 Subject: [PATCH 10/24] fix output of integrity check on big endian platforms --- src/crypto_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index b6ad4f5..f4a002e 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -1329,7 +1329,7 @@ int sqlcipher_codec_ctx_integrity_check(codec_ctx *ctx, Parse *pParse, char *col } if(file_sz % ctx->page_sz != 0) { - result = sqlite3_mprintf("page %d has an invalid size of %d bytes", page, file_sz - ((file_sz / ctx->page_sz) * ctx->page_sz)); + result = sqlite3_mprintf("page %d has an invalid size of %lld bytes", page, file_sz - ((file_sz / ctx->page_sz) * ctx->page_sz)); sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } From 424d75a5a4ec4cea4e814c5f9b3d20cd799985af Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Thu, 3 Oct 2019 15:40:59 -0400 Subject: [PATCH 11/24] adjust backup API block so that encrypted->encrypted is permitted --- test/sqlcipher-backup.test | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 test/sqlcipher-backup.test diff --git a/test/sqlcipher-backup.test b/test/sqlcipher-backup.test new file mode 100644 index 0000000..92058e0 --- /dev/null +++ b/test/sqlcipher-backup.test @@ -0,0 +1,157 @@ +# SQLCipher +# codec.test developed by Stephen Lombardo (Zetetic LLC) +# sjlombardo at zetetic dot net +# http://zetetic.net +# +# Copyright (c) 2018, ZETETIC LLC +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the ZETETIC LLC nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# This file implements regression tests for SQLite library. The +# focus of this script is testing code cipher features. +# +# NOTE: tester.tcl has overridden the definition of sqlite3 to +# automatically pass in a key value. Thus tests in this file +# should explicitly close and open db with sqlite_orig in order +# to bypass default key assignment. + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/sqlcipher.tcl + +# backup from plaintext to plaintext +# is allowed +do_test sqlcipher-backup-plain-plain { + sqlite_orig db test.db + set rc {} + execsql { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1, randstr(16384,16384)); + } + + set md5a [execsql {SELECT md5sum(a,b) FROM t1}] + sqlite_orig db2 backup.db + sqlite3_backup B db2 main db main + lappend rc [B step -1] + lappend rc [B finish] + + db close + db2 close + + sqlite_orig db backup.db + + set md5b [execsql {SELECT md5sum(a,b) FROM t1}] + + lappend rc [ execsql { + PRAGMA integrity_check; + } ] + + lappend rc [string equal $md5a $md5b] +} {SQLITE_DONE SQLITE_OK ok 1} +db close +file delete -force test.db +file delete -force backup.db + +# backup from encrypted to encrypted +# is allowed +do_test sqlcipher-backup-encrypted-encrypted { + sqlite_orig db test.db + set rc {} + execsql { + PRAGMA key = 'testkey'; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1, randstr(16384,16384)); + } + set md5a [execsql {SELECT md5sum(a,b) FROM t1}] + + sqlite_orig db2 backup.db + execsql { PRAGMA key = 'testkey' } db2; + + sqlite3_backup B db2 main db main + lappend rc [B step -1] + lappend rc [B finish] + + db close + db2 close + + sqlite_orig db backup.db + execsql { PRAGMA key = 'testkey' }; + + set md5b [execsql {SELECT md5sum(a,b) FROM t1}] + + lappend rc [ execsql { + PRAGMA integrity_check; + PRAGMA cipher_integrity_check; + } ] + + lappend rc [string equal $md5a $md5b] + +} {SQLITE_DONE SQLITE_OK ok 1} +db close +file delete -force test.db +file delete -force backup.db + +# backup from plaintext to encrypted +# is blocked +do_test sqlcipher-backup-plain-encrypted { + sqlite_orig db test.db + set rc {} + execsql { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1, randstr(16384,16384)); + } + + sqlite_orig db2 backup.db + execsql { PRAGMA key = 'testkey' } db2; + + lappend rc [catch {sqlite3_backup B db2 main db main}] + lappend rc [sqlite3_errcode db2] + lappend rc [sqlite3_errmsg db2] +} {1 SQLITE_ERROR {backup is not supported with encrypted databases}} +db close +db2 close +file delete -force test.db +file delete -force backup.db + +# backup from encrypted to plaintext +# is blocked +do_test sqlcipher-backup-encrypted-plain { + sqlite_orig db test.db + set rc {} + execsql { + PRAGMA key = 'testkey'; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1, randstr(16384,16384)); + } + + sqlite_orig db2 backup.db + + lappend rc [catch {sqlite3_backup B db2 main db main}] + lappend rc [sqlite3_errcode db2] + lappend rc [sqlite3_errmsg db2] +} {1 SQLITE_ERROR {backup is not supported with encrypted databases}} +db close +db2 close +file delete -force test.db +file delete -force backup.db + +finish_test From 6936ef0d1158d64a55411a1d8e9ab045eaad3092 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Thu, 3 Oct 2019 15:43:04 -0400 Subject: [PATCH 12/24] complete 424d75a5a4ec4cea4e814c5f9b3d20cd799985af --- src/backup.c | 3 ++- test/sqlcipher.test | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backup.c b/src/backup.c index c4440b1..3139b2f 100644 --- a/src/backup.c +++ b/src/backup.c @@ -165,7 +165,8 @@ sqlite3_backup *sqlite3_backup_init( sqlite3CodecGetKey(pDestDb, sqlcipher_find_db_index(pDestDb, zDestDb), &zKey, &destNKey); zKey = NULL; - if(srcNKey || destNKey) { + /* either both databases must be plaintext, or both must be encrypted */ + if((srcNKey == 0 && destNKey > 0) || (srcNKey > 0 && destNKey == 0)) { sqlite3ErrorWithMsg(pDestDb, SQLITE_ERROR, "backup is not supported with encrypted databases"); return NULL; } diff --git a/test/sqlcipher.test b/test/sqlcipher.test index eed7365..00bb087 100644 --- a/test/sqlcipher.test +++ b/test/sqlcipher.test @@ -48,5 +48,6 @@ slave_test_file $testdir/sqlcipher-rekey.test slave_test_file $testdir/sqlcipher-plaintext-header.test slave_test_file $testdir/sqlcipher-pragmas.test slave_test_file $testdir/sqlcipher-integrity.test +slave_test_file $testdir/sqlcipher-backup.test finish_test From 4ce256966e2add336802ae6a381f9cc104859e14 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Fri, 4 Oct 2019 16:49:18 -0400 Subject: [PATCH 13/24] handle memory-related debug / trace logging separately --- src/crypto.h | 22 ++++++++++++---------- src/crypto_impl.c | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index cc6f8ac..0fdbb67 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -115,16 +115,6 @@ void sqlite3pager_reset(Pager *pPager); #include #endif -#ifdef CODEC_DEBUG_MUTEX -#ifdef __ANDROID__ -#define CODEC_TRACE_MUTEX(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);} -#else -#define CODEC_TRACE_MUTEX(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);} -#endif -#else -#define CODEC_TRACE_MUTEX(...) -#endif - #ifdef CODEC_DEBUG #ifdef __ANDROID__ #define CODEC_TRACE(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);} @@ -135,6 +125,18 @@ void sqlite3pager_reset(Pager *pPager); #define CODEC_TRACE(...) #endif +#ifdef CODEC_DEBUG_MUTEX +#define CODEC_TRACE_MUTEX(...) CODEC_TRACE(__VA_ARGS__) +#else +#define CODEC_TRACE_MUTEX(...) +#endif + +#ifdef CODEC_DEBUG_MEMORY +#define CODEC_TRACE_MEMORY(...) CODEC_TRACE(__VA_ARGS__) +#else +#define CODEC_TRACE_MEMORY(...) +#endif + #ifdef CODEC_DEBUG_PAGEDATA #define CODEC_HEXDUMP(DESC,BUFFER,LEN) \ { \ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index f4a002e..11119b4 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -112,7 +112,7 @@ static void sqlcipher_mem_shutdown(void *pAppData) { static void *sqlcipher_mem_malloc(int n) { void *ptr = default_mem_methods.xMalloc(n); if(mem_security_on) { - CODEC_TRACE("sqlcipher_mem_malloc: calling sqlcipher_mlock(%p,%d)\n", ptr, n); + CODEC_TRACE_MEMORY("sqlcipher_mem_malloc: calling sqlcipher_mlock(%p,%d)\n", ptr, n); sqlcipher_mlock(ptr, n); if(!mem_security_activated) mem_security_activated = 1; } @@ -125,7 +125,7 @@ static void sqlcipher_mem_free(void *p) { int sz; if(mem_security_on) { sz = sqlcipher_mem_size(p); - CODEC_TRACE("sqlcipher_mem_free: calling sqlcipher_memset(%p,0,%d) and sqlcipher_munlock(%p, %d) \n", p, sz, p, sz); + CODEC_TRACE_MEMORY("sqlcipher_mem_free: calling sqlcipher_memset(%p,0,%d) and sqlcipher_munlock(%p, %d) \n", p, sz, p, sz); sqlcipher_memset(p, 0, sz); sqlcipher_munlock(p, sz); if(!mem_security_activated) mem_security_activated = 1; @@ -281,7 +281,7 @@ void* sqlcipher_memset(void *v, unsigned char value, int len) { if (v == NULL) return v; - CODEC_TRACE("sqlcipher_memset: setting %p[0-%d]=%d)\n", a, len, value); + CODEC_TRACE_MEMORY("sqlcipher_memset: setting %p[0-%d]=%d)\n", a, len, value); for(i = 0; i < len; i++) { a[i] = value; } @@ -325,10 +325,10 @@ void sqlcipher_mlock(void *ptr, int sz) { if(ptr == NULL || sz == 0) return; - CODEC_TRACE("sqlcipher_mem_lock: calling mlock(%p,%lu); _SC_PAGESIZE=%lu\n", ptr - offset, sz + offset, pagesize); + CODEC_TRACE_MEMORY("sqlcipher_mem_lock: calling mlock(%p,%lu); _SC_PAGESIZE=%lu\n", ptr - offset, sz + offset, pagesize); rc = mlock(ptr - offset, sz + offset); if(rc!=0) { - CODEC_TRACE("sqlcipher_mem_lock: mlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno); + CODEC_TRACE_MEMORY("sqlcipher_mem_lock: mlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno); } #elif defined(_WIN32) #if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP)) @@ -352,10 +352,10 @@ void sqlcipher_munlock(void *ptr, int sz) { if(ptr == NULL || sz == 0) return; - CODEC_TRACE("sqlcipher_mem_unlock: calling munlock(%p,%lu)\n", ptr - offset, sz + offset); + CODEC_TRACE_MEMORY("sqlcipher_mem_unlock: calling munlock(%p,%lu)\n", ptr - offset, sz + offset); rc = munlock(ptr - offset, sz + offset); if(rc!=0) { - CODEC_TRACE("sqlcipher_mem_unlock: munlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno); + CODEC_TRACE_MEMORY("sqlcipher_mem_unlock: munlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno); } #elif defined(_WIN32) #if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP)) @@ -379,7 +379,7 @@ void sqlcipher_munlock(void *ptr, int sz) { * memory segment so it can be paged */ void sqlcipher_free(void *ptr, int sz) { - CODEC_TRACE("sqlcipher_free: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); + CODEC_TRACE_MEMORY("sqlcipher_free: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); sqlcipher_memset(ptr, 0, sz); sqlcipher_munlock(ptr, sz); sqlite3_free(ptr); @@ -392,9 +392,9 @@ void sqlcipher_free(void *ptr, int sz) { */ void* sqlcipher_malloc(int sz) { void *ptr; - CODEC_TRACE("sqlcipher_malloc: calling sqlite3Malloc(%d)\n", sz); + CODEC_TRACE_MEMORY("sqlcipher_malloc: calling sqlite3Malloc(%d)\n", sz); ptr = sqlite3Malloc(sz); - CODEC_TRACE("sqlcipher_malloc: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); + CODEC_TRACE_MEMORY("sqlcipher_malloc: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); sqlcipher_memset(ptr, 0, sz); sqlcipher_mlock(ptr, sz); return ptr; From b7f660c29ee3b26a9e4ad641d9e515a9521c0880 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 8 Oct 2019 14:10:32 -0400 Subject: [PATCH 14/24] merge license with extension header --- src/crypto.c | 10 +++++----- src/crypto_impl.c | 3 --- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 64d1eae..d1ec2d6 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -35,8 +35,8 @@ #include "sqlcipher.h" #include "crypto.h" -#ifdef SQLCIPHER_LICENSE -#include "sqlcipher-license.h" +#ifdef SQLCIPHER_EXT +#include "sqlcipher_ext.h" #endif /* Generate code to return a string value */ @@ -97,7 +97,7 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef CODEC_TRACE("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx); -#ifdef SQLCIPHER_LICENSE +#ifdef SQLCIPHER_EXT if( sqlite3StrICmp(zLeft, "cipher_license")==0 && zRight ){ char *license_result = sqlite3_mprintf("%d", sqlcipher_license_key(zRight)); codec_vdbe_return_string(pParse, "cipher_license", license_result, P4_DYNAMIC); @@ -667,7 +667,7 @@ static void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { CODEC_TRACE("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz); -#ifdef SQLCIPHER_LICENSE +#ifdef SQLCIPHER_EXT if(sqlcipher_license_check(ctx) != SQLITE_OK) return NULL; #endif @@ -753,7 +753,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { sqlite3_mutex_enter(db->mutex); CODEC_TRACE_MUTEX("sqlite3CodecAttach: entered database mutex %p\n", db->mutex); -#ifdef SQLCIPHER_LICENSE +#ifdef SQLCIPHER_EXT if((rc = sqlite3_set_authorizer(db, sqlcipher_license_authorizer, db)) != SQLITE_OK) { sqlite3_mutex_leave(db->mutex); return rc; diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 11119b4..5bb9e93 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -43,9 +43,6 @@ #include #endif #endif -#ifdef SQLCIPHER_EXT -#include "sqlcipher_ext.h" -#endif static volatile unsigned int default_flags = DEFAULT_CIPHER_FLAGS; static volatile unsigned char hmac_salt_mask = HMAC_SALT_MASK; From 9d3769e101c45b242921292818354e45ab8e056f Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 8 Oct 2019 14:23:59 -0400 Subject: [PATCH 15/24] remove redundant backup tests that have been moved to sqlcipher-backup.test --- test/sqlcipher-core.test | 63 ---------------------------------------- 1 file changed, 63 deletions(-) diff --git a/test/sqlcipher-core.test b/test/sqlcipher-core.test index 211b76c..ca53990 100644 --- a/test/sqlcipher-core.test +++ b/test/sqlcipher-core.test @@ -801,67 +801,4 @@ db close dba close file delete -force test.db -do_test backup-encrypted-to-plain { - sqlite_orig db test.db - sqlite_orig db2 backup.db - execsql { - PRAGMA key = 'test'; - CREATE TABLE t1(a,b); - INSERT INTO t1(a,b) VALUES (1,2); - } - list [catch { sqlite3_backup B db2 main db main } msg] $msg -} {1 {sqlite3_backup_init() failed}} -db close -db2 close -file delete -force test.db -file delete -force backup.db - -do_test backup-plain-to-encrypted { - sqlite_orig db test.db - sqlite_orig db2 backup.db - execsql { - CREATE TABLE t1(a,b); - INSERT INTO t1(a,b) VALUES (1,2); - } - execsql { - PRAGMA key = 'test'; - } db2 - - list [catch { sqlite3_backup B db2 main db main } msg] $msg -} {1 {sqlite3_backup_init() failed}} -db close -db2 close -file delete -force test.db -file delete -force backup.db - -do_test backup-encrypted-to-encrypted { - sqlite_orig db test.db - sqlite_orig db2 backup.db - execsql { - PRAGMA key = 'test'; - CREATE TABLE t1(a,b); - INSERT INTO t1(a,b) VALUES (1,2); - } - execsql { - PRAGMA key = 'test'; - } db2 - list [catch { sqlite3_backup B db2 main db main } msg] $msg -} {1 {sqlite3_backup_init() failed}} -db close -db2 close -file delete -force test.db -file delete -force backup.db - -do_test backup-plain-to-plain { - sqlite_orig db test.db - sqlite_orig db2 backup.db - execsql { - CREATE TABLE t1(a,b); - INSERT INTO t1(a,b) VALUES (1,2); - } - sqlite3_backup B db2 main db main - B step -1 - B finish -} {SQLITE_OK} - finish_test From 7d63c0e686bb2f90ce5cd246554ad42da389d708 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Mon, 14 Oct 2019 13:12:30 -0400 Subject: [PATCH 16/24] remove unused variable in integrity_check --- src/crypto_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 5bb9e93..edd492c 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -1265,7 +1265,7 @@ cleanup: int sqlcipher_codec_ctx_integrity_check(codec_ctx *ctx, Parse *pParse, char *column) { Pgno page = 1; - int i, rc = 0; + int rc = 0; char *result; unsigned char *hmac_out = NULL; sqlite3_file *fd = sqlite3PagerFile(ctx->pBt->pBt->pPager); From e714766eba6261de065475c4e125bdbeec42df8d Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Sun, 27 Oct 2019 18:21:41 -0400 Subject: [PATCH 17/24] Snapshot of upstream SQLite 3.30.1 --- Makefile.in | 1 - Makefile.linux-gcc | 26 +- Makefile.msc | 3 +- VERSION | 2 +- autoconf/Makefile.msc | 2 +- configure | 18 +- ext/expert/expert1.test | 2 + ext/fts3/fts3.c | 40 +- ext/fts3/fts3_snippet.c | 4 +- ext/fts3/fts3_write.c | 9 +- ext/fts5/fts5Int.h | 2 + ext/fts5/fts5_config.c | 2 +- ext/fts5/fts5_expr.c | 36 + ext/fts5/fts5_index.c | 14 +- ext/fts5/fts5_main.c | 281 +++-- ext/fts5/fts5_storage.c | 2 + ext/fts5/test/fts5content.test | 15 + ext/fts5/test/fts5corrupt3.test | 685 +++++++++++- ext/fts5/test/fts5faultB.test | 22 + ext/fts5/test/fts5misc.test | 111 ++ ext/fts5/test/fts5multi.test | 99 ++ ext/fts5/test/fts5plan.test | 6 +- ext/fts5/test/fts5rank.test | 18 + ext/fts5/test/fts5simple.test | 13 + ext/lsm1/Makefile | 4 +- ext/lsm1/lsm_vtab.c | 2 +- ext/lsm1/test/lsm1_simple.test | 59 + ext/misc/carray.c | 2 +- ext/misc/fossildelta.c | 3 + ext/misc/json1.c | 27 +- ext/misc/regexp.c | 4 +- ext/rbu/rbuexpr.test | 93 ++ ext/rbu/rbupartial.test | 9 + ext/rbu/rbuprogress.test | 32 + ext/rbu/sqlite3rbu.c | 128 ++- ext/rtree/rtree.c | 21 +- ext/rtree/rtreefuzz001.test | 272 +++++ ext/session/sqlite3session.c | 2 +- main.mk | 1 - manifest | 411 +++---- manifest.uuid | 2 +- src/alter.c | 5 +- src/analyze.c | 213 ++-- src/attach.c | 14 + src/auth.c | 2 +- src/backup.c | 2 + src/btree.c | 48 +- src/build.c | 127 ++- src/ctime.c | 2 - src/expr.c | 386 ++++--- src/fkey.c | 7 +- src/func.c | 26 +- src/global.c | 10 +- src/insert.c | 17 +- src/loadext.c | 8 +- src/main.c | 53 +- src/memjournal.c | 5 - src/mutex.h | 1 + src/os.c | 10 +- src/os_unix.c | 61 +- src/os_win.c | 2 + src/parse.y | 104 +- src/pcache.c | 1 + src/pcache1.c | 1 + src/pragma.c | 11 +- src/pragma.h | 8 +- src/prepare.c | 62 +- src/resolve.c | 117 +- src/select.c | 180 ++- src/shell.c.in | 292 +++-- src/sqlite.h.in | 75 +- src/sqlite3ext.h | 4 + src/sqliteInt.h | 200 ++-- src/tclsqlite.c | 126 ++- src/test1.c | 74 +- src/test_config.c | 6 - src/test_hexio.c | 73 ++ src/treeview.c | 52 +- src/trigger.c | 24 +- src/update.c | 25 +- src/upsert.c | 8 +- src/util.c | 4 +- src/vdbe.c | 216 +++- src/vdbe.h | 8 +- src/vdbeInt.h | 1 - src/vdbeapi.c | 6 +- src/vdbeaux.c | 71 +- src/vdbeblob.c | 3 +- src/vdbemem.c | 75 +- src/vdbesort.c | 14 +- src/vtab.c | 78 +- src/wal.c | 2 + src/walker.c | 38 +- src/where.c | 124 ++- src/whereInt.h | 14 +- src/wherecode.c | 118 +- src/whereexpr.c | 36 +- src/window.c | 441 ++++++-- test/affinity2.test | 75 ++ test/aggnested.test | 30 +- test/alter.test | 1 - test/altertab.test | 1 - test/altertab3.test | 144 +++ test/analyze.test | 33 +- test/analyze3.test | 8 +- test/analyze5.test | 38 +- test/analyze6.test | 2 +- test/analyze7.test | 4 +- test/analyze8.test | 4 +- test/analyzeA.test | 186 ---- test/analyzeB.test | 682 ------------ test/analyzeC.test | 14 + test/auth.test | 6 +- test/check.test | 44 + test/checkfault.test | 41 + test/close.test | 7 + test/colname.test | 6 + test/conflict3.test | 68 ++ test/corruptL.test | 21 +- test/corruptM.test | 186 ++++ test/dbfuzz001.test | 2 +- test/dbfuzz2.c | 3 + test/dbstatus.test | 2 +- test/distinct2.test | 72 ++ test/filter1.test | 188 ++++ test/filter2.tcl | 132 +++ test/filter2.test | 156 +++ test/filterfault.test | 44 + test/fkey8.test | 1 - test/fts3corrupt4.test | 455 +++++++- test/fts3corrupt5.test | 1 - test/fts3expr5.test | 1 - test/fts3snippet.test | 24 + test/fts4merge5.test | 58 + test/fts4record.test | 120 ++ test/fts4rename.test | 1 - test/func.test | 40 +- test/fuzzcheck.c | 3 + test/fuzzdata7.db | Bin 16811008 -> 16819200 bytes test/fuzzdata8.db | Bin 1239040 -> 1357824 bytes test/in.test | 35 + test/in4.test | 13 +- test/in5.test | 17 + test/index6.test | 47 +- test/index7.test | 2 +- test/indexexpr1.test | 37 + test/indexexpr2.test | 76 ++ test/insert.test | 16 + test/instr.test | 21 + test/intarray.test | 8 +- test/intreal.test | 12 + test/join.test | 44 +- test/json104.test | 2 - test/like.test | 1 - test/like3.test | 13 + test/mallocA.test | 18 - test/minmax4.test | 83 ++ test/nulls1.test | 253 +++++ test/orderbyA.test | 147 +++ test/permutations.test | 7 +- test/pg_common.tcl | 4 +- test/pragma.test | 16 +- test/pragma5.test | 4 +- test/releasetest.tcl | 2 + test/releasetest_data.tcl | 435 ++++++-- test/rowvalue.test | 13 + test/rowvalue7.test | 10 + test/schema.test | 20 +- test/select1.test | 65 ++ test/skipscan1.test | 27 +- test/tclsqlite.test | 4 +- test/tempdb2.test | 1 - test/tkt-18458b1a.test | 53 + test/tkt-3a77c9714e.test | 16 +- test/tkt-a7debbe0.test | 103 ++ test/tkt-b75a9ca6b0.test | 2 +- test/tkt-cbd054fa6b.test | 21 +- test/trigger1.test | 14 + test/triggerC.test | 1 - test/upsert1.test | 10 + test/view.test | 63 ++ test/vtab1.test | 52 +- test/vtabH.test | 60 +- test/walvfs.test | 1 - test/wapptest.tcl | 145 +-- test/where.test | 34 +- test/where9.test | 7 +- test/whereG.test | 42 + test/wild001.test | 311 ------ test/window1.test | 69 +- test/window2.tcl | 22 + test/window2.test | 37 + test/window4.tcl | 20 + test/window4.test | 47 + test/window6.test | 1 - test/window7.test | 110 +- test/window8.tcl | 130 ++- test/window8.test | 1809 +++++++++++++++++++++++++++++-- test/window9.test | 134 +++ test/windowA.test | 309 ++++++ test/windowB.test | 339 ++++++ test/windowerr.tcl | 3 + test/windowerr.test | 5 + test/windowfault.test | 22 + test/without_rowid1.test | 31 +- test/without_rowid6.test | 13 + test/without_rowid7.test | 60 + tool/lemon.c | 23 +- tool/lempar.c | 29 +- tool/mkkeywordhash.c | 3 + tool/mkpragmatab.tcl | 6 +- tool/speed-check.sh | 9 + 212 files changed, 11313 insertions(+), 3386 deletions(-) create mode 100644 ext/fts5/test/fts5misc.test create mode 100644 ext/fts5/test/fts5multi.test create mode 100644 ext/rbu/rbuexpr.test delete mode 100644 test/analyzeA.test delete mode 100644 test/analyzeB.test create mode 100644 test/checkfault.test create mode 100644 test/corruptM.test create mode 100644 test/filter1.test create mode 100644 test/filter2.tcl create mode 100644 test/filter2.test create mode 100644 test/filterfault.test create mode 100644 test/fts4merge5.test create mode 100644 test/fts4record.test create mode 100644 test/nulls1.test create mode 100644 test/orderbyA.test create mode 100644 test/tkt-18458b1a.test create mode 100644 test/tkt-a7debbe0.test delete mode 100644 test/wild001.test create mode 100644 test/windowA.test create mode 100644 test/windowB.test create mode 100644 test/without_rowid7.test diff --git a/Makefile.in b/Makefile.in index 8df0982..cadc2ed 100644 --- a/Makefile.in +++ b/Makefile.in @@ -609,7 +609,6 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE -SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/Makefile.linux-gcc b/Makefile.linux-gcc index 1491a4b..ad5d4dd 100644 --- a/Makefile.linux-gcc +++ b/Makefile.linux-gcc @@ -19,7 +19,7 @@ TOP = ../sqlite #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. # -BCC = gcc -g -O2 +BCC = gcc -g -O0 #BCC = /opt/ancic/bin/c89 -0 #### If the target operating system supports the "usleep()" system @@ -38,8 +38,8 @@ THREADSAFE = -DTHREADSAFE=0 #### Specify any extra linker options needed to make the library # thread safe # -#THREADLIB = -lpthread -THREADLIB = +THREADLIB = -lpthread -lm -ldl +#THREADLIB = #### Specify any extra libraries needed to access required functions. # @@ -54,11 +54,9 @@ TLIBS = # You can make the library go almost twice as fast if you compile # with -DNDEBUG=1 # -#OPTS = -DSQLITE_DEBUG=2 -#OPTS = -DSQLITE_DEBUG=1 -#OPTS = -OPTS = -DNDEBUG=1 -OPTS += -DHAVE_FDATASYNC=1 +OPTS += -DSQLITE_DEBUG=1 +OPTS += -DSQLITE_ENABLE_WHERETRACE +OPTS += -DSQLITE_ENABLE_SELECTTRACE #### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. @@ -70,7 +68,7 @@ EXE = # will run on the target platform. This is usually the same # as BCC, unless you are cross-compiling. # -TCC = gcc -O6 +TCC = gcc -O0 #TCC = gcc -g -O0 -Wall #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage #TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 @@ -91,18 +89,12 @@ SHPREFIX = lib #### Extra compiler options needed for programs that use the TCL library. # -#TCL_FLAGS = -#TCL_FLAGS = -DSTATIC_BUILD=1 -TCL_FLAGS = -I/home/drh/tcltk/8.5linux -#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1 -#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux +TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6 #### Linker options needed to link against the TCL library. # #LIBTCL = -ltcl -lm -ldl -LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl -#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt -#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc +LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz #### Additional objects for SQLite library when TCL support is enabled. #TCLOBJ = diff --git a/Makefile.msc b/Makefile.msc index 595763c..01d20d2 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -73,7 +73,7 @@ API_ARMOR = 0 !IFNDEF NO_WARN !IF $(USE_FULLWARN)!=0 NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 !ENDIF !ENDIF @@ -351,7 +351,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1 !ENDIF OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 diff --git a/VERSION b/VERSION index c7c9773..72bde0a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.29.0 +3.30.1 diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index df9b96a..2a7042e 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -73,7 +73,7 @@ API_ARMOR = 0 !IFNDEF NO_WARN !IF $(USE_FULLWARN)!=0 NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 !ENDIF !ENDIF diff --git a/configure b/configure index a8b1214..dce4f6c 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.29.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.30.1. # # # 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.29.0' -PACKAGE_STRING='sqlite 3.29.0' +PACKAGE_VERSION='3.30.1' +PACKAGE_STRING='sqlite 3.30.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1466,7 +1466,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.29.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.30.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1531,7 +1531,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.29.0:";; + short | recursive ) echo "Configuration of sqlite 3.30.1:";; esac cat <<\_ACEOF @@ -1657,7 +1657,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.29.0 +sqlite configure 3.30.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2076,7 +2076,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.29.0, which was +It was created by sqlite $as_me 3.30.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12232,7 +12232,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.29.0, which was +This file was extended by sqlite $as_me 3.30.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12298,7 +12298,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.29.0 +sqlite config.status 3.30.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test index 912c074..a0a18f6 100644 --- a/ext/expert/expert1.test +++ b/ext/expert/expert1.test @@ -134,6 +134,7 @@ do_setup_rec_test $tn.5 { SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?) } +if 0 { do_setup_rec_test $tn.6 { CREATE TABLE t1(a, b, c); } { @@ -142,6 +143,7 @@ do_setup_rec_test $tn.6 { CREATE INDEX t1_idx_00000061 ON t1(a); SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061 } +} do_setup_rec_test $tn.7 { CREATE TABLE t1(a, b, c); diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index b357fcd..2e19d68 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -308,6 +308,18 @@ SQLITE_EXTENSION_INIT1 #endif +/* +** The following are copied from sqliteInt.h. +** +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#ifndef SQLITE_AMALGAMATION +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( @@ -2086,10 +2098,11 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ } /* -** Value used to signify the end of an position-list. This is safe because -** it is not possible to have a document with 2^31 terms. +** Value used to signify the end of an position-list. This must be +** as large or larger than any value that might appear on the +** position-list, even a position list that has been corrupted. */ -#define POSITION_LIST_END 0x7fffffff +#define POSITION_LIST_END LARGEST_INT64 /* ** This function is used to help parse position-lists. When this function is @@ -2165,14 +2178,14 @@ static int fts3PoslistMerge( fts3GetVarint32(&p1[1], &iCol1); if( iCol1==0 ) return FTS_CORRUPT_VTAB; } - else if( *p1==POS_END ) iCol1 = POSITION_LIST_END; + else if( *p1==POS_END ) iCol1 = 0x7fffffff; else iCol1 = 0; if( *p2==POS_COLUMN ){ fts3GetVarint32(&p2[1], &iCol2); if( iCol2==0 ) return FTS_CORRUPT_VTAB; } - else if( *p2==POS_END ) iCol2 = POSITION_LIST_END; + else if( *p2==POS_END ) iCol2 = 0x7fffffff; else iCol2 = 0; if( iCol1==iCol2 ){ @@ -2474,7 +2487,8 @@ static void fts3PutDeltaVarint3( iWrite = *piPrev - iVal; } assert( *pbFirst || *piPrev==0 ); - assert( *pbFirst==0 || iWrite>0 ); + assert_fts3_nc( *pbFirst==0 || iWrite>0 ); + assert( *pbFirst==0 || iWrite>=0 ); *pp += sqlite3Fts3PutVarint(*pp, iWrite); *piPrev = iVal; *pbFirst = 1; @@ -2580,6 +2594,8 @@ static int fts3DoclistOrMerge( fts3PoslistCopy(&p, &p2); fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); } + + assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) ); } if( rc!=SQLITE_OK ){ @@ -3179,18 +3195,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){ return rc; } -/* -** The following are copied from sqliteInt.h. -** -** Constants for the largest and smallest possible 64-bit signed integers. -** These macros are designed to work correctly on both 32-bit and 64-bit -** compilers. -*/ -#ifndef SQLITE_AMALGAMATION -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - /* ** If the numeric type of argument pVal is "integer", then return it ** converted to a 64-bit signed integer. Otherwise, return a copy of diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c index d5ebda6..6db3fd7 100644 --- a/ext/fts3/fts3_snippet.c +++ b/ext/fts3/fts3_snippet.c @@ -433,10 +433,10 @@ static void fts3SnippetDetails( while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){ int j; - u64 mPhrase = (u64)1 << i; + u64 mPhrase = (u64)1 << (i%64); u64 mPos = (u64)1 << (iCsr - iStart); assert( iCsr>=iStart && (iCsr - iStart)<=64 ); - assert( i>=0 && i<=64 ); + assert( i>=0 ); if( (mCover|mCovered)&mPhrase ){ iScore++; }else{ diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 889a674..6960c31 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -3797,14 +3797,14 @@ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ p->nNode = nNode; /* Figure out if this is a leaf or an internal node. */ - if( p->aNode[0] ){ + if( aNode && aNode[0] ){ /* An internal node. */ p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); }else{ p->iOff = 1; } - return nodeReaderNext(p); + return aNode ? nodeReaderNext(p) : SQLITE_OK; } /* @@ -3941,6 +3941,7 @@ static int fts3AppendToNode( nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); nSuffix = nTerm - nPrefix; + if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; memcpy(pPrev->a, zTerm, nTerm); pPrev->n = nTerm; @@ -4295,8 +4296,8 @@ static int fts3IncrmergeLoad( NodeReader reader; pNode = &pWriter->aNodeWriter[i]; - rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - if( reader.aNode ){ + if( pNode->block.a){ + rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); blobGrowBuffer(&pNode->key, reader.term.n, &rc); if( rc==SQLITE_OK ){ diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 1019147..c29b42b 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -178,6 +178,7 @@ struct Fts5Config { char *zContentExprlist; Fts5Tokenizer *pTok; fts5_tokenizer *pTokApi; + int bLock; /* True when table is preparing statement */ /* Values loaded from the %_config table */ int iCookie; /* Incremented when %_config is modified */ @@ -694,6 +695,7 @@ int sqlite3Fts5ExprEof(Fts5Expr*); i64 sqlite3Fts5ExprRowid(Fts5Expr*); void sqlite3Fts5ExprFree(Fts5Expr*); +int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2); /* Called during startup to register a UDF with SQLite */ int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*); diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index 7a16e38..4e1707b 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -683,7 +683,7 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){ rc = sqlite3_declare_vtab(pConfig->db, zSql); sqlite3_free(zSql); } - + return rc; } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index f1bf3f2..ce462af 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -309,6 +309,42 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){ } } +int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ + Fts5Parse sParse; + memset(&sParse, 0, sizeof(sParse)); + + if( *pp1 ){ + Fts5Expr *p1 = *pp1; + int nPhrase = p1->nPhrase + p2->nPhrase; + + p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0); + p2->pRoot = 0; + + if( sParse.rc==SQLITE_OK ){ + Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc( + p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*) + ); + if( ap==0 ){ + sParse.rc = SQLITE_NOMEM; + }else{ + int i; + memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*)); + for(i=0; inPhrase; i++){ + ap[i] = p2->apExprPhrase[i]; + } + p1->nPhrase = nPhrase; + p1->apExprPhrase = ap; + } + } + sqlite3_free(p2->apExprPhrase); + sqlite3_free(p2); + }else{ + *pp1 = p2; + } + + return sParse.rc; +} + /* ** Argument pTerm must be a synonym iterator. Return the current rowid ** that it points to. diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 73249b0..7d504a4 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -690,6 +690,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ }else{ /* TODO1: Fix this */ pRet->p[nByte] = 0x00; + pRet->p[nByte+1] = 0x00; pRet->szLeaf = fts5GetU16(&pRet->p[2]); } } @@ -712,7 +713,7 @@ static void fts5DataRelease(Fts5Data *pData){ static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ - if( pRet->szLeaf>pRet->nn ){ + if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ p->rc = FTS5_CORRUPT; fts5DataRelease(pRet); pRet = 0; @@ -4996,9 +4997,12 @@ static void fts5MergePrefixLists( 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); + sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10); if( p->rc ) break; sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); @@ -5046,6 +5050,12 @@ static void fts5MergePrefixLists( } /* 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; + } fts5BufferSafeAppendVarint(&out, tmp.n * 2); fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); fts5DoclistIterNext(&i1); diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 06b8183..fc4ec0c 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -465,17 +465,39 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){ ** Implementation of the xBestIndex method for FTS5 tables. Within the ** WHERE constraint, it searches for the following: ** -** 1. A MATCH constraint against the special column. +** 1. A MATCH constraint against the table column. ** 2. A MATCH constraint against the "rank" column. -** 3. An == constraint against the rowid column. -** 4. A < or <= constraint against the rowid column. -** 5. A > or >= constraint against the rowid column. +** 3. A MATCH constraint against some other column. +** 4. An == constraint against the rowid column. +** 5. A < or <= constraint against the rowid column. +** 6. A > or >= constraint against the rowid column. ** -** Within the ORDER BY, either: +** Within the ORDER BY, the following are supported: ** ** 5. ORDER BY rank [ASC|DESC] ** 6. ORDER BY rowid [ASC|DESC] ** +** Information for the xFilter call is passed via both the idxNum and +** idxStr variables. Specifically, idxNum is a bitmask of the following +** flags used to encode the ORDER BY clause: +** +** FTS5_BI_ORDER_RANK +** FTS5_BI_ORDER_ROWID +** FTS5_BI_ORDER_DESC +** +** idxStr is used to encode data from the WHERE clause. For each argument +** passed to the xFilter method, the following is appended to idxStr: +** +** Match against table column: "m" +** Match against rank column: "r" +** Match against other column: "" +** Equality constraint against the rowid: "=" +** A < or <= against the rowid: "<" +** A > or >= against the rowid: ">" +** +** This function ensures that there is at most one "r" or "=". And that if +** there exists an "=" then there is no "<" or ">". +** ** Costs are assigned as follows: ** ** a) If an unusable MATCH operator is present in the WHERE clause, the @@ -503,32 +525,18 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts5Config *pConfig = pTab->pConfig; const int nCol = pConfig->nCol; int idxFlags = 0; /* Parameter passed through to xFilter() */ - int bHasMatch; - int iNext; int i; - struct Constraint { - int op; /* Mask against sqlite3_index_constraint.op */ - int fts5op; /* FTS5 mask for idxFlags */ - int iCol; /* 0==rowid, 1==tbl, 2==rank */ - int omit; /* True to omit this if found */ - int iConsIndex; /* Index in pInfo->aConstraint[] */ - } aConstraint[] = { - {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, - FTS5_BI_MATCH, 1, 1, -1}, - {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, - FTS5_BI_RANK, 2, 1, -1}, - {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1}, - {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, - FTS5_BI_ROWID_LE, 0, 0, -1}, - {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, - FTS5_BI_ROWID_GE, 0, 0, -1}, - }; + char *idxStr; + int iIdxStr = 0; + int iCons = 0; + + int bSeenEq = 0; + int bSeenGt = 0; + int bSeenLt = 0; + int bSeenMatch = 0; + int bSeenRank = 0; - int aColMap[3]; - aColMap[0] = -1; - aColMap[1] = nCol; - aColMap[2] = nCol+1; assert( SQLITE_INDEX_CONSTRAINT_EQbLock ){ + pTab->base.zErrMsg = sqlite3_mprintf( + "recursively defined fts5 content table" + ); + return SQLITE_ERROR; + } + + idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1); + if( idxStr==0 ) return SQLITE_NOMEM; + pInfo->idxStr = idxStr; + pInfo->needToFreeIdxStr = 1; + for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; int iCol = p->iColumn; - - if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol) - || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol) + if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH + || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol) ){ /* A MATCH operator or equivalent */ - if( p->usable ){ - idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16); - aConstraint[0].iConsIndex = i; - }else{ + if( p->usable==0 || iCol<0 ){ /* As there exists an unusable MATCH constraint this is an ** unusable plan. Set a prohibitively high cost. */ pInfo->estimatedCost = 1e50; + assert( iIdxStr < pInfo->nConstraint*6 + 1 ); + idxStr[iIdxStr] = 0; return SQLITE_OK; + }else{ + if( iCol==nCol+1 ){ + if( bSeenRank ) continue; + idxStr[iIdxStr++] = 'r'; + bSeenRank = 1; + }else{ + bSeenMatch = 1; + idxStr[iIdxStr++] = 'm'; + if( iColaConstraintUsage[i].argvIndex = ++iCons; + pInfo->aConstraintUsage[i].omit = 1; } - }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){ - int j; - for(j=1; jiCol] && (p->op & pC->op) && p->usable ){ - pC->iConsIndex = i; - idxFlags |= pC->fts5op; + } + else if( p->usable && bSeenEq==0 + && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 + ){ + idxStr[iIdxStr++] = '='; + bSeenEq = 1; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + } + } + + if( bSeenEq==0 ){ + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; + if( p->iColumn<0 && p->usable ){ + int op = p->op; + if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){ + if( bSeenLt ) continue; + idxStr[iIdxStr++] = '<'; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + bSeenLt = 1; + }else + if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){ + if( bSeenGt ) continue; + idxStr[iIdxStr++] = '>'; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + bSeenGt = 1; } } } } + idxStr[iIdxStr] = '\0'; /* Set idxFlags flags for the ORDER BY clause */ if( pInfo->nOrderBy==1 ){ int iSort = pInfo->aOrderBy[0].iColumn; - if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){ + if( iSort==(pConfig->nCol+1) && bSeenMatch ){ idxFlags |= FTS5_BI_ORDER_RANK; }else if( iSort==-1 ){ idxFlags |= FTS5_BI_ORDER_ROWID; @@ -583,26 +636,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } /* Calculate the estimated cost based on the flags set in idxFlags. */ - bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH); - if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){ - pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0; - if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo); - }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ - pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0; - }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ - pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0; + if( bSeenEq ){ + pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0; + if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( bSeenLt && bSeenGt ){ + pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0; + }else if( bSeenLt || bSeenGt ){ + pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0; }else{ - pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; - } - - /* Assign argvIndex values to each constraint in use. */ - iNext = 1; - for(i=0; iiConsIndex>=0 ){ - pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; - pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; - } + pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0; } pInfo->idxNum = idxFlags; @@ -925,7 +967,7 @@ static int fts5CursorFirstSorted( ** ** If SQLite a built-in statement cache, this wouldn't be a problem. */ rc = fts5PrepareStatement(&pSorter->pStmt, pConfig, - "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", + "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s", pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), @@ -981,10 +1023,10 @@ static int fts5SpecialMatch( assert( pTab->p.base.zErrMsg==0 ); pCsr->ePlan = FTS5_PLAN_SPECIAL; - if( 0==sqlite3_strnicmp("reads", z, n) ){ + if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){ pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex); } - else if( 0==sqlite3_strnicmp("id", z, n) ){ + else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){ pCsr->iSpecial = pCsr->iCsrId; } else{ @@ -1125,7 +1167,7 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){ static int fts5FilterMethod( sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, /* Strategy index */ - const char *zUnused, /* Unused */ + const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ @@ -1133,19 +1175,17 @@ static int fts5FilterMethod( Fts5Config *pConfig = pTab->p.pConfig; Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int rc = SQLITE_OK; /* Error code */ - int iVal = 0; /* Counter for apVal[] */ int bDesc; /* True if ORDER BY [rank|rowid] DESC */ int bOrderByRank; /* True if ORDER BY rank */ - sqlite3_value *pMatch = 0; /* MATCH ? expression (or NULL) */ sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ int iCol; /* Column on LHS of MATCH operator */ char **pzErrmsg = pConfig->pzErrmsg; - - UNUSED_PARAM(zUnused); - UNUSED_PARAM(nVal); + int i; + int iIdxStr = 0; + Fts5Expr *pExpr = 0; if( pCsr->ePlan ){ fts5FreeCursorComponents(pCsr); @@ -1158,23 +1198,60 @@ static int fts5FilterMethod( assert( pCsr->pRank==0 ); assert( pCsr->zRank==0 ); assert( pCsr->zRankArgs==0 ); + assert( pTab->pSortCsr==0 || nVal==0 ); assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg ); pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - /* Decode the arguments passed through to this function. - ** - ** Note: The following set of if(...) statements must be in the same - ** order as the corresponding entries in the struct at the top of - ** fts5BestIndexMethod(). */ - if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++]; - iCol = (idxNum>>16); - assert( iCol>=0 && iCol<=pConfig->nCol ); - assert( iVal==nVal ); + /* Decode the arguments passed through to this function. */ + for(i=0; i='0' && idxStr[iIdxStr]<='9' ){ + iCol = 0; + do{ + iCol = iCol*10 + (idxStr[iIdxStr]-'0'); + iIdxStr++; + }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ); + }else{ + iCol = pConfig->nCol; + } + + if( zText[0]=='*' ){ + /* The user has issued a query of the form "MATCH '*...'". This + ** indicates that the MATCH expression is not a full text query, + ** but a request for an internal parameter. */ + rc = fts5SpecialMatch(pTab, pCsr, &zText[1]); + goto filter_out; + }else{ + char **pzErr = &pTab->p.base.zErrMsg; + rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr); + pExpr = 0; + } + if( rc!=SQLITE_OK ) goto filter_out; + } + + break; + } + case '=': + pRowidEq = apVal[i]; + break; + case '<': + pRowidLe = apVal[i]; + break; + default: assert( idxStr[iIdxStr-1]=='>' ); + pRowidGe = apVal[i]; + break; + } + } bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0); pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0); @@ -1201,7 +1278,7 @@ static int fts5FilterMethod( ** (pCursor) is used to execute the query issued by function ** fts5CursorFirstSorted() above. */ assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 ); - assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); + assert( nVal==0 && bOrderByRank==0 && bDesc==0 ); assert( pCsr->iLastRowid==LARGEST_INT64 ); assert( pCsr->iFirstRowid==SMALLEST_INT64 ); if( pTab->pSortCsr->bDesc ){ @@ -1214,29 +1291,15 @@ static int fts5FilterMethod( pCsr->ePlan = FTS5_PLAN_SOURCE; pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); - }else if( pMatch ){ - const char *zExpr = (const char*)sqlite3_value_text(apVal[0]); - if( zExpr==0 ) zExpr = ""; - + }else if( pCsr->pExpr ){ rc = fts5CursorParseRank(pConfig, pCsr, pRank); if( rc==SQLITE_OK ){ - if( zExpr[0]=='*' ){ - /* The user has issued a query of the form "MATCH '*...'". This - ** indicates that the MATCH expression is not a full text query, - ** but a request for an internal parameter. */ - rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]); + if( bOrderByRank ){ + pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; + rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); }else{ - char **pzErr = &pTab->p.base.zErrMsg; - rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr); - if( rc==SQLITE_OK ){ - if( bOrderByRank ){ - pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; - rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); - }else{ - pCsr->ePlan = FTS5_PLAN_MATCH; - rc = fts5CursorFirst(pTab, pCsr, bDesc); - } - } + pCsr->ePlan = FTS5_PLAN_MATCH; + rc = fts5CursorFirst(pTab, pCsr, bDesc); } } }else if( pConfig->zContent==0 ){ @@ -1253,7 +1316,7 @@ static int fts5FilterMethod( ); if( rc==SQLITE_OK ){ if( pCsr->ePlan==FTS5_PLAN_ROWID ){ - sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); + sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq); }else{ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid); sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid); @@ -1262,6 +1325,8 @@ static int fts5FilterMethod( } } + filter_out: + sqlite3Fts5ExprFree(pExpr); pConfig->pzErrmsg = pzErrmsg; return rc; } @@ -2232,7 +2297,7 @@ static void fts5ApiCallback( iCsrId = sqlite3_value_int64(argv[0]); pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); - if( pCsr==0 ){ + if( pCsr==0 || pCsr->ePlan==0 ){ char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index 611e6bc..960c180 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -138,7 +138,9 @@ static int fts5StorageGetStmt( }else{ int f = SQLITE_PREPARE_PERSISTENT; if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB; + p->pConfig->bLock++; rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0); + p->pConfig->bLock--; sqlite3_free(zSql); if( rc!=SQLITE_OK && pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); diff --git a/ext/fts5/test/fts5content.test b/ext/fts5/test/fts5content.test index a74b26d..bd510a5 100644 --- a/ext/fts5/test/fts5content.test +++ b/ext/fts5/test/fts5content.test @@ -253,5 +253,20 @@ do_execsql_test 6.2 { SELECT name FROM sqlite_master; } {} +#--------------------------------------------------------------------------- +# Check that an fts5 table cannot be its own content table. +# +reset_db +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE t1 USING fts5(a, c=t1 ); + INSERT INTO t1( a ) VALUES('abc'); +} +do_catchsql_test 7.2 { + SELECT * FROM t1; +} {1 {recursively defined fts5 content table}} +do_catchsql_test 7.3 { + SELECT * FROM t1('abc'); +} {1 {recursively defined fts5 content table}} finish_test + diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test index c5544c8..bab61e8 100644 --- a/ext/fts5/test/fts5corrupt3.test +++ b/ext/fts5/test/fts5corrupt3.test @@ -767,7 +767,7 @@ SELECT * FROM t1 WHERE t1 MATCH 'abandon'; do_catchsql_test 13.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; -} {1 {vtable constructor failed: t1}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -958,7 +958,7 @@ do_test 15.0 { do_catchsql_test 15.1 { INSERT INTO t1(t1) VALUES('integrity-check'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #--------------------------------------------------------------------------- # @@ -3903,19 +3903,19 @@ do_test 33.0 { | end crash-fed6e90021ba5d.db }]} {} -do_execsql_test 33.1 { +do_catchsql_test 33.1 { CREATE VIRTUAL TABLE t2 USING fts5vocab('t1','row'); CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col'); CREATE VIRTUAL TABLE t4 USING fts5vocab('t1','instance'); -} +} {/*malformed database schema*/} do_catchsql_test 33.2 { SELECT * FROM t2; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} do_catchsql_test 33.3 { SELECT * FROM t2, t3, t4 WHERE t2.term=t3.term AND t3.term=t4.term; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -4637,17 +4637,17 @@ do_test 37.0 { do_catchsql_test 37.1 { SELECT * FROM t3; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db -do_execsql_test 37.0 { +do_execsql_test 37a.0 { CREATE VIRTUAL TABLE t1 USING fts5(b, c); INSERT INTO t1 VALUES('a', 'b'); SELECT quote(block) FROM t1_data WHERE rowid=10; } {X'000000000101010001010101'} -do_execsql_test 37.1 { +do_execsql_test 37a.1 { UPDATE t1_data SET block = X'FFFFFFFF0101010001010101' WHERE rowid = 10; SELECT rowid FROM t1('a'); } {1} @@ -4894,7 +4894,7 @@ do_test 38.0 { do_catchsql_test 38.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE t1 MATCH 'thread*'; -} {0 {}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -5326,16 +5326,16 @@ do_test 40.0 { | end crash2.txt.db }]} {} -do_execsql_test 40.1 { +do_catchsql_test 40.1 { BEGIN; INSERT INTO t1(b) VALUES(X'819192e578de3fa24af3733ca8769291a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bf'); INSERT INTO t1(b) VALUES(X'c8ae0d0e7c3175946e62ba2b449511d4eb504079984a20f77969f62206c9f3d7ea25358ab705e6978627290b6d48db9032f815a06a79a4f4b809841a0942eed12954ed166f666111812a508abc3bec87958846edaec0a6fe14564bc0a4b78f1c35ebcacca6bae29cc37ae9b59d8a2d7593af1e47dda0ece2268a98d20febafad037964f139851f9a57f48b3706b01721769071991412044cd6006f1d72eb6eb4aa5ad77e378176db8c15575fbeee47165e38a7c6c5a557ac2dfe11813976eaf6741cf593a9e457053a3c34cddfbe605a6e25419f993de8374fafcd3636509d8416a51dc7bcc14cfca322ae343078f47e23522431c17d0da0c033'); INSERT INTO t1(b) VALUES(X'dc29a94e873a45a4243fce9b912aaefbadf1d0423e0345793874b356eeb500b92fb05284c1601fe9bad3143f72162f10242cec27c44ebf764c8fc9fb0824e32c4161472a4f914f579e0e8274f08ca1a02e59b9d8eec1f31061f9ccb9ed97a6f06534e991f7992c761489e6a7724f6e9c2b581e77487ded3a986d53c4419bbd3e9747cee300e670dd7294874c77e2ed48da68eaa6c3ec954a09ac410493d98e34d6686e54fbbe80696705f10e040c66093efb40746b33600685c94c664c7942835a9e954866121d5dcfb2cb12e92521ea3df175ee17072502dad9b9c1565f801b2179799011eb7418bfa00323e3157589e648ff7378be233c79b7'); -} +} {/*malformed database schema*/} do_catchsql_test 40.2 { INSERT INTO t1(a,b) VALUES(1,11),(2,22),(3, true ),(4,44); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -5789,7 +5789,7 @@ do_test 43.0 { do_catchsql_test 43.1 { INSERT INTO t1(t1) VALUES('optimize'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -6047,7 +6047,7 @@ do_catchsql_test 45.2 { INSERT INTO t1(t1, rank) VALUES('merge', 5); INSERT INTO t1(t1, rank) VALUES('merge', 5); INSERT INTO t1(t1, rank) VALUES('merge', 5); -} {0 {}} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6265,7 +6265,7 @@ do_test 46.0 { do_catchsql_test 46.1 { SELECT snippet(t1,'[','', '--',-1,10) FROM t1('*'); -} {0 {{}}} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6418,7 +6418,7 @@ do_test 47.0 { do_catchsql_test 47.1 { INSERT INTO t1(t1) VALUES('integrity-check'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} do_catchsql_test 47.2 { SELECT count(*) FROM ( @@ -6426,7 +6426,7 @@ do_catchsql_test 47.2 { highlight(t1, 2, '[', ']') FROM t1('g h') WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank ) -} {0 3} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6908,7 +6908,7 @@ do_catchsql_test 50.1 { #------------------------------------------------------------------------- reset_db -do_execsql_test 51.1 { +do_execsql_test 51.0 { BEGIN TRANSACTION; PRAGMA writable_schema=ON; CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); @@ -6976,7 +6976,7 @@ COMMIT; do_catchsql_test 51.1 { SELECT max(rowid)==0 FROM t1('e*'); -} {0 0} +} {1 {database disk image is malformed}} #-------------------------------------------------------------------------- reset_db @@ -7130,7 +7130,7 @@ do_test 52.0 { do_catchsql_test 52.1 { SELECT fts5_decode(id, block) FROM t1_data; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7346,7 +7346,7 @@ do_test 53.0 { do_catchsql_test 53.1 { WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x<>1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7562,7 +7562,7 @@ do_test 54.0 { do_catchsql_test 54.1 { SELECT rowid==-1 FROM t1('t*'); -} {0 {0 0 0}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7777,10 +7777,10 @@ do_test 55.0 { | end crash-b366b5ac0d3887.db }]} {} -do_execsql_test 55.1 { +do_catchsql_test 55.1 { SAVEPOINT one; DELETE FROM t1 WHERE a MATCH 'ts'; -} +} {/*malformed database schema*/} do_execsql_test 55.2 { ROLLBACK TO one; @@ -8013,7 +8013,7 @@ do_test 56.1 { set res "1 {database disk image is malformed}" } set res -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -8131,7 +8131,7 @@ do_test 57.0 { do_catchsql_test 57.1 { INSERT INTO t1(t1) VALUES('optimize') -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -8339,9 +8339,9 @@ do_test 58.0 { | end crash-5a5acd0ab42d31.db }]} {} -do_execsql_test 58.1 { +do_catchsql_test 58.1 { SELECT * FROM t1('t*'); -} {{} {} {} {} {} {}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- do_test 59.0 { @@ -8544,7 +8544,7 @@ do_test 59.0 { do_catchsql_test 59.1 { SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*eŸ' -} {0 {}} +} {1 {database disk image is malformed}} #------------------------------------------------------------------------- do_test 60.0 { @@ -8750,7 +8750,7 @@ do_test 60.0 { do_catchsql_test 60.2 { SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ' -} {0 {}} +} {1 {database disk image is malformed}} #------------------------------------------------------------------------- do_test 61.0 { @@ -8948,13 +8948,13 @@ do_test 61.0 { | end crash-e5fa281edabddf.db }]} {} -do_execsql_test 61.1 { +do_catchsql_test 61.1 { CREATE VIRTUAL TABLE t3 USING fts5vocab('t1'(),'col' ); -} +} {/*malformed database schema*/} do_catchsql_test 61.2 { SELECT * FROM t3 ORDER BY rowid; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} breakpoint #------------------------------------------------------------------------- @@ -9159,7 +9159,622 @@ do_test 62.0 { do_catchsql_test 62.1 { WITH c(x) AS (VALUES(false) UNION ALL SELECT x+1 FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; -} {0 {}} +} {/*malformed database schema*/} + +#--------------------------------------------------------------------------- +do_test 63.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 24576 pagesize 4096 filename crash-8230e6c3b368f5.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 06 0e 0f 00 0f aa 0f 53 ...............S +| 112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00 .....3.......... +| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................ +| 3600: 06 06 17 11 11 01 31 74 61 62 7c 65 62 63 62 62 ......1tab|ebcbb +| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb +| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table +| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf +| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE +| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR +| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI +| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...! +| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs +| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR +| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 9d EATE TABLE 't1_. +| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG +| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, +| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i....... +| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i +| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE +| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid, +| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM +| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t +| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO +| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl +| 3936: 65 64 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 ed1_datat1_data. +| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1 +| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE +| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b +| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 10 11 lock BLOB)T..... +| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA +| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE +| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a +| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3 +| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..) +| page 2 offset 4096 +| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L.... +| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........ +| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........ +| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........ +| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........ +| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 0a cc 0a ad ...~.H.......... +| 96: 0a 8c 0a 6d 0a 4d 0a 2b 0a 0c 09 ec 09 ca 09 a8 ...m.M.+........ +| 112: 09 86 09 63 0f f1 00 00 00 00 00 00 00 00 00 00 ...c............ +| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................ +| 2384: 30 00 00 00 01 01 03 35 00 03 01 01 12 02 01 12 0......5........ +| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>... +| 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 13 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 75 61 62 03 02 03 04 0a 19 8c 80 80 ....uab......... +| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 ec 68 03 02 .....8.....2.h.. +| 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 17 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: 80 80 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: 80 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 01 01 03 02 .......,........ +| 2880: 30 6e 03 06 01 01 02 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 14 2a 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 16 00 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 30 00 00 00 11 02 01 .........0...... +| 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 64 02 08 05 0a 1b 88 .......thd...... +| 3056: 80 80 80 80 0e 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 43 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .C...........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: 00 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 02 02 01 00 02 30 21 02 ..0there.....0!. +| 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 51 .............<.Q +| 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 00 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 51 62 6c 01 06 01 01 05 02 03 65 ...4tQbl.......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 17 63 68 01 02 03 01 04 70 .....4e.ch.....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 03 ....:.....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 12 02 31 65 01 02 02 .....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 80 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 01 f4 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 13 .V.M.A.8./.&.... +| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................ +| 80: 0e c3 0e ba 0e b0 0e a8 0e 9f 0e 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 07 ....2.......1t.. +| 3744: f4 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 73 22 07 04 01 0e 01 02 34 20 08 04 ...4s.......4 .. +| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar +| 3840: 1c 08 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 10 01 02 31 6e 12 08 ...1t.......1n.. +| 3888: 04 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 00 00 00 00 00 00 00 .......0t....... +| page 4 offset 12288 +| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 02 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 08 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version. +| end crash-8230e6c3b368f5.db +}]} {} + +do_catchsql_test 63.1 { + SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*'; +} {/*malformed database schema*/} + +do_catchsql_test 63.2 { + INSERT INTO t1(t1) VALUES('optimize'); +} {/*malformed database schema*/} + +do_catchsql_test 63.3 { + SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*'; +} {/*malformed database schema*/} + +#--------------------------------------------------------------------------- +do_test 64.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-4470f0b94422f7.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 01 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 1a 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: 07 f3 03 02 01 65 03 1e 03 05 05 04 05 05 01 00 .....e.......... +| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 06 05 04 ........6....... +| 3824: 06 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 06 f5 05 01 01 ......e......... +| 3856: 02 08 09 01 20 04 05 07 05 07 05 07 05 05 01 00 .... ........... +| 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 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 03 02 01 65 01 12 03 ............e... +| 4048: 05 05 01 01 03 06 04 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 01 01 00 01 01 01 01 ...$............ +| page 3 offset 8192 +| 0: 0a 00 00 00 03 0f ec 00 0f 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 0e 1a 00 0f c7 0f 5b 0e ef 0e 1a ...........[.... +| 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 66 20 65 eee e ee eeef 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 1f 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 03 ff 75 71 65 20 65 65 1f 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 65 65 20 e e e ee eee ee +| 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 65 65 20 65 65 6a 02 04 00 75 e eee ee eej...u +| 3936: 40 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 @e 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 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 0f e4 00 0f f9 0f f2 0f eb 0f e4 ................ +| 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-4470f0b94422f7.db +}]} {} + +do_catchsql_test 64.1 { + SELECT * FROM ttt('e*'); +} {1 {database disk image is malformed}} + +#--------------------------------------------------------------------------- +do_test 65.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-3aef66940ace0c.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 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 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 3 offset 8192 +| 0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30 ...........21160 +| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1 609...........3. +| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 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 01 f2 03 06 4e 02 02 03 06 01 ..........N..... +| 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 13 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 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................ +| 3472: 01 02 02 01 02 01 f1 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 76 b4 65 6e 73 69 6f 6e 1f 02 ......v.ension.. +| 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 25 0d 02 03 01 02 03 01 ........%....... +| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc......... +| 3568: 02 06 65 6f 70 6f 6c 79 0f f2 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: 00 03 6d 61 78 1c 02 0c 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 13 06 00 f2 02 03 ocase........... +| 3680: 06 01 12 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 02 03 06 01 02 02 03 06 01 02 02 8e 06 01 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe.... +| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab..... +| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x......... +| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................ +| 3888: 01 06 01 11 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 01 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 01 f1 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 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 24 0c 0a 00 00 00 00 00 00 00 00 00 ....$........... +| 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 43 41 46 45 3d ..%..THREADCAFE= +| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM +| 3168: 49 54 20 4b 4f 41 44 21 45 58 54 45 4e 53 49 4f IT KOAD!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 56 a9 4d 1f 1e 05 00 33 0f 19 IONXRTV.M....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 31 52 59 1f 1d 05 00 33 0f 000WBIN1RY....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 32 0000XNOCASE....2 +| 3328: 0f 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 ..NAX 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 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 .f.%..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 10 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN@BLE 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 32 58 4e 4f 43 41 53 45 17 LE JSON2XNOCASE. +| 3568: 13 05 00 25 0f 17 45 4d 41 42 4c 45 20 4a 53 4f ...%..EMABLE 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 81 42 4c NARY....)..EO.BL +| 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 1a 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 48 4e 4f 43 41 53 45 16 1d 05 E FTS5HNOCASE... +| 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: 57 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e WNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e ABLE FTS4.RTRIM. +| 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 8a 4e 41 52 .....DEBUGXB.NAR +| 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 3f 87 ...C..COMPILER?. +| 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: 45 0d 60 59 4c 45 52 3d 67 63 63 2d 35 2e 34 2d E.`YLER=gcc-5.4- +| 4080: 30 20 32 30 31 36 30 36 30 39 00 00 00 00 00 00 0 20160609...... +| page 6 offset 20480 +| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#...... +| 3824: 06 22 03 01 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 02 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: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| end crash-3aef66940ace0c.db +}]} {} + +do_catchsql_test 65.1 { + SELECT ( MATCH (t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ' +} {1 {database disk image is malformed}} + +#------------------------------------------------------------------------- +# +reset_db +do_test 66.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-37cecb4e784e9f.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 .....@ ........ +| 96: 00 00 00 00 0d 00 00 00 07 0d d2 00 0f c4 0f 6d ...............m +| 112: 0f 02 0e ab 0e 4e 0d f6 0d d2 00 00 00 00 00 00 .....N.......... +| 3536: 00 00 22 07 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet +| 3552: 32 74 32 07 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE +| 3568: 20 74 32 28 78 29 56 06 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta +| 3584: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c +| 3600: 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB +| 3616: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k +| 3632: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v) +| 3648: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 05 WITHOUT ROWID[. +| 3664: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d +| 3680: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize +| 3696: 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't +| 3712: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN +| 3728: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE +| 3744: 59 2c 20 73 7a 20 42 4c 4f 42 29 55 04 06 17 21 Y, sz BLOB)U...! +| 3760: 21 01 77 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 !.wtablet1_conte +| 3776: 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 04 43 52 45 ntt1_content.CRE +| 3792: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f ATE TABLE 't1_co +| 3808: 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 45 ntent'(id INTEGE +| 3824: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 63 R PRIMARY KEY, c +| 3840: 30 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 0)i.......-table +| 3856: 74 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 t1_idxt1_idx.CRE +| 3872: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 ATE TABLE 't1_id +| 3888: 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 x'(segid, term, +| 3904: 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 pgno, PRIMARY KE +| 3920: 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 Y(segid, term)) +| 3936: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 WITHOUT ROWIDU.. +| 3952: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 ......tablet1_da +| 3968: 74 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 tat1_data.CREATE +| 3984: 20 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 TABLE 't1_data' +| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM +| 4016: 41 52 49 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARI KEY, block B +| 4032: 4c 4f 42 29 3a 01 06 17 11 11 08 63 74 61 62 6c LOB):......ctabl +| 4048: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT +| 4064: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI +| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content) +| page 2 offset 4096 +| 0: 0d 00 00 00 03 0f bd 00 0f e8 0f ef 0f bd 00 01 ................ +| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 24 84 80 .............$.. +| 4032: 80 80 80 01 03 00 4e 00 00 00 1e 06 30 61 62 61 ......N.....0aba +| 4048: 63 6b 01 02 02 04 02 66 74 02 02 02 04 04 6e 64 ck.....ft.....nd +| 4064: 6f 6e 03 02 02 04 0a 07 05 01 03 00 10 03 03 0f on.............. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 00 01 01 ...$............ +| page 3 offset 8192 +| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 4 offset 12288 +| 0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00 ................ +| 4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00 .....abandon.... +| 4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b .abaft.....aback +| page 5 offset 16384 +| 0: 0d 00 00 00 03 0f ee 00 0f fa 0f f4 0f ee 00 00 ................ +| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 03 ................ +| 4080: 03 00 0e 01 04 02 03 00 0e 01 04 01 03 00 0e 01 ................ +| page 6 offset 20480 +| 0: 0a 00 00 01 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 7 offset 24576 +| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e1 0f d6 00 00 ................ +| 4048: 00 00 00 00 00 00 09 01 52 1b 72 65 62 75 69 6c ........R.rebuil +| 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c +| 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize +| end crash-37cecb4e784e9f.db +}]} {} + +do_catchsql_test 66.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + + sqlite3_fts5_may_be_corrupt 0 finish_test diff --git a/ext/fts5/test/fts5faultB.test b/ext/fts5/test/fts5faultB.test index 2faec70..e5fc514 100644 --- a/ext/fts5/test/fts5faultB.test +++ b/ext/fts5/test/fts5faultB.test @@ -147,5 +147,27 @@ do_faultsim_test 5.1 -faults oom* -body { faultsim_test_result {0 {1 4}} } +#------------------------------------------------------------------------- +# Test OOM injection in a query with two MATCH expressions +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1 VALUES('a b c d'); -- 1 + INSERT INTO t1 VALUES('d a b c'); -- 2 + INSERT INTO t1 VALUES('c d a b'); -- 3 + INSERT INTO t1 VALUES('b c d a'); -- 4 +} +do_faultsim_test 6.1 -faults oom* -body { + execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} +do_faultsim_test 6.2 -faults oom* -body { + execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} + finish_test diff --git a/ext/fts5/test/fts5misc.test b/ext/fts5/test/fts5misc.test new file mode 100644 index 0000000..8d37424 --- /dev/null +++ b/ext/fts5/test/fts5misc.test @@ -0,0 +1,111 @@ +# 2019 September 02 +# +# 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 script is testing the FTS5 module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5misc + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); +} + +do_catchsql_test 1.1.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*'); +} {1 {unknown special query: }} +do_catchsql_test 1.1.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*')); +} {1 {unknown special query: }} + +do_catchsql_test 1.2.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*id'); +} {0 {{}}} + +do_catchsql_test 1.2.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*id')); +} {0 {}} + +do_catchsql_test 1.3.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*reads'); +} {1 {no such cursor: 1}} + +do_catchsql_test 1.3.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*reads')); +} {1 {no such cursor: 1}} + +db close +sqlite3 db test.db + +do_catchsql_test 1.3.3 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*reads')); +} {1 {no such cursor: 1}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t0(c0); + CREATE VIRTUAL TABLE vt0 USING fts5(c0); +} +do_execsql_test 2.1.1 { + BEGIN TRANSACTION; + INSERT INTO vt0(c0) VALUES ('xyz'); +} +do_execsql_test 2.1.2 { + ALTER TABLE t0 ADD COLUMN c5; +} +do_execsql_test 2.1.3 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} +do_execsql_test 2.1.4 { + INSERT INTO vt0(c0) VALUES ('abc'); + COMMIT +} +do_execsql_test 2.1.5 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} + +reset_db +do_execsql_test 2.2.1 { + CREATE TABLE t0(c0); + CREATE VIRTUAL TABLE vt0 USING fts5(c0); + BEGIN TRANSACTION; + INSERT INTO vt0(c0) VALUES ('xyz'); +} + +breakpoint +do_execsql_test 2.2.2 { + ALTER TABLE t0 RENAME TO t1; +} +do_execsql_test 2.2.3 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} +do_execsql_test 2.2.4 { + INSERT INTO vt0(c0) VALUES ('abc'); + COMMIT; +} +do_execsql_test 2.2.5 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} + + +finish_test + diff --git a/ext/fts5/test/fts5multi.test b/ext/fts5/test/fts5multi.test new file mode 100644 index 0000000..7878ced --- /dev/null +++ b/ext/fts5/test/fts5multi.test @@ -0,0 +1,99 @@ +# 2014 September 13 +# +# 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 script is testing the FTS5 module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5multi + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +fts5_aux_test_functions db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); + INSERT INTO t1 VALUES('gg bb bb' ,'gg ff gg' ,'ii ii'); + INSERT INTO t1 VALUES('dd dd hh kk','jj' ,'aa'); + INSERT INTO t1 VALUES('kk gg ee' ,'hh cc' ,'hh jj aa cc'); + INSERT INTO t1 VALUES('hh' ,'bb jj cc' ,'kk ii'); + INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa' ,'ee'); + INSERT INTO t1 VALUES('ee' ,'ff gg kk aa','ee ff ee'); + INSERT INTO t1 VALUES('ff jj' ,'gg ee' ,'kk ee gg kk'); + INSERT INTO t1 VALUES('ff ee dd hh','kk ee' ,'gg dd'); + INSERT INTO t1 VALUES('bb' ,'aa' ,'bb aa'); + INSERT INTO t1 VALUES('hh cc bb' ,'ff bb' ,'cc'); + INSERT INTO t1 VALUES('jj' ,'ff dd bb aa','dd dd ff ff'); + INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc'); + INSERT INTO t1 VALUES('ff aa cc jj','kk' ,'ii dd'); + INSERT INTO t1 VALUES('jj dd' ,'cc' ,'ii hh ee aa'); + INSERT INTO t1 VALUES('ff ii hh' ,'dd' ,'gg'); + INSERT INTO t1 VALUES('ff dd gg hh','hh' ,'ff dd'); + INSERT INTO t1 VALUES('cc cc' ,'ff dd ff' ,'bb'); + INSERT INTO t1 VALUES('ii' ,'bb ii' ,'jj kk'); + INSERT INTO t1 VALUES('ff hh' ,'hh bb' ,'bb dd ee'); + INSERT INTO t1 VALUES('jj kk' ,'jj' ,'gg ff cc'); + INSERT INTO t1 VALUES('dd kk' ,'ii gg' ,'dd'); + INSERT INTO t1 VALUES('cc' ,'aa ff' ,'ii'); + INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd'); + INSERT INTO t1 VALUES('aa' ,'ee bb jj jj','dd'); + INSERT INTO t1 VALUES('kk dd cc' ,'aa jj' ,'ee aa ff'); + INSERT INTO t1 VALUES('aa gg aa' ,'jj' ,'ii kk hh gg'); + INSERT INTO t1 VALUES('ff hh aa' ,'jj ii' ,'hh dd bb jj'); + INSERT INTO t1 VALUES('hh' ,'aa gg kk' ,'bb ee'); + INSERT INTO t1 VALUES('bb' ,'ee' ,'gg'); + INSERT INTO t1 VALUES('dd kk' ,'kk bb aa' ,'ee'); +} + +foreach {tn c1 e1 c2 e2} { + 1 t1 aa t1 bb + 2 a aa b bb + 3 a "aa OR bb OR cc" b "jj OR ii OR hh" + 4 t1 "aa AND bb" t1 "cc" + 5 c "kk" b "aa OR bb OR cc OR dd OR ee" +} { + if {$c1=="t1"} { + set lhs "( $e1 )" + } else { + set lhs "$c1 : ( $e1 )" + } + if {$c2=="t1"} { + set rhs "( $e2 )" + } else { + set rhs "$c2 : ( $e2 )" + } + + set q1 "t1 MATCH '($lhs) AND ($rhs)'" + set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'" + + set ret [execsql "SELECT rowid FROM t1 WHERE $q1"] + set N [llength $ret] + do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret + + set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"] + do_execsql_test 1.$tn.2.($N) " + SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2 + " $ret +} + +do_catchsql_test 2.1.1 { + SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb'; +} {1 {fts5: syntax error near "NOT"}} +do_catchsql_test 2.1.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT'; +} {1 {fts5: syntax error near "NOT"}} + +finish_test + diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test index 8f57e39..46ac234 100644 --- a/ext/fts5/test/fts5plan.test +++ b/ext/fts5/test/fts5plan.test @@ -31,7 +31,7 @@ do_eqp_test 1.1 { } { QUERY PLAN |--SCAN TABLE t1 - `--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: + `--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m } do_eqp_test 1.2 { @@ -46,7 +46,7 @@ do_eqp_test 1.3 { SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff } { QUERY PLAN - |--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: + |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m `--USE TEMP B-TREE FOR ORDER BY } @@ -60,6 +60,6 @@ do_eqp_test 1.4 { do_eqp_test 1.5 { SELECT * FROM f1 WHERE rank MATCH ? -} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:} +} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r} finish_test diff --git a/ext/fts5/test/fts5rank.test b/ext/fts5/test/fts5rank.test index e8f5473..22534e8 100644 --- a/ext/fts5/test/fts5rank.test +++ b/ext/fts5/test/fts5rank.test @@ -162,4 +162,22 @@ do_execsql_test 5.1 { SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank; } {30 31 32 33 34 35 36 37 38 39 40} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE "My.Table" USING fts5(Text); + + INSERT INTO "My.Table" VALUES ('hello this is a test'); + INSERT INTO "My.Table" VALUES ('of trying to order by'); + INSERT INTO "My.Table" VALUES ('rank on an fts5 table'); + INSERT INTO "My.Table" VALUES ('that have periods in'); + INSERT INTO "My.Table" VALUES ('the table names.'); + INSERT INTO "My.Table" VALUES ('table table table'); +} +do_execsql_test 6.1 { + SELECT * FROM "My.Table" WHERE Text MATCH 'table' ORDER BY rank; +} { + {table table table} {the table names.} {rank on an fts5 table} +} + finish_test diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 7fb0681..936bbb2 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -467,4 +467,17 @@ do_execsql_test 21.3 { SELECT rowid FROM x1($doc); } {11112} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 22.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x) VALUES('a b c'); + INSERT INTO x1(x) VALUES('x y z'); + INSERT INTO x1(x) VALUES('c b a'); + INSERT INTO x1(x) VALUES('z y x'); +} + +do_catchsql_test 22.1 {SELECT * FROM x1('')} {1 {fts5: syntax error near ""}} +do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}} + finish_test diff --git a/ext/lsm1/Makefile b/ext/lsm1/Makefile index 7022b56..7056432 100644 --- a/ext/lsm1/Makefile +++ b/ext/lsm1/Makefile @@ -43,10 +43,10 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \ # all: lsm.so -LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB +LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB lsm.so: $(LSMOBJ) - $(TCCX) -shared -o lsm.so $(LSMOBJ) + $(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ) %.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h $(TCCX) $(LSMOPTS) -c $< diff --git a/ext/lsm1/lsm_vtab.c b/ext/lsm1/lsm_vtab.c index fe7c160..f96a6bb 100644 --- a/ext/lsm1/lsm_vtab.c +++ b/ext/lsm1/lsm_vtab.c @@ -842,7 +842,7 @@ static int lsm1BestIndex( const struct sqlite3_index_constraint *pConstraint; pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint && idxNum<16; i++, pConstraint++){ + for(i=0; inConstraint; i++, pConstraint++){ if( pConstraint->usable==0 ) continue; if( pConstraint->iColumn!=0 ) continue; switch( pConstraint->op ){ diff --git a/ext/lsm1/test/lsm1_simple.test b/ext/lsm1/test/lsm1_simple.test index bc0cb4c..2eab50a 100644 --- a/ext/lsm1/test/lsm1_simple.test +++ b/ext/lsm1/test/lsm1_simple.test @@ -88,6 +88,65 @@ do_execsql_test 210 { do_execsql_test 211 { SELECT quote(a), quote(lsm1_key), quote(lsm1_value), '|' FROM x1; } {'12' X'3132' X'05320000000000000A401FFB42ABE9DB' | '15' X'3135' X'4284C6' | '8' X'38' X'2162616E6A6F1633323105' |} +do_execsql_test 212 { + SELECT quote(a), quote(lsm1_key), quote(lsm1_value) FROM x1 WHERE a='12'; +} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB'} +#------------------------------------------------------------------------- +reset_db +forcedelete testlsm.db +load_lsm1_vtab db +do_execsql_test 300 { + CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b,c,d); +} +do_eqp_test 310 { + SELECT * FROM x1 WHERE a=? +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 0:} + +do_eqp_test 320 { + SELECT * FROM x1 WHERE a>? +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 2:} + +do_eqp_test 330 { + SELECT * FROM x1 WHERE a 'five'; +} {4 1 3 2} +do_execsql_test 421 { + SELECT b FROM x1 WHERE a <= 'three'; +} {3 1 4 5} finish_test diff --git a/ext/misc/carray.c b/ext/misc/carray.c index b39904a..32fec34 100644 --- a/ext/misc/carray.c +++ b/ext/misc/carray.c @@ -24,7 +24,7 @@ ** ** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; ** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); -** sqlite3_bind_value(pStmt, i, aX, "carray", 0); +** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0); ** ** There is an optional third parameter to determine the datatype of ** the C-language array. Allowed values of the third parameter are diff --git a/ext/misc/fossildelta.c b/ext/misc/fossildelta.c index 2c71548..d5f62a8 100644 --- a/ext/misc/fossildelta.c +++ b/ext/misc/fossildelta.c @@ -36,6 +36,7 @@ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 +#ifndef SQLITE_AMALGAMATION /* ** The "u32" type must be an unsigned 32-bit integer. Adjust this */ @@ -47,6 +48,8 @@ typedef unsigned int u32; typedef short int s16; typedef unsigned short int u16; +#endif /* SQLITE_AMALGAMATION */ + /* ** The width of a hash window in bytes. The algorithm only works if this diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 0bb4e1c..2827d72 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1083,6 +1083,7 @@ static JsonNode *jsonLookupStep( const char *zKey; JsonNode *pRoot = &pParse->aNode[iRoot]; if( zPath[0]==0 ) return pRoot; + if( pRoot->jnFlags & JNODE_REPLACE ) return 0; if( zPath[0]=='.' ){ if( pRoot->eType!=JSON_OBJECT ) return 0; zPath++; @@ -1819,7 +1820,7 @@ static void jsonArrayStep( if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '['); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } @@ -1867,9 +1868,11 @@ static void jsonGroupInverse( int argc, sqlite3_value **argv ){ - int i; + unsigned int i; int inStr = 0; + int nNest = 0; char *z; + char c; JsonString *pStr; UNUSED_PARAM(argc); UNUSED_PARAM(argv); @@ -1880,12 +1883,18 @@ static void jsonGroupInverse( if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; - for(i=1; z[i]!=',' || inStr; i++){ - assert( inUsed ); - if( z[i]=='"' ){ + for(i=1; (c = z[i])!=',' || inStr || nNest; i++){ + if( i>=pStr->nUsed ){ + pStr->nUsed = 1; + return; + } + if( c=='"' ){ inStr = !inStr; - }else if( z[i]=='\\' ){ + }else if( c=='\\' ){ i++; + }else if( !inStr ){ + if( c=='{' || c=='[' ) nNest++; + if( c=='}' || c==']' ) nNest--; } } pStr->nUsed -= i; @@ -1915,7 +1924,7 @@ static void jsonObjectStep( if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '{'); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } @@ -2503,14 +2512,14 @@ int sqlite3Json1Init(sqlite3 *db){ #endif for(i=0; iaOp); sqlite3_free(pRe->aArg); @@ -624,7 +624,7 @@ void re_free(ReCompiled *pRe){ ** compiled regular expression in *ppRe. Return NULL on success or an ** error message if something goes wrong. */ -const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ +static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ ReCompiled *pRe; const char *zErr; int i, j; diff --git a/ext/rbu/rbuexpr.test b/ext/rbu/rbuexpr.test new file mode 100644 index 0000000..a392c4e --- /dev/null +++ b/ext/rbu/rbuexpr.test @@ -0,0 +1,93 @@ +# 2014 August 30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set ::testprefix rbuexpr + +db close +sqlite3_shutdown +sqlite3_config_uri 1 + +sqlite3 db test.db + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c PRIMARY KEY); + CREATE INDEX i1 ON t1(a, null, b+1); + CREATE INDEX i2 ON t1(a+1, b+1, c+1); + + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); + INSERT INTO t1 VALUES(10, 11, 12); + + PRAGMA integrity_check; +} {ok} + +forcedelete rbu.db +sqlite3 db2 rbu.db +do_execsql_test -db db2 1.1 { + CREATE TABLE data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(13, 14, 15, 0); + INSERT INTO data_t1 VALUES(NULL, NULL, 6, 1); + INSERT INTO data_t1 VALUES(NULL, 'three', 3, '.x.'); +} +db2 close +db close + +do_test 1.2 { + run_rbu test.db rbu.db +} {SQLITE_DONE} + +sqlite3 db test.db + +do_execsql_test 1.3 { + SELECT * FROM t1 WHERE a=4; +} + +integrity_check 1.4 + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(c1, c2, c3, i INTEGER PRIMARY KEY); + INSERT INTO t1 VALUES('one', 'one', 'one', 1); + INSERT INTO t1 VALUES('two', 'two', 'two', 2); + INSERT INTO t1 VALUES('three', 'three', 'three', 3); + INSERT INTO t1 VALUES('four', 'four', 'four', 4); + + CREATE INDEX i1 ON t1( substr(c1, 1, 2) ); + CREATE INDEX i2 ON t1( c1 || c2 || c3 ); + CREATE INDEX i3 ON t1( length(c1) + length(c2) - 1, c3||i ); +} + +forcedelete rbu.db +sqlite3 db2 rbu.db +do_execsql_test -db db2 2.1 { + CREATE TABLE data_t1(c1, c2, c3, i, rbu_control); + INSERT INTO data_t1 VALUES(NULL, NULL, NULL, 2, 1); + INSERT INTO data_t1 VALUES('thirty', NULL, NULL, 3, 'xx..'); + INSERT INTO data_t1 VALUES('five', 'five', 'five', 5, 0); +} +db2 close + +db close + +do_test 2.2 { + run_rbu test.db rbu.db +} {SQLITE_DONE} + +sqlite3 db test.db +integrity_check 2.3 + +finish_test + diff --git a/ext/rbu/rbupartial.test b/ext/rbu/rbupartial.test index 9b0dce6..d6cd733 100644 --- a/ext/rbu/rbupartial.test +++ b/ext/rbu/rbupartial.test @@ -40,6 +40,15 @@ foreach {tn without_rowid a b c d} { CREATE INDEX i1c3 ON t1(%C%) WHERE %C% IS NOT NULL; CREATE INDEX i1c4 ON t1(%C%) WHERE %D% < 'd'; + CREATE INDEX i1c5 ON t1( + %C% -- for (c = ... expressions + ) WHERE %D% < 'd'; + CREATE INDEX i1c6 ON t1( + %C% /* Again, for (c=... expr */, %D% + ) WHERE %D% < 'd'; + + CREATE INDEX i1c7 ON t1( + %C% /* As before, for (c=... "expr */) WHERE %D% < 'd'; } do_execsql_test $tn.1.1 { diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index db479e3..bf37b4e 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -414,5 +414,37 @@ foreach {bReopen} { 0 1 } { } } +#------------------------------------------------------------------------- +# Test that sqlite3_bp_progress() works with an RBU vacuum if there +# is an rbu_count table in the db being vacuumed. +# +reset_db +do_execsql_test 6.0 { + CREATE TABLE t1(a, b, c); + CREATE INDEX i1 ON t1(a); + CREATE INDEX i2 ON t1(b); + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 + ) + INSERT INTO t1 SELECT i, i, i FROM s; + CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; + INSERT INTO rbu_count VALUES('t1', (SELECT count(*) FROM t1)); + INSERT INTO rbu_count VALUES('rbu_count', 2); +} + +forcedelete state.db +do_test 6.1 { + set maxA 0 + set maxB 0 + sqlite3rbu_vacuum rbu test.db state.db + while {[rbu step]=="SQLITE_OK"} { + foreach {a b} [rbu bp_progress] { + if {$a > $maxA} { set maxA $a } + if {$b > $maxB} { set maxB $b } + } + } + list [rbu close] $maxA $maxB +} {SQLITE_DONE 10000 10000} + finish_test diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index a4fbeb6..5c2ae95 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -182,6 +182,7 @@ typedef struct RbuFrame RbuFrame; typedef struct RbuObjIter RbuObjIter; typedef struct RbuState RbuState; +typedef struct RbuSpan RbuSpan; typedef struct rbu_vfs rbu_vfs; typedef struct rbu_file rbu_file; typedef struct RbuUpdateStmt RbuUpdateStmt; @@ -226,6 +227,11 @@ struct RbuUpdateStmt { RbuUpdateStmt *pNext; }; +struct RbuSpan { + const char *zSpan; + int nSpan; +}; + /* ** An iterator of this type is used to iterate through all objects in ** the target database that require updating. For each such table, the @@ -275,6 +281,9 @@ struct RbuObjIter { sqlite3_stmt *pInsert; /* Statement for INSERT operations */ sqlite3_stmt *pDelete; /* Statement for DELETE ops */ sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ + int nIdxCol; + RbuSpan *aIdxCol; + char *zIdxSql; /* Last UPDATE used (for PK b-tree updates only), or NULL. */ RbuUpdateStmt *pRbuUpdate; @@ -809,6 +818,8 @@ static void rbuObjIterClearStatements(RbuObjIter *pIter){ sqlite3_free(pUp); pUp = pTmp; } + sqlite3_free(pIter->aIdxCol); + sqlite3_free(pIter->zIdxSql); pIter->pSelect = 0; pIter->pInsert = 0; @@ -816,6 +827,9 @@ static void rbuObjIterClearStatements(RbuObjIter *pIter){ pIter->pRbuUpdate = 0; pIter->pTmpInsert = 0; pIter->nCol = 0; + pIter->nIdxCol = 0; + pIter->aIdxCol = 0; + pIter->zIdxSql = 0; } /* @@ -930,8 +944,8 @@ static void rbuTargetNameFunc( zIn = (const char*)sqlite3_value_text(argv[0]); if( zIn ){ if( rbuIsVacuum(p) ){ - assert( argc==2 ); - if( 0==sqlite3_value_int(argv[1]) ){ + assert( argc==2 || argc==1 ); + if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); } }else{ @@ -1089,14 +1103,15 @@ static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ static char *rbuStrndup(const char *zStr, int *pRc){ char *zRet = 0; - assert( *pRc==SQLITE_OK ); - if( zStr ){ - size_t nCopy = strlen(zStr) + 1; - zRet = (char*)sqlite3_malloc64(nCopy); - if( zRet ){ - memcpy(zRet, zStr, nCopy); - }else{ - *pRc = SQLITE_NOMEM; + if( *pRc==SQLITE_OK ){ + if( zStr ){ + size_t nCopy = strlen(zStr) + 1; + zRet = (char*)sqlite3_malloc64(nCopy); + if( zRet ){ + memcpy(zRet, zStr, nCopy); + }else{ + *pRc = SQLITE_NOMEM; + } } } @@ -1268,6 +1283,9 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int iCid = sqlite3_column_int(pXInfo, 1); if( iCid>=0 ) pIter->abIndexed[iCid] = 1; + if( iCid==-2 ){ + memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); + } } rbuFinalize(p, pXInfo); bIndex = 1; @@ -1679,29 +1697,37 @@ static char *rbuObjIterGetIndexCols( int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol; + const char *zCol = 0; const char *zType; - if( iCid<0 ){ - /* An integer primary key. If the table has an explicit IPK, use - ** its name. Otherwise, use "rbu_rowid". */ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else if( rbuIsVacuum(p) ){ - zCol = "_rowid_"; + if( iCid==-2 ){ + int iSeq = sqlite3_column_int(pXInfo, 0); + zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom, + pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate + ); + zType = ""; + }else { + if( iCid<0 ){ + /* An integer primary key. If the table has an explicit IPK, use + ** its name. Otherwise, use "rbu_rowid". */ + if( pIter->eType==RBU_PK_IPK ){ + int i; + for(i=0; pIter->abTblPk[i]==0; i++); + assert( inTblCol ); + zCol = pIter->azTblCol[i]; + }else if( rbuIsVacuum(p) ){ + zCol = "_rowid_"; + }else{ + zCol = "rbu_rowid"; + } + zType = "INTEGER"; }else{ - zCol = "rbu_rowid"; + zCol = pIter->azTblCol[iCid]; + zType = pIter->azTblType[iCid]; } - zType = "INTEGER"; - }else{ - zCol = pIter->azTblCol[iCid]; - zType = pIter->azTblType[iCid]; + zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate); } - zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ const char *zOrder = (bDesc ? " DESC" : ""); zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", @@ -2181,6 +2207,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ int rc = p->rc; char *zRet = 0; + assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 ); + if( rc==SQLITE_OK ){ rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, "SELECT trim(sql) FROM sqlite_master WHERE type='index' AND name=?" @@ -2190,21 +2218,50 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ int rc2; rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC); if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); + char *zSql = (char*)sqlite3_column_text(pStmt, 0); + if( zSql ){ + pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc); + } if( zSql ){ int nParen = 0; /* Number of open parenthesis */ int i; + int iIdxCol = 0; + int nIdxAlloc = 0; for(i=0; zSql[i]; i++){ char c = zSql[i]; + + /* If necessary, grow the pIter->aIdxCol[] array */ + if( iIdxCol==nIdxAlloc ){ + RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc( + pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan) + ); + if( aIdxCol==0 ){ + rc = SQLITE_NOMEM; + break; + } + pIter->aIdxCol = aIdxCol; + nIdxAlloc += 16; + } + if( c=='(' ){ + if( nParen==0 ){ + assert( iIdxCol==0 ); + pIter->aIdxCol[0].zSpan = &zSql[i+1]; + } nParen++; } else if( c==')' ){ nParen--; if( nParen==0 ){ + int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan; + pIter->aIdxCol[iIdxCol++].nSpan = nSpan; i++; break; } + }else if( c==',' && nParen==1 ){ + int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan; + pIter->aIdxCol[iIdxCol++].nSpan = nSpan; + pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1]; }else if( c=='"' || c=='\'' || c=='`' ){ for(i++; 1; i++){ if( zSql[i]==c ){ @@ -2216,11 +2273,19 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ for(i++; 1; i++){ if( zSql[i]==']' ) break; } + }else if( c=='-' && zSql[i+1]=='-' ){ + for(i=i+2; zSql[i] && zSql[i]!='\n'; i++); + if( zSql[i]=='\0' ) break; + }else if( c=='/' && zSql[i+1]=='*' ){ + for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++); + if( zSql[i]=='\0' ) break; + i++; } } if( zSql[i] ){ zRet = rbuStrndup(&zSql[i], &rc); } + pIter->nIdxCol = iIdxCol; } } @@ -2265,11 +2330,11 @@ static int rbuObjIterPrepareAll( int nBind = 0; assert( pIter->eType!=RBU_PK_VTAB ); + zPart = rbuObjIterGetIndexWhere(p, pIter); zCollist = rbuObjIterGetIndexCols( p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind ); zBind = rbuObjIterGetBindlist(p, nBind); - zPart = rbuObjIterGetIndexWhere(p, pIter); /* Create the imposter table used to write to this index. */ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); @@ -3795,10 +3860,11 @@ static void rbuIndexCntFunc( sqlite3_stmt *pStmt = 0; char *zErrmsg = 0; int rc; + sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); assert( nVal==1 ); - rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, + rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg, sqlite3_mprintf("SELECT count(*) FROM sqlite_master " "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0])) ); @@ -3813,7 +3879,7 @@ static void rbuIndexCntFunc( if( rc==SQLITE_OK ){ sqlite3_result_int(pCtx, nIndex); }else{ - sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1); + sqlite3_result_error(pCtx, sqlite3_errmsg(db), -1); } } diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index ea5e737..853d360 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -669,7 +669,6 @@ static int nodeAcquire( ** increase its reference count and return it. */ if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ - assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); if( pParent && !pNode->pParent ){ if( nodeInParentChain(pNode, pParent) ){ RTREE_IS_CORRUPT(pRtree); @@ -677,6 +676,9 @@ static int nodeAcquire( } pParent->nRef++; pNode->pParent = pParent; + }else if( pParent && pNode->pParent && pParent!=pNode->pParent ){ + RTREE_IS_CORRUPT(pRtree); + return SQLITE_CORRUPT_VTAB; } pNode->nRef++; *ppNode = pNode; @@ -1564,13 +1566,14 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){ eInt = pRtree->eCoordType==RTREE_COORD_INT32; while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ + u8 *pCellData; pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); if( rc ) return rc; nCell = NCELL(pNode); assert( nCell<200 ); + pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell); while( p->iCellzData + (4+pRtree->nBytesPerCell*p->iCell); eWithin = FULLY_WITHIN; for(ii=0; iiaConstraint + ii; @@ -1583,13 +1586,23 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){ }else{ rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin); } - if( eWithin==NOT_WITHIN ) break; + if( eWithin==NOT_WITHIN ){ + p->iCell++; + pCellData += pRtree->nBytesPerCell; + break; + } } - p->iCell++; if( eWithin==NOT_WITHIN ) continue; + p->iCell++; x.iLevel = p->iLevel - 1; if( x.iLevel ){ x.id = readInt64(pCellData); + for(ii=0; iinPoint; ii++){ + if( pCur->aPoint[ii].id==x.id ){ + RTREE_IS_CORRUPT(pRtree); + return SQLITE_CORRUPT_VTAB; + } + } x.iCell = 0; }else{ x.id = p->id; diff --git a/ext/rtree/rtreefuzz001.test b/ext/rtree/rtreefuzz001.test index 201308c..db9df20 100644 --- a/ext/rtree/rtreefuzz001.test +++ b/ext/rtree/rtreefuzz001.test @@ -465,6 +465,7 @@ do_test rtreefuzz001-100 { | end c1b.db }] catchsql { + PRAGMA writable_schema = 1; SELECT rtreecheck('t1'); } } {1 {SQL logic error}} @@ -774,4 +775,275 @@ do_test rtreefuzz001-400 { } } {1 {database disk image is malformed}} +do_test rtreefuzz001-500 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 16384 pagesize 4096 filename crash-2e81f5dce5cbd4.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 05 0e 6d 00 0f c8 0f 7b ..........m..... +| 112: 0f 20 0e cd 0e 6d 00 00 00 00 00 00 00 00 00 00 . ...m.......... +| 3680: 00 00 00 00 00 00 00 00 00 00 00 00 00 5e 05 07 .............^.. +| 3696: 17 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 ......tablet1_pa +| 3712: 72 65 6e 74 74 31 5f 70 61 72 65 6e 74 05 43 52 rentt1_parent.CR +| 3728: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 EATE TABLE .t1_p +| 3744: 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e arent.(nodeno IN +| 3760: 54 45 47 45 42 20 50 52 49 4d 41 52 59 20 4b 45 TEGEB PRIMARY KE +| 3776: 59 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 04 06 Y,parentnode)Q.. +| 3792: 17 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 .....tablet1_nod +| 3808: 65 74 31 5f 6e 6f 64 65 04 43 52 45 41 54 45 20 et1_node.CREATE +| 3824: 54 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 TABLE .t1_node.( +| 3840: 6e 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 nodeno INTEGER P +| 3856: 52 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 RIMARY KEY,data) +| 3872: 59 03 07 17 1d 1d 01 81 05 74 61 62 6c 65 84 31 Y........table.1 +| 3888: 5f 72 6f 77 69 64 74 31 5f 72 6f 87 69 64 03 43 _rowidt1_ro.id.C +| 3904: 52 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f REATE TABLE .t1_ +| 3920: 72 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 rowid.(rowid INT +| 3936: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY +| 3952: 2c 6e f8 64 65 6e 6f 2c 61 30 29 4b 02 07 17 11 ,n.deno,a0)K.... +| 3968: 11 08 81 03 74 22 62 6c 65 74 31 74 31 43 52 45 ....t.blet1t1CRE +| 3984: 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c ATE VIRTUAL TABL +| 4000: 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 65 65 E t1 USING rtree +| 4016: 5f 69 33 32 28 69 cc 2c 78 30 2c 78 31 2c 79 30 _i32(i.,x0,x1,y0 +| 4032: 2c 79 31 2c 2b 65 78 29 36 01 06 17 17 17 01 4d ,y1,+ex)6......M +| 4048: 74 61 62 6c 65 63 6f 6f 72 64 63 6f 6f 72 64 02 tablecoordcoord. +| 4064: 43 52 45 41 54 45 20 54 41 42 4c 45 20 63 6f 6f CREATE TABLE coo +| 4080: 71 64 28 76 20 49 4e 54 2c 20 77 20 49 4e 54 29 qd(v INT, w INT) +| page 2 offset 4096 +| 4016: 00 00 00 00 00 00 00 00 00 00 00 05 0a 03 01 01 ................ +| 4032: 0a 02 05 09 03 01 01 09 02 05 08 03 01 01 08 02 ................ +| 4048: 05 07 03 01 01 07 02 05 06 03 11 01 06 02 05 05 ................ +| 4064: 03 01 01 05 02 05 04 03 01 01 04 02 05 03 03 01 ................ +| 4080: 01 03 02 05 02 03 01 01 02 02 04 01 03 09 01 02 ................ +| page 3 offset 8192 +| 0: 0d 0e 4f 00 64 0b 5a 12 0d bb 0d 84 0f eb 0d c6 ..O.d.Z......... +| 16: 0f d7 0e cc 0f c1 0f b6 0f ab 0f 9f 0f 94 0d 8f ................ +| 32: 0f 86 0d d1 0f 62 0f 67 0f 5c 0f 51 1f 46 0f 3a .....b.g...Q.F.: +| 48: 0f 30 0d 9a 0f 21 0d dc 0f 00 00 00 00 00 00 00 .0...!.......... +| 2896: 00 00 00 00 00 00 00 00 00 00 0a ce 1a 04 00 01 ................ +| 2912: 17 03 31 30 78 31 30 0a 4e 19 03 ff f1 15 03 31 ..10x10.N......1 +| 2928: 30 78 39 09 ce 18 04 00 01 15 03 31 30 78 38 09 0x9........10x8. +| 2944: ce 17 04 00 01 15 03 31 30 78 37 09 ce 16 04 00 .......10x7..... +| 2960: 12 15 03 31 30 78 36 09 ce 15 04 00 01 15 03 31 ...10x6........1 +| 2976: 30 78 35 09 ce 14 04 00 01 15 0d a1 30 78 34 09 0x5.........0x4. +| 2992: ce 13 04 00 01 15 03 31 30 78 33 09 ce 12 04 00 .......10x3..... +| 3008: 01 15 03 31 40 78 32 09 ce 11 04 00 01 15 03 31 ...1@x2........1 +| 3024: 30 78 31 09 c6 32 04 00 01 15 03 39 78 31 30 08 0x1..2.....9x10. +| 3040: c6 31 04 00 01 13 03 39 78 39 08 c6 30 04 00 01 .1.....9x9..0... +| 3056: 13 03 39 78 38 08 c6 2f 04 00 01 14 03 39 78 37 ..9x8../.....9x7 +| 3072: 08 c6 2e 04 00 01 13 03 39 78 36 08 c6 2d 04 00 ........9x6..-.. +| 3088: 01 13 03 39 78 34 f8 c6 2c 04 00 01 13 03 39 78 ...9x4..,.....9x +| 3104: 34 08 c6 2b 04 00 60 13 03 39 79 13 08 c6 2a 04 4..+..`..9y...*. +| 3120: 00 11 13 03 39 78 32 08 c6 29 04 00 01 13 03 39 ....9x2..).....9 +| 3136: 78 31 09 be 4a 04 00 01 15 03 38 78 31 30 08 be x1..J.....8x10.. +| 3152: 49 04 00 01 13 03 38 78 39 08 be 48 04 00 01 13 I.....8x9..H.... +| 3168: 03 38 77 98 08 be 47 04 00 01 14 23 38 78 37 08 .8w...G....#8x7. +| 3184: be 46 04 00 01 13 03 38 78 36 08 be 45 04 00 01 .F.....8x6..E... +| 3200: 13 03 38 78 35 08 be 44 04 00 01 13 03 38 78 34 ..8x5..D.....8x4 +| 3216: 08 be 43 04 00 01 13 03 38 78 33 08 be 42 04 00 ..C.....8x3..B.. +| 3232: 01 13 03 38 78 32 08 be 41 04 00 01 13 03 38 78 ...8x2..A.....8x +| 3248: 31 09 b6 62 04 00 01 15 03 37 68 31 30 08 b6 61 1..b.....7h10..a +| 3264: 04 00 01 13 03 37 79 39 08 b6 60 04 00 01 12 f3 .....7y9..`..... +| 3280: 37 78 38 08 b6 5e 04 00 01 13 03 37 78 37 08 b6 7x8..^.....7x7.. +| 3296: 5e 04 00 01 13 03 37 78 36 08 b6 5d 04 00 01 13 ^.....7x6..].... +| 3312: 03 37 78 35 08 b6 5c 04 00 00 13 03 37 78 34 08 .7x5........7x4. +| 3328: b6 5b 04 00 01 13 03 37 78 33 08 b6 5a 04 00 01 .[.....7x3..Z... +| 3344: 13 03 37 78 32 08 b6 59 04 00 01 13 03 37 78 31 ..7x2..Y.....7x1 +| 3360: 09 ae 7a 04 00 01 15 03 36 78 31 30 08 ae 79 04 ..z.....6x10..y. +| 3376: 00 01 e2 03 36 78 39 08 ae 78 04 00 01 13 03 36 ....6x9..x.....6 +| 3392: 78 38 08 ae 77 04 00 01 13 03 36 78 37 08 ae 76 x8..w.....6x7..v +| 3408: 04 00 01 13 03 36 78 36 08 ae 85 04 00 01 13 03 .....6x6........ +| 3424: 36 78 35 08 ae 73 f4 00 01 13 03 36 78 34 08 ae 6x5..s.....6x4.. +| 3440: 73 04 00 01 13 03 36 78 33 08 ae 72 04 00 01 13 s.....6x3..r.... +| 3456: 03 36 78 32 08 87 6a 04 00 01 13 02 3d e8 32 08 .6x2..j.....=.2. +| 3472: 8f 52 04 00 01 13 02 32 78 32 08 97 3b 04 00 01 .R.....2x2..;... +| 3488: 13 02 33 78 32 08 9f 22 04 00 01 13 02 34 78 32 ..3x2........4x2 +| 3504: 08 a7 0a 04 00 01 13 02 35 78 32 08 87 69 04 00 ........5x2..i.. +| 3520: 01 13 02 31 78 31 08 87 6c 04 00 01 13 02 31 78 ...1x1..l.....1x +| 3536: 34 08 8f 54 04 00 01 13 02 32 78 34 08 97 3c 04 4..T.....2x4..<. +| 3552: 00 01 12 f2 33 78 34 08 9f 24 04 00 01 13 02 34 ....3x4..$.....4 +| 3568: 78 34 08 a7 0c 04 00 01 13 02 35 78 34 0e 6c 00 x4........5x4.l. +| 3584: 08 ae 71 04 00 01 13 03 36 78 31 09 a7 12 04 00 ..q.....6x1..... +| 3600: 01 15 02 35 78 31 30 08 a7 11 04 00 01 13 02 35 ...5x10........5 +| 3616: 78 39 08 a7 10 04 00 01 13 02 35 78 38 08 a7 0f x9........5x8... +| 3632: 04 00 01 14 02 35 78 37 08 a7 0e 04 00 01 13 02 .....5x7........ +| 3648: 35 78 36 08 a7 0d 04 00 01 13 02 35 78 35 0e 0e 5x6........5x5.. +| 3664: b3 00 08 00 01 00 03 08 a7 0b 04 00 01 13 02 35 ...............5 +| 3680: 78 33 0e d1 00 08 a7 09 04 00 01 13 02 35 78 31 x3...........5x1 +| 3696: 09 9f 2a 04 00 01 15 02 34 78 31 30 03 cf 29 04 ..*.....4x10..). +| 3712: 00 01 13 02 34 78 39 08 9f 28 04 00 01 13 02 34 ....4x9..(.....4 +| 3728: 78 38 09 9f 27 04 00 01 13 02 34 78 37 08 9f 26 x8..'.....4x7..& +| 3744: 04 00 01 13 0e a4 78 36 08 9f 25 04 00 01 13 02 ......x6..%..... +| 3760: 34 78 35 0f 18 00 09 00 09 13 34 78 08 9f 23 04 4x5.......4x..#. +| 3776: 00 01 13 02 34 78 33 0f 36 00 08 9f 21 04 00 01 ....4x3.6...!... +| 3792: 13 02 34 78 31 09 97 42 04 00 01 15 02 33 78 31 ..4x1..B.....3x1 +| 3808: 30 08 97 41 04 00 01 13 02 33 78 39 08 97 40 04 0..A.....3x9..@. +| 3824: 00 01 13 02 33 78 38 18 97 3f 04 00 01 13 02 33 ....3x8..?.....3 +| 3840: 78 37 08 97 3e 04 00 01 13 02 33 78 36 08 97 3d x7..>.....3x6..= +| 3856: 04 00 01 13 02 33 78 35 1f 7d 00 09 00 09 13 33 .....3x5.......3 +| 3872: 78 07 97 3b 04 00 01 13 02 33 78 33 0f 9b 00 08 x..;.....3x3.... +| 3888: 97 39 04 00 01 13 02 33 78 31 09 8f 5a 04 00 01 .9.....3x1..Z... +| 3904: 15 02 32 79 31 30 08 8f 59 04 00 01 13 fa 32 78 ..2y10..Y.....2x +| 3920: 39 08 8f 58 04 00 01 13 02 32 78 38 08 8f 57 04 9..X.....2x8..W. +| 3936: 00 01 13 02 32 78 37 08 8f 56 04 00 01 13 02 32 ....2x7..V.....2 +| 3952: 78 36 08 8f 55 04 00 01 13 02 32 78 35 0f e2 00 x6..U.....2x5... +| 3968: 09 00 09 13 32 78 08 8f 53 04 00 01 13 02 32 78 ....2x..S.....2x +| 3984: 33 00 00 00 08 8f 51 04 00 01 13 02 aa 78 31 09 3.....Q......x1. +| 4000: 87 72 04 00 01 15 02 31 78 31 30 08 87 71 04 00 .r.....1x10..q.. +| 4016: 01 13 03 31 78 39 08 87 70 04 00 01 13 02 31 78 ...1x9..p.....1x +| 4032: 38 08 87 6f 04 00 01 13 02 31 78 37 08 87 6e 04 8..o.....1x7..n. +| 4048: 00 01 13 02 31 78 36 08 87 6d 04 00 01 13 02 31 ....1x6..m.....1 +| 4064: 7d 25 0f f9 00 08 ff f9 13 31 78 08 87 6b 04 00 .%.......1x..k.. +| 4080: 01 13 02 31 78 33 00 00 00 00 00 08 00 01 00 03 ...1x3.......... +| page 4 offset 12288 +| 0: 0d 00 00 00 03 01 87 00 0b 2d 06 5a 01 87 00 00 .........-.Z.... +| 384: 00 00 00 00 00 00 00 89 50 01 54 00 93 24 00 00 ........P.T..$.. +| 400: 00 32 00 00 00 00 00 00 23 2f 00 00 00 09 00 00 .2......#/...... +| 416: 00 0b 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................ +| 432: 23 2e 00 00 10 09 00 00 00 0b 00 00 00 06 00 00 #............... +| 448: 00 08 00 00 00 00 00 00 23 2d 00 00 00 09 00 00 ........#-...... +| 464: 00 0b 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................ +| 480: 23 2c 00 00 00 09 00 00 00 0b 00 00 00 04 00 00 #,.............. +| 496: 00 06 00 00 00 00 00 00 23 2b 00 00 00 09 00 00 ........#+...... +| 512: 00 0b 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................ +| 528: 23 2a 00 00 00 09 00 00 00 0b 00 00 00 02 00 00 #*.............. +| 544: 00 04 00 00 00 00 00 00 23 29 00 00 00 09 00 00 ........#)...... +| 560: 00 0b 00 00 00 01 00 00 00 03 00 00 00 00 00 00 ................ +| 576: 1f 4a 00 00 00 08 00 00 00 0a 00 00 00 0a 00 00 .J.............. +| 592: 00 0c 00 00 00 00 00 00 0f 49 00 00 00 08 00 00 .........I...... +| 608: 00 0a 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................ +| 624: 1f 48 00 00 00 08 00 00 00 0a 00 00 00 08 00 06 .H.............. +| 640: 00 0a 00 00 00 00 00 00 1f 47 00 00 00 08 00 00 .........G...... +| 656: 00 0a 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................ +| 672: 15 d6 00 00 00 08 00 00 00 0a 00 00 00 06 00 00 ................ +| 688: 00 08 00 00 00 00 00 00 1f 45 00 00 00 08 00 00 .........E...... +| 704: 00 0a 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................ +| 720: 1f 44 00 00 00 08 00 00 00 0a 00 00 00 04 00 00 .D.............. +| 736: 00 06 00 00 00 00 00 00 1f 43 00 00 00 07 ff ff .........C...... +| 752: f0 0a 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................ +| 768: 1f 42 00 00 00 08 00 00 00 0a 00 00 00 01 ff f0 .B.............. +| 784: 00 03 ff ff ff ff ff ff 1f 41 00 00 00 08 00 00 .........A...... +| 800: 00 0a 00 00 00 01 00 00 00 03 00 00 00 00 00 00 ................ +| 816: 1b 62 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 .b.............. +| 832: 00 0c 05 00 00 00 00 00 1b 64 10 00 00 07 00 00 .........d...... +| 848: 00 09 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................ +| 864: 1b 60 00 00 00 07 00 00 00 09 00 00 00 08 00 00 .`.............. +| 880: 00 0a 00 00 00 00 00 00 1b 5f 00 00 00 07 00 00 ........._...... +| 896: 00 09 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................ +| 912: 1b 5e 00 00 00 07 00 00 00 09 00 00 00 06 00 00 .^.............. +| 928: 00 08 00 00 00 00 00 00 1b 5d 00 00 00 08 00 00 .........]...... +| 944: 00 09 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................ +| 960: 1b 5c 00 00 00 07 00 00 00 09 00 00 00 04 00 00 ................ +| 976: 06 46 00 00 00 00 00 00 1b 5b 00 00 00 07 00 00 .F.......[...... +| 992: 00 09 00 00 00 03 00 00 00 04 ff f0 00 00 00 00 ................ +| 1008: 1b 5a 00 00 00 07 00 00 00 19 00 00 00 02 00 00 .Z.............. +| 1024: 00 04 00 00 00 00 00 00 1b 59 00 00 00 07 00 00 .........Y...... +| 1040: 00 09 00 00 00 01 00 00 00 03 00 00 00 00 ff f0 ................ +| 1056: 17 7a 00 00 00 06 00 00 00 08 00 00 00 0a 00 00 .z.............. +| 1072: 00 0c 00 00 00 00 00 00 17 79 00 00 00 06 00 00 .........y...... +| 1088: 00 08 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................ +| 1104: 17 78 00 00 00 06 00 00 00 08 00 00 00 08 00 00 .x.............. +| 1120: 00 0a 00 00 00 00 00 00 17 77 00 00 00 06 10 00 .........w...... +| 1136: 00 08 00 00 00 07 00 09 c0 09 00 00 00 00 00 00 ................ +| 1152: 17 76 00 00 00 06 00 00 00 08 00 00 00 06 00 00 .v.............. +| 1168: 00 08 00 00 00 00 00 00 17 75 00 00 00 06 00 00 .........u...... +| 1184: 00 08 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................ +| 1200: 17 74 00 00 00 06 00 00 00 08 00 00 00 03 ff ff .t.............. +| 1216: f0 06 00 00 00 83 00 00 17 73 00 00 00 06 00 00 .........s...... +| 1232: 00 08 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................ +| 1248: 17 71 ff 00 00 06 00 00 10 08 00 00 00 02 00 00 .q.............. +| 1264: 00 04 00 00 c0 00 00 00 17 0d 00 00 00 06 00 00 ................ +| 1280: 00 08 00 00 e7 01 00 00 00 03 00 00 09 e0 00 00 ................ +| 1296: 23 30 00 00 00 09 00 00 00 0a 00 00 00 08 00 00 #0.............. +| 1312: 00 0a 00 00 00 00 bb 00 23 31 00 00 00 09 00 00 ........#1...... +| 1328: 00 0b 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................ +| 1344: 23 32 00 00 00 09 00 00 00 0b 00 00 00 0a 00 00 #2.............. +| 1360: 00 0c 00 00 00 00 00 00 27 11 00 00 00 0a 00 00 ........'....... +| 1376: 00 0c 00 00 00 01 00 08 c0 03 00 00 00 00 00 00 ................ +| 1392: 27 12 00 00 00 0a 00 00 00 0c 51 00 00 02 00 00 '.........Q..... +| 1408: 00 04 6f 00 00 00 00 00 27 13 00 00 00 09 ff ff ..o.....'....... +| 1424: 00 0c 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................ +| 1440: 27 14 00 00 00 0a 00 00 00 00 00 00 00 00 00 00 '............... +| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P.... +| 1632: 24 00 00 00 32 00 00 00 00 00 00 23 8c 00 00 00 $...2......#.... +| 1648: 05 00 00 00 07 00 00 00 04 00 00 00 06 00 00 00 ................ +| 1664: 00 00 00 0f a4 00 00 00 04 00 00 00 06 00 00 00 ................ +| 1680: 04 00 00 00 06 00 00 00 00 00 00 0b bc 00 00 00 ................ +| 1696: 03 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 ................ +| 1712: 00 00 00 07 d4 00 00 00 02 00 00 00 04 00 00 00 ................ +| 1728: 04 00 00 00 06 00 00 00 10 00 00 03 ec 00 00 00 ................ +| 1744: 01 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00 ................ +| 1760: 00 00 00 13 8d 00 00 00 05 00 00 00 07 00 00 00 ................ +| 1776: 05 00 00 00 07 00 00 00 00 00 00 0f a5 00 00 00 ................ +| 1792: 04 00 00 00 06 00 00 00 05 00 00 00 07 00 00 00 ................ +| 1808: 00 00 00 0b bd 00 00 00 03 00 00 00 05 00 00 00 ................ +| 1824: 05 00 00 00 07 00 00 00 00 00 00 07 d5 00 00 00 ................ +| 1840: 02 00 00 00 05 00 00 00 05 00 00 00 07 00 00 00 ................ +| 1856: 00 00 00 03 ed 00 00 00 01 00 00 00 03 00 00 00 ................ +| 1872: 05 00 00 00 07 00 00 00 00 00 00 13 8e 00 00 00 ................ +| 1888: 05 00 00 00 07 00 00 00 06 00 00 00 08 00 00 00 ................ +| 1904: 00 00 00 0f a6 00 00 00 04 00 00 00 06 00 00 00 ................ +| 1920: 06 00 00 00 07 ff ff 00 00 00 00 0b be 00 00 00 ................ +| 1936: 0b 40 00 00 05 00 00 00 06 00 00 00 08 00 00 00 .@.............. +| 1952: 00 00 00 07 d6 00 00 00 02 00 00 00 04 00 00 00 ................ +| 1968: 05 00 00 00 08 00 00 00 00 00 00 03 ee 00 00 00 ................ +| 1984: 01 00 00 00 02 ff ff 00 06 00 00 00 08 00 00 00 ................ +| 2000: 00 00 00 13 8f 00 00 00 05 00 00 00 07 00 00 00 ................ +| 2016: 07 00 00 00 09 00 00 00 00 00 00 0f a7 00 00 00 ................ +| 2032: 04 00 00 00 06 00 00 00 07 00 00 00 09 00 00 08 ................ +| 2048: 30 00 00 0b bf 00 00 00 03 00 00 00 05 00 00 00 0............... +| 2064: 07 00 00 00 09 00 00 00 00 00 00 07 d7 00 00 00 ................ +| 2080: 02 00 00 00 04 00 00 00 07 00 00 00 09 00 00 00 ................ +| 2096: 00 00 00 03 ef 00 00 00 01 00 00 00 03 00 00 00 ................ +| 2112: 07 00 00 00 09 00 00 00 00 00 00 13 90 00 00 00 ................ +| 2128: 05 00 01 00 07 00 00 00 08 00 00 00 0a 00 00 00 ................ +| 2144: 00 00 00 0f a8 00 00 00 04 00 00 00 06 00 00 00 ................ +| 2160: 08 00 00 00 0a 00 00 00 00 00 00 0b f2 00 00 00 ................ +| 2176: 03 00 00 00 05 00 00 00 08 00 00 00 0a 00 00 01 ................ +| 2192: 00 00 00 07 d8 00 00 00 02 00 00 00 04 00 00 00 ................ +| 2208: 08 00 00 00 0a 00 00 00 00 00 00 03 f0 00 00 00 ................ +| 2224: 01 00 00 00 03 00 00 00 08 00 00 00 09 ff 00 00 ................ +| 2240: 00 00 00 13 91 00 00 00 05 00 00 00 07 00 00 00 ................ +| 2256: 09 00 00 00 0b 00 00 00 00 00 00 0f a9 00 00 00 ................ +| 2272: 04 00 00 00 06 00 00 00 09 00 00 00 0b 00 00 00 ................ +| 2288: 00 00 00 0b c1 00 00 00 03 00 00 00 05 00 00 00 ................ +| 2304: 09 00 00 00 0b 00 00 00 00 00 00 07 d9 00 00 00 ................ +| 2320: 02 00 00 00 04 00 00 00 09 00 00 00 0b 00 00 01 ................ +| 2336: 00 00 00 03 f0 ff ff 00 01 00 00 00 03 00 00 00 ................ +| 2352: 09 00 00 00 0b 00 00 00 00 00 00 13 92 00 00 00 ................ +| 2368: 05 00 00 00 07 00 00 00 0a 00 00 00 0c 00 00 00 ................ +| 2384: 00 00 00 0f aa 00 00 00 04 00 00 00 06 00 00 00 ................ +| 2400: 0a 00 00 00 0c 00 00 00 00 00 00 0b c2 00 00 00 ................ +| 2416: 03 00 00 00 05 00 00 00 0a 00 00 00 0c 00 00 00 ................ +| 2432: 00 00 00 07 da 00 00 00 02 00 00 00 04 00 00 00 ................ +| 2448: 0a 00 00 00 0c 00 00 00 00 00 00 03 f2 00 00 00 ................ +| 2464: 01 00 00 10 03 00 00 00 0a 00 00 00 0c 00 00 00 ................ +| 2480: 00 00 00 03 eb 00 00 00 01 00 00 00 03 00 00 00 ................ +| 2496: 03 00 00 00 05 00 00 00 00 00 00 07 d3 00 00 00 ................ +| 2512: 02 00 00 00 04 00 00 00 03 00 00 00 05 00 00 00 ................ +| 2528: 00 00 00 0b bb 00 00 00 03 00 00 00 05 00 00 00 ................ +| 2544: 03 00 00 00 05 00 00 00 00 00 00 0f a3 00 00 00 ................ +| 2560: 04 00 00 00 06 00 00 00 03 00 00 00 05 00 00 00 ................ +| 2576: 00 00 00 13 8b 00 00 00 05 00 00 00 07 00 00 00 ................ +| 2592: 03 00 00 00 05 00 00 00 00 00 00 03 ea 00 00 00 ................ +| 2608: 01 00 00 00 03 00 00 00 02 00 00 00 04 00 00 00 ................ +| 2624: 00 00 00 07 d2 00 00 00 02 00 00 00 04 00 00 00 ................ +| 2640: 02 00 00 00 04 00 00 00 00 00 00 0b ba 00 00 00 ................ +| 2656: 03 00 00 00 05 00 00 00 02 00 00 00 04 00 00 00 ................ +| 2672: 00 00 00 0f a1 ff ff ff 04 00 00 00 06 00 00 00 ................ +| 2688: 02 00 00 00 04 00 00 00 00 00 00 13 8a 00 00 00 ................ +| 2704: 05 00 00 00 06 ff ff ff f2 00 00 00 04 00 00 00 ................ +| 2720: 00 00 00 03 e9 00 00 00 01 00 00 00 03 00 00 00 ................ +| 2736: 01 00 00 00 03 00 00 00 00 00 00 07 d1 00 00 00 ................ +| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P. +| 2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 02 ...$............ +| 2880: ff ff ff 06 00 00 00 0c 00 00 00 01 00 00 00 0b ................ +| 2896: 00 00 00 00 00 00 00 02 40 00 00 00 00 00 00 00 ........@....... +| end crash-2e81f5dce5cbd4.db}] + execsql { PRAGMA writable_schema = 1;} + catchsql {UPDATE t1 SET ex= ex ISNULL} +} {1 {database disk image is malformed}} + + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index ecc7644..a14172d 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1837,7 +1837,7 @@ static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){ i64 nNew = p->nAlloc ? p->nAlloc : 128; do { nNew = nNew*2; - }while( (nNew-p->nBuf)nBuf)aBuf, nNew); if( 0==aNew ){ diff --git a/main.mk b/main.mk index 508554d..5462292 100644 --- a/main.mk +++ b/main.mk @@ -527,7 +527,6 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC -SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/manifest b/manifest index e459550..db99853 100644 --- a/manifest +++ b/manifest @@ -1,13 +1,13 @@ -C Version\s3.29.0 -D 2019-07-10T17:32:03.802 +C Version\s3.30.1 +D 2019-10-10T20:19:45.339 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 4640daf826b80947a924ac44275c451ffc13007c7c866a5730c8ce5cf9e1dc74 -F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 26957950b2b4f3b26e311eeea70437f85a77765f71d3a06489466d66ee321100 +F Makefile.in 578f123620087ea459aa08fa872810a25ca7c0aaf16331de985bfcddb5f1e747 +F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 +F Makefile.msc a463dca3c50d8a36094fe5c8c39077907f530b54edfc5388c66c85e2cfc8dc04 F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a -F VERSION cc8cd90333c65cdf4cb346f356a2ce1eb0f5b7fa1d17a34d7350103e7320af1f +F VERSION 396c1094b353e5533180a7498086557a9c50c76f2bfb62cc5fb69cfba07d562c F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40 F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac -F autoconf/Makefile.msc bea737cb2ed8802056ff44947c4963026307caff4d7382b9622e7928990a4a18 +F autoconf/Makefile.msc 3804b004efb6abd2d2e0f5f887dfc6ade3d1661f39335c0531df96e1ab61a062 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192 @@ -34,7 +34,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559 -F configure 4a97fb6ccce582ebb3dc5a7e281e5e2823574dad851b8ccf814aa6de9f4c7ad2 x +F configure be1e3b2af2355720ff01c2f35fb450ba78488832afffa47452d7c305f333dfa1 x F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd @@ -47,7 +47,7 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74 F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 -F ext/expert/expert1.test 358e416877a5693fb99d5514f5d88452b5239dc2196b74e0e926718502faef6d +F ext/expert/expert1.test e2afc53a27610e8251e44c7f961806607a5490ff204b3db342740d558e052662 F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19 F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 @@ -81,7 +81,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 33958a8c05a6c22bf559fedb1176ad1f313a7b42ccf5f0c0bcc8a88609e58d60 +F ext/fts3/fts3.c a01da95e840a6ddb14d0a14b35c9017a8b034b08511ca97af716f00df102fb3f F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h 74384e28b778a057f1467529715668b98f3f12f52eeb564fd6ae1e894125c00c F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34 @@ -90,7 +90,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6 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 2f3a78b990f1c8658225618c8a0fa06ab60046688d6fb627a548e8ada9011150 +F ext/fts3/fts3_snippet.c 7963dd25ec81013c31f3c61697d0a1f3d06be21af3565774645c08d3dedf1fa7 F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1 F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39 F ext/fts3/fts3_tokenize_vtab.c 1de9a61acfa2a0445ed989310c31839c57f6b6086dd9d5c97177ae734a17fd8b @@ -99,7 +99,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f -F ext/fts3/fts3_write.c 9e88111ca9f70e4079880d842c8323bffc4968b39ee38c0a75962a3485af9333 +F ext/fts3/fts3_write.c 13582783abedf905e6946ce95edff7103c07810fb03a9c3b40212d21a3efa09c F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73 @@ -110,15 +110,15 @@ F ext/fts3/unicode/mkunicode.tcl bf7fcaa6d68e6d38223467983785d054f1cff4d9e3905dd F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7 -F ext/fts5/fts5Int.h 5c26dce0ec9272fca726c6fddb92f634d0c912d4ca170330270d488a94b80416 +F ext/fts5/fts5Int.h 0ec19a906a54c0e53f8a380c0ff70f11a866aa259490bc13aa39f8d2491800fd F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70 -F ext/fts5/fts5_config.c d7523cba5e66da077233c023aecbc3e6a37978ff75a18131c5ab5b1229d5bac7 -F ext/fts5/fts5_expr.c 840c88d55e78083a5e61a35968df877712ae28791b347eced1e98e3b337d2d3c +F ext/fts5/fts5_config.c 606a29f2962a8f4508923e6ad833974b32a3ab4093f63fd6de0fb33a87eed54c +F ext/fts5/fts5_expr.c 5661fe64f4f5a499710df9561075de84b743f01e808af46df4130a9ec343a0fd F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75 -F ext/fts5/fts5_index.c 5a89e0341297fade9a8f2c7aecc1ebd2e7e0989da84ece4d287a153da73cf0e6 -F ext/fts5/fts5_main.c abd04720e2729ba5bab2648d9d541faab18f45d481ae21fc30f125b55e979d6b -F ext/fts5/fts5_storage.c b24f6916fcdd68989a549f25962f286bdba9d9d59c7581567a6a0eb647cd07cc +F ext/fts5/fts5_index.c 6601d085d8e8cf4750ee49e2e1d18907582cc0aab78233d3b21bc240ba76a199 +F ext/fts5/fts5_main.c bf637030722badf06667d28f7159e4c209dbafd7aa76c33f387104b78ad147e1 +F ext/fts5/fts5_storage.c 801b4e3cd33786a60a07b6b01f86d0fbdf7e68325054e08d17176293a8081e99 F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7 @@ -154,10 +154,10 @@ F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f3 F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4 -F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116 +F ext/fts5/test/fts5content.test 9517cc527a8e8a33949652d5c7b5e251f8c3d5ae3f23f01d4320e30f29a0336b F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f -F ext/fts5/test/fts5corrupt3.test ee32b76e1b4beae8051f0bd5bc9cc9609667fdaed87886eda69b96b305d21897 +F ext/fts5/test/fts5corrupt3.test e188a43cecb3ff53b6236f862f82b2ec36962b9e39f20cb620dfa07aed70afa4 F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91 F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775 F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e @@ -176,7 +176,7 @@ F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd1640 F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2 F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119 F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c -F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e +F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5 F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079 F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2 @@ -189,21 +189,23 @@ F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc27826807405 F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35 F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6 F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2 +F ext/fts5/test/fts5misc.test 9a7263add42d55b8e22fc6ebbee2904390e923f4aa11d05fffaf617032f95db5 +F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581 F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45 F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd 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 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41 +F ext/fts5/test/fts5plan.test 771b999d161e24fd803ce0290adb7c6e7c9b9cc2c6a0adb344813fb89473aa32 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/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728 -F ext/fts5/test/fts5rank.test ca5000241924ecc2882db33c60f4f3a62b1ee6b16b5a9c8c6ddd9b6b2138489c +F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee7e017ce46f2416 F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7 F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415 F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6 -F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72 +F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0 F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb @@ -229,7 +231,7 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt a295e91db742b153e8dce8f7efd31d28ad1eea4df31ef4daa3eedc85be2f5138 F ext/icu/icu.c c2c7592574c08cd1270d909b8fb8797f6ea1f49e931e71dbcc25506b9b224580 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 -F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad +F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013 F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86 F ext/lsm1/lsm-test/lsmtest.h cf58528ffe0cfe535e91b44584e2ec5fb1caacdabecef0d8dcf83bf83168bf28 @@ -269,10 +271,10 @@ F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678 F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62 -F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655de79ae +F ext/lsm1/lsm_vtab.c 169bfe7ef8e6c9de9c77e17c4c50c9ae55fb0167d80be3d1be82c991184b6f35 F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82 -F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422 +F ext/lsm1/test/lsm1_simple.test a04d08e8661ae6fc53786c67f0bd102c6692f003e859dde03ed9ac3f12e066e5 F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0 F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240 F ext/misc/amatch.c 50a9ef2d38dabfa371f8c1904097d493271e63d58ccb0e9b79a4fa4a94e66660 @@ -280,7 +282,7 @@ F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a2 F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2 -F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 +F ext/misc/carray.c 91e9a7f512fda934894bed30464552fffa7d3073b5be04189ae0bd0c59f26bfd F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243 F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 @@ -290,10 +292,10 @@ F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287 F ext/misc/eval.c 4b4757592d00fd32e44c7a067e6a0e4839c81a4d57abc4131ee7806d1be3104e F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f F ext/misc/fileio.c 288e7230e0fe464d71b0694e2d8bdd3a353118ac2e31da3964b95f460f09915f -F ext/misc/fossildelta.c 5c04d0a5657615daf4c6cd01c4281de8983dd28f6eed592b2691c10e3f6710e1 +F ext/misc/fossildelta.c 7708651072eb5620ab21bbfb518d184f27b2c29c0131b09b9a2d8852a8016430 F ext/misc/fuzzer.c c4e27daf41433a64cad5265cd27dbcb891147e9994d0422200ce81ce9a54b625 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c c99b5f04fccba87c1c8c5ab5c0e53eef37c0144086e33911290a67dfba541d59 +F ext/misc/json1.c 66ccdfa63283adb2c015019b431eeee1f5af40a78d9aad10afd22c2c6db0e3b0 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 @@ -302,7 +304,7 @@ F ext/misc/nextchar.c 279f80fe8ef5ba413242e2704e246503ac601f005eefb180d19e6c9203 F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c F ext/misc/percentile.c 148dd07286b16e50f232bb638a47850085ad37d51f270429905bd865e595d1ca F ext/misc/prefixes.c 7be86d17525cfae6ed462fc3c519efc44488ac329890f77491c8f82871f57e17 -F ext/misc/regexp.c 79345bf03496155a640ee0300d3307296761cebb5e115b4e342cc2fb5861ec10 +F ext/misc/regexp.c 653b6ab5e89bcb5d45f9ebe0747d7f8f3f5706cac963fcbc9a3ddbe5fdc1efa2 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77 F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad @@ -345,6 +347,7 @@ F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68 F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41 F ext/rbu/rbudiff.test 156957851136b63c143478518dc1bda6c832103cdbe8ac1d7cdd47edb3cbe0a3 F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20 +F ext/rbu/rbuexpr.test 10d0420537c3bc7666e576d72adeffe7e86cfbb00dcc30aa9ce096c042415190 F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8 F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1e73fd3d0c F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179 @@ -352,8 +355,8 @@ F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204 F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9 -F ext/rbu/rbupartial.test 1c8bd6d42615b94caf08f129f5817fa26975523f0f51bceda1dca90e8114c7c4 -F ext/rbu/rbuprogress.test 04614ff8820bab9c1ec1b7dbec1edc4b45474421d4fe7abbd2a879a9c02884f9 +F ext/rbu/rbupartial.test f25df014b8dbe3c5345851fba6e66f79ab237f57dc201b2d5f0dbae658ae5a4c +F ext/rbu/rbuprogress.test 857cf1f8166c83ef977edb9ef4fc42d80f71fbd798652b46ae2f3a7031870f8d F ext/rbu/rburesume.test dbdc4ca504e9c76375a69e5f0d91205db967dcc509a5166ca80231f8fda49eb1 F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926 F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8 @@ -362,7 +365,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 8741c0ee1496b41ff888b983a1a32547bc8822602603c68b3e524e5e0e287395 +F ext/rbu/sqlite3rbu.c f3a3e09f575157052813be667d6ab3b54f47fb02e6e1c9f767ad7bb8f1fb90b3 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -376,7 +379,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350 F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/geopoly.c c591164125808f8bba9659e92665b78412cd263e654b6f05294f3a8da7cdd9fb -F ext/rtree/rtree.c 78c0d989c32e5baac471f0463e83cda5006c7e71ded39d633b5fc001a301a26e +F ext/rtree/rtree.c f8d9ea7d988c1002bff5acfac77d188f2f5d9eb025f24d5038a3d70a9c3f3d9d F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 7573134f1b4f59df36c1b0a6de51268fd3b9c714d91f3811482263e734e416ea F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -400,7 +403,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 836d87653851ae8e7b506d8bd3d62329548adc48ff9bc0a9051efd576710be7b +F ext/rtree/rtreefuzz001.test eef1ed593bb15886cd5d5367a2f2492f81e315848896cdf7afb6e21454978827 F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff @@ -435,7 +438,7 @@ F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b295 F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810 F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5 F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d -F ext/session/sqlite3session.c 3d9d3a414be386b87d83e642f4d93c8cbe83fe7b975d17b398f96caa1bfdc2cf +F ext/session/sqlite3session.c a4dfb372f270df93422b0dc7666fd46849e6979b62a152f11287c21eed4ac21b F ext/session/sqlite3session.h 919be6649d39d6413ce7a63fc3e3bca3270e18bc2d57ad4040a70007b9e54397 F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 @@ -444,7 +447,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 125adda36bb32c99dc3a11340bd029ef373b9523eac2b2af76087bfe82d4fdf8 +F main.mk 09716d345766a55b25ed157b14786526cf67c761c61d99c53e117196fb3b391a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -456,37 +459,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c c1b5e5639b88dcc146db326315f2dea4f7f1c599e524eeb421d544927a0b1e86 -F src/analyze.c 58db66344a5c58dcabb57f26696f6f2993956c830446da40b444051d2fdaf644 -F src/attach.c 78e986baee90cb7b83fb9eafa79c22581a8ada14030fd633b0683c95cf11213c -F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df -F src/backup.c b1d37f6f7f5913944583733ed0f9e182f3ece0d42c27f46701142141a6e6fd33 +F src/alter.c 5773b28684a001dcab45adcefa3cbf5e846335c0c8fee0da8a3770cb0123bba8 +F src/analyze.c a3f4ea45cdb4e9df78d4ea7beb87ec8a7a46f494173b641cd28512a40a97bff2 +F src/attach.c 3ca19504849c2d9be10fc5899d6811f9d6e848665d1a41ffb53df0cd6e7c13ed +F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 +F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 1dbc191e5c1d9bca84a956fed5d73924c574ae5390855009f067bd0f6422e462 +F src/btree.c fdc4389b271bca30138db27dc2dfb9f52c2a7baaa44845aaf31a3c54663d837f F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f -F src/build.c 23a0253ab53e62feadcc0c6f31e7e418ef9d4b92c82a1398e98433776b920a4e +F src/build.c 4814d55abb5553ac82763f6df9e185503d913f912cc0abea00965bb02912cc2d F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 37f3d21193c4f7d141d0691cced5b39c99951bfef78df9887faf9167b9c42f37 +F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251 F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf -F src/expr.c 2756d2875ac5b7a7efcc54edea3c8a31f4126684ded18da6fb406f4d3780a5f5 +F src/expr.c 18974550063a6a1c8eef69e63d2ad88ceb4395ef139a60cc0d0a28632f41d553 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c 0e14d4bef8eac2d87bbd517e492d9084c65008d117823f8922c5e7b2b599bd33 -F src/func.c 905c0424900979fade3731b4a271592059425c988cb7d5b245032253712dd7c8 -F src/global.c 1e942b1e6fb6a2a15e6015bda72be0abefc4b1339a8640a47b1b71b7f317917b +F src/fkey.c 6b79f4c2447691aa9ac86e2a6a774b65f3b3dd053d4220a4893051a0de20f82e +F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12 +F src/global.c a1a8d698762ddd9a1543aac26c1e0029b20fcc3fcb56bfa41ec8cea2368f2798 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c f20925c2c08144442dabeb73dcd0f5026f5f085d827f3d5635f7c45e5d195320 +F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa -F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c -F src/main.c 591a0084b1a6b0ed6741f77181bd1a630ca10bb460420f00e8c11809da7df5b9 +F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d +F src/main.c 3851950717170ade4f6d718c18c6c7400ef5994c2a654679af2cff2ffd0fb2b9 F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -494,45 +497,45 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memdb.c 02a5fcec19b9d40dd449ca802dc1b2e8f93f255fbf2a886277a3c3800d8d35db -F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 +F src/memjournal.c 7561c01c90958f3ba9bc6cb2d857123d932bdfa5539ea34427a0957b2e35154d F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8 F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604 -F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 +F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58 F src/mutex_w32.c 7670d770c94bbfe8289bec9d7f1394c5a00a57c37f892aab6b6612d085255235 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 -F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de +F src/os.c 20f7b32c1e8839999fa7e79756a6cdc3041b44d7fc635c25a1b9399180d1fbd9 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0 -F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0 +F src/os_unix.c a76a75f179cb233d54e505c3e0c84832224cfe5dfb3ee470bdcaf1ed29da57ab +F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 -F src/parse.y 026e3e6fff32432166a4eae0bdb78ad09a53c84eb49acb44dc32e49b4c0b8a48 -F src/pcache.c fd2d0553b3222d6b9f7cb251079e5bca1299d1161da3027b525932d8bf46340a +F src/parse.y 50bfcb34be7320dd0cb875021a93ae6451c8f0b083f21b71934a1a3a9108015a +F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 -F src/pcache1.c e6373934cdafea272d94feb224344f9fd93ff94318221b64ccabd72d98b4672e -F src/pragma.c 925bcac0afd98a0d4255c7524b93239ab4d83893d96f7f8fdccd78d4929a39bb -F src/pragma.h 4a9fabff14db4487a734dfeeb4be984ce662bfdccfae16145b9c732327735e13 -F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3 +F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848 +F src/pragma.c b47bc7db02ab13d04c680aee424466b4e34f4ef5aa7b2e464876ec005806f98f +F src/pragma.h 40962d65b645bb3f08c1f4c456effd01c6e7f073f68ea25177e0c95e181cff75 +F src/prepare.c 132484635a30f873ee7eccd47f93ed1932503863b93b28423b42332d81adffaf F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 93b7bc7c45efa6322d92293361c51a873690daed50cf77eeff88a448246b0d5a +F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 62f21307b280791c50554c9fa3766758dd695ed66a05d2408d213355c7b0aa89 -F src/shell.c.in 82f8a473c01662f52233c6c75b9bf88d0d2cab276086d5d4ca6f2ff57a3e48eb -F src/sqlite.h.in 83ebc8ab1a2e82d92214006ea2c15bf8a0604f3fac2c31dd9ce9021f568c71f2 +F src/select.c b3d64a7a3342471ce078251c5ba132f8ec66f994534f1070dda025b354a09a62 +F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274 +F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 -F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5 -F src/sqliteInt.h bf65dfa6565fae2e0d501088fc9c5212244adc1429a543827a16b2f5eaf41982 +F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31 +F src/sqliteInt.h b8cabe8fcef93b7251422db41903c04abb4052df015eacb886dabd496fc3e0e8 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c cfe7f93daf9d8787f65e099efb67d7cdfc2c35236dec5d3f6758520bd3519424 -F src/test1.c f57c229ad7878215d0b3bb5d59ffe94772c099ce5b5e147a4a59d3157923a988 +F src/tclsqlite.c 50c93be3e1c03b4e6cf6756e5197afcfe7f5cd0497d83a7ac317cde09e19b290 +F src/test1.c 17e1395cbddeb9226b756d723a7566b45b43b99a5f9f55afb4ff70888de6ad6f F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb @@ -547,13 +550,13 @@ 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 5ebafbcd5c75ac1c16bb0c8fe926dc325cc03e780943a88ca50e0d9a4fc4d2f5 +F src/test_config.c e25826d693039cdd45963de378cbf39e3af0e8aa7a8a6fc159876f4e7b5a4f8c F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91 F src/test_devsym.c 6109b45c3db3ef7b002320947ed448c027356ab8b885156ff535fd8684d4a571 F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480 F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276 -F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d +F src/test_hexio.c d170d0e1a6431afdeac086a250d2595078288c2257615d37949355361399bcaa F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664 F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71 F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7 @@ -587,40 +590,40 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e -F src/treeview.c cf03f9f6efb93288c7b9f17374ea48e4ce9111b0bc7e428d6850c3eee532b461 -F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73 -F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2 -F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 +F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5 +F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e +F src/update.c 7f05fad5e145248a00048aeb0bac78b8fdb4ed17216e14a6eb24c55596e87ee7 +F src/upsert.c 710c91bb13e3c3fed5b6fe17cb13e09560bdd003ad8b8c51e6b16c80cfc48b10 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 -F src/util.c aef606a78b85d042138a841babbc0f98471b19b9a340b962e8fae307bc8cf3da +F src/util.c fffdfa627be74d69ef425f92db124e7148af449bb8a3286e79577c42bca84061 F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf -F src/vdbe.c aaa36d1ac7d55baf007e9c03ee7c826834a51dfe7a56ba4c386318695dd87c99 -F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237 -F src/vdbeInt.h 3ba14553508d66f58753952d6dd287dce4ec735de02c6440858b4891aed51c17 -F src/vdbeapi.c f9161e5c77f512fbb80091ce8af621d19c9556bda5e734cffaac1198407400da -F src/vdbeaux.c 3a803d75875031309204df90977059b12ffb706d16b4baa5e2d99f4353962582 -F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 -F src/vdbemem.c f6f277d17d50972571d1394535d4c3d156fdea871d8f327f5b9479984054015a -F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47 +F src/vdbe.c da4030a71acf42be18001b9b7067d6d34ffb76610603ce6fafa52854b9e52936 +F src/vdbe.h 3f2b571e702e77e6bf031f0236e554aedfae643e991f69000320f481408455cf +F src/vdbeInt.h e95de5129124d77f01439e6635012adfaf23c0017bff47296126143cf18bd0c6 +F src/vdbeapi.c 95001d0f84ee3cda344fed98ca0d7961deb4fc836b83495630d0af1f7cc4789e +F src/vdbeaux.c d17dfbf1e03ef706cad9e2076c7f2354882c191a84e73e00c69c50bb7823e5ce +F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1 +F src/vdbemem.c d8e10d1773806105e62094c4ede0a4684f46caaf07667a45e6d461e94306b530 +F src/vdbesort.c da75f505aba230060ce6472605a4aa6494f73eeb1071e1cc2643c3d4035e671b F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0 -F src/vtab.c 1fa256c6ddad7a81e2a4dc080d015d4b0a7135767717d311298e47f6fca64bb3 +F src/vtab.c 5a0b7193d586991b3db30e343d6b59959906bfe8658a6a0a85709b20ca50bb49 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c b09a2a9cab50efa08451a8c81d47052120ad5da174048c6d0b08d405384abdf2 +F src/wal.c bbd6838bd79c0a32144d482fb0b6a9d2d1a252fb3b16d5005ec30f2f80413b0d F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a -F src/walker.c 7607f1a68130c028255d8d56094ea602fc402c79e1e35a46e6282849d90d5fe4 -F src/where.c 2f11eeb14335b7640f886b2fb441f54a94c35ab5cde8b53461a1074bfd587081 -F src/whereInt.h 1b728f71654ebf8421a1715497a587f02d6f538e819af58dc826908f8577e810 -F src/wherecode.c 37a1004237d630d785c47bba2290eac652a7a8b0047518eba3cb7c808b604c4a -F src/whereexpr.c 5e559bdd24b06e3bc2e68f258bf751302954dc1e432daf71fdd8098a71462326 -F src/window.c 3408c0f606574d41033d461506bad68790239844b23e70610738a71152873d05 +F src/walker.c d5a94907dcac990e31976be9dc769d17f6a806782593d6aec9d760ee01ec22cd +F src/where.c 9f3f23efc45934e7b7ea6c0c1042420b73053e7c3264feef6faf9ce6fbd5df61 +F src/whereInt.h 2c6bae136a7c0be6ff75dc36950d1968c67d005c8e51d7a9d77cb996bb4843d9 +F src/wherecode.c 535c8e228478fd971b9a5b6cb6773995b0fbf7020d5989508a5094ce5b8cd95b +F src/whereexpr.c 05c283d26aa9c3f5d1bf13a5f6a573b43295b9db280eff18e26f97d7d7f119b4 +F src/window.c 064f251451c8e2a1c76b6269229d911a651e119c6a5f522b6eaebf8dc8714041 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 -F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd +F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 -F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1 +F test/aggnested.test 12106f0748e8e9bfc1a8e6840e203e051eae06a26ed13fc9fd5db108a8d6db54 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13 -F test/alter.test 93dee7c0ff9106fbd53a8bbf519107904b884050a99c4565412c58c37d68c802 +F test/alter.test 16ed8d2470193f34bc711e51506ff1211ebfab8025ca3b9510ff2aef139874cb F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 @@ -630,21 +633,19 @@ F test/altercol.test 54374d2ba18af25bb24e23acf18a60270d4ec120b7ec0558078b59d5aa1 F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b -F test/altertab.test b6901287474841cffbd8f90b098d3bd7d8445868b42caeb01b27034698f7245f +F test/altertab.test b2004ac589207fed7e19877bc3f1ad65142be482f269c176ee407e3b4a65f1a0 F test/altertab2.test 8883693952f6d7fb5f754dbf1d694ed780aa883027bef04cb1fb99a3b88c9272 -F test/altertab3.test 7a2419829b2b908985b2c83d680388ef2eb9a74e446b68cee7b9b1551ae69078 +F test/altertab3.test c755ef31f8a61911331b46d71e43f6f3ef94af05c56314b168e47520355fa18e F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f -F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c -F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 +F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7 +F test/analyze3.test 01f0b122e3e54ad2544f14f7cc7dcb4c2cb8753cad5e88c6b8d49615b3fd6a2b F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e -F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 -F test/analyze6.test 7b2667b879976ac4b90d8df80d5456328684f1f6f6fdef9469d6e53401f2f469 -F test/analyze7.test a37f4d9cb699a8af068ae02df1bb08bf844df8e98a92a8126cbff89e226879d8 -F test/analyze8.test e32a970564271114786703750e6939cf81dea4b8580874e38e9213ee092f6936 +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/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc -F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70 -F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 +F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46eac710 F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb @@ -663,7 +664,7 @@ F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3 F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438 -F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e +F test/auth.test 2154625c05bc79f0e0ea72cb2358395a8041243caa0fd7ce7617d50da4331794 F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec @@ -725,9 +726,10 @@ F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bc F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 3619f0c58c2e4b2a94aa86e75607e497d34ef40ab74418e71aef7b4ca5155895 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef -F test/check.test dcc952a127c394ce0de2aa634d26c78207e855327cc63a24d3638ca8fbfa641e +F test/check.test 4b57ecbbb300336382ca21ef983dfa70b291a70ae430690494d13f1629f45a38 +F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014 F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760 -F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8 +F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 F test/collate1.test f9b653f515ef3324a0c4e3c6adbf136bb1903622af678d482a60c11c9c054e6c @@ -742,10 +744,10 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 -F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d +F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e F test/conflict.test c7cc007e2af151516ddf38f7412fe10d473a694f55e3df437e2c7b31c2590e8d F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c -F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 +F test/conflict3.test 56d18aedfa521a7ebffadb8254cfff10caf4e49cd8659cb54da39513aed478ba F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3 F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35 @@ -767,7 +769,8 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af -F test/corruptL.test 15882a75d06de29df9ad33a3503eb0fe21efbd1afcd676949c0d82e1f4e55360 +F test/corruptL.test dfad96373bf9264d73039315ea6013994b90bf6776847adc7ec06b6fad3c04b2 +F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067 F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86 @@ -793,11 +796,11 @@ F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10 F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e -F test/dbfuzz001.test e32d14465f1c77712896fda6a1ccc0f037b481c191c1696a9c44f6c9e4964faf +F test/dbfuzz001.test 42aad1dcef6219fbee86a9b7d08832c9bbb2e41508f6f128ae91745927276292 F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee -F test/dbfuzz2.c b93db9056ad057733463ba333f89d2d195a95155805065c5962422955d7fb011 +F test/dbfuzz2.c c2c9cb40082a77b7e95ffb8b2da1e93322efadfb1c8c1e0001c95a0af1e156c2 F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38 -F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e +F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759 F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef F test/default.test 3e46c421eebefd2787c2f96673efabf792d360f3a1d5073918cbe450ce672a62 F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0 @@ -810,7 +813,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c -F test/distinct2.test df0bb52b754661ea84ec9ff488d48913c97bd31d83ca17ce0bf1334645e660cf +F test/distinct2.test b854b442111bf362328981f55d39d0df13140383b112057f6e046e311f14e5c3 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05 F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d @@ -856,6 +859,10 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717 F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3 F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4 +F test/filter1.test edd797ab2ef38de16064c9e3945efd941cba72d27e8f070c349501ff95d2727d +F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8 +F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a +F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768 F test/fkey2.test d35d1c81e7569bdd2b872e91750f7098117d2e8291369f70b7e3d50a0e523dc2 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 @@ -863,7 +870,7 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0 F test/fkey7.test 64fb28da03da5dfe3cdef5967aa7e832c2507bf7fb8f0780cacbca1f2338d031 -F test/fkey8.test 1d44df25d3b9cba72db4b4324201daf6ae1fc8a85cb68146bd6669a977d8867d +F test/fkey8.test 48ef829d63f5f7b37aabd4df9363ac05f65539d1da8c4a44251631769d920579 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb @@ -930,8 +937,8 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f -F test/fts3corrupt4.test c311911898e9ddac93fe71b947660a9716b285e2e600ad02810c231ff79a5925 -F test/fts3corrupt5.test 1911bd38381fe7eb28b204e7171937d09e113e5ceb018399ded9f42ec7e6ae66 +F test/fts3corrupt4.test 545c50e70d1fe922b6efef12019a92829832f52993c5421086489ce72bde2251 +F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5 F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338 F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de @@ -943,7 +950,7 @@ F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c7 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 F test/fts3expr4.test f5b2832549f01b1f7f73389fa21d4b875499bc95bf7c8b36271844888c6a0938 -F test/fts3expr5.test 1368738e3298a7ce0dee3a44d6ebb8f468b2a76f3d1dd18d4ea6d8bc2eeccc1b +F test/fts3expr5.test a5b9a053becbdb8e973fbf4d6d3abaabeb42d511d1848bd57931f3e0a1cf983e F test/fts3fault.test 798e45af84be7978ca33d5bdc94246eb44724db24174b5d8e9b1ac46c57fb08d F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0 F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 @@ -960,7 +967,7 @@ F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba16 F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e -F test/fts3snippet.test dace744104d1a44dc12dc9dd10b8d7542342df503d96942b7c4a55034e761789 +F test/fts3snippet.test 430bb5ace2b31ccd99de4d71775d956da832c114c4b3e39589748f114458647c F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d @@ -978,14 +985,16 @@ F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b +F test/fts4merge5.test 69932d85cda8a1c4dcfb742865900ed8fbda51724b8cf9a45bbe226dfd06c596 F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7 F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a -F test/fts4rename.test 6015a355ec3a11a51eb5b88802b3b2c1788786c54b77b17f3e077b7c93ff8611 +F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb +F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3cfd0c880 F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429 F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test e4313baba80bf933e58eb89a7c617bec0f0c348c862b096ec4387f36e05ad0a6 +F test/func.test 0889128141b99b38aa9ce78445acfc4c1f9fbe9aa4f51d4c6aff88ae43cf125b F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6 F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f @@ -998,15 +1007,15 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 -F test/fuzzcheck.c d0e76671ea5c3a766768b65d69f7d755aa614a98c17b84fa4496f4cd2e2fa515 +F test/fuzzcheck.c 3ad76298a80cda31d270dc5e4f31194fa38d507d3e9b3f355cf1c283895cd5a5 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 -F test/fuzzdata7.db babb1c560fef766171972c119c1bc3b7be20b134e2f46ae0c52390cd3059b6f4 -F test/fuzzdata8.db c69ca6d4bf1b25fd56ab432e9b96f2db0da752cfc6aa32700867f3a2d8a0514a +F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac640639711 +F test/fuzzdata8.db c75b0fd1d28c262f9c3a9428393ff9c420ea5bdbe0b33c557a971915a94bab71 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -1020,11 +1029,11 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8 F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 -F test/in.test 63e642e97bc22c8fd970752fb4f0b3992a957003ea87524fe69e5a700500c500 +F test/in.test 3e9bd58597a444123a40a9ac94cae0fec8897e17e9f519b02fc370bcf5ba5175 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 -F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 -F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08 +F test/in4.test 0f77b0ff371549e6a119d0356be10bdba72258162e9701e83527a560482f5e98 +F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f F test/in6.test 62d943a02f722948f4410ee0b53c3cb39acd7c41afb083df8d7004238fe90a20 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f @@ -1042,28 +1051,28 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 -F test/index6.test a6cf96bb70bf57b2221e102060a18af46bc366f704722f410d6f42c13a75534a -F test/index7.test 2222ccd1858097f734d6ac3d39117334fd1cc26460f92fced4ef57cd15c940c1 +F test/index6.test 4d1dd3cab97fba2ddf30bb70afc82eab35bd6e61788b3ac941e55263f81ef7e9 +F test/index7.test 1d764c0cca45f5a76150b08e127ccc8d52492cfa788b5fafed4be784a351b020 F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e -F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test d319e7d1b1043403f39a20c892d512e02b5549c6004806b977030f2430c60208 +F test/indexexpr1.test c26c8b352311c1deb30642cd0379e5cb94e416c7e9e0885e92d9e01554df2db9 +F test/indexexpr2.test b580f378423bca443ffab47ada677203cfcf8a60f48a8aa20065f27c8f7739b5 F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 -F test/insert.test 9773604f8e1a2595f51488a5643c359d8a11dc55a11cb185910d93387d378458 +F test/insert.test 72004f6a900a25bd3f1ce9a72e73d02749644666a8ce6d6d2dba061137e5aa63 F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30 F test/insert4.test 7802ada6ba8738661b9f6c0e26858d3375b40cc7180289fd350644cd7a08fec9 F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74 -F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba +F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4 F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a -F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7 +F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440 F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054 F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8 -F test/intreal.test 2c80b5c90c597e65c6606b333515261c73a534b6c527b7009e97ed6b78f8b79a +F test/intreal.test 2a87e85a5949bd55e41ef04c58f5800587c5380bdbc559ff1c79b614b0e6a533 F test/io.test f95bca1783b01ea7761671560d023360d2dfa4cc F test/ioerr.test 470fcc78e9cd352d162baf782fe301ea807d764241f58a48fc58109c2dfcdb6b F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26 @@ -1072,7 +1081,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a -F test/join.test d53a3662762eff50b65da8775201e609878a27dd0885a1ae7bcde9bb46cecbc5 +F test/join.test 7610c1818f8921618279ab633fc03c93d54f6c8fb9e9e7e96b252319ece346d4 F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 @@ -1087,15 +1096,15 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test 8f8977b00ba02f9a26c1d1f52f29f540f6d5eb162cbd5eb78bb805366d4ab26d F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b -F test/json104.test cf0dbd220cba81e6c3cf8bc326e2321049cec05ab0b529308d76f28a52529800 +F test/json104.test 317f4ec4b2d87afbba4d2460cf5be297aea76f2285eb618d276dbcd40a50950f F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7 -F test/like.test 5013f18e7242fe118524fcf8e484b8827bcd5906b509d106f3587c7bfcf274ae +F test/like.test 3d702d79bf871fa32985b1ce334294c587e3948d3ab972001e811a58577e8b3c F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da -F test/like3.test 62bf82ac674b7d4126e73532e1ad96cdcd8e1752a4ed90b28a6f98305f5a66aa +F test/like3.test 4f940ad275c006319950054a7a65661f476772171b82b6fdf795e4dda36f246f F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04 @@ -1119,7 +1128,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e -F test/mallocA.test 672cd7dedb63771bade3a6f557f851a4ad161d4a +F test/mallocA.test aea76f2dd8bcc2d19748f6b911e876cefda74a563753bf26af046e9d34bb97e6 F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6 F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4 @@ -1145,7 +1154,7 @@ F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41 F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063 F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 -F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f +F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87 F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d @@ -1177,6 +1186,7 @@ F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 +F test/nulls1.test 725fb4d99db2ddcce59ca6bf847cd92db8f1af861785918892f84ac3bcd4223d F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823 F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2 @@ -1193,6 +1203,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859 F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 +F test/orderbyA.test df608e59efc2ef50c1eddf1a773b272de3252e9401bfec86d04b52fd973866d5 F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6abbc5 F test/ossfuzz.c 18af635fa73d12a109b305faca727a734c1fa28a421b161d9d15c5a84a4998a2 F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17 @@ -1210,13 +1221,13 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 4282fb00e5ac0f8c2cd1be62652f6da4ac03ce3c58b7d785fa17f4684492a0e0 -F test/pg_common.tcl 4740dc35190d6acdab14c097783331361301ab504a94d948f6afbb56ce0a51e8 -F test/pragma.test cf066fe0f7f5d49f4758de4986407b8676c61aaa7871599340d64f42a8edc352 +F test/permutations.test 8587800fe1a0eb01456a3f4500b821e54e3347e78acf11dbf05f4990530f6cee +F test/pg_common.tcl 222a1bad1c41c308fa366313cd7b51b3be7e9b21c8736a421b974ac941693b54 +F test/pragma.test 59becdfd720b80d463ab750f69f7118fde10dfd556aa5d554f3bf6b7e5ea7533 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 F test/pragma4.test 1cb4b32f1a304ed9e291d7c4d49c91c2c8dc1b9450e6d2c1198b2cc895d40d77 -F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 +F test/pragma5.test 2be6a44c91e8585ccb4c71c5f221ccebe0692a49557215a912916ed391188959 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9 F test/printf.test 0300699733e53101b2ce48800518427249edd4053bb50fa0621c6607482f0fdb @@ -1238,8 +1249,8 @@ F test/recover.test ccb8c2623902a92ebb76770edd075cb4f75a4760bb7afde38026572c6e79 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d -F test/releasetest.tcl 968fc1e8fd23e113fb8a04379747f3a9f2c12d207b2de85aeff5a825962e1cd7 x -F test/releasetest_data.tcl 146a73e8c8212f962b6558fee0711b895f11b607ee0610e6910781dc8f83797d +F test/releasetest.tcl fb76d8fcc95ac29d6356cd9e52b726ab9e43a24082897618dfbcb7c2b0049153 x +F test/releasetest_data.tcl 9919fc6ac5bc92f8878fecfd1840db15999f660a6c9f609240b41aa62b885c88 F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa @@ -1249,13 +1260,13 @@ F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3 -F test/rowvalue.test b8680f07d19c8c5223b808bba998faffcec6d505f5689ff6070280119173bb51 +F test/rowvalue.test a3e729d5c1f32da03bba15af1e3128218d2ba3c40d4f4ed5fa0497a713df68ea F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256 F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356 F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6 F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087 -F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8 +F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0 F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504 @@ -1269,7 +1280,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2 F test/scanstatus.test 874e35011779b07725a47dbf1dd6282b0ca04af7e028fb0b534ee544b571be42 -F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 +F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38 F test/schema4.test 3b26c9fa916abb6dadf894137adcf41b7796f7b9 @@ -1278,7 +1289,7 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384 F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 -F test/select1.test 7d41f354998524070317207d4e2b68e725e4cf14a57835fc746d4bea686a8714 +F test/select1.test 703154cbf66d0a9fbbd5b771dc3d2c4d3700121d133d695958d4a9c5a33251e8 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 3905450067c28766bc83ee397f6d87342de868baa60f2bcfd00f286dfbd62cb9 F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328 @@ -1323,7 +1334,7 @@ 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 b1fef3046d555836712d4a3a7c8ae8193356c6a15bee59cb3976e4ee98596c97 +F test/skipscan1.test 2a64ca7b3e6246bb86b47c9051bfd324603b1b60675fe606513535267713e080 F test/skipscan2.test 3eb703ce794f139e7b83567911046298bcde29606116727f9b700ce34f559d2d F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 @@ -1383,9 +1394,9 @@ F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90 F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132 F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 5a06962d8f18edf4703931f6b7dacd83678d02fa5c8ced9a7958c007ad58626a +F test/tclsqlite.test f9acb83122be0a7c4997ab7f17742507874dced95144c20217c2428553f110bb F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08 -F test/tempdb2.test 2479226e4cb96f4c663eccd2d12c077cf6bda29ca5cc69a8a58a06127105dd62 +F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a @@ -1406,6 +1417,7 @@ F test/threadtest3.c 38a612ea62854349ed66372f330a40d73c5cf956 F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925 F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90 F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c +F test/tkt-18458b1a.test c543c4b8e8c7c2200579a635e72c15bc374a92d44eddb1d588d4fdeca9cca532 F test/tkt-26ff0c2d1e.test c15bec890c4d226c0da2f35ff30f9e84c169cfef90e73a8cb5cec11d723dfa96 F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2 F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0 @@ -1415,7 +1427,7 @@ F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1 F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678 F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7 -F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8 +F test/tkt-3a77c9714e.test 90e3e8455ee945a4076d4c44062b8845708af24a880355328fe7008f2047c9f0 F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70 F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0 F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a @@ -1441,17 +1453,18 @@ F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667 F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6 F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4 +F test/tkt-a7debbe0.test 65a647034e3416d068f81e7d86fffc07edfae371c70b8761714edb56ec1c7521 F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72e0d32fac73e F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3 -F test/tkt-b75a9ca6b0.test 1bc0381538fd21f96a10dbabc10ffc51b5b2e5f412d34bae571273ca784003d7 +F test/tkt-b75a9ca6b0.test ade89229d853a67a21bbd5e6e1e787a8f9d21f19908d1b7fca6bf3d4d5aa0767 F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877 F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898 F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447 F test/tkt-c694113d5.test 82c461924ada5c14866c47e85535b0b0923ba16a2e907e370061a5ca77f65d77 -F test/tkt-cbd054fa6b.test 06ccd57af3c0c7895d0f7dc844f13c51f8258885 +F test/tkt-cbd054fa6b.test 708475ef4d730a6853512c8ce363bcbd3becf0e26826e1f4cd46e2f52ff38edf F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09 F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30 @@ -1555,7 +1568,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677 -F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61 +F test/trigger1.test 6be279c9d48b25320eab68c30fd5268ab787955679f4c584128f71800247fb50 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 @@ -1566,7 +1579,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41 F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe -F test/triggerC.test f1210921924f3a6aaa8c1538115fe56c9c448e8e3033bf0dab38ae78db937c41 +F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad @@ -1587,7 +1600,7 @@ F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981 F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60 F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3 -F test/upsert1.test 994bde41800bb77dbe32fcd2e1f6c4b49cc9f2c6cd345731c774dff02b51c110 +F test/upsert1.test 9b115320149e6d72db64511a373c522746c2a2156efdbdb52add33504f66c989 F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5 @@ -1605,8 +1618,8 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2 F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test 40d54c9ddf5b9fdee692bf936d3352159fe467838f92742aa1d08c7c7d1eac73 -F test/vtab1.test 47b935205d7b6290765973abd6fce0e13e94e040017099170f43f81886efa5ba +F test/view.test 10ea54300a097d7c0337fd104abffe4a4786d1598b94017a37efe0e0d3e04dd5 +F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1621,7 +1634,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b -F test/vtabH.test e65540eed0f7434cdf0b160374570b51f3e3179548f0fa5e99b1d33f8dcdf9a0 +F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404ca F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783 @@ -1662,10 +1675,10 @@ F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cf F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 -F test/walvfs.test c0faffda13d045a96dfc541347886bb1a3d6f3205857fc98e683edfab766ea88 +F test/walvfs.test f1accd66c876e3a0f6b4bef5b18d13411062d0ff0a0016e32bb41570474e99fc F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec -F test/wapptest.tcl 56d2b7974ecd8cca3189a670f757306d5ff3334cc9fe3744f7a6ad7ae4380e8c x -F test/where.test 0607caa5a1fbfe7b93b95705981b463a3a0408038f22ae6e9dc11b36902b0e95 +F test/wapptest.tcl 3cca775aede0591756a1fc0da55bbb3715d8c363873fd2cfdd4d555b0a4af57d x +F test/where.test 19c709c9f0f6ed12c23f909f6592aa55fba34269d5a2898537aa27a22b9ce650 F test/where2.test 478d2170637b9211f593120648858593bf2445a1 F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 @@ -1673,14 +1686,14 @@ F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1 F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f -F test/where9.test 4fb43ad451758d9535693e110d4398fb6a6e3e153dc57bba5e61f884566c725f +F test/where9.test 2c554b97bbdb2fdf26c57099f60db8a52bfcf7c147f2c256f9798fa0e267ca85 F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4 F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89 -F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52 +F test/whereG.test 4cda56de49f0c7d9a4f2590a3ddc5f79a7f2a03d2229d0f5bb5d3981ce57f293 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364 F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a @@ -1690,39 +1703,41 @@ F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0 F test/wherelimit2.test 9bf0aa56cca40ea0e4c5e2915341355a2bbc0859ec4ce1589197fe2a9d94635f -F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 8d453bfaa3f8f0873ba16ca1270c7368f18445065a0003a1b5954ac4e95797b4 -F test/window2.tcl 0c2918ef2a1640553fd791972d458356808a608418c64c02a0a379cecfc7fb0d -F test/window2.test 96ef949f0197c025652f6c6e5812cdbfb948989bd40cf79cbb02104249a89513 +F test/window1.test 453bb9dcb1b447eddbb4777c97620f02543a4375359723b7372ff09dcf847045 +F test/window2.tcl 66db96fd9fd202bc31ee7f8ce7904cb469564864cff3f74e009bfef8102333f4 +F test/window2.test af2a001ded703bb8f2474fb0edfef170d5aba00f5c1f2aa9f65935b5da13df90 F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03 F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb -F test/window4.tcl 5fbaab489677914ee5686b2008426e336daf88a2f58be7df92757f780a5ebf91 -F test/window4.test bf8f86586ce101bf98e2306e597fa24aadc96c58d70ba4d11f956cf8ca4e0be3 +F test/window4.tcl d732df0e81beedc0ba8a563ade68611d322d27303ad0c0c8e4444107c39e84ec +F test/window4.test 807f3e6b15f9338e5b9742b87c5c7ca825b42b9657fde6096e890119370848e0 F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e -F test/window6.test 465e608c021020fb0948a90200e154cd787bc910449e3dafee44c9ca5bd407fe +F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32 F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f -F test/window7.test ce7f865241fdd1c5c4db869cd7bb2986c3be836bc2e73649a6846dd920f63e0f -F test/window8.tcl 9e9a82ae9eea90a4a83481d641a812b974980c38f9247f3b89a6e3c8bed45518 -F test/window8.test df187dc19921f7be0ab709d531d681bd80ccaac96a913a89ecee8b272b91d43f -F test/window9.test 06495ac733843849b1fca8a79d13ba330d04aba02099703198af2ba7e231f90c -F test/windowerr.tcl abf4d6d0c6d360213af98ed7d538295d905689e83692106f3ece0e3afb9d7f36 -F test/windowerr.test 675b5e6debfc9370bfacb0b91e2a93a8923512f92600b16f4ea70a1cd9b8e6e4 -F test/windowfault.test 403693d7d951c5473f052f7ecddb61ed15ac9d212f238b8904ea270ba90f83e5 +F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd +F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2 +F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b +F test/window9.test ae8be07be05a5a4c8ead1818ac5d45f278b8dd456e589d67f24270b0070c35a0 +F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be +F test/windowB.test 7a983ea1cc1cf72be7f378e4b32f6cb2d73014c5cd8b25aaee825164cd4269e5 +F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0 +F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b +F test/windowfault.test a90b397837209f15e54afa62e8be39b2759a0101fae04e05a08bcc50e243a452 F test/with1.test d32792084dcb5f6c047d77bb8a032822ef9fe050ade07d0aeffa37753a05e3c9 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with3.test b5f1372097690c6ef84db2f13fc7e64a88c7263c3f88493605f90597e8a68d45 F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 -F test/without_rowid1.test 89d101a7c6e0802882002cf3713f405319ddb6b9f08449dcc08c6082c995cab1 +F test/without_rowid1.test 0abe18762b74714580c1d4d00a8e540e58966d3e46aae41ddb1a1d2c88c9277d F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a -F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e +F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e +F test/without_rowid7.test d7c59a93d726b55812d620f8f284e01904a5b85f9ee9eea8f2f68571a5e8c40e F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66 F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174 @@ -1750,8 +1765,8 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c cc43148d2793ab93668e74a6a6319bb71c2e65c1ffcd6deeaa59e12be9362a43 -F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc +F tool/lemon.c 61d5f0af1eff8f754b75ddca668c9897fd30759e389bfffb42ce9e4d38fd4746 +F tool/lempar.c eb2841e2a7fd484cf44b1f526b06e7ab0f216d2f41818bf9485e8f38e3d1db19 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1759,12 +1774,12 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3 -F tool/mkkeywordhash.c 537b1a11ec1829b51b633da3ba2cc889b4a3f7356b06a07423b6d4cce92c2350 +F tool/mkkeywordhash.c bc5bcc92ebcaf15345346be7cf2204b83ed649b5208234adb5e543c061209bbf F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 8250ef3df54aee09f6c6ed36cad390bb6dd20bbe71927d8bff069ed9fe0bbf98 +F tool/mkpragmatab.tcl f115d63ada8171f9da28dc8e34e043a1a159692d46b89f66b6e681140bc4683d F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1789,7 +1804,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec -F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6 +F tool/speed-check.sh 2b042d703a9472f08c3b13be27afac658426f8e4fc87cd2d575953fda86f08d1 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff @@ -1831,11 +1846,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6f328c35947d6b3a0741514757b8944692203e89bdb2e7f9bbce8ad9288be344 -R 3dc95c8af87e7b557da20a5426ebc03a +P c6cc2390e91097a32992d11c74af8e77a6a42862ec8a936b549e156250629407 +R 9b77b3da995b6a235a01d1e768df1101 T +bgcolor * #d0c0ff T +sym-release * -T +sym-version-3.29.0 * +T +sym-version-3.30.1 * U drh -Z 4d356946c4c6edd871b6d6986b095a05 +Z 6b715002b9e76fa6c3cf0c09f9813287 # Remove this line to create a well-formed manifest. diff --git a/manifest.uuid b/manifest.uuid index 3f05969..6238afa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6 +18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b diff --git a/src/alter.c b/src/alter.c index 3957ede..9d02d38 100644 --- a/src/alter.c +++ b/src/alter.c @@ -136,8 +136,8 @@ void sqlite3AlterRenameTable( if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ goto exit_rename_table; } - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto - exit_rename_table; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){ + goto exit_rename_table; } #ifndef SQLITE_OMIT_VIEW @@ -435,6 +435,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ goto exit_begin_add_column; } + sqlite3MayAbort(pParse); assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); diff --git a/src/analyze.c b/src/analyze.c index e6b27aa..1904b9b 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -27,13 +27,13 @@ ** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled ** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only -** created and used by SQLite versions 3.7.9 and later and with +** created and used by SQLite versions 3.7.9 through 3.29.0 when ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 -** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced -** version of sqlite_stat3 and is only available when compiled with -** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is -** not possible to enable both STAT3 and STAT4 at the same time. If they -** are both enabled, then STAT4 takes precedence. +** is a superset of sqlite_stat2 and is also now deprecated. The +** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only +** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite +** versions 3.8.1 and later. STAT4 is the only variant that is still +** supported. ** ** For most applications, sqlite_stat1 provides all the statistics required ** for the query planner to make good choices. @@ -144,17 +144,11 @@ #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 -# define IsStat3 0 -#elif defined(SQLITE_ENABLE_STAT3) -# define IsStat4 0 -# define IsStat3 1 #else # define IsStat4 0 -# define IsStat3 0 # undef SQLITE_STAT4_SAMPLES # define SQLITE_STAT4_SAMPLES 1 #endif -#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */ /* ** This routine generates code that opens the sqlite_statN tables. @@ -183,14 +177,10 @@ static void openStatTable( { "sqlite_stat1", "tbl,idx,stat" }, #if defined(SQLITE_ENABLE_STAT4) { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" }, - { "sqlite_stat3", 0 }, -#elif defined(SQLITE_ENABLE_STAT3) - { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" }, - { "sqlite_stat4", 0 }, #else - { "sqlite_stat3", 0 }, { "sqlite_stat4", 0 }, #endif + { "sqlite_stat3", 0 }, }; int i; sqlite3 *db = pParse->db; @@ -271,7 +261,7 @@ typedef struct Stat4Sample Stat4Sample; struct Stat4Sample { tRowcnt *anEq; /* sqlite_stat4.nEq */ tRowcnt *anDLt; /* sqlite_stat4.nDLt */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 tRowcnt *anLt; /* sqlite_stat4.nLt */ union { i64 iRowid; /* Rowid in main table of the key */ @@ -302,7 +292,7 @@ struct Stat4Accum { /* Reclaim memory used by a Stat4Sample */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 static void sampleClear(sqlite3 *db, Stat4Sample *p){ assert( db!=0 ); if( p->nRowid ){ @@ -314,7 +304,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){ /* Initialize the BLOB value of a ROWID */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ assert( db!=0 ); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); @@ -330,7 +320,7 @@ static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ /* Initialize the INTEGER value of a ROWID. */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){ assert( db!=0 ); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); @@ -343,7 +333,7 @@ static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){ /* ** Copy the contents of object (*pFrom) into (*pTo). */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ pTo->isPSample = pFrom->isPSample; pTo->iCol = pFrom->iCol; @@ -364,7 +354,7 @@ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ */ static void stat4Destructor(void *pOld){ Stat4Accum *p = (Stat4Accum*)pOld; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 int i; for(i=0; inCol; i++) sampleClear(p->db, p->aBest+i); for(i=0; imxSample; i++) sampleClear(p->db, p->a+i); @@ -384,7 +374,7 @@ static void stat4Destructor(void *pOld){ ** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the ** total number of columns in the table. ** -** Note 2: C is only used for STAT3 and STAT4. +** Note 2: C is only used for STAT4. ** ** For indexes on ordinary rowid tables, N==K+1. But for indexes on ** WITHOUT ROWID tables, N=K+P where P is the number of columns in the @@ -407,7 +397,7 @@ static void statInit( int nColUp; /* nCol rounded up for alignment */ int n; /* Bytes of space to allocate */ sqlite3 *db; /* Database connection */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 int mxSample = SQLITE_STAT4_SAMPLES; #endif @@ -424,7 +414,7 @@ static void statInit( n = sizeof(*p) + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */ + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */ + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */ + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample) @@ -444,7 +434,7 @@ static void statInit( p->current.anDLt = (tRowcnt*)&p[1]; p->current.anEq = &p->current.anDLt[nColUp]; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 { u8 *pSpace; /* Allocated space not yet assigned */ int i; /* Used to iterate through p->aSample[] */ @@ -479,7 +469,7 @@ static void statInit( sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor); } static const FuncDef statInitFuncdef = { - 2+IsStat34, /* nArg */ + 2+IsStat4, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ @@ -519,7 +509,7 @@ static int sampleIsBetterPost( } #endif -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Return true if pNew is to be preferred over pOld. ** @@ -538,15 +528,11 @@ static int sampleIsBetter( assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); if( (nEqNew>nEqOld) ) return 1; -#ifdef SQLITE_ENABLE_STAT4 if( nEqNew==nEqOld ){ if( pNew->iColiCol ) return 1; return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); } return 0; -#else - return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); -#endif } /* @@ -559,7 +545,6 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ assert( IsStat4 || nEqZero==0 ); -#ifdef SQLITE_ENABLE_STAT4 /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0 ** values in the anEq[] array of any sample in Stat4Accum.a[]. In ** other words, if nMaxEqZero is n, then it is guaranteed that there @@ -593,7 +578,6 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ goto find_new_min; } } -#endif /* If necessary, remove sample iMin to make room for the new sample. */ if( p->nSample>=p->mxSample ){ @@ -614,10 +598,8 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ /* The "rows less-than" for the rowid column must be greater than that ** for the last sample in the p->a[] array. Otherwise, the samples would ** be out of order. */ -#ifdef SQLITE_ENABLE_STAT4 assert( p->nSample==0 || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] ); -#endif /* Insert the new sample */ pSample = &p->a[p->nSample]; @@ -627,9 +609,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ /* Zero the first nEqZero entries in the anEq[] array. */ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); -#ifdef SQLITE_ENABLE_STAT4 - find_new_min: -#endif +find_new_min: if( p->nSample>=p->mxSample ){ int iMin = -1; for(i=0; imxSample; i++){ @@ -642,7 +622,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ p->iMin = iMin; } } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ /* ** Field iChng of the index being scanned has changed. So at this point @@ -683,28 +663,7 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ } #endif -#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) - if( iChng==0 ){ - tRowcnt nLt = p->current.anLt[0]; - tRowcnt nEq = p->current.anEq[0]; - - /* Check if this is to be a periodic sample. If so, add it. */ - if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){ - p->current.isPSample = 1; - sampleInsert(p, &p->current, 0); - p->current.isPSample = 0; - }else - - /* Or if it is a non-periodic sample. Add it in this case too. */ - if( p->nSamplemxSample - || sampleIsBetter(p, &p->current, &p->a[p->iMin]) - ){ - sampleInsert(p, &p->current, 0); - } - } -#endif - -#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifndef SQLITE_ENABLE_STAT4 UNUSED_PARAMETER( p ); UNUSED_PARAMETER( iChng ); #endif @@ -724,7 +683,7 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ ** index being analyzed. The stat_get() SQL function will later be used to ** extract relevant information for constructing the sqlite_statN tables. ** -** The R parameter is only used for STAT3 and STAT4 +** The R parameter is only used for STAT4 */ static void statPush( sqlite3_context *context, @@ -756,14 +715,14 @@ static void statPush( } for(i=iChng; inCol; i++){ p->current.anDLt[i]++; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 p->current.anLt[i] += p->current.anEq[i]; #endif p->current.anEq[i] = 1; } } p->nRow++; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){ sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2])); }else{ @@ -796,7 +755,7 @@ static void statPush( #endif } static const FuncDef statPushFuncdef = { - 2+IsStat34, /* nArg */ + 2+IsStat4, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ @@ -827,7 +786,7 @@ static const FuncDef statPushFuncdef = { ** parameter will always be a poiner to a Stat4Accum object, never a ** NULL. ** -** If neither STAT3 nor STAT4 are enabled, then J is always +** If STAT4 is not enabled, then J is always ** STAT_GET_STAT1 and is hence omitted and this routine becomes ** a one-parameter function, stat_get(P), that always returns the ** stat1 table entry information. @@ -838,8 +797,8 @@ static void statGet( sqlite3_value **argv ){ Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - /* STAT3 and STAT4 have a parameter on this routine. */ +#ifdef SQLITE_ENABLE_STAT4 + /* STAT4 has a parameter on this routine. */ int eCall = sqlite3_value_int(argv[1]); assert( argc==2 ); assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ @@ -894,7 +853,7 @@ static void statGet( sqlite3_result_text(context, zRet, -1, sqlite3_free); } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 else if( eCall==STAT_GET_ROWID ){ if( p->iGet<0 ){ samplePushPrevious(p, 0); @@ -923,9 +882,7 @@ static void statGet( } } - if( IsStat3 ){ - sqlite3_result_int64(context, (i64)aCnt[0]); - }else{ + { char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); @@ -942,13 +899,13 @@ static void statGet( } } } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( argc ); #endif } static const FuncDef statGetFuncdef = { - 1+IsStat34, /* nArg */ + 1+IsStat4, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ @@ -961,7 +918,7 @@ static const FuncDef statGetFuncdef = { static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ assert( regOut!=regStat4 && regOut!=regStat4+1 ); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1); #elif SQLITE_DEBUG assert( iParam==STAT_GET_STAT1 ); @@ -970,7 +927,7 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ #endif sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut, (char*)&statGetFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 1 + IsStat34); + sqlite3VdbeChangeP5(v, 1 + IsStat4); } /* @@ -997,7 +954,7 @@ static void analyzeOneTable( int regNewRowid = iMem++; /* Rowid for the inserted record */ int regStat4 = iMem++; /* Register to hold Stat4Accum object */ int regChng = iMem++; /* Index of changed index field */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 int regRowid = iMem++; /* Rowid argument passed to stat_push() */ #endif int regTemp = iMem++; /* Temporary use register */ @@ -1131,16 +1088,16 @@ static void analyzeOneTable( ** (3) the number of rows in the index, ** ** - ** The third argument is only used for STAT3 and STAT4 + ** The third argument is only used for STAT4 */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3); #endif sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2); sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4, (char*)&statInitFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 2+IsStat34); + sqlite3VdbeChangeP5(v, 2+IsStat4); /* Implementation of the following: ** @@ -1211,12 +1168,12 @@ static void analyzeOneTable( /* ** chng_addr_N: - ** regRowid = idx(rowid) // STAT34 only - ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only + ** regRowid = idx(rowid) // STAT4 only + ** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only ** Next csr ** if !eof(csr) goto next_row; */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 assert( regRowid==(regStat4+2) ); if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid); @@ -1237,7 +1194,7 @@ static void analyzeOneTable( assert( regChng==(regStat4+1) ); sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp, (char*)&statPushFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 2+IsStat34); + sqlite3VdbeChangeP5(v, 2+IsStat4); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ @@ -1251,8 +1208,8 @@ static void analyzeOneTable( #endif sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - /* Add the entries to the stat3 or stat4 table. */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* Add the entries to the stat4 table. */ +#ifdef SQLITE_ENABLE_STAT4 { int regEq = regStat1; int regLt = regStat1+1; @@ -1275,21 +1232,17 @@ static void analyzeOneTable( callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); VdbeCoverage(v); -#ifdef SQLITE_ENABLE_STAT3 - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); -#else for(i=0; ibUnordered = 1; }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ - pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3)); + int sz = sqlite3Atoi(z+3); + if( sz<2 ) sz = 2; + pIndex->szIdxRow = sqlite3LogEst(sz); }else if( sqlite3_strglob("noskipscan*", z)==0 ){ pIndex->noSkipScan = 1; } @@ -1551,7 +1506,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ if( pIndex ){ tRowcnt *aiRowEst = 0; int nCol = pIndex->nKeyCol+1; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* Index.aiRowEst may already be set here if there are duplicate ** sqlite_stat1 entries for this index. In that case just clobber ** the old data with the new instead of allocating a new array. */ @@ -1587,7 +1542,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ ** and its contents. */ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( pIdx->aSample ){ int j; for(j=0; jnSample; j++){ @@ -1603,10 +1558,10 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ #else UNUSED_PARAMETER(db); UNUSED_PARAMETER(pIdx); -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Populate the pIdx->aAvgEq[] array based on the samples currently ** stored in pIdx->aSample[]. @@ -1684,12 +1639,11 @@ static Index *findIndexOrPrimaryKey( } /* -** Load the content from either the sqlite_stat4 or sqlite_stat3 table +** Load the content from either the sqlite_stat4 ** into the relevant Index.aSample[] arrays. ** ** Arguments zSql1 and zSql2 must point to SQL statements that return -** data equivalent to the following (statements are different for stat3, -** see the caller of this function for details): +** data equivalent to the following: ** ** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx ** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4 @@ -1698,7 +1652,6 @@ static Index *findIndexOrPrimaryKey( */ static int loadStatTbl( sqlite3 *db, /* Database handle */ - int bStat3, /* Assume single column records only */ const char *zSql1, /* SQL statement 1 (see above) */ const char *zSql2, /* SQL statement 2 (see above) */ const char *zDb /* Database name (e.g. "main") */ @@ -1732,17 +1685,13 @@ static int loadStatTbl( if( zIndex==0 ) continue; nSample = sqlite3_column_int(pStmt, 1); pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); - assert( pIdx==0 || bStat3 || pIdx->nSample==0 ); - /* Index.nSample is non-zero at this point if data has already been - ** loaded from the stat4 table. In this case ignore stat3 data. */ - if( pIdx==0 || pIdx->nSample ) continue; - if( bStat3==0 ){ - assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nIdxCol = pIdx->nKeyCol; - }else{ - nIdxCol = pIdx->nColumn; - } + assert( pIdx==0 || pIdx->nSample==0 ); + if( pIdx==0 ) continue; + assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); + if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ + nIdxCol = pIdx->nKeyCol; + }else{ + nIdxCol = pIdx->nColumn; } pIdx->nSampleCol = nIdxCol; nByte = sizeof(IndexSample) * nSample; @@ -1784,9 +1733,8 @@ static int loadStatTbl( pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); if( pIdx==0 ) continue; /* This next condition is true if data has already been loaded from - ** the sqlite_stat4 table. In this case ignore stat3 data. */ + ** the sqlite_stat4 table. */ nCol = pIdx->nSampleCol; - if( bStat3 && nCol>1 ) continue; if( pIdx!=pPrevIdx ){ initAvgEq(pPrevIdx); pPrevIdx = pIdx; @@ -1819,7 +1767,7 @@ static int loadStatTbl( } /* -** Load content from the sqlite_stat4 and sqlite_stat3 tables into +** Load content from the sqlite_stat4 table into ** the Index.aSample[] arrays of all indices. */ static int loadStat4(sqlite3 *db, const char *zDb){ @@ -1827,37 +1775,28 @@ static int loadStat4(sqlite3 *db, const char *zDb){ assert( db->lookaside.bDisable ); if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ - rc = loadStatTbl(db, 0, + rc = loadStatTbl(db, "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", zDb ); } - - if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){ - rc = loadStatTbl(db, 1, - "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", - "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3", - zDb - ); - } - return rc; } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ /* -** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The +** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The ** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] -** arrays. The contents of sqlite_stat3/4 are used to populate the +** arrays. The contents of sqlite_stat4 are used to populate the ** Index.aSample[] arrays. ** ** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR -** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined -** during compilation and the sqlite_stat3/4 table is present, no data is +** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined +** during compilation and the sqlite_stat4 table is present, no data is ** read from it. ** -** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the +** If SQLITE_ENABLE_STAT4 was defined during compilation and the ** sqlite_stat4 table is not present in the database, SQLITE_ERROR is ** returned. However, in this case, data is read from the sqlite_stat1 ** table (if it is present) before returning. @@ -1885,7 +1824,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); pIdx->hasStat1 = 0; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 sqlite3DeleteIndexSamples(db, pIdx); pIdx->aSample = 0; #endif @@ -1913,7 +1852,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ } /* Load the statistics from the sqlite_stat4 table. */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( rc==SQLITE_OK ){ db->lookaside.bDisable++; rc = loadStat4(db, sInfo.zDatabase); diff --git a/src/attach.c b/src/attach.c index 55e0eb5..1dcb407 100644 --- a/src/attach.c +++ b/src/attach.c @@ -299,6 +299,7 @@ static void detachFunc( sqlite3 *db = sqlite3_context_db_handle(context); int i; Db *pDb = 0; + HashElem *pEntry; char zErr[128]; UNUSED_PARAMETER(NotUsed); @@ -323,6 +324,18 @@ static void detachFunc( goto detach_error; } + /* If any TEMP triggers reference the schema being detached, move those + ** triggers to reference the TEMP schema itself. */ + assert( db->aDb[1].pSchema ); + pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); + while( pEntry ){ + Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); + if( pTrig->pTabSchema==pDb->pSchema ){ + pTrig->pTabSchema = pTrig->pSchema; + } + pEntry = sqliteHashNext(pEntry); + } + sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; @@ -560,6 +573,7 @@ int sqlite3FixExpr( Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ + ExprSetProperty(pExpr, EP_Indirect); if( pExpr->op==TK_VARIABLE ){ if( pFix->pParse->db->init.busy ){ pExpr->op = TK_NULL; diff --git a/src/auth.c b/src/auth.c index 6fcdce2..40673d5 100644 --- a/src/auth.c +++ b/src/auth.c @@ -78,7 +78,7 @@ int sqlite3_set_authorizer( sqlite3_mutex_enter(db->mutex); db->xAuth = (sqlite3_xauth)xAuth; db->pAuthArg = pArg; - sqlite3ExpirePreparedStatements(db, 0); + if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } diff --git a/src/backup.c b/src/backup.c index 2090b49..5e9c974 100644 --- a/src/backup.c +++ b/src/backup.c @@ -619,8 +619,10 @@ int sqlite3_backup_finish(sqlite3_backup *p){ } if( p->isAttached ){ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); + assert( pp!=0 ); while( *pp!=p ){ pp = &(*pp)->pNext; + assert( pp!=0 ); } *pp = p->pNext; } diff --git a/src/btree.c b/src/btree.c index 6c73a94..7ff91e6 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1647,9 +1647,12 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ u8 *pSpace = pageFindSlot(pPage, nByte, &rc); if( pSpace ){ - assert( pSpace>=data && (pSpace - data)<65536 ); - *pIdx = (int)(pSpace - data); - return SQLITE_OK; + assert( pSpace+nByte<=data+pPage->pBt->usableSize ); + if( (*pIdx = (int)(pSpace-data))<=gap ){ + return SQLITE_CORRUPT_PAGE(pPage); + }else{ + return SQLITE_OK; + } }else if( rc ){ return rc; } @@ -4876,6 +4879,7 @@ static int accessPayload( assert( aWrite>=pBufStart ); /* due to (6) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); + if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT; nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else @@ -6664,12 +6668,7 @@ static void insertCell( assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - /* The cell should normally be sized correctly. However, when moving a - ** malformed cell from a leaf page to an interior page, if the cell size - ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size - ** might be less than 8 (leaf-size + pointer) on the interior node. Hence - ** the term after the || in the following assert(). */ - assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) ); + assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); assert( pPage->nFree>=0 ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ @@ -6901,7 +6900,7 @@ static int rebuildPage( assert( i(u32)usableSize) ){ j = 0; } + if( j>(u32)usableSize ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kszCell[i]!=0 ); + sz = pCArray->szCell[i]; if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ if( (pData - pBegin)nOverflow)); if( pOld->nOverflow>0 ){ - if( limitaiOvfl[0] ){ + if( NEVER(limitaiOvfl[0]) ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } @@ -7962,6 +7963,8 @@ static int balance_nonroot( )); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + assert( nNew>=1 && nNew<=ArraySize(apNew) ); + assert( apNew[nNew-1]!=0 ); put4byte(pRight, apNew[nNew-1]->pgno); /* If the sibling pages are not leaves, ensure that the right-child pointer @@ -8307,11 +8310,13 @@ static int balance(BtCursor *pCur){ VVA_ONLY( int balance_deeper_called = 0 ); do { - int iPage = pCur->iPage; + int iPage; MemPage *pPage = pCur->pPage; if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break; - if( iPage==0 ){ + if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ + break; + }else if( (iPage = pCur->iPage)==0 ){ if( pPage->nOverflow ){ /* The root page of the b-tree is overfull. In this case call the ** balance_deeper() function to create a new child for the root-page @@ -8332,8 +8337,6 @@ static int balance(BtCursor *pCur){ }else{ break; } - }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ - break; }else{ MemPage * const pParent = pCur->apPage[iPage-1]; int const iIdx = pCur->aiIdx[iPage-1]; @@ -8475,7 +8478,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ Pgno ovflPgno; /* Next overflow page to write */ u32 ovflPageSize; /* Size to write on overflow page */ - if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ + if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd + || pCur->info.pPayload < pPage->aData + pPage->cellOffset + ){ return SQLITE_CORRUPT_BKPT; } /* Overwrite the local portion first */ @@ -8716,6 +8721,8 @@ int sqlite3BtreeInsert( memcpy(newCell, oldCell, 4); } rc = clearCell(pPage, oldCell, &info); + testcase( pCur->curFlags & BTCF_ValidOvfl ); + invalidateOverflowCache(pCur); if( info.nSize==szNew && info.nLocal==info.nPayload && (!ISAUTOVACUUM || szNewminLocal) ){ @@ -8729,7 +8736,12 @@ int sqlite3BtreeInsert( ** new entry uses overflow pages, as the insertCell() call below is ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ - if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; + if( oldCell < pPage->aData+pPage->hdrOffset+10 ){ + return SQLITE_CORRUPT_BKPT; + } + if( oldCell+szNew > pPage->aDataEnd ){ + return SQLITE_CORRUPT_BKPT; + } memcpy(oldCell, newCell, szNew); return SQLITE_OK; } diff --git a/src/build.c b/src/build.c index 5331459..a3d1abf 100644 --- a/src/build.c +++ b/src/build.c @@ -456,7 +456,7 @@ void sqlite3FreeIndex(sqlite3 *db, Index *p){ sqlite3ExprListDelete(db, p->aColExpr); sqlite3DbFree(db, p->zColAff); if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 sqlite3_free(p->aiRowEst); #endif sqlite3DbFree(db, p); @@ -829,13 +829,40 @@ int sqlite3WritableSchema(sqlite3 *db){ ** trigger). All names are legal except those that begin with the string ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace ** is reserved for internal use. +** +** When parsing the sqlite_master table, this routine also checks to +** make sure the "type", "name", and "tbl_name" columns are consistent +** with the SQL. */ -int sqlite3CheckObjectName(Parse *pParse, const char *zName){ - if( !pParse->db->init.busy && pParse->nested==0 - && sqlite3WritableSchema(pParse->db)==0 - && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ - sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); - return SQLITE_ERROR; +int sqlite3CheckObjectName( + Parse *pParse, /* Parsing context */ + const char *zName, /* Name of the object to check */ + const char *zType, /* Type of this object */ + const char *zTblName /* Parent table name for triggers and indexes */ +){ + sqlite3 *db = pParse->db; + if( sqlite3WritableSchema(db) || db->init.imposterTable ){ + /* Skip these error checks for writable_schema=ON */ + return SQLITE_OK; + } + if( db->init.busy ){ + if( sqlite3_stricmp(zType, db->init.azInit[0]) + || sqlite3_stricmp(zName, db->init.azInit[1]) + || sqlite3_stricmp(zTblName, db->init.azInit[2]) + ){ + if( sqlite3Config.bExtraSchemaChecks ){ + sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */ + return SQLITE_ERROR; + } + } + }else{ + if( pParse->nested==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) + ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", + zName); + return SQLITE_ERROR; + } } return SQLITE_OK; } @@ -916,7 +943,7 @@ void sqlite3StartTable( } pParse->sNameToken = *pName; if( zName==0 ) return; - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){ goto begin_table_error; } if( db->init.iDb==1 ) isTemp = 1; @@ -1416,7 +1443,7 @@ void sqlite3AddPrimaryKey( pTab->keyConf = (u8)onError; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= autoInc*TF_Autoincrement; - if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder; + if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags; }else if( autoInc ){ #ifndef SQLITE_OMIT_AUTOINCREMENT sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " @@ -1831,6 +1858,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ Index *pIdx; Index *pPk; int nPk; + int nExtra; int i, j; sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; @@ -1866,13 +1894,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); } - pList->a[0].sortOrder = pParse->iPkSortOrder; + pList->a[0].sortFlags = pParse->iPkSortOrder; assert( pParse->pNewTable==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; pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk->nKeyCol==1 ); }else{ pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); @@ -1887,6 +1916,8 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pPk->nColumn--; }else{ testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ); + pPk->azColl[j] = pPk->azColl[i]; + pPk->aSortOrder[j] = pPk->aSortOrder[i]; pPk->aiColumn[j++] = pPk->aiColumn[i]; } } @@ -1895,7 +1926,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ assert( pPk!=0 ); pPk->isCovering = 1; if( !db->init.imposterTable ) pPk->uniqNotNull = 1; - nPk = pPk->nKeyCol; + nPk = pPk->nColumn = pPk->nKeyCol; /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master ** table entry. This is only required if currently generating VDBE @@ -1945,21 +1976,21 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ /* Add all table columns to the PRIMARY KEY index */ - if( nPknCol ){ - if( resizeIndexObject(db, pPk, pTab->nCol) ) return; - for(i=0, j=nPk; inCol; i++){ - if( !hasColumn(pPk->aiColumn, j, i) ){ - assert( jnColumn ); - pPk->aiColumn[j] = i; - pPk->azColl[j] = sqlite3StrBINARY; - j++; - } - } - assert( pPk->nColumn==j ); - assert( pTab->nCol==j ); - }else{ - pPk->nColumn = pTab->nCol; + nExtra = 0; + for(i=0; inCol; i++){ + if( !hasColumn(pPk->aiColumn, nPk, i) ) nExtra++; } + if( resizeIndexObject(db, pPk, nPk+nExtra) ) return; + for(i=0, j=nPk; inCol; i++){ + if( !hasColumn(pPk->aiColumn, j, i) ){ + assert( jnColumn ); + pPk->aiColumn[j] = i; + pPk->azColl[j] = sqlite3StrBINARY; + j++; + } + } + assert( pPk->nColumn==j ); + assert( pTab->nCol<=j ); recomputeColumnsNotIndexed(pPk); } @@ -2156,7 +2187,7 @@ void sqlite3EndTable( addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); if( pParse->nErr ) return; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; @@ -2420,10 +2451,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ #ifndef SQLITE_OMIT_AUTHORIZATION xAuth = db->xAuth; db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); db->xAuth = xAuth; #else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); #endif pParse->nTab = n; if( pTable->pCheck ){ @@ -2439,7 +2470,8 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ && pParse->nErr==0 && pTable->nCol==pSel->pEList->nExpr ){ - sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel, + SQLITE_AFF_NONE); } }else if( pSelTab ){ /* CREATE VIEW name AS... without an argument list. Construct @@ -2784,7 +2816,8 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ } #endif if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 - && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){ + && sqlite3StrNICmp(pTab->zName+7, "stat", 4)!=0 + && sqlite3StrNICmp(pTab->zName+7, "parameters", 10)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); goto exit_drop_table; } @@ -3121,6 +3154,27 @@ Index *sqlite3AllocateIndexObject( return p; } +/* +** If expression list pList contains an expression that was parsed with +** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in +** pParse and return non-zero. Otherwise, return zero. +*/ +int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ + if( pList ){ + int i; + for(i=0; inExpr; i++){ + if( pList->a[i].bNulls ){ + u8 sf = pList->a[i].sortFlags; + sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", + (sf==0 || sf==3) ? "FIRST" : "LAST" + ); + return 1; + } + } + } + return 0; +} + /* ** Create a new index for an SQL table. pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed. Both will @@ -3172,6 +3226,9 @@ void sqlite3CreateIndex( if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } + if( sqlite3HasExplicitNulls(pParse, pList) ){ + goto exit_create_index; + } /* ** Find the table that is to be indexed. Return early if not found. @@ -3270,7 +3327,7 @@ void sqlite3CreateIndex( zName = sqlite3NameFromToken(db, pName); if( zName==0 ) goto exit_create_index; assert( pName->z!=0 ); - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){ goto exit_create_index; } if( !IN_RENAME_OBJECT ){ @@ -3336,7 +3393,7 @@ void sqlite3CreateIndex( sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; assert( pList->nExpr==1 ); - sqlite3ExprListSetSortOrder(pList, sortOrder); + sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED); }else{ sqlite3ExprListCheckLength(pParse, pList, "index"); if( pParse->nErr ) goto exit_create_index; @@ -3454,7 +3511,7 @@ void sqlite3CreateIndex( goto exit_create_index; } pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->sortOrder & sortOrderMask; + requestedSortOrder = pListItem->sortFlags & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; } @@ -3629,6 +3686,7 @@ void sqlite3CreateIndex( /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable */ + assert( pName!=0 || pStart==0 ); if( pStart ){ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; if( pName->z[n-1]==';' ) n--; @@ -4671,7 +4729,8 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ const char *zColl = pIdx->azColl[i]; pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 : sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + pKey->aSortFlags[i] = pIdx->aSortOrder[i]; + assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) ); } if( pParse->nErr ){ assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); diff --git a/src/ctime.c b/src/ctime.c index ebb6e85..013a0c2 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -306,8 +306,6 @@ static const char * const sqlite3azCompileOpt[] = { #endif #if defined(SQLITE_ENABLE_STAT4) "ENABLE_STAT4", -#elif defined(SQLITE_ENABLE_STAT3) - "ENABLE_STAT3", #endif #if SQLITE_ENABLE_STMTVTAB "ENABLE_STMTVTAB", diff --git a/src/expr.c b/src/expr.c index c4f201a..2cc2d33 100644 --- a/src/expr.c +++ b/src/expr.c @@ -44,7 +44,6 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){ */ char sqlite3ExprAffinity(Expr *pExpr){ int op; - if( pExpr->flags & EP_Generic ) return 0; while( ExprHasProperty(pExpr, EP_Skip) ){ assert( pExpr->op==TK_COLLATE ); pExpr = pExpr->pLeft; @@ -71,7 +70,7 @@ char sqlite3ExprAffinity(Expr *pExpr){ pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } - return pExpr->affinity; + return pExpr->affExpr; } /* @@ -106,10 +105,22 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ } /* -** Skip over any TK_COLLATE operators and any unlikely() -** or likelihood() function at the root of an expression. +** Skip over any TK_COLLATE operators. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ + while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ + assert( pExpr->op==TK_COLLATE ); + pExpr = pExpr->pLeft; + } + return pExpr; +} + +/* +** Skip over any TK_COLLATE operators and/or any unlikely() +** or likelihood() or likely() functions at the root of an +** expression. +*/ +Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); @@ -144,7 +155,6 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ Expr *p = pExpr; while( p ){ int op = p->op; - if( p->flags & EP_Generic ) break; if( op==TK_REGISTER ) op = p->op2; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER) && p->y.pTab!=0 @@ -230,7 +240,7 @@ int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){ */ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); - if( aff1 && aff2 ){ + if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){ /* Both sides of the comparison are columns. If one has numeric ** affinity, use that. Otherwise use no affinity. */ @@ -239,15 +249,10 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ }else{ return SQLITE_AFF_BLOB; } - }else if( !aff1 && !aff2 ){ - /* Neither side of the comparison is a column. Compare the - ** results directly. - */ - return SQLITE_AFF_BLOB; }else{ /* One side is a column, the other is not. Use the columns affinity. */ - assert( aff1==0 || aff2==0 ); - return (aff1 + aff2); + assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE ); + return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE; } } @@ -280,14 +285,13 @@ static char comparisonAffinity(Expr *pExpr){ */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); - switch( aff ){ - case SQLITE_AFF_BLOB: - return 1; - case SQLITE_AFF_TEXT: - return idx_affinity==SQLITE_AFF_TEXT; - default: - return sqlite3IsNumericAffinity(idx_affinity); + if( affx.pList==0 || p->pRight==0 ); if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); if( p->pRight ){ + assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3ExprDeleteNN(db, p->pRight); }else if( ExprHasProperty(p, EP_xIsSelect) ){ + assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); - } - if( ExprHasProperty(p, EP_WinFunc) ){ - assert( p->op==TK_FUNCTION ); - sqlite3WindowDelete(db, p->y.pWin); +#ifndef SQLITE_OMIT_WINDOWFUNC + if( ExprHasProperty(p, EP_WinFunc) ){ + sqlite3WindowDelete(db, p->y.pWin); + } +#endif } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); @@ -1083,16 +1090,6 @@ static int exprStructSize(Expr *p){ return EXPR_FULLSIZE; } -/* -** Copy the complete content of an Expr node, taking care not to read -** past the end of the structure for a reduced-size version of the source -** Expr. -*/ -static void exprNodeCopy(Expr *pDest, Expr *pSrc){ - memset(pDest, 0, sizeof(Expr)); - memcpy(pDest, pSrc, exprStructSize(pSrc)); -} - /* ** The dupedExpr*Size() routines each return the number of bytes required ** to store a copy of an expression or expression tree. They differ in @@ -1332,10 +1329,13 @@ static With *withDup(sqlite3 *db, With *p){ ** objects found there, assembling them onto the linked list at Select->pWin. */ static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){ - assert( ExprHasProperty(pExpr, EP_WinFunc) ); - pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin; - pWalker->u.pSelect->pWin = pExpr->y.pWin; + if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){ + Select *pSelect = pWalker->u.pSelect; + Window *pWin = pExpr->y.pWin; + assert( pWin ); + assert( IsWindowFunc(pExpr) ); + assert( pWin->ppThis==0 ); + sqlite3WindowLink(pSelect, pWin); } return WRC_Continue; } @@ -1409,8 +1409,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); - pItem->sortOrder = pOldItem->sortOrder; + pItem->sortFlags = pOldItem->sortFlags; pItem->done = 0; + pItem->bNulls = pOldItem->bNulls; pItem->bSpanIsTab = pOldItem->bSpanIsTab; pItem->bSorterRef = pOldItem->bSorterRef; pItem->u = pOldItem->u; @@ -1521,7 +1522,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ #ifndef SQLITE_OMIT_WINDOWFUNC pNew->pWin = 0; pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); - if( p->pWin ) gatherSelectWindows(pNew); + if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew); #endif pNew->selId = p->selId; *pp = pNew; @@ -1630,6 +1631,10 @@ ExprList *sqlite3ExprListAppendVector( for(i=0; inId; i++){ Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i); + assert( pSubExpr!=0 || db->mallocFailed ); + assert( pSubExpr==0 || pSubExpr->iTable==0 ); + if( pSubExpr==0 ) continue; + pSubExpr->iTable = pColumns->nId; pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); if( pList ){ assert( pList->nExpr==iFirst+i+1 ); @@ -1662,15 +1667,34 @@ vector_append_error: /* ** Set the sort order for the last element on the given ExprList. */ -void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ +void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ + struct ExprList_item *pItem; if( p==0 ) return; - assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 ); assert( p->nExpr>0 ); - if( iSortOrder<0 ){ - assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC ); - return; + + assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 ); + assert( iSortOrder==SQLITE_SO_UNDEFINED + || iSortOrder==SQLITE_SO_ASC + || iSortOrder==SQLITE_SO_DESC + ); + assert( eNulls==SQLITE_SO_UNDEFINED + || eNulls==SQLITE_SO_ASC + || eNulls==SQLITE_SO_DESC + ); + + pItem = &p->a[p->nExpr-1]; + assert( pItem->bNulls==0 ); + if( iSortOrder==SQLITE_SO_UNDEFINED ){ + iSortOrder = SQLITE_SO_ASC; + } + pItem->sortFlags = (u8)iSortOrder; + + if( eNulls!=SQLITE_SO_UNDEFINED ){ + pItem->bNulls = 1; + if( iSortOrder!=eNulls ){ + pItem->sortFlags |= KEYINFO_ORDER_BIGNULL; + } } - p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; } /* @@ -2169,27 +2193,30 @@ int sqlite3ExprCanBeNull(const Expr *p){ */ int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ u8 op; + int unaryMinus = 0; if( aff==SQLITE_AFF_BLOB ) return 1; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ + if( p->op==TK_UMINUS ) unaryMinus = 1; + p = p->pLeft; + } op = p->op; if( op==TK_REGISTER ) op = p->op2; switch( op ){ case TK_INTEGER: { - return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC; + return aff>=SQLITE_AFF_NUMERIC; } case TK_FLOAT: { - return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC; + return aff>=SQLITE_AFF_NUMERIC; } case TK_STRING: { - return aff==SQLITE_AFF_TEXT; + return !unaryMinus && aff==SQLITE_AFF_TEXT; } case TK_BLOB: { - return 1; + return !unaryMinus; } case TK_COLUMN: { assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ - return p->iColumn<0 - && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC); + return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0; } default: { return 0; @@ -2372,7 +2399,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ #ifndef SQLITE_OMIT_SUBQUERY int sqlite3FindInIndex( Parse *pParse, /* Parsing context */ - Expr *pX, /* The right-hand side (RHS) of the IN operator */ + Expr *pX, /* The IN expression */ u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ int *prRhsHasNull, /* Register holding NULL status. See notes */ int *aiMap, /* Mapping from Index fields to RHS fields */ @@ -2797,9 +2824,9 @@ void sqlite3CodeRhsOfIN( int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; - int r1, r2, r3; + int r1, r2; affinity = sqlite3ExprAffinity(pLeft); - if( !affinity ){ + if( affinity<=SQLITE_AFF_NONE ){ affinity = SQLITE_AFF_BLOB; } if( pKeyInfo ){ @@ -2825,9 +2852,9 @@ void sqlite3CodeRhsOfIN( } /* Evaluate the expression and insert it into the temp table */ - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1); + sqlite3ExprCode(pParse, pE2, r1); + sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1); } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); @@ -2840,6 +2867,7 @@ void sqlite3CodeRhsOfIN( /* Subroutine return */ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn); sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1); + sqlite3ClearTempRegCache(pParse); } } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -2853,7 +2881,7 @@ void sqlite3CodeRhsOfIN( ** ** The pExpr parameter is the SELECT or EXISTS operator to be coded. ** -** The register that holds the result. For a multi-column SELECT, +** Return the register that holds the result. For a multi-column SELECT, ** the result is stored in a contiguous array of registers and the ** return value is the register of the left-most result column. ** Return 0 if an error occurs. @@ -2931,11 +2959,21 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); VdbeComment((v, "Init EXISTS result")); } - pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0); if( pSel->pLimit ){ - sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft); + /* The subquery already has a limit. If the pre-existing limit is X + ** then make the new limit X<>0 so that the new limit is either 1 or 0 */ + sqlite3 *db = pParse->db; + pLimit = sqlite3Expr(db, TK_INTEGER, "0"); + if( pLimit ){ + pLimit->affExpr = SQLITE_AFF_NUMERIC; + pLimit = sqlite3PExpr(pParse, TK_NE, + sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit); + } + sqlite3ExprDelete(db, pSel->pLimit->pLeft); pSel->pLimit->pLeft = pLimit; }else{ + /* If there is no pre-existing limit add a limit of 1 */ + pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); } pSel->iLimit = 0; @@ -2950,6 +2988,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ /* Subroutine return */ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn); sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1); + sqlite3ClearTempRegCache(pParse); } return rReg; @@ -3097,13 +3136,21 @@ static void sqlite3ExprCodeIN( int r2, regToFree; int regCkNull = 0; int ii; + int bLhsReal; /* True if the LHS of the IN has REAL affinity */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } + bLhsReal = sqlite3ExprAffinity(pExpr->pLeft)==SQLITE_AFF_REAL; for(ii=0; iinExpr; ii++){ - r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); + if( bLhsReal ){ + r2 = regToFree = sqlite3GetTempReg(pParse); + sqlite3ExprCode(pParse, pList->a[ii].pExpr, r2); + sqlite3VdbeAddOp4(v, OP_Affinity, r2, 1, 0, "E", P4_STATIC); + }else{ + r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); + } if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); } @@ -3388,7 +3435,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ ** the correct value for the expression. */ static void exprToRegister(Expr *pExpr, int iReg){ - Expr *p = sqlite3ExprSkipCollate(pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr); p->op2 = p->op; p->op = TK_REGISTER; p->iTable = iReg; @@ -3489,7 +3536,7 @@ expr_code_doover: */ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); - if( aff!=SQLITE_AFF_BLOB ){ + if( aff>SQLITE_AFF_BLOB ){ static const char zAff[] = "B\000C\000D\000E"; assert( SQLITE_AFF_BLOB=='A' ); assert( SQLITE_AFF_TEXT=='B' ); @@ -3505,7 +3552,19 @@ expr_code_doover: if( iTab<0 ){ if( pParse->iSelfTab<0 ){ /* Generating CHECK constraints or inserting into partial index */ - return pExpr->iColumn - pParse->iSelfTab; + assert( pExpr->y.pTab!=0 ); + assert( pExpr->iColumn>=XN_ROWID ); + assert( pExpr->iColumny.pTab->nCol ); + if( pExpr->iColumn>=0 + && pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL + ){ + sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab, + target); + sqlite3VdbeAddOp1(v, OP_RealAffinity, target); + return target; + }else{ + return pExpr->iColumn - pParse->iSelfTab; + } }else{ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ @@ -3792,7 +3851,7 @@ expr_code_doover: assert( nFarg==1 ); aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); sqlite3VdbeLoadString(v, target, - aff ? azAff[aff-SQLITE_AFF_BLOB] : "none"); + (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); return target; } #endif @@ -3900,8 +3959,8 @@ expr_code_doover: pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); } assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT ); - if( pExpr->iTable - && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) + if( pExpr->iTable!=0 + && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pExpr->iTable, n); @@ -4004,10 +4063,23 @@ expr_code_doover: break; } + /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions + ** that derive from the right-hand table of a LEFT JOIN. The + ** Expr.iTable value is the table number for the right-hand table. + ** The expression is only evaluated if that table is not currently + ** on a LEFT JOIN NULL row. + */ case TK_IF_NULL_ROW: { int addrINR; + u8 okConstFactor = pParse->okConstFactor; addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); + /* Temporarily disable factoring of constant expressions, since + ** even though expressions may appear to be constant, they are not + ** really constant because they originate from the right-hand side + ** of a LEFT JOIN. */ + pParse->okConstFactor = 0; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + pParse->okConstFactor = okConstFactor; sqlite3VdbeJumpHere(v, addrINR); sqlite3VdbeChangeP3(v, addrINR, inReg); break; @@ -4044,6 +4116,8 @@ expr_code_doover: Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ + Expr *pDel = 0; + sqlite3 *db = pParse->db; assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); assert(pExpr->x.pList->nExpr > 0); @@ -4052,13 +4126,17 @@ expr_code_doover: nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(pParse); if( (pX = pExpr->pLeft)!=0 ){ - exprNodeCopy(&tempX, pX); + pDel = sqlite3ExprDup(db, pX, 0); + if( db->mallocFailed ){ + sqlite3ExprDelete(db, pDel); + break; + } testcase( pX->op==TK_COLUMN ); - exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1)); + exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); testcase( regFree1==0 ); memset(&opCompare, 0, sizeof(opCompare)); opCompare.op = TK_EQ; - opCompare.pLeft = &tempX; + opCompare.pLeft = pDel; pTest = &opCompare; /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: ** The value in regFree1 might get SCopy-ed into the file result. @@ -4086,32 +4164,33 @@ expr_code_doover: }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } + sqlite3ExprDelete(db, pDel); sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { - assert( pExpr->affinity==OE_Rollback - || pExpr->affinity==OE_Abort - || pExpr->affinity==OE_Fail - || pExpr->affinity==OE_Ignore + assert( pExpr->affExpr==OE_Rollback + || pExpr->affExpr==OE_Abort + || pExpr->affExpr==OE_Fail + || pExpr->affExpr==OE_Ignore ); if( !pParse->pTriggerTab ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return 0; } - if( pExpr->affinity==OE_Abort ){ + if( pExpr->affExpr==OE_Abort ){ sqlite3MayAbort(pParse); } assert( !ExprHasProperty(pExpr, EP_IntValue) ); - if( pExpr->affinity==OE_Ignore ){ + if( pExpr->affExpr==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); VdbeCoverage(v); }else{ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, - pExpr->affinity, pExpr->u.zToken, 0, 0); + pExpr->affExpr, pExpr->u.zToken, 0, 0); } break; @@ -4176,7 +4255,7 @@ int sqlite3ExprCodeAtInit( */ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ int r2; - pExpr = sqlite3ExprSkipCollate(pExpr); + pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); if( ConstFactorOk(pParse) && pExpr->op!=TK_REGISTER && sqlite3ExprIsConstantNotJoin(pExpr) @@ -4367,40 +4446,44 @@ static void exprCodeBetween( void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ int jumpIfNull /* Take the jump if the BETWEEN is NULL */ ){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ Expr compLeft; /* The x>=y term */ Expr compRight; /* The x<=z term */ - Expr exprX; /* The x subexpression */ int regFree1 = 0; /* Temporary use register */ + Expr *pDel = 0; + sqlite3 *db = pParse->db; memset(&compLeft, 0, sizeof(Expr)); memset(&compRight, 0, sizeof(Expr)); memset(&exprAnd, 0, sizeof(Expr)); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - exprNodeCopy(&exprX, pExpr->pLeft); - exprAnd.op = TK_AND; - exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; - compLeft.op = TK_GE; - compLeft.pLeft = &exprX; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; - compRight.op = TK_LE; - compRight.pLeft = &exprX; - compRight.pRight = pExpr->x.pList->a[1].pExpr; - exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); - if( xJump ){ - xJump(pParse, &exprAnd, dest, jumpIfNull); - }else{ - /* Mark the expression is being from the ON or USING clause of a join - ** so that the sqlite3ExprCodeTarget() routine will not attempt to move - ** it into the Parse.pConstExpr list. We should use a new bit for this, - ** for clarity, but we are out of bits in the Expr.flags field so we - ** have to reuse the EP_FromJoin bit. Bummer. */ - exprX.flags |= EP_FromJoin; - sqlite3ExprCodeTarget(pParse, &exprAnd, dest); + pDel = sqlite3ExprDup(db, pExpr->pLeft, 0); + if( db->mallocFailed==0 ){ + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = pDel; + compLeft.pRight = pExpr->x.pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = pDel; + compRight.pRight = pExpr->x.pList->a[1].pExpr; + exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); + if( xJump ){ + xJump(pParse, &exprAnd, dest, jumpIfNull); + }else{ + /* Mark the expression is being from the ON or USING clause of a join + ** so that the sqlite3ExprCodeTarget() routine will not attempt to move + ** it into the Parse.pConstExpr list. We should use a new bit for this, + ** for clarity, but we are out of bits in the Expr.flags field so we + ** have to reuse the EP_FromJoin bit. Bummer. */ + pDel->flags |= EP_FromJoin; + sqlite3ExprCodeTarget(pParse, &exprAnd, dest); + } + sqlite3ReleaseTempReg(pParse, regFree1); } - sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ExprDelete(db, pDel); /* Ensure adequate test coverage */ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); @@ -4839,20 +4922,17 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ return 2; } if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ - if( pA->op==TK_FUNCTION ){ + if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; #ifndef SQLITE_OMIT_WINDOWFUNC - /* Justification for the assert(): - ** window functions have p->op==TK_FUNCTION but aggregate functions - ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate - ** function and a window function should have failed before reaching - ** this point. And, it is not possible to have a window function and - ** a scalar function with the same name and number of arguments. So - ** if we reach this point, either A and B both window functions or - ** neither are a window functions. */ - assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); + assert( pA->op==pB->op ); + if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){ + return 2; + } if( ExprHasProperty(pA,EP_WinFunc) ){ - if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; + if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){ + return 2; + } } #endif }else if( pA->op==TK_NULL ){ @@ -4876,7 +4956,8 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->op2!=pB->op2 ) return 2; - if( pA->iTable!=pB->iTable + if( pA->op!=TK_IN + && pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } } @@ -4906,7 +4987,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ for(i=0; inExpr; i++){ Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; + if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1; if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1; } return 0; @@ -4918,42 +4999,47 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ */ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ return sqlite3ExprCompare(0, - sqlite3ExprSkipCollate(pA), - sqlite3ExprSkipCollate(pB), + sqlite3ExprSkipCollateAndLikely(pA), + sqlite3ExprSkipCollateAndLikely(pB), iTab); } /* ** Return non-zero if Expr p can only be true if pNN is not NULL. +** +** Or if seenNot is true, return non-zero if Expr p can only be +** non-NULL if pNN is not NULL */ static int exprImpliesNotNull( Parse *pParse, /* Parsing context */ Expr *p, /* The expression to be checked */ Expr *pNN, /* The expression that is NOT NULL */ int iTab, /* Table being evaluated */ - int seenNot /* True if p is an operand of NOT */ + int seenNot /* Return true only if p can be any non-NULL value */ ){ assert( p ); assert( pNN ); - if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ) return 1; + if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){ + return pNN->op!=TK_NULL; + } switch( p->op ){ case TK_IN: { if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0; assert( ExprHasProperty(p,EP_xIsSelect) || (p->x.pList!=0 && p->x.pList->nExpr>0) ); - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } case TK_BETWEEN: { ExprList *pList = p->x.pList; assert( pList!=0 ); assert( pList->nExpr==2 ); if( seenNot ) return 0; - if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, seenNot) - || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, seenNot) + if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1) + || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1) ){ return 1; } - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } case TK_EQ: case TK_NE: @@ -4963,20 +5049,21 @@ static int exprImpliesNotNull( case TK_GE: case TK_PLUS: case TK_MINUS: + case TK_BITOR: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: + seenNot = 1; + /* Fall thru */ case TK_STAR: case TK_REM: case TK_BITAND: - case TK_BITOR: - case TK_SLASH: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: { + case TK_SLASH: { if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1; /* Fall thru into the next case */ } case TK_SPAN: case TK_COLLATE: - case TK_BITNOT: case TK_UPLUS: case TK_UMINUS: { return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); @@ -4984,8 +5071,9 @@ static int exprImpliesNotNull( case TK_TRUTH: { if( seenNot ) return 0; if( p->op2!=TK_IS ) return 0; - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } + case TK_BITNOT: case TK_NOT: { return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } @@ -5051,7 +5139,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; switch( pExpr->op ){ case TK_ISNOT: - case TK_NOT: case TK_ISNULL: case TK_NOTNULL: case TK_IS: @@ -5059,8 +5146,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ case TK_CASE: case TK_IN: case TK_FUNCTION: + case TK_TRUTH: testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_NOT ); testcase( pExpr->op==TK_ISNULL ); testcase( pExpr->op==TK_NOTNULL ); testcase( pExpr->op==TK_IS ); @@ -5068,6 +5155,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_CASE ); testcase( pExpr->op==TK_IN ); testcase( pExpr->op==TK_FUNCTION ); + testcase( pExpr->op==TK_TRUTH ); return WRC_Prune; case TK_COLUMN: if( pWalker->u.iCur==pExpr->iTable ){ @@ -5076,6 +5164,18 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ } return WRC_Prune; + case TK_AND: + if( sqlite3ExprImpliesNonNullRow(pExpr->pLeft, pWalker->u.iCur) + && sqlite3ExprImpliesNonNullRow(pExpr->pRight, pWalker->u.iCur) + ){ + pWalker->eCode = 1; + } + return WRC_Prune; + + case TK_BETWEEN: + sqlite3WalkExpr(pWalker, pExpr->pLeft); + return WRC_Prune; + /* Virtual tables are allowed to use constraints like x=NULL. So ** a term of the form x=y does not prove that y is not null if x ** is the column of a virtual table */ @@ -5096,6 +5196,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ){ return WRC_Prune; } + default: return WRC_Continue; } @@ -5125,7 +5226,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ */ int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ Walker w; - p = sqlite3ExprSkipCollate(p); + p = sqlite3ExprSkipCollateAndLikely(p); while( p ){ if( p->op==TK_NOTNULL ){ p = p->pLeft; @@ -5231,7 +5332,10 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ } if( inThis++; - }else{ + }else if( nSrc==0 || pExpr->iTablea[0].iCursor ){ + /* In a well-formed parse tree (no name resolution errors), + ** TK_COLUMN nodes with smaller Expr.iTable values are in an + ** outer context. Those are the only ones to count as "other" */ p->nOther++; } } @@ -5248,8 +5352,9 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; struct SrcCount cnt; assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); w.xExprCallback = exprSrcCount; - w.xSelectCallback = 0; + w.xSelectCallback = sqlite3SelectWalkNoop; w.u.pSrcCount = &cnt; cnt.pSrc = pSrcList; cnt.nThis = 0; @@ -5518,6 +5623,11 @@ void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ /* ** Mark all temporary registers as being unavailable for reuse. +** +** Always invoke this procedure after coding a subroutine or co-routine +** that might be invoked from other parts of the code, to ensure that +** the sub/co-routine does not use registers in common with the code that +** invokes the sub/co-routine. */ void sqlite3ClearTempRegCache(Parse *pParse){ pParse->nTempReg = 0; diff --git a/src/fkey.c b/src/fkey.c index 14ee983..fc75023 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -478,13 +478,13 @@ static Expr *exprTableRegister( if( iCol>=0 && iCol!=pTab->iPKey ){ pCol = &pTab->aCol[iCol]; pExpr->iTable = regBase + iCol + 1; - pExpr->affinity = pCol->affinity; + pExpr->affExpr = pCol->affinity; zColl = pCol->zColl; if( zColl==0 ) zColl = db->pDfltColl->zName; pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl); }else{ pExpr->iTable = regBase; - pExpr->affinity = SQLITE_AFF_INTEGER; + pExpr->affExpr = SQLITE_AFF_INTEGER; } } return pExpr; @@ -1287,7 +1287,7 @@ static Trigger *fkActionTrigger( tFrom.n = nFrom; pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ - pRaise->affinity = OE_Abort; + pRaise->affExpr = OE_Abort; } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), @@ -1332,6 +1332,7 @@ static Trigger *fkActionTrigger( return 0; } assert( pStep!=0 ); + assert( pTrigger!=0 ); switch( action ){ case OE_Restrict: diff --git a/src/func.c b/src/func.c index 5aea2d7..3201b6d 100644 --- a/src/func.c +++ b/src/func.c @@ -203,6 +203,8 @@ static void instrFunc( int N = 1; int isText; unsigned char firstChar; + sqlite3_value *pC1 = 0; + sqlite3_value *pC2 = 0; UNUSED_PARAMETER(argc); typeHaystack = sqlite3_value_type(argv[0]); @@ -215,12 +217,22 @@ static void instrFunc( zHaystack = sqlite3_value_blob(argv[0]); zNeedle = sqlite3_value_blob(argv[1]); isText = 0; - }else{ + }else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){ zHaystack = sqlite3_value_text(argv[0]); zNeedle = sqlite3_value_text(argv[1]); isText = 1; + }else{ + pC1 = sqlite3_value_dup(argv[0]); + zHaystack = sqlite3_value_text(pC1); + if( zHaystack==0 ) goto endInstrOOM; + nHaystack = sqlite3_value_bytes(pC1); + pC2 = sqlite3_value_dup(argv[1]); + zNeedle = sqlite3_value_text(pC2); + if( zNeedle==0 ) goto endInstrOOM; + nNeedle = sqlite3_value_bytes(pC2); + isText = 1; } - if( zNeedle==0 || (nHaystack && zHaystack==0) ) return; + if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM; firstChar = zNeedle[0]; while( nNeedle<=nHaystack && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0) @@ -234,6 +246,13 @@ static void instrFunc( if( nNeedle>nHaystack ) N = 0; } sqlite3_result_int(context, N); +endInstr: + sqlite3_value_free(pC1); + sqlite3_value_free(pC2); + return; +endInstrOOM: + sqlite3_result_error_nomem(context); + goto endInstr; } /* @@ -1986,9 +2005,6 @@ void sqlite3RegisterBuiltinFunctions(void){ sqlite3AlterFunctions(); #endif sqlite3WindowFunctions(); -#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) - sqlite3AnalyzeFunctions(); -#endif sqlite3RegisterDateTimeFunctions(); sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc)); diff --git a/src/global.c b/src/global.c index b512e6f..4689e94 100644 --- a/src/global.c +++ b/src/global.c @@ -214,6 +214,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0, /* bSmallMalloc */ + 1, /* bExtraSchemaChecks */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ @@ -260,6 +261,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* bInternalFunctions */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ + 0, /* iPrngSeed */ }; /* @@ -269,14 +271,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { */ FuncDefHash sqlite3BuiltinFunctions; -/* -** Constant tokens for values 0 and 1. -*/ -const Token sqlite3IntTokens[] = { - { "0", 1 }, - { "1", 1 } -}; - #ifdef VDBE_PROFILE /* ** The following performance counter can be used in place of diff --git a/src/insert.c b/src/insert.c index 2fe015f..d9078b8 100644 --- a/src/insert.c +++ b/src/insert.c @@ -88,18 +88,19 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ } for(n=0; nnColumn; n++){ i16 x = pIdx->aiColumn[n]; + char aff; if( x>=0 ){ - pIdx->zColAff[n] = pTab->aCol[x].affinity; + aff = pTab->aCol[x].affinity; }else if( x==XN_ROWID ){ - pIdx->zColAff[n] = SQLITE_AFF_INTEGER; + aff = SQLITE_AFF_INTEGER; }else{ - char aff; assert( x==XN_EXPR ); assert( pIdx->aColExpr!=0 ); aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); - if( aff==0 ) aff = SQLITE_AFF_BLOB; - pIdx->zColAff[n] = aff; } + if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; + pIdx->zColAff[n] = aff; } pIdx->zColAff[n] = 0; } @@ -139,11 +140,12 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ } for(i=0; inCol; i++){ + assert( pTab->aCol[i].affinity!=0 ); zColAff[i] = pTab->aCol[i].affinity; } do{ zColAff[i--] = 0; - }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); + }while( i>=0 && zColAff[i]<=SQLITE_AFF_BLOB ); pTab->zColAff = zColAff; } assert( zColAff!=0 ); @@ -832,6 +834,9 @@ void sqlite3Insert( pTab->zName); goto insert_cleanup; } + if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ + goto insert_cleanup; + } pTabList->a[0].iCursor = iDataCur; pUpsert->pUpsertSrc = pTabList; pUpsert->regData = regData; diff --git a/src/loadext.c b/src/loadext.c index 9ca139c..423a16f 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -461,7 +461,13 @@ static const sqlite3_api_routines sqlite3Apis = { #endif /* Version 3.28.0 and later */ sqlite3_stmt_isexplain, - sqlite3_value_frombind + sqlite3_value_frombind, + /* Version 3.30.0 and later */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_drop_modules, +#else + 0, +#endif }; /* diff --git a/src/main.c b/src/main.c index 6127006..3ef3a3d 100644 --- a/src/main.c +++ b/src/main.c @@ -836,6 +836,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ } aFlagOp[] = { { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, + { SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, @@ -1235,11 +1236,8 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ Module *pMod = (Module *)sqliteHashData(i); - if( pMod->xDestroy ){ - pMod->xDestroy(pMod->pAux); - } sqlite3VtabEponymousTableClear(db, pMod); - sqlite3DbFree(db, pMod); + sqlite3VtabModuleUnref(db, pMod); } sqlite3HashClear(&db->aModule); #endif @@ -1720,7 +1718,8 @@ int sqlite3CreateFunc( } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); - extraFlags = enc & SQLITE_DETERMINISTIC; + assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); + extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|SQLITE_SUBTYPE); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); #ifndef SQLITE_OMIT_UTF16 @@ -1783,6 +1782,7 @@ int sqlite3CreateFunc( p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); + testcase( p->funcFlags & SQLITE_DIRECTONLY ); p->xSFunc = xSFunc ? xSFunc : xStep; p->xFinalize = xFinal; p->xValue = xValue; @@ -3075,6 +3075,7 @@ static int openDatabase( db->nMaxSorterMmap = 0x7FFFFFFF; db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger + | SQLITE_EnableView | SQLITE_CacheSpill /* The SQLITE_DQS compile-time option determines the default settings @@ -3824,12 +3825,33 @@ int sqlite3_test_control(int op, ...){ break; } - /* - ** Reset the PRNG back to its uninitialized state. The next call - ** to sqlite3_randomness() will reseed the PRNG using a single call - ** to the xRandomness method of the default VFS. + /* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db); + ** + ** Control the seed for the pseudo-random number generator (PRNG) that + ** is built into SQLite. Cases: + ** + ** x!=0 && db!=0 Seed the PRNG to the current value of the + ** schema cookie in the main database for db, or + ** x if the schema cookie is zero. This case + ** is convenient to use with database fuzzers + ** as it allows the fuzzer some control over the + ** the PRNG seed. + ** + ** x!=0 && db==0 Seed the PRNG to the value of x. + ** + ** x==0 && db==0 Revert to default behavior of using the + ** xRandomness method on the primary VFS. + ** + ** This test-control also resets the PRNG so that the new seed will + ** be used for the next call to sqlite3_randomness(). */ - case SQLITE_TESTCTRL_PRNG_RESET: { + case SQLITE_TESTCTRL_PRNG_SEED: { + int x = va_arg(ap, int); + int y; + sqlite3 *db = va_arg(ap, sqlite3*); + assert( db==0 || db->aDb[0].pSchema!=0 ); + if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; } + sqlite3Config.iPrngSeed = x; sqlite3_randomness(0,0); break; } @@ -4042,6 +4064,17 @@ int sqlite3_test_control(int op, ...){ break; } + /* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int); + ** + ** Set or clear a flag that causes SQLite to verify that type, name, + ** and tbl_name fields of the sqlite_master table. This is normally + ** on, but it is sometimes useful to turn it off for testing. + */ + case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: { + sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int); + break; + } + /* Set the threshold at which OP_Once counters reset back to zero. ** By default this is 0x7ffffffe (over 2 billion), but that value is ** too big to test in a reasonable amount of time, so this control is diff --git a/src/memjournal.c b/src/memjournal.c index 3b0e7a6..0a14e84 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -96,14 +96,9 @@ static int memjrnlRead( int iChunkOffset; FileChunk *pChunk; -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; } -#endif - - assert( (iAmt+iOfst)<=p->endpoint.iOffset ); assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 ); if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ sqlite3_int64 iOff = 0; diff --git a/src/mutex.h b/src/mutex.h index 03eb1fa..a6806a2 100644 --- a/src/mutex.h +++ b/src/mutex.h @@ -67,4 +67,5 @@ #define MUTEX_LOGIC(X) #else #define MUTEX_LOGIC(X) X +int sqlite3_mutex_held(sqlite3_mutex*); #endif /* defined(SQLITE_MUTEX_OMIT) */ diff --git a/src/os.c b/src/os.c index 54b7fcf..b9ad29d 100644 --- a/src/os.c +++ b/src/os.c @@ -258,7 +258,15 @@ void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ } #endif /* SQLITE_OMIT_LOAD_EXTENSION */ int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return pVfs->xRandomness(pVfs, nByte, zBufOut); + if( sqlite3Config.iPrngSeed ){ + memset(zBufOut, 0, nByte); + if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int); + memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte); + return SQLITE_OK; + }else{ + return pVfs->xRandomness(pVfs, nByte, zBufOut); + } + } int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ return pVfs->xSleep(pVfs, nMicro); diff --git a/src/os_unix.c b/src/os_unix.c index f20763e..f2ac89f 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -105,13 +105,29 @@ # include #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ - (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) -# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ - && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) -# define HAVE_GETHOSTUUID 1 -# else -# warning "gethostuuid() is disabled." +/* +** Try to determine if gethostuuid() is available based on standard +** macros. This might sometimes compute the wrong value for some +** obscure platforms. For those cases, simply compile with one of +** the following: +** +** -DHAVE_GETHOSTUUID=0 +** -DHAVE_GETHOSTUUID=1 +** +** None if this matters except when building on Apple products with +** -DSQLITE_ENABLE_LOCKING_STYLE. +*/ +#ifndef HAVE_GETHOSTUUID +# define HAVE_GETHOSTUUID 0 +# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ + (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) +# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ + && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) +# undef HAVE_GETHOSTUUID +# define HAVE_GETHOSTUUID 1 +# else +# warning "gethostuuid() is disabled." +# endif # endif #endif @@ -521,13 +537,14 @@ static struct unix_syscall { #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) # ifdef __ANDROID__ { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, +#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) # else { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, +#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent) # endif #else { "ioctl", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) }; /* End of the overrideable system calls */ @@ -5769,6 +5786,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ UnixUnusedFd **pp; assert( sqlite3_mutex_notheld(pInode->pLockMutex) ); sqlite3_mutex_enter(pInode->pLockMutex); + flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); pUnused = *pp; if( pUnused ){ @@ -5822,7 +5840,7 @@ static int getFileMode( ** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the ** original filename is unavailable. But 8_3_NAMES is only used for ** FAT filesystems and permissions do not matter there, so just use -** the default permissions. +** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero. */ static int findCreateFileMode( const char *zPath, /* Path of file (possibly) being created */ @@ -6057,11 +6075,19 @@ static int unixOpen( goto open_finished; } - /* If this process is running as root and if creating a new rollback - ** journal or WAL file, set the ownership of the journal or WAL to be - ** the same as the original database. + /* The owner of the rollback journal or WAL file should always be the + ** same as the owner of the database file. Try to ensure that this is + ** the case. The chown() system call will be a no-op if the current + ** process lacks root privileges, be we should at least try. Without + ** this step, if a root process opens a database file, it can leave + ** behinds a journal/WAL that is owned by root and hence make the + ** database inaccessible to unprivileged processes. + ** + ** If openMode==0, then that means uid and gid are not set correctly + ** (probably because SQLite is configured to use 8+3 filename mode) and + ** in that case we do not want to attempt the chown(). */ - if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ + if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){ robustFchown(fd, uid, gid); } } @@ -6072,7 +6098,8 @@ static int unixOpen( if( p->pPreallocatedUnused ){ p->pPreallocatedUnused->fd = fd; - p->pPreallocatedUnused->flags = flags; + p->pPreallocatedUnused->flags = + flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); } if( isDelete ){ @@ -6918,7 +6945,7 @@ int sqlite3_hostid_num = 0; #define PROXY_HOSTIDLEN 16 /* conch file host id length */ -#ifdef HAVE_GETHOSTUUID +#if HAVE_GETHOSTUUID /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); #endif @@ -6929,7 +6956,7 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait); static int proxyGetHostID(unsigned char *pHostID, int *pError){ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memset(pHostID, 0, PROXY_HOSTIDLEN); -#ifdef HAVE_GETHOSTUUID +#if HAVE_GETHOSTUUID { struct timespec timeout = {1, 0}; /* 1 sec timeout */ if( gethostuuid(pHostID, &timeout) ){ @@ -7603,7 +7630,7 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ assert( 0 ); /* The call assures that only valid opcodes are sent */ } } - /*NOTREACHED*/ + /*NOTREACHED*/ assert(0); return SQLITE_ERROR; } diff --git a/src/os_win.c b/src/os_win.c index aafc89f..32758ab 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -4215,6 +4215,7 @@ static int winShmMap( rc = winOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; pShm = pDbFd->pShm; + assert( pShm!=0 ); } pShmNode = pShm->pShmNode; @@ -4517,6 +4518,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ } } if( pFd->mmapSize >= iOff+nAmt ){ + assert( pFd->pMapRegion!=0 ); *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } diff --git a/src/parse.y b/src/parse.y index fc5bff1..2b69dd5 100644 --- a/src/parse.y +++ b/src/parse.y @@ -211,6 +211,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT + NULLS FIRST LAST %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif SQLITE_OMIT_COMPOUND_SELECT @@ -458,6 +459,7 @@ cmd ::= select(X). { ** SQLITE_LIMIT_COMPOUND_SELECT. */ static void parserDoubleLinkSelect(Parse *pParse, Select *p){ + assert( p!=0 ); if( p->pPrior ){ Select *pNext = 0, *pLoop; int mxSelect, cnt = 0; @@ -780,13 +782,13 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} -sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). { +sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z) nulls(X). { A = sqlite3ExprListAppend(pParse,A,Y); - sqlite3ExprListSetSortOrder(A,Z); + sqlite3ExprListSetSortOrder(A,Z,X); } -sortlist(A) ::= expr(Y) sortorder(Z). { +sortlist(A) ::= expr(Y) sortorder(Z) nulls(X). { A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(A,Z); + sqlite3ExprListSetSortOrder(A,Z,X); } %type sortorder {int} @@ -795,6 +797,11 @@ sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;} +%type nulls {int} +nulls(A) ::= NULLS FIRST. {A = SQLITE_SO_ASC;} +nulls(A) ::= NULLS LAST. {A = SQLITE_SO_DESC;} +nulls(A) ::= . {A = SQLITE_SO_UNDEFINED;} + %type groupby_opt {ExprList*} %destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);} groupby_opt(A) ::= . {A = 0;} @@ -948,7 +955,7 @@ idlist(A) ::= nm(Y). if( p ){ /* memset(p, 0, sizeof(Expr)); */ p->op = (u8)op; - p->affinity = 0; + p->affExpr = 0; p->flags = EP_Leaf; p->iAgg = -1; p->pLeft = p->pRight = 0; @@ -1044,11 +1051,11 @@ expr(A) ::= id(X) LP STAR RP. { } %ifndef SQLITE_OMIT_WINDOWFUNC -expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_clause(Z). { +expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP filter_over(Z). { A = sqlite3ExprFunction(pParse, Y, &X, D); sqlite3WindowAttach(pParse, A, Z); } -expr(A) ::= id(X) LP STAR RP over_clause(Z). { +expr(A) ::= id(X) LP STAR RP filter_over(Z). { A = sqlite3ExprFunction(pParse, 0, &X, 0); sqlite3WindowAttach(pParse, A, Z); } @@ -1174,34 +1181,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, A); - A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); - }else if( Y->nExpr==1 ){ - /* Expressions of the form: - ** - ** expr1 IN (?1) - ** expr1 NOT IN (?2) - ** - ** with exactly one value on the RHS can be simplified to something - ** like this: - ** - ** expr1 == ?1 - ** expr1 <> ?2 - ** - ** But, the RHS of the == or <> is marked with the EP_Generic flag - ** so that it may not contribute to the computation of comparison - ** affinity or the collating sequence to use for comparison. Otherwise, - ** the semantics would be subtly different from IN or NOT IN. - */ - Expr *pRHS = Y->a[0].pExpr; - Y->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, Y); - /* pRHS cannot be NULL because a malloc error would have been detected - ** before now and control would have never reached this point */ - if( ALWAYS(pRHS) ){ - pRHS->flags &= ~EP_Collate; - pRHS->flags |= EP_Generic; - } - A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS); + A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0"); }else{ A = sqlite3PExpr(pParse, TK_IN, A, 0); if( A ){ @@ -1507,13 +1487,13 @@ trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E). expr(A) ::= RAISE LP IGNORE RP. { A = sqlite3PExpr(pParse, TK_RAISE, 0, 0); if( A ){ - A->affinity = OE_Ignore; + A->affExpr = OE_Ignore; } } expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. { A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); if( A ) { - A->affinity = (char)T; + A->affExpr = (char)T; } } %endif !SQLITE_OMIT_TRIGGER @@ -1657,8 +1637,14 @@ windowdefn(A) ::= nm(X) AS LP window(Y) RP. { %type part_opt {ExprList*} %destructor part_opt {sqlite3ExprListDelete(pParse->db, $$);} -%type filter_opt {Expr*} -%destructor filter_opt {sqlite3ExprDelete(pParse->db, $$);} +%type filter_clause {Expr*} +%destructor filter_clause {sqlite3ExprDelete(pParse->db, $$);} + +%type over_clause {Window*} +%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);} + +%type filter_over {Window*} +%destructor filter_over {sqlite3WindowDelete(pParse->db, $$);} %type range_or_rows {int} @@ -1724,25 +1710,35 @@ frame_exclude(A) ::= GROUP|TIES(X). {A = @X; /*A-overwrites-X*/} %destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);} window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; } -%type over_clause {Window*} -%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);} -over_clause(A) ::= filter_opt(W) OVER LP window(Z) RP. { - A = Z; - assert( A!=0 ); - A->pFilter = W; +filter_over(A) ::= filter_clause(F) over_clause(O). { + O->pFilter = F; + A = O; } -over_clause(A) ::= filter_opt(W) OVER nm(Z). { +filter_over(A) ::= over_clause(O). { + A = O; +} +filter_over(A) ::= filter_clause(F). { A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( A ){ - A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n); - A->pFilter = W; + A->eFrmType = TK_FILTER; + A->pFilter = F; }else{ - sqlite3ExprDelete(pParse->db, W); + sqlite3ExprDelete(pParse->db, F); } } -filter_opt(A) ::= . { A = 0; } -filter_opt(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } +over_clause(A) ::= OVER LP window(Z) RP. { + A = Z; + assert( A!=0 ); +} +over_clause(A) ::= OVER nm(Z). { + A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( A ){ + A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n); + } +} + +filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } %endif /* SQLITE_OMIT_WINDOWFUNC */ /* @@ -1750,12 +1746,12 @@ filter_opt(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } ** are synthesized and do not actually appear in the grammar: */ %token - TRUEFALSE /* True or false keyword */ - ISNOT /* Combination of IS and NOT */ - FUNCTION /* A function invocation */ COLUMN /* Reference to a table column */ AGG_FUNCTION /* An aggregate function */ AGG_COLUMN /* An aggregated column */ + TRUEFALSE /* True or false keyword */ + ISNOT /* Combination of IS and NOT */ + FUNCTION /* A function invocation */ UMINUS /* Unary minus */ UPLUS /* Unary plus */ TRUTH /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */ diff --git a/src/pcache.c b/src/pcache.c index 9125d5d..36829be 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -262,6 +262,7 @@ int sqlite3PcacheInitialize(void){ ** built-in default page cache is used instead of the application defined ** page cache. */ sqlite3PCacheSetDefault(); + assert( sqlite3GlobalConfig.pcache2.xInit!=0 ); } return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); } diff --git a/src/pcache1.c b/src/pcache1.c index c9d5586..d005143 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -424,6 +424,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ + assert( pCache->pFree!=0 ); p = pCache->pFree; pCache->pFree = p->pNext; p->pNext = 0; diff --git a/src/pragma.c b/src/pragma.c index a62fc99..858e314 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1157,6 +1157,15 @@ void sqlite3Pragma( Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx==0 ){ + /* If there is no index named zRight, check to see if there is a + ** WITHOUT ROWID table named zRight, and if there is, show the + ** structure of the PRIMARY KEY index for that table. */ + pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); + if( pTab && !HasRowid(pTab) ){ + pIdx = sqlite3PrimaryKeyIndex(pTab); + } + } if( pIdx ){ int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); int i; @@ -1236,7 +1245,7 @@ void sqlite3Pragma( } break; -#ifdef SQLITE_INTROSPECTION_PRAGMAS +#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS case PragTyp_FUNCTION_LIST: { int i; HashElem *j; diff --git a/src/pragma.h b/src/pragma.h index 11e55ee..b7f3282 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -311,7 +311,7 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_FullFSync }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "function_list", /* ePragTyp: */ PragTyp_FUNCTION_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -435,7 +435,7 @@ static const PragmaName aPragmaName[] = { #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) #if !defined(SQLITE_OMIT_VIRTUALTABLE) -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "module_list", /* ePragTyp: */ PragTyp_MODULE_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -470,7 +470,7 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_ParserTrace }, #endif #endif -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "pragma_list", /* ePragTyp: */ PragTyp_PRAGMA_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -668,4 +668,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, #endif }; -/* Number of pragmas: 62 on by default, 81 total. */ +/* Number of pragmas: 65 on by default, 81 total. */ diff --git a/src/prepare.c b/src/prepare.c index 3f1a79b..70c1626 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -64,9 +64,11 @@ int sqlite3IndexHasDuplicateRootPage(Index *pIndex){ ** ** Each callback contains the following information: ** -** argv[0] = name of thing being created -** argv[1] = root page number for table or index. 0 for trigger or view. -** argv[2] = SQL text for the CREATE statement. +** argv[0] = type of object: "table", "index", "trigger", or "view". +** argv[1] = name of thing being created +** argv[2] = associated table if an index or trigger +** argv[3] = root page number for table or index. 0 for trigger or view. +** argv[4] = SQL text for the CREATE statement. ** */ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ @@ -74,21 +76,21 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ sqlite3 *db = pData->db; int iDb = pData->iDb; - assert( argc==3 ); + assert( argc==5 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); DbClearProperty(db, iDb, DB_Empty); pData->nInitRow++; if( db->mallocFailed ){ - corruptSchema(pData, argv[0], 0); + corruptSchema(pData, argv[1], 0); return 1; } assert( iDb>=0 && iDbnDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if( argv[1]==0 ){ - corruptSchema(pData, argv[0], 0); - }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){ + if( argv[3]==0 ){ + corruptSchema(pData, argv[1], 0); + }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){ /* 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 @@ -101,9 +103,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ assert( db->init.busy ); db->init.iDb = iDb; - db->init.newTnum = sqlite3Atoi(argv[1]); + db->init.newTnum = sqlite3Atoi(argv[3]); db->init.orphanTrigger = 0; - TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); + db->init.azInit = argv; + TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = saved_iDb; @@ -112,17 +115,17 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ - pData->rc = rc; + if( rc > pData->rc ) pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ - corruptSchema(pData, argv[0], sqlite3_errmsg(db)); + corruptSchema(pData, argv[1], sqlite3_errmsg(db)); } } } sqlite3_finalize(pStmt); - }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ - corruptSchema(pData, argv[0], 0); + }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){ + corruptSchema(pData, argv[1], 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 @@ -131,13 +134,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ ** to do here is record the root page number for that index. */ Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName); + pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName); if( pIndex==0 - || sqlite3GetInt32(argv[1],&pIndex->tnum)==0 + || sqlite3GetInt32(argv[3],&pIndex->tnum)==0 || pIndex->tnum<2 || sqlite3IndexHasDuplicateRootPage(pIndex) ){ - corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index"); + corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index"); } } return 0; @@ -158,7 +161,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ int size; #endif Db *pDb; - char const *azArg[4]; + char const *azArg[6]; int meta[5]; InitData initData; const char *zMasterName; @@ -177,18 +180,20 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ ** table name will be inserted automatically by the parser so we can just ** use the abbreviation "x" here. The parser will also automatically tag ** the schema table as read-only. */ - azArg[0] = zMasterName = SCHEMA_TABLE(iDb); - azArg[1] = "1"; - azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text," + azArg[0] = "table"; + azArg[1] = zMasterName = SCHEMA_TABLE(iDb); + azArg[2] = azArg[1]; + azArg[3] = "1"; + azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text," "rootpage int,sql text)"; - azArg[3] = 0; + azArg[5] = 0; initData.db = db; initData.iDb = iDb; initData.rc = SQLITE_OK; initData.pzErrMsg = pzErrMsg; initData.mInitFlags = mFlags; initData.nInitRow = 0; - sqlite3InitCallback(&initData, 3, (char **)azArg, 0); + sqlite3InitCallback(&initData, 5, (char **)azArg, 0); if( initData.rc ){ rc = initData.rc; goto error_out; @@ -314,7 +319,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ { char *zSql; zSql = sqlite3MPrintf(db, - "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", + "SELECT*FROM\"%w\".%s ORDER BY rowid", db->aDb[iDb].zDbSName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { @@ -635,7 +640,10 @@ static int sqlite3Prepare( rc = sParse.rc; #ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + /* Justification for the ALWAYS(): The only way for rc to be SQLITE_OK and + ** sParse.pVdbe to be NULL is if the input SQL is an empty string, but in + ** that case, sParse.explain will be false. */ + if( sParse.explain && rc==SQLITE_OK && ALWAYS(sParse.pVdbe) ){ static const char * const azColName[] = { "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", "id", "parent", "notused", "detail" @@ -660,8 +668,8 @@ static int sqlite3Prepare( if( db->init.busy==0 ){ sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags); } - if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(sParse.pVdbe); + if( rc!=SQLITE_OK || db->mallocFailed ){ + if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe); assert(!(*ppStmt)); }else{ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; diff --git a/src/resolve.c b/src/resolve.c index 8dac077..e66dc18 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -96,6 +96,13 @@ static void resolveAlias( pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); pExpr->flags |= EP_MemToken; } + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + if( pExpr->y.pWin!=0 ){ + pExpr->y.pWin->pOwner = pExpr; + }else{ + assert( db->mallocFailed ); + } + } sqlite3DbFree(db, pDup); } ExprSetProperty(pExpr, EP_Alias); @@ -381,7 +388,7 @@ static int lookupName( { #ifndef SQLITE_OMIT_TRIGGER if( iCol<0 ){ - pExpr->affinity = SQLITE_AFF_INTEGER; + pExpr->affExpr = SQLITE_AFF_INTEGER; }else if( pExpr->iTable==0 ){ testcase( iCol==31 ); testcase( iCol==32 ); @@ -413,7 +420,7 @@ static int lookupName( ){ cnt = 1; pExpr->iColumn = -1; - pExpr->affinity = SQLITE_AFF_INTEGER; + pExpr->affExpr = SQLITE_AFF_INTEGER; } /* @@ -689,7 +696,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->y.pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; pExpr->iColumn = -1; - pExpr->affinity = SQLITE_AFF_INTEGER; + pExpr->affExpr = SQLITE_AFF_INTEGER; break; } #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) @@ -749,7 +756,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin)); - +#ifndef SQLITE_OMIT_WINDOWFUNC + Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0); +#endif assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); @@ -821,6 +830,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** SQL is being compiled using sqlite3NestedParse() */ no_such_func = 1; pDef = 0; + }else + if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 + && ExprHasProperty(pExpr, EP_Indirect) + && !IN_RENAME_OBJECT + ){ + /* Functions tagged with SQLITE_DIRECTONLY may not be used + ** inside of triggers and views */ + sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views", + pDef->zName); } } @@ -830,18 +848,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ || (pDef->xValue==0 && pDef->xInverse==0) || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ); - if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ + if( pDef && pDef->xValue==0 && pWin ){ sqlite3ErrorMsg(pParse, "%.*s() may not be used as a window function", nId, zId ); pNC->nErr++; }else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) - || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) + || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin) + || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0) ){ const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ + if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){ zType = "window"; }else{ zType = "aggregate"; @@ -869,34 +887,44 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ nId, zId); pNC->nErr++; } +#ifndef SQLITE_OMIT_WINDOWFUNC + else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ + sqlite3ErrorMsg(pParse, + "FILTER may not be used with non-aggregate %.*s()", + nId, zId + ); + pNC->nErr++; + } +#endif if( is_agg ){ /* Window functions may not be arguments of aggregate functions. ** Or arguments of other window functions. But aggregate functions ** may be arguments for window functions. */ #ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(NC_AllowWin | (!pExpr->y.pWin ? NC_AllowAgg : 0)); + pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0)); #else pNC->ncFlags &= ~NC_AllowAgg; #endif } } +#ifndef SQLITE_OMIT_WINDOWFUNC + else if( ExprHasProperty(pExpr, EP_WinFunc) ){ + is_agg = 1; + } +#endif sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pExpr->y.pWin ){ + if( pWin ){ Select *pSel = pNC->pWinSelect; + assert( pWin==pExpr->y.pWin ); if( IN_RENAME_OBJECT==0 ){ - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); - } - sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); - sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); - if( 0==pSel->pWin - || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) - ){ - pExpr->y.pWin->pNextWin = pSel->pWin; - pSel->pWin = pExpr->y.pWin; + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pWin, pDef); } + sqlite3WalkExprList(pWalker, pWin->pPartition); + sqlite3WalkExprList(pWalker, pWin->pOrderBy); + sqlite3WalkExpr(pWalker, pWin->pFilter); + sqlite3WindowLink(pSel, pWin); pNC->ncFlags |= NC_HasWin; }else #endif /* SQLITE_OMIT_WINDOWFUNC */ @@ -904,12 +932,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ NameContext *pNC2 = pNC; pExpr->op = TK_AGG_FUNCTION; pExpr->op2 = 0; +#ifndef SQLITE_OMIT_WINDOWFUNC + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); + } +#endif while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ pExpr->op2++; pNC2 = pNC2->pNext; } - assert( pDef!=0 ); - if( pNC2 ){ + assert( pDef!=0 || IN_RENAME_OBJECT ); + if( pNC2 && pDef ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); @@ -947,7 +980,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } case TK_IS: case TK_ISNOT: { - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); + Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight); assert( !ExprHasProperty(pExpr, EP_Reduced) ); /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", ** and "x IS NOT FALSE". */ @@ -1158,7 +1191,7 @@ static int resolveCompoundOrderBy( int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; - pE = sqlite3ExprSkipCollate(pItem->pExpr); + pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); @@ -1252,7 +1285,7 @@ int sqlite3ResolveOrderGroupBy( ExprList *pEList; struct ExprList_item *pItem; - if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; + if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0; if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); return 1; @@ -1274,17 +1307,13 @@ int sqlite3ResolveOrderGroupBy( #ifndef SQLITE_OMIT_WINDOWFUNC /* -** Walker callback for resolveRemoveWindows(). +** Walker callback for windowRemoveExprFromSelect(). */ static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ + UNUSED_PARAMETER(pWalker); if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window **pp; - for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pExpr->y.pWin ){ - *pp = (*pp)->pNextWin; - break; - } - } + Window *pWin = pExpr->y.pWin; + sqlite3WindowUnlinkFromSelect(pWin); } return WRC_Continue; } @@ -1293,16 +1322,18 @@ static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ ** Remove any Window objects owned by the expression pExpr from the ** Select.pWin list of Select object pSelect. */ -static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){ - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.xExprCallback = resolveRemoveWindowsCb; - sWalker.u.pSelect = pSelect; - sqlite3WalkExpr(&sWalker, pExpr); +static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){ + if( pSelect->pWin ){ + Walker sWalker; + memset(&sWalker, 0, sizeof(Walker)); + sWalker.xExprCallback = resolveRemoveWindowsCb; + sWalker.u.pSelect = pSelect; + sqlite3WalkExpr(&sWalker, pExpr); + } } #else -# define resolveRemoveWindows(x,y) -#endif +# define windowRemoveExprFromSelect(a, b) +#endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. @@ -1339,7 +1370,7 @@ static int resolveOrderGroupBy( pParse = pNC->pParse; for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ Expr *pE = pItem->pExpr; - Expr *pE2 = sqlite3ExprSkipCollate(pE); + Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE); if( zType[0]!='G' ){ iCol = resolveAsName(pParse, pSelect->pEList, pE2); if( iCol>0 ){ @@ -1373,7 +1404,7 @@ static int resolveOrderGroupBy( /* Since this expresion is being changed into a reference ** to an identical expression in the result set, remove all Window ** objects belonging to the expression from the Select.pWin list. */ - resolveRemoveWindows(pSelect, pE); + windowRemoveExprFromSelect(pSelect, pE); pItem->u.x.iOrderByCol = j+1; } } diff --git a/src/select.c b/src/select.c index 53d33a7..7cc5cde 100644 --- a/src/select.c +++ b/src/select.c @@ -100,6 +100,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ sqlite3WindowListDelete(db, p->pWinDefn); } + assert( p->pWin==0 ); #endif if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); @@ -663,7 +664,7 @@ static void pushOntoSorter( if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; - memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ + memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); testcase( pKI->nAllField > pKI->nKeyField+2 ); pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, @@ -1274,7 +1275,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*); KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ - p->aSortOrder = (u8*)&p->aColl[N+X]; + p->aSortFlags = (u8*)&p->aColl[N+X]; p->nKeyField = (u16)N; p->nAllField = (u16)(N+X); p->enc = ENC(db); @@ -1351,7 +1352,7 @@ KeyInfo *sqlite3KeyInfoFromExprList( assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; iaColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); - pInfo->aSortOrder[i-iStart] = pItem->sortOrder; + pInfo->aSortFlags[i-iStart] = pItem->sortFlags; } } return pInfo; @@ -1643,8 +1644,6 @@ static const char *columnTypeImpl( assert( pExpr!=0 ); assert( pNC->pSrcList!=0 ); - assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates - ** are processed */ switch( pExpr->op ){ case TK_COLUMN: { /* The expression is a column. Locate the table the column is being @@ -1961,12 +1960,11 @@ int sqlite3ColumnsFromExprList( if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS " phrase, use as the name */ }else{ - Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr); + Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr); while( pColExpr->op==TK_DOT ){ pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } - assert( pColExpr->op!=TK_AGG_COLUMN ); if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; @@ -2034,7 +2032,8 @@ int sqlite3ColumnsFromExprList( void sqlite3SelectAddColumnTypeAndCollation( Parse *pParse, /* Parsing contexts */ Table *pTab, /* Add column type information to this table */ - Select *pSelect /* SELECT used to determine types and collations */ + Select *pSelect, /* SELECT used to determine types and collations */ + char aff /* Default affinity for columns */ ){ sqlite3 *db = pParse->db; NameContext sNC; @@ -2067,7 +2066,7 @@ void sqlite3SelectAddColumnTypeAndCollation( pCol->colFlags |= COLFLAG_HASTYPE; } } - if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; + if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl && pCol->zColl==0 ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); @@ -2080,7 +2079,7 @@ void sqlite3SelectAddColumnTypeAndCollation( ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ -Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ +Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){ Table *pTab; sqlite3 *db = pParse->db; u64 savedFlags; @@ -2100,7 +2099,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); @@ -2254,7 +2253,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ } assert( sqlite3KeyInfoIsWriteable(pRet) ); pRet->aColl[i] = pColl; - pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder; + pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags; } } @@ -2965,11 +2964,14 @@ static int generateOutputSubroutine( /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out - ** of the scan loop. + ** of the scan loop. Note that the select might return multiple columns + ** if it is the RHS of a row-value IN operator. */ case SRT_Mem: { - assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); + if( pParse->nErr==0 ){ + testcase( pIn->nSdst>1 ); + sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst); + } /* The LIMIT clause will jump out of the loop for us */ break; } @@ -3226,7 +3228,7 @@ static int multiSelectOrderBy( assert( sqlite3KeyInfoIsWriteable(pKeyDup) ); for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); - pKeyDup->aSortOrder[i] = 0; + pKeyDup->aSortFlags[i] = 0; } } } @@ -3476,6 +3478,18 @@ static Expr *substExpr( } sqlite3ExprDelete(db, pExpr); pExpr = pNew; + + /* 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); + } } } }else{ @@ -3489,6 +3503,14 @@ static Expr *substExpr( }else{ substExprList(pSubst, pExpr->x.pList); } +#ifndef SQLITE_OMIT_WINDOWFUNC + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window *pWin = pExpr->y.pWin; + pWin->pFilter = substExpr(pSubst, pWin->pFilter); + substExprList(pSubst, pWin->pPartition); + substExprList(pSubst, pWin->pOrderBy); + } +#endif } return pExpr; } @@ -3949,6 +3971,7 @@ static int flattenSubquery( for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ int nSubSrc; u8 jointype = 0; + assert( pSub!=0 ); pSubSrc = pSub->pSrc; /* FROM clause of subquery */ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ pSrc = pParent->pSrc; /* FROM clause of the outer query */ @@ -4399,24 +4422,27 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */ const char *zFunc; /* Name of aggregate function pFunc */ ExprList *pOrderBy; - u8 sortOrder; + u8 sortFlags; assert( *ppMinMax==0 ); assert( pFunc->op==TK_AGG_FUNCTION ); - if( pEList==0 || pEList->nExpr!=1 ) return eRet; + assert( !IsWindowFunc(pFunc) ); + if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){ + return eRet; + } zFunc = pFunc->u.zToken; if( sqlite3StrICmp(zFunc, "min")==0 ){ eRet = WHERE_ORDERBY_MIN; - sortOrder = SQLITE_SO_ASC; + sortFlags = KEYINFO_ORDER_BIGNULL; }else if( sqlite3StrICmp(zFunc, "max")==0 ){ eRet = WHERE_ORDERBY_MAX; - sortOrder = SQLITE_SO_DESC; + sortFlags = KEYINFO_ORDER_DESC; }else{ return eRet; } *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); assert( pOrderBy!=0 || db->mallocFailed ); - if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder; + if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags; return eRet; } @@ -4450,7 +4476,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( NEVER(pAggInfo->nFunc==0) ) return 0; if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0; - if( pExpr->flags&EP_Distinct ) return 0; + if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0; return pTab; } @@ -4897,6 +4923,10 @@ 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 ){ + sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", + pTab->zName); + } pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); nCol = pTab->nCol; pTab->nCol = -1; @@ -5190,7 +5220,8 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Select *pSel = pFrom->pSelect; if( pSel ){ while( pSel->pPrior ) pSel = pSel->pPrior; - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel, + SQLITE_AFF_NONE); } } } @@ -5330,6 +5361,25 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ int regAgg; ExprList *pList = pF->pExpr->x.pList; assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); + assert( !IsWindowFunc(pF->pExpr) ); + if( ExprHasProperty(pF->pExpr, EP_WinFunc) ){ + Expr *pFilter = pF->pExpr->y.pWin->pFilter; + if( pAggInfo->nAccumulator + && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + ){ + if( regHit==0 ) regHit = ++pParse->nMem; + /* If this is the first row of the group (regAcc==0), clear the + ** "magnet" register regHit so that the accumulator registers + ** are populated if the FILTER clause jumps over the the + ** invocation of min() or max() altogether. Or, if this is not + ** the first row (regAcc==1), set the magnet register so that the + ** accumulators are not populated unless the min()/max() is invoked and + ** indicates that they should be. */ + sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit); + } + addrNext = sqlite3VdbeMakeLabel(pParse); + sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL); + } if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); @@ -5339,7 +5389,9 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ regAgg = 0; } if( pF->iDistinct>=0 ){ - addrNext = sqlite3VdbeMakeLabel(pParse); + if( addrNext==0 ){ + addrNext = sqlite3VdbeMakeLabel(pParse); + } testcase( nArg==0 ); /* Error condition */ testcase( nArg>1 ); /* Also an error */ codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); @@ -5375,6 +5427,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } + pAggInfo->directMode = 0; if( addrHitTest ){ sqlite3VdbeJumpHere(v, addrHitTest); @@ -5420,7 +5473,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ Select *pS = pWalker->u.pSelect; if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){ sqlite3 *db = pWalker->pParse->db; - Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); @@ -5842,7 +5895,7 @@ int sqlite3Select( ** assume the column name is non-NULL and segfault. The use of an empty ** string for the fake column name seems safer. */ - if( pItem->colUsed==0 ){ + if( pItem->colUsed==0 && pItem->zName!=0 ){ sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); } @@ -5856,8 +5909,15 @@ int sqlite3Select( ** 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. */ - assert( pItem->addrFillSub==0 ); + ** 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 ); /* Increment Parse.nHeight by the height of the largest expression ** tree referred to by this, the parent select. The child select @@ -5931,7 +5991,7 @@ int sqlite3Select( int retAddr; struct SrcList_item *pPrior; - assert( pItem->addrFillSub==0 ); + testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */ pItem->regReturn = ++pParse->nMem; topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); pItem->addrFillSub = topAddr+1; @@ -6171,23 +6231,35 @@ int sqlite3Select( } assert( 66==sqlite3LogEst(100) ); if( p->nSelectRow>66 ) p->nSelectRow = 66; + + /* If there is both a GROUP BY and an ORDER BY clause and they are + ** identical, then it may be possible to disable the ORDER BY clause + ** on the grounds that the GROUP BY will cause elements to come out + ** in the correct order. It also may not - the GROUP BY might use a + ** database index that causes rows to be grouped together as required + ** but not actually sorted. Either way, record the fact that the + ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp + ** variable. */ + if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){ + int ii; + /* The GROUP BY processing doesn't care whether rows are delivered in + ** ASC or DESC order - only that each group is returned contiguously. + ** So set the ASC/DESC flags in the GROUP BY to match those in the + ** ORDER BY to maximize the chances of rows being delivered in an + ** order that makes the ORDER BY redundant. */ + for(ii=0; iinExpr; ii++){ + u8 sortFlags = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC; + pGroupBy->a[ii].sortFlags = sortFlags; + } + if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ + orderByGrp = 1; + } + } }else{ assert( 0==sqlite3LogEst(1) ); p->nSelectRow = 0; } - /* If there is both a GROUP BY and an ORDER BY clause and they are - ** identical, then it may be possible to disable the ORDER BY clause - ** on the grounds that the GROUP BY will cause elements to come out - ** in the correct order. It also may not - the GROUP BY might use a - ** database index that causes rows to be grouped together as required - ** but not actually sorted. Either way, record the fact that the - ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp - ** variable. */ - if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ - orderByGrp = 1; - } - /* Create a label to jump to when we want to abort the query */ addrEnd = sqlite3VdbeMakeLabel(pParse); @@ -6222,9 +6294,16 @@ int sqlite3Select( minMaxFlag = WHERE_ORDERBY_NORMAL; } for(i=0; ix.pList); + sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList); +#ifndef SQLITE_OMIT_WINDOWFUNC + assert( !IsWindowFunc(pExpr) ); + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter); + } +#endif sNC.ncFlags &= ~NC_InAggFunc; } sAggInfo.mxReg = pParse->nMem; @@ -6536,13 +6615,18 @@ int sqlite3Select( { int regAcc = 0; /* "populate accumulators" flag */ - /* If there are accumulator registers but no min() or max() functions, - ** allocate register regAcc. Register regAcc will contain 0 the first - ** time the inner loop runs, and 1 thereafter. The code generated - ** by updateAccumulator() only updates the accumulator registers if - ** regAcc contains 0. */ + /* If there are accumulator registers but no min() or max() functions + ** without FILTER clauses, allocate register regAcc. Register regAcc + ** will contain 0 the first time the inner loop runs, and 1 thereafter. + ** The code generated by updateAccumulator() uses this to ensure + ** that the accumulator registers are (a) updated only once if + ** there are no min() or max functions or (b) always updated for the + ** first row visited by the aggregate, so that they are updated at + ** least once even if the FILTER clause means the min() or max() + ** function visits zero rows. */ if( sAggInfo.nAccumulator ){ for(i=0; ifuncFlags&SQLITE_FUNC_NEEDCOLL ) break; } if( i==sAggInfo.nFunc ){ diff --git a/src/shell.c.in b/src/shell.c.in index f3edee2..7f82675 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1256,12 +1256,12 @@ static void editFunc( } sz = sqlite3_value_bytes(argv[0]); if( bBin ){ - x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f); + x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f); }else{ const char *z = (const char*)sqlite3_value_text(argv[0]); /* Remember whether or not the value originally contained \r\n */ if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; - x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f); + x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f); } fclose(f); f = 0; @@ -1289,12 +1289,12 @@ static void editFunc( fseek(f, 0, SEEK_END); sz = ftell(f); rewind(f); - p = sqlite3_malloc64( sz+(bBin==0) ); + p = sqlite3_malloc64( sz+1 ); if( p==0 ){ sqlite3_result_error_nomem(context); goto edit_func_end; } - x = fread(p, 1, sz, f); + x = fread(p, 1, (size_t)sz, f); fclose(f); f = 0; if( x!=sz ){ @@ -1766,7 +1766,8 @@ static void eqp_render_level(ShellState *p, int iEqpId){ for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ pNext = eqp_next_row(p, iEqpId, pRow); z = pRow->zText; - utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); + utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, + pNext ? "|--" : "`--", z); if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); eqp_render_level(p, pRow->iEqpId); @@ -1957,7 +1958,7 @@ static int shell_callback( while( j>0 && IsSpace(z[j-1]) ){ j--; } z[j] = 0; if( strlen30(z)>=79 ){ - for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */ + for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ if( c==cEnd ){ cEnd = 0; }else if( c=='"' || c=='\'' || c=='`' ){ @@ -2536,7 +2537,7 @@ static int display_stats( raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); raw_printf(pArg->out, "Number of times run: %d\n", iCur); @@ -3459,20 +3460,20 @@ static const char *(azHelp[]) = { ".archive ... Manage SQL archives", " Each command must have exactly one of the following options:", " -c, --create Create a new archive", - " -u, --update Add files or update files with changed mtime", - " -i, --insert Like -u but always add even if mtime unchanged", + " -u, --update Add or update files with changed mtime", + " -i, --insert Like -u but always add even if unchanged", " -t, --list List contents of archive", " -x, --extract Extract files from archive", " Optional arguments:", " -v, --verbose Print each filename as it is processed", - " -f FILE, --file FILE Operate on archive FILE (default is current db)", - " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", - " -C DIR, --directory DIR Change to directory DIR to read/extract files", + " -f FILE, --file FILE Use archive FILE (default is current db)", + " -a FILE, --append FILE Open FILE using the apndvfs VFS", + " -C DIR, --directory DIR Read/extract files from directory DIR", " -n, --dryrun Show the SQL that would have occurred", " Examples:", - " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", - " .ar -tf archive.sar # List members of archive.sar", - " .ar -xvf archive.sar # Verbosely extract files from archive.sar", + " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", + " .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", #endif @@ -3481,7 +3482,7 @@ static const char *(azHelp[]) = { #endif ".backup ?DB? FILE Backup DB (default \"main\") to FILE", " --append Use the appendvfs", - " --async Write to FILE without a journal and without fsync()", + " --async Write to FILE without journal and fsync()", ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", ".cd DIRECTORY Change the working directory to DIRECTORY", @@ -3501,15 +3502,15 @@ static const char *(azHelp[]) = { " Other Modes:", #ifdef SQLITE_DEBUG " test Show raw EXPLAIN QUERY PLAN output", - " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"", + " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", - ".excel Display the output of next command in a spreadsheet", + ".excel Display the output of next command in spreadsheet", ".exit ?CODE? Exit this program with return-code CODE", - ".expert EXPERIMENTAL. Suggest indexes for specified queries", + ".expert EXPERIMENTAL. Suggest indexes for queries", /* Because explain mode comes on automatically now, the ".explain" mode -** is removed from the help screen. It is still supported for legacy, however */ -/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ +** is removed from the help screen. It is still supported for legacy, however */ +/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off",*/ ".filectrl CMD ... Run various sqlite3_file_control() operations", " Run \".filectrl\" with no arguments for details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", @@ -3556,7 +3557,7 @@ static const char *(azHelp[]) = { " --append Use appendvfs to append database to the end of FILE", #ifdef SQLITE_ENABLE_DESERIALIZE " --deserialize Load into memory useing sqlite3_deserialize()", - " --hexdb Load the output of \"dbtotxt\" as an in-memory database", + " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", @@ -3569,7 +3570,7 @@ static const char *(azHelp[]) = { " init Initialize the TEMP table that holds bindings", " list List the current parameter bindings", " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", - " PARAMETER should start with '$', ':', '@', or '?'", + " PARAMETER should start with one of: $ : @ ?", " unset PARAMETER Remove PARAMETER from the binding table", ".print STRING... Print literal STRING", #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -3584,6 +3585,11 @@ static const char *(azHelp[]) = { ".read FILE Read input from FILE", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".recover Recover as much data as possible from corrupt db.", + " --freelist-corrupt Assume the freelist is corrupt", + " --recovery-db NAME Store recovery metadata in database file NAME", + " --lost-and-found TABLE Alternative name for the lost-and-found table", + " --no-rowids Do not attempt to recover rowid values", + " that are not also INTEGER PRIMARY KEYs", #endif ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ".save FILE Write in-memory database into FILE", @@ -3615,7 +3621,7 @@ static const char *(azHelp[]) = { " Options:", " --schema Also hash the sqlite_master table", " --sha3-224 Use the sha3-224 algorithm", - " --sha3-256 Use the sha3-256 algorithm. This is the default.", + " --sha3-256 Use the sha3-256 algorithm (default)", " --sha3-384 Use the sha3-384 algorithm", " --sha3-512 Use the sha3-512 algorithm", " Any other argument is a LIKE pattern for tables to hash", @@ -3649,6 +3655,10 @@ static const char *(azHelp[]) = { " --row Trace each row (SQLITE_TRACE_ROW)", " --close Trace connection close (SQLITE_TRACE_CLOSE)", #endif /* SQLITE_OMIT_TRACE */ +#ifdef SQLITE_DEBUG + ".unmodule NAME ... Unregister virtual table modules", + " --allexcept Unregister everything except those named", +#endif ".vfsinfo ?AUX? Information about the top-level VFS", ".vfslist List all available VFSes", ".vfsname ?AUX? Print the name of the VFS stack", @@ -3891,6 +3901,8 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){ rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); if( rc!=2 ) goto readHexDb_error; if( n<0 ) goto readHexDb_error; + if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error; + n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ a = sqlite3_malloc( n ? n : 1 ); if( a==0 ){ utf8_printf(stderr, "Out of memory!\n"); @@ -3975,6 +3987,23 @@ static void shellInt32( } } +/* +** Scalar function "shell_idquote(X)" returns string X quoted as an identifier, +** using "..." with internal double-quote characters doubled. +*/ +static void shellIdQuote( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName = (const char*)sqlite3_value_text(argv[0]); + UNUSED_PARAMETER(argc); + if( zName ){ + char *z = sqlite3_mprintf("\"%w\"", zName); + sqlite3_result_text(context, z, -1, sqlite3_free); + } +} + /* ** Scalar function "shell_escape_crnl" used by the .recover command. ** The argument passed to this function is the output of built-in @@ -4151,6 +4180,8 @@ static void open_db(ShellState *p, int openFlags){ shellEscapeCrnl, 0, 0); sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, shellInt32, 0, 0); + sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0, + shellIdQuote, 0, 0); #ifndef SQLITE_NOHAVE_SYSTEM sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); @@ -5498,7 +5529,7 @@ void shellReset( #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) -/********************************************************************************* +/****************************************************************************** ** The ".archive" or ".ar" command. */ /* @@ -5696,7 +5727,8 @@ static int arParseCommand( i = n; }else{ if( iArg>=(nArg-1) ){ - return arErrorMsg(pAr, "option requires an argument: %c",z[i]); + return arErrorMsg(pAr, "option requires an argument: %c", + z[i]); } zArg = azArg[++iArg]; } @@ -6084,10 +6116,10 @@ end_ar_transaction: ** Implementation of ".ar" dot command. */ static int arDotCommand( - ShellState *pState, /* Current shell tool state */ - int fromCmdLine, /* True if -A command-line option, not .ar cmd */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + int fromCmdLine, /* True if -A command-line option, not .ar cmd */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ ArCommand cmd; int rc; @@ -6187,7 +6219,7 @@ end_ar_command: return rc; } /* End of the ".archive" or ".ar" command logic -**********************************************************************************/ +*******************************************************************************/ #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) @@ -6328,6 +6360,10 @@ static RecoverTable *recoverNewTable( sqlite3_stmt *pStmt = 0; rc = sqlite3_open("", &dbtmp); + if( rc==SQLITE_OK ){ + sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0, + shellIdQuote, 0, 0); + } if( rc==SQLITE_OK ){ rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0); } @@ -6384,18 +6420,18 @@ static RecoverTable *recoverNewTable( } } - pTab->zQuoted = shellMPrintf(&rc, "%Q", zName); + pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName); pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1)); pTab->nCol = nSqlCol; if( bIntkey ){ - pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk); + pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk); }else{ pTab->azlCol[0] = shellMPrintf(&rc, ""); } i = 1; shellPreparePrintf(dbtmp, &rc, &pStmt, - "SELECT %Q || group_concat(name, ', ') " + "SELECT %Q || group_concat(shell_idquote(name), ', ') " " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) " "FROM pragma_table_info(%Q)", bIntkey ? ", " : "", pTab->iPk, @@ -6509,7 +6545,7 @@ static RecoverTable *recoverOrphanTable( pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable)); if( pTab ){ - pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab); + pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab); pTab->nCol = nCol; pTab->iPk = -2; if( nCol>0 ){ @@ -6558,6 +6594,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ RecoverTable *pOrphan = 0; int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ + int bRowids = 1; /* 0 if --no-rowids */ for(i=1; iout, azArg[0]); return 1; } } @@ -6587,6 +6624,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ shellExecPrintf(pState->db, &rc, /* Attach an in-memory database named 'recovery'. Create an indexed ** cache of the sqlite_dbptr virtual table. */ + "PRAGMA writable_schema = on;" "ATTACH %Q AS recovery;" "DROP TABLE IF EXISTS recovery.dbptr;" "DROP TABLE IF EXISTS recovery.freelist;" @@ -6617,6 +6655,21 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ ); } + /* If this is an auto-vacuum database, add all pointer-map pages to + ** the freelist table. Do this regardless of whether or not + ** --freelist-corrupt was specified. */ + shellExec(pState->db, &rc, + "WITH ptrmap(pgno) AS (" + " SELECT 2 WHERE shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13" + " )" + " UNION ALL " + " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp " + " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)" + ")" + "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap" + ); + shellExec(pState->db, &rc, "CREATE TABLE recovery.dbptr(" " pgno, child, PRIMARY KEY(child, pgno)" @@ -6665,7 +6718,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ " )" " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" ") " - "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;" + "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;" "UPDATE recovery.map AS o SET intkey = (" " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" ");" @@ -6690,6 +6743,11 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ ** CREATE TABLE statements that extracted from the existing schema. */ if( rc==SQLITE_OK ){ sqlite3_stmt *pStmt = 0; + /* ".recover" might output content in an order which causes immediate + ** foreign key constraints to be violated. So disable foreign-key + ** constraint enforcement to prevent problems when running the output + ** script. */ + raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n"); raw_printf(pState->out, "BEGIN;\n"); raw_printf(pState->out, "PRAGMA writable_schema = on;\n"); shellPrepare(pState->db, &rc, @@ -6720,8 +6778,12 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ shellPrepare(pState->db, &rc, "SELECT pgno FROM recovery.map WHERE root=?", &pPages ); + shellPrepare(pState->db, &rc, - "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')" + "SELECT max(field), group_concat(shell_escape_crnl(quote" + "(case when (? AND field<0) then NULL else value end)" + "), ', ')" + ", min(field) " "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" "GROUP BY cell", &pCells ); @@ -6740,6 +6802,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ int bNoop = 0; RecoverTable *pTab; + assert( bIntkey==0 || bIntkey==1 ); pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop); if( bNoop || rc ) continue; if( pTab==0 ){ @@ -6750,29 +6813,44 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ if( pTab==0 ) break; } - if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){ + if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){ raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); } sqlite3_bind_int(pPages, 1, iRoot); - sqlite3_bind_int(pCells, 2, pTab->iPk); + if( bRowids==0 && pTab->iPk<0 ){ + sqlite3_bind_int(pCells, 1, 1); + }else{ + sqlite3_bind_int(pCells, 1, 0); + } + sqlite3_bind_int(pCells, 3, pTab->iPk); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ int iPgno = sqlite3_column_int(pPages, 0); - sqlite3_bind_int(pCells, 1, iPgno); + sqlite3_bind_int(pCells, 2, iPgno); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ int nField = sqlite3_column_int(pCells, 0); + int iMin = sqlite3_column_int(pCells, 2); const char *zVal = (const char*)sqlite3_column_text(pCells, 1); + RecoverTable *pTab2 = pTab; + if( pTab!=pOrphan && (iMin<0)!=bIntkey ){ + if( pOrphan==0 ){ + pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); + } + pTab2 = pOrphan; + if( pTab2==0 ) break; + } + nField = nField+1; - if( pTab==pOrphan ){ + if( pTab2==pOrphan ){ raw_printf(pState->out, "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n", - pTab->zQuoted, iRoot, iPgno, nField, - bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField] + pTab2->zQuoted, iRoot, iPgno, nField, + iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField] ); }else{ raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", - pTab->zQuoted, pTab->azlCol[nField], zVal + pTab2->zQuoted, pTab2->azlCol[nField], zVal ); } } @@ -6831,7 +6909,7 @@ static int do_meta_command(char *zLine, ShellState *p){ int nArg = 0; int n, c; int rc = 0; - char *azArg[50]; + char *azArg[52]; #ifndef SQLITE_OMIT_VIRTUALTABLE if( p->expert.pExpert ){ @@ -6841,7 +6919,7 @@ static int do_meta_command(char *zLine, ShellState *p){ /* Parse the input line into tokens. */ - while( zLine[h] && nArgout, "ANALYZE sqlite_master;\n"); @@ -8070,12 +8148,8 @@ static int do_meta_command(char *zLine, ShellState *p){ ** Clear all bind parameters by dropping the TEMP table that holds them. */ if( nArg==2 && strcmp(azArg[1],"clear")==0 ){ - int wrSchema = 0; - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;", 0, 0, 0); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); }else /* .parameter list @@ -8388,7 +8462,7 @@ static int do_meta_command(char *zLine, ShellState *p){ zDiv = " UNION ALL "; appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); if( sqlite3_stricmp(zDb, "main")!=0 ){ - appendText(&sSelect, zDb, '"'); + appendText(&sSelect, zDb, '\''); }else{ appendText(&sSelect, "NULL", 0); } @@ -8397,15 +8471,16 @@ static int do_meta_command(char *zLine, ShellState *p){ appendText(&sSelect, " AS snum, ", 0); appendText(&sSelect, zDb, '\''); appendText(&sSelect, " AS sname FROM ", 0); - appendText(&sSelect, zDb, '"'); + appendText(&sSelect, zDb, quoteChar(zDb)); appendText(&sSelect, ".sqlite_master", 0); } sqlite3_finalize(pStmt); -#ifdef SQLITE_INTROSPECTION_PRAGMAS +#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS if( zName ){ appendText(&sSelect, " UNION ALL SELECT shell_module_schema(name)," - " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0); + " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", + 0); } #endif appendText(&sSelect, ") WHERE ", 0); @@ -8504,7 +8579,8 @@ static int do_meta_command(char *zLine, ShellState *p){ if( pSession->p==0 ) goto session_not_open; out = fopen(azCmd[1], "wb"); if( out==0 ){ - utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]); + utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", + azCmd[1]); }else{ int szChng; void *pChng; @@ -8825,8 +8901,7 @@ static int do_meta_command(char *zLine, ShellState *p){ { utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); - raw_printf(stderr, "Should be one of: --schema" - " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n"); + showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } @@ -8872,8 +8947,7 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( strcmp(zTab, "sqlite_stat1")==0 ){ appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" " ORDER BY tbl,idx;", 0); - }else if( strcmp(zTab, "sqlite_stat3")==0 - || strcmp(zTab, "sqlite_stat4")==0 ){ + }else if( strcmp(zTab, "sqlite_stat4")==0 ){ appendText(&sQuery, "SELECT * FROM ", 0); appendText(&sQuery, zTab, 0); appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); @@ -9105,25 +9179,26 @@ static int do_meta_command(char *zLine, ShellState *p){ int ctrlCode; /* Integer code for that option */ const char *zUsage; /* Usage notes */ } aCtrl[] = { - { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, - { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, - /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ - /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ - { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, - /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ - { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, - { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, - { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, - { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, - { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, + { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, + { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, + /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ + /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ + { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, + { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, + /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/ + { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, + { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, #ifdef YYCOVERAGE - { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, + { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif - { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, - { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" }, - { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, - { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, - { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" }, + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, + { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, + { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE"}, }; int testctrl = -1; int iCtrl = -1; @@ -9204,6 +9279,27 @@ static int do_meta_command(char *zLine, ShellState *p){ } break; + /* sqlite3_test_control(int, int, sqlite3*) */ + case SQLITE_TESTCTRL_PRNG_SEED: + if( nArg==3 || nArg==4 ){ + int ii = (int)integerValue(azArg[2]); + sqlite3 *db; + if( ii==0 && strcmp(azArg[2],"random")==0 ){ + sqlite3_randomness(sizeof(ii),&ii); + printf("-- random seed: %d\n", ii); + } + if( nArg==3 ){ + db = 0; + }else{ + db = p->db; + /* Make sure the schema has been loaded */ + sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0); + } + rc2 = sqlite3_test_control(testctrl, ii, db); + isOk = 3; + } + break; + /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: @@ -9245,7 +9341,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } } if( isOk==0 && iCtrl>=0 ){ - utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage); + utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ raw_printf(p->out, "%d\n", rc2); @@ -9323,6 +9419,31 @@ static int do_meta_command(char *zLine, ShellState *p){ }else #endif /* !defined(SQLITE_OMIT_TRACE) */ +#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE) + if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ + int ii; + int lenOpt; + char *zOpt; + if( nArg<2 ){ + raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + zOpt = azArg[1]; + if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; + lenOpt = (int)strlen(zOpt); + if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ + assert( azArg[nArg]==0 ); + sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); + }else{ + for(ii=1; iidb, azArg[ii], 0, 0); + } + } + }else +#endif + #if SQLITE_USER_AUTHENTICATION if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ if( nArg<2 ){ @@ -9337,7 +9458,8 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = 1; goto meta_command_exit; } - rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3])); + rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], + strlen30(azArg[3])); if( rc ){ utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); rc = 1; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4dd14ac..9dbc807 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2093,6 +2093,17 @@ struct sqlite3_mem_methods { ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. ** +** [[SQLITE_DBCONFIG_ENABLE_VIEW]] +**

    SQLITE_DBCONFIG_ENABLE_VIEW
    +**
    ^This option is used to enable or disable [CREATE VIEW | views]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable views, +** positive to enable views or negative to leave the setting unchanged. +** 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.
    +** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] **
    SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
    **
    ^This option is used to enable or disable the @@ -2265,7 +2276,8 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ #define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ #define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -3814,7 +3826,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column -** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. +** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. **

    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 z%0A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

  • ** ** @@ -4849,6 +4861,12 @@ int sqlite3_reset(sqlite3_stmt *pStmt); ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** +** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] +** flag, which if present prevents the function from being invoked from +** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY] +** flag is recommended for any application-defined SQL function that has +** side-effects. +** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** @@ -4965,8 +4983,30 @@ int sqlite3_create_window_function( ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. +** +** The SQLITE_DETERMINISTIC flag means that the new function will always +** maps the same inputs into the same output. The abs() function is +** deterministic, for example, but randomblob() is not. +** +** The SQLITE_DIRECTONLY flag means that the function may only be invoked +** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is +** a security feature which is recommended for all +** [application-defined SQL functions] that have side-effects. This flag +** prevents an attacker from adding triggers and views to a schema then +** tricking a high-privilege application into causing unintended side-effects +** while performing ordinary queries. +** +** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. +** Specifying this flag makes no difference for scalar or aggregate user +** functions. However, if it is not specified for a user-defined window +** function, then any sub-types belonging to arguments passed to the window +** function may be discarded before the window function is called (i.e. +** sqlite3_value_subtype() will always return 0). */ -#define SQLITE_DETERMINISTIC 0x800 +#define SQLITE_DETERMINISTIC 0x000000800 +#define SQLITE_DIRECTONLY 0x000080000 +#define SQLITE_SUBTYPE 0x000100000 /* ** CAPI3REF: Deprecated Functions @@ -6612,6 +6652,12 @@ struct sqlite3_index_info { ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. +** +** ^If the third parameter (the pointer to the sqlite3_module object) is +** NULL then no new module is create and any existing modules with the +** same name are dropped. +** +** See also: [sqlite3_drop_modules()] */ int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ @@ -6627,6 +6673,23 @@ int sqlite3_create_module_v2( void(*xDestroy)(void*) /* Module destructor function */ ); +/* +** CAPI3REF: Remove Unnecessary Virtual Table Implementations +** METHOD: sqlite3 +** +** ^The sqlite3_drop_modules(D,L) interface removes all virtual +** table modules from database connection D except those named on list L. +** The L parameter must be either NULL or a pointer to an array of pointers +** to strings where the array is terminated by a single NULL pointer. +** ^If the L parameter is NULL, then all virtual table modules are removed. +** +** See also: [sqlite3_create_module()] +*/ +int sqlite3_drop_modules( + sqlite3 *db, /* Remove modules from this connection */ + const char **azKeep /* Except, do not remove the ones named here */ +); + /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab @@ -7335,7 +7398,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_FIRST 5 #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 @@ -7358,7 +7421,9 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_IMPOSTER 25 #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 -#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_PRNG_SEED 28 +#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 +#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 088148b..416ac94 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -322,6 +322,8 @@ struct sqlite3_api_routines { /* Version 3.28.0 and later */ int (*stmt_isexplain)(sqlite3_stmt*); int (*value_frombind)(sqlite3_value*); + /* Version 3.30.0 and later */ + int (*drop_modules)(sqlite3*,const char**); }; /* @@ -614,6 +616,8 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.28.0 and later */ #define sqlite3_stmt_isexplain sqlite3_api->isexplain #define sqlite3_value_frombind sqlite3_api->frombind +/* Version 3.30.0 and later */ +#define sqlite3_drop_modules sqlite3_api->drop_modules #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1c46183..21d5ae8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -212,15 +212,15 @@ ** So we have to define the macros in different ways depending on the ** compiler. */ -#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) #elif !defined(__GNUC__) /* Works for compilers other than LLVM */ # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) -#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ -# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) @@ -935,20 +935,6 @@ typedef INT16_TYPE LogEst; # define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE #endif -/* -** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined. -** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also -** define SQLITE_ENABLE_STAT3_OR_STAT4 -*/ -#ifdef SQLITE_ENABLE_STAT4 -# undef SQLITE_ENABLE_STAT3 -# define SQLITE_ENABLE_STAT3_OR_STAT4 1 -#elif SQLITE_ENABLE_STAT3 -# define SQLITE_ENABLE_STAT3_OR_STAT4 1 -#elif SQLITE_ENABLE_STAT3_OR_STAT4 -# undef SQLITE_ENABLE_STAT3_OR_STAT4 -#endif - /* ** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not ** the Select query generator tracing logic is turned on. @@ -1412,6 +1398,7 @@ struct sqlite3 { unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ unsigned imposterTable : 1; /* Building an imposter table */ unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ + char **azInit; /* "type", "name", and "tbl_name" columns */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ @@ -1550,16 +1537,17 @@ struct sqlite3 { #define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ #define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ #define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ +#define SQLITE_EnableView 0x80000000 /* Enable the use of views */ /* Flags used only if debugging */ #define HI(X) ((u64)(X)<<32) #ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ -#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */ +#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */ +#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */ #endif /* @@ -1587,8 +1575,8 @@ struct sqlite3 { #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_Stat34 0x0800 /* Use STAT3 or STAT4 data */ - /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ +#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 */ @@ -1676,6 +1664,7 @@ struct FuncDestructor { ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API +** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ @@ -1696,6 +1685,8 @@ struct FuncDestructor { #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ +#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ +#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -1809,6 +1800,7 @@ struct Savepoint { struct Module { const sqlite3_module *pModule; /* Callback pointers */ const char *zName; /* Name passed to create_module() */ + int nRefModule; /* Number of pointers to this object */ void *pAux; /* pAux passed to create_module() */ void (*xDestroy)(void *); /* Module destructor function */ Table *pEpoTab; /* Eponymous table for this module */ @@ -1874,11 +1866,12 @@ struct CollSeq { ** Note also that the numeric types are grouped together so that testing ** for a numeric type is a single comparison. And the BLOB type is first. */ -#define SQLITE_AFF_BLOB 'A' -#define SQLITE_AFF_TEXT 'B' -#define SQLITE_AFF_NUMERIC 'C' -#define SQLITE_AFF_INTEGER 'D' -#define SQLITE_AFF_REAL 'E' +#define SQLITE_AFF_NONE 0x40 /* '@' */ +#define SQLITE_AFF_BLOB 0x41 /* 'A' */ +#define SQLITE_AFF_TEXT 0x42 /* 'B' */ +#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */ +#define SQLITE_AFF_INTEGER 0x44 /* 'D' */ +#define SQLITE_AFF_REAL 0x45 /* 'E' */ #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) @@ -2146,10 +2139,16 @@ struct KeyInfo { u16 nKeyField; /* Number of key columns in the index */ u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ - u8 *aSortOrder; /* Sort order for each column. */ + u8 *aSortFlags; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; +/* +** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. +*/ +#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */ +#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */ + /* ** This object holds a record which has been parsed out into individual ** fields, for the purposes of doing a comparison. @@ -2257,7 +2256,7 @@ struct Index { unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ @@ -2289,7 +2288,7 @@ struct Index { #define XN_EXPR (-2) /* Indexed column is an expression */ /* -** Each sample stored in the sqlite_stat3 table is represented in memory +** Each sample stored in the sqlite_stat4 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ @@ -2447,7 +2446,7 @@ typedef int ynVar; */ struct Expr { u8 op; /* Operation performed by this node */ - char affinity; /* The affinity of the column or 0 if not a column */ + char affExpr; /* affinity, or RAISE type */ u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ @@ -2478,6 +2477,8 @@ struct Expr { ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood + ** TK_IN: ephemerial table holding RHS + ** TK_SELECT_COLUMN: Number of columns on the LHS ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). @@ -2491,7 +2492,7 @@ struct Expr { union { Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL ** for a column of an index on an expression */ - Window *pWin; /* TK_FUNCTION: Window definition for the func */ + Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */ struct { /* TK_IN, TK_SELECT, and TK_EXISTS */ int iAddr; /* Subroutine entry address */ int regReturn; /* Register used to hold return address */ @@ -2506,36 +2507,37 @@ struct Expr { ** EP_Agg == NC_HasAgg == SF_HasAgg ** EP_Win == NC_HasWin */ -#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ -#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ -#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ -#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ -#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ -#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ -#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ -#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ -#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ -#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ -#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ -#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ -#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ -#define EP_Win 0x008000 /* Contains window functions */ -#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ -#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ -#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ -#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ -#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ -#define EP_Alias 0x400000 /* Is an alias for a result set column */ -#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 */ -#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ -#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ -#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ -#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ +#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ +#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ +#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ +#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ +#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ +#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ + /* 0x000200 Available for reuse */ +#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ +#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ +#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ +#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ +#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_Win 0x008000 /* Contains window functions */ +#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ +#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ +#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ +#define EP_Alias 0x400000 /* Is an alias for a result set column */ +#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 */ +#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ +#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ +#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ +#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ +#define EP_Indirect 0x40000000 /* Contained within a TRIGGER or a VIEW */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -2579,6 +2581,18 @@ struct Expr { */ #define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ +/* +** True if the expression passed as an argument was a function with +** an OVER() clause (a window function). +*/ +#ifdef SQLITE_OMIT_WINDOWFUNC +# define IsWindowFunc(p) 0 +#else +# define IsWindowFunc(p) ( \ + ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \ + ) +#endif + /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such @@ -2601,11 +2615,12 @@ struct ExprList { Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ - u8 sortOrder; /* 1 for DESC or 0 for ASC */ + u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ unsigned reusable :1; /* Constant expression is reusable */ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -2896,6 +2911,7 @@ struct Select { #define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ #define SF_ComplexResult 0x40000 /* Result contains subquery or function */ +#define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */ /* ** The results of a SELECT can be distributed in several ways, as defined @@ -3400,11 +3416,12 @@ typedef struct { */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ - int bCoreMutex; /* True to enable core mutexing */ - int bFullMutex; /* True to enable full mutexing */ - int bOpenUri; /* True to interpret filenames as URIs */ - int bUseCis; /* Use covering indices for full-scans */ - int bSmallMalloc; /* Avoid large memory allocations if true */ + u8 bCoreMutex; /* True to enable core mutexing */ + u8 bFullMutex; /* True to enable full mutexing */ + u8 bOpenUri; /* True to interpret filenames as URIs */ + u8 bUseCis; /* Use covering indices for full-scans */ + u8 bSmallMalloc; /* Avoid large memory allocations if true */ + u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ @@ -3456,6 +3473,7 @@ struct Sqlite3Config { int bInternalFunctions; /* Internal SQL functions are visible */ 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 */ }; /* @@ -3552,10 +3570,11 @@ struct TreeView { #endif /* SQLITE_DEBUG */ /* -** This object is used in various ways, all related to window functions +** This object is used in various ways, most (but not all) related to window +** functions. ** ** (1) A single instance of this structure is attached to the -** the Expr.pWin field for each window function in an expression tree. +** the Expr.y.pWin field for each window function in an expression tree. ** This object holds the information contained in the OVER clause, ** plus additional fields used during code generation. ** @@ -3566,6 +3585,10 @@ struct TreeView { ** (3) The terms of the WINDOW clause of a SELECT are instances of this ** object on a linked list attached to Select.pWinDefn. ** +** (4) For an aggregate function with a FILTER clause, an instance +** of this object is stored in Expr.y.pWin with eFrmType set to +** TK_FILTER. In this case the only field used is Window.pFilter. +** ** The uses (1) and (2) are really the same Window object that just happens ** to be accessible in two different ways. Use case (3) are separate objects. */ @@ -3581,12 +3604,13 @@ struct Window { u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ Expr *pStart; /* Expression for " PRECEDING" */ Expr *pEnd; /* Expression for " FOLLOWING" */ + Window **ppThis; /* Pointer to this object in Select.pWin list */ Window *pNextWin; /* Next window function belonging to this SELECT */ Expr *pFilter; /* The FILTER expression */ FuncDef *pFunc; /* The function */ int iEphCsr; /* Partition buffer or Peer buffer */ - int regAccum; - int regResult; + int regAccum; /* Accumulator */ + int regResult; /* Interim result */ int csrApp; /* Function cursor (used by min/max) */ int regApp; /* Function register (also used by min/max) */ int regPart; /* Array of registers for PARTITION BY values */ @@ -3596,14 +3620,18 @@ struct Window { int regOne; /* Register containing constant value 1 */ int regStartRowid; int regEndRowid; + u8 bExprArgs; /* Defer evaluation of window function arguments + ** due to the SQLITE_SUBTYPE flag */ }; #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3WindowDelete(sqlite3*, Window*); +void sqlite3WindowUnlinkFromSelect(Window*); void sqlite3WindowListDelete(sqlite3 *db, Window *p); Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); void sqlite3WindowAttach(Parse*, Expr*, Window*); -int sqlite3WindowCompare(Parse*, Window*, Window*); +void sqlite3WindowLink(Select *pSel, Window *pWin); +int sqlite3WindowCompare(Parse*, Window*, Window*, int); void sqlite3WindowCodeInit(Parse*, Window*); void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); int sqlite3WindowRewrite(Parse*, Select*); @@ -3875,7 +3903,7 @@ void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprUnmapAndDelete(Parse*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); -void sqlite3ExprListSetSortOrder(ExprList*,int); +void sqlite3ExprListSetSortOrder(ExprList*,int,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); void sqlite3ExprListDelete(sqlite3*, ExprList*); @@ -3894,8 +3922,8 @@ void sqlite3CollapseDatabaseArray(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); void sqlite3DeleteColumnNames(sqlite3*,Table*); int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); -void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*); -Table *sqlite3ResultSetOfSelect(Parse*,Select*); +void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); +Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); void sqlite3OpenMasterTable(Parse *, int); Index *sqlite3PrimaryKeyIndex(Table*); i16 sqlite3ColumnOfIndex(Index*, i16); @@ -4196,7 +4224,7 @@ LogEst sqlite3LogEstAdd(LogEst,LogEst); LogEst sqlite3LogEstFromDouble(double); #endif #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_ENABLE_STAT4) || \ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) u64 sqlite3LogEstToInt(LogEst); #endif @@ -4262,9 +4290,10 @@ int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprSkipCollate(Expr*); +Expr *sqlite3ExprSkipCollateAndLikely(Expr*); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3WritableSchema(sqlite3*); -int sqlite3CheckObjectName(Parse *, const char *); +int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); void sqlite3VdbeSetChanges(sqlite3 *, int); int sqlite3AddInt64(i64*,i64); int sqlite3SubInt64(i64*,i64); @@ -4297,7 +4326,6 @@ extern const unsigned char sqlite3OpcodeProperty[]; extern const char sqlite3StrBINARY[]; extern const unsigned char sqlite3UpperToLower[]; extern const unsigned char sqlite3CtypeMap[]; -extern const Token sqlite3IntTokens[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern FuncDefHash sqlite3BuiltinFunctions; #ifndef SQLITE_OMIT_WSD @@ -4351,6 +4379,7 @@ void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); +int sqlite3HasExplicitNulls(Parse*, ExprList*); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); @@ -4383,8 +4412,7 @@ int sqlite3ExprCheckIN(Parse*, Expr*); # define sqlite3ExprCheckIN(x,y) SQLITE_OK #endif -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -void sqlite3AnalyzeFunctions(void); +#ifdef SQLITE_ENABLE_STAT4 int sqlite3Stat4ProbeSetValue( Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*); int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); @@ -4431,6 +4459,7 @@ void sqlite3AutoLoadExtensions(sqlite3*); # define sqlite3VtabInSync(db) 0 # define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) +# define sqlite3VtabModuleUnref(D,X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK # define sqlite3GetVTable(X,Y) ((VTable*)0) @@ -4442,6 +4471,7 @@ void sqlite3AutoLoadExtensions(sqlite3*); int sqlite3VtabCommit(sqlite3 *db); void sqlite3VtabLock(VTable *); void sqlite3VtabUnlock(VTable *); + void sqlite3VtabModuleUnref(sqlite3*,Module*); void sqlite3VtabUnlockList(sqlite3*); int sqlite3VtabSavepoint(sqlite3 *, int, int); void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index a78d567..80a0572 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1917,33 +1917,33 @@ static int SQLITE_TCLAPI DbObjCmd( "authorizer", "backup", "bind_fallback", "busy", "cache", "changes", "close", "collate", "collation_needed", - "commit_hook", "complete", "copy", - "deserialize", "enable_load_extension", "errorcode", - "eval", "exists", "function", - "incrblob", "interrupt", "last_insert_rowid", - "nullvalue", "onecolumn", "preupdate", - "profile", "progress", "rekey", - "restore", "rollback_hook", "serialize", - "status", "timeout", "total_changes", - "trace", "trace_v2", "transaction", - "unlock_notify", "update_hook", "version", - "wal_hook", 0 + "commit_hook", "complete", "config", + "copy", "deserialize", "enable_load_extension", + "errorcode", "eval", "exists", + "function", "incrblob", "interrupt", + "last_insert_rowid", "nullvalue", "onecolumn", + "preupdate", "profile", "progress", + "rekey", "restore", "rollback_hook", + "serialize", "status", "timeout", + "total_changes", "trace", "trace_v2", + "transaction", "unlock_notify", "update_hook", + "version", "wal_hook", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, - DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY, - DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE, - DB_EVAL, DB_EXISTS, DB_FUNCTION, - DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, - DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE, - DB_PROFILE, DB_PROGRESS, DB_REKEY, - DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE, - DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, - DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, - DB_WAL_HOOK + DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG, + DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION, + DB_ERRORCODE, DB_EVAL, DB_EXISTS, + DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, + DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, + DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, + DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, + DB_SERIALIZE, DB_STATUS, DB_TIMEOUT, + DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2, + DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, + DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2331,6 +2331,74 @@ static int SQLITE_TCLAPI DbObjCmd( break; } + /* $db config ?OPTION? ?BOOLEAN? + ** + ** Configure the database connection using the sqlite3_db_config() + ** interface. + */ + case DB_CONFIG: { + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { + { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, + { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, + { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, + { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, + { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, + { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, + }; + Tcl_Obj *pResult; + int ii; + if( objc>4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?"); + return TCL_ERROR; + } + if( objc==2 ){ + /* With no arguments, list all configuration options and with the + ** current value */ + pResult = Tcl_NewListObj(0,0); + for(ii=0; iidb, aDbConfig[ii].op, -1, &v); + Tcl_ListObjAppendElement(interp, pResult, + Tcl_NewStringObj(aDbConfig[ii].zName,-1)); + Tcl_ListObjAppendElement(interp, pResult, + Tcl_NewIntObj(v)); + } + }else{ + const char *zOpt = Tcl_GetString(objv[2]); + int onoff = -1; + int v = 0; + if( zOpt[0]=='-' ) zOpt++; + for(ii=0; ii=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){ + Tcl_AppendResult(interp, "unknown config option: \"", zOpt, + "\"", (void*)0); + return TCL_ERROR; + } + if( objc==4 ){ + if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){ + return TCL_ERROR; + } + } + sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v); + pResult = Tcl_NewIntObj(v); + } + Tcl_SetObjResult(interp, pResult); + break; + } + /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? ** ** Copy data into table from filename, optionally using SEPARATOR @@ -2741,10 +2809,16 @@ deserialize_error: } /* - ** $db function NAME [-argcount N] [-deterministic] SCRIPT + ** $db function NAME [OPTIONS] SCRIPT ** ** Create a new SQL function called NAME. Whenever that function is ** called, invoke SCRIPT to evaluate the function. + ** + ** Options: + ** --argcount N Function has exactly N arguments + ** --deterministic The function is pure + ** --directonly Prohibit use inside triggers and views + ** --returntype TYPE Specify the return type of the function */ case DB_FUNCTION: { int flags = SQLITE_UTF8; @@ -2777,6 +2851,9 @@ deserialize_error: if( n>1 && strncmp(z, "-deterministic",n)==0 ){ flags |= SQLITE_DETERMINISTIC; }else + if( n>1 && strncmp(z, "-directonly",n)==0 ){ + flags |= SQLITE_DIRECTONLY; + }else if( n>1 && strncmp(z, "-returntype", n)==0 ){ const char *azType[] = {"integer", "real", "text", "blob", "any", 0}; assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 ); @@ -2792,7 +2869,8 @@ deserialize_error: eType++; }else{ Tcl_AppendResult(interp, "bad option \"", z, - "\": must be -argcount, -deterministic or -returntype", (char*)0 + "\": must be -argcount, -deterministic, -directonly," + " or -returntype", (char*)0 ); return TCL_ERROR; } diff --git a/src/test1.c b/src/test1.c index 9aaf792..ffd6091 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1110,6 +1110,33 @@ static int SQLITE_TCLAPI test_create_function( return TCL_OK; } +/* +** Usage: sqlite3_drop_modules DB ?NAME ...? +** +** Invoke the sqlite3_drop_modules(D,L) interface on database +** connection DB, in order to drop all modules except those named in +** the argument. +*/ +static int SQLITE_TCLAPI test_drop_modules( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0); +#endif + return TCL_OK; +} + /* ** Routines to implement the x_count() aggregate function. ** @@ -6373,7 +6400,41 @@ static int SQLITE_TCLAPI reset_prng_state( int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ - sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET); + sqlite3_randomness(0,0); + return TCL_OK; +} +/* +** tclcmd: prng_seed INT ?DB? +** +** Set up the SQLITE_TESTCTRL_PRNG_SEED pragma with parameter INT and DB. +** INT is an integer. DB is a database connection, or a NULL pointer if +** omitted. +** +** When INT!=0 and DB!=0, set the PRNG seed to the value of the schema +** cookie for DB, or to INT if the schema cookie happens to be zero. +** +** When INT!=0 and DB==0, set the PRNG seed to just INT. +** +** If INT==0 and DB==0 then use the default procedure of calling the +** xRandomness method on the default VFS to get the PRNG seed. +*/ +static int SQLITE_TCLAPI prng_seed( + 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 */ +){ + int i = 0; + sqlite3 *db = 0; + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp,objv[0],&i) ) return TCL_ERROR; + if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){ + return TCL_ERROR; + } + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, i, db); return TCL_OK; } @@ -7139,9 +7200,9 @@ static int SQLITE_TCLAPI optimization_control( { "order-by-idx-join", SQLITE_OrderByIdxJoin }, { "transitive", SQLITE_Transitive }, { "omit-noop-join", SQLITE_OmitNoopJoin }, - { "stat3", SQLITE_Stat34 }, - { "stat4", SQLITE_Stat34 }, + { "stat4", SQLITE_Stat4 }, { "skip-scan", SQLITE_SkipScan }, + { "push-down", SQLITE_PushDown }, }; if( objc!=4 ){ @@ -7740,6 +7801,11 @@ static int SQLITE_TCLAPI test_decode_hexdb( int pgsz; rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz); if( rc!=2 ) continue; + if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){ + Tcl_AppendResult(interp, "bad 'pagesize' field", (void*)0); + return TCL_ERROR; + } + n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ if( n<512 ){ Tcl_AppendResult(interp, "bad 'size' field", (void*)0); return TCL_ERROR; @@ -7822,6 +7888,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 }, { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, + { "sqlite3_drop_modules", (Tcl_CmdProc*)test_drop_modules }, { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_bind", (Tcl_CmdProc*)test_bind }, @@ -7918,6 +7985,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "save_prng_state", save_prng_state, 0 }, { "restore_prng_state", restore_prng_state, 0 }, { "reset_prng_state", reset_prng_state, 0 }, + { "prng_seed", prng_seed, 0 }, { "database_never_corrupt", database_never_corrupt, 0}, { "database_may_be_corrupt", database_may_be_corrupt, 0}, { "optimization_control", optimization_control,0}, diff --git a/src/test_config.c b/src/test_config.c index 0500234..e6c0330 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -585,12 +585,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY); #endif -#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) - Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY); -#else - Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY); -#endif - #if defined(SQLITE_ENABLE_STMTVTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE) Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "1", TCL_GLOBAL_ONLY); #else diff --git a/src/test_hexio.c b/src/test_hexio.c index 7b62ea0..78a5ba2 100644 --- a/src/test_hexio.c +++ b/src/test_hexio.c @@ -337,6 +337,17 @@ static int getFts3Varint(const char *p, sqlite_int64 *v){ return (int) (q - (unsigned char *)p); } +static int putFts3Varint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= 10 ); + return (int) (q - (unsigned char *)p); +} /* ** USAGE: read_fts3varint BLOB VARNAME @@ -367,6 +378,67 @@ static int SQLITE_TCLAPI read_fts3varint( return TCL_OK; } +/* +** USAGE: make_fts3record ARGLIST +*/ +static int SQLITE_TCLAPI make_fts3record( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Obj **aArg = 0; + int nArg = 0; + unsigned char *aOut = 0; + int nOut = 0; + int nAlloc = 0; + int i; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "LIST"); + return TCL_ERROR; + } + if( Tcl_ListObjGetElements(interp, objv[1], &nArg, &aArg) ){ + return TCL_ERROR; + } + + for(i=0; inAlloc ){ + int nNew = nAlloc?nAlloc*2:128; + unsigned char *aNew = sqlite3_realloc(aOut, nNew); + if( aNew==0 ){ + sqlite3_free(aOut); + return TCL_ERROR; + } + aOut = aNew; + nAlloc = nNew; + } + nOut += putFts3Varint((char*)&aOut[nOut], iVal); + }else{ + int nVal = 0; + char *zVal = Tcl_GetStringFromObj(aArg[i], &nVal); + while( (nOut + nVal)>nAlloc ){ + int nNew = nAlloc?nAlloc*2:128; + unsigned char *aNew = sqlite3_realloc(aOut, nNew); + if( aNew==0 ){ + sqlite3_free(aOut); + return TCL_ERROR; + } + aOut = aNew; + nAlloc = nNew; + } + memcpy(&aOut[nOut], zVal, nVal); + nOut += nVal; + } + } + + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aOut, nOut)); + sqlite3_free(aOut); + return TCL_OK; +} + /* ** Register commands with the TCL interpreter. @@ -383,6 +455,7 @@ int Sqlitetest_hexio_Init(Tcl_Interp *interp){ { "hexio_render_int32", hexio_render_int32 }, { "utf8_to_utf8", utf8_to_utf8 }, { "read_fts3varint", read_fts3varint }, + { "make_fts3record", make_fts3record }, }; int i; for(i=0; iselFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), - p->selId, p, p->selFlags, - (int)p->nSelectRow - ); + if( p->selFlags & SF_WhereBegin ){ + sqlite3TreeViewLine(pView, "sqlite3WhereBegin()"); + }else{ + sqlite3TreeViewLine(pView, + "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), + p->selId, p, p->selFlags, + (int)p->nSelectRow + ); + } if( cnt++ ) sqlite3TreeViewPop(pView); if( p->pPrior ){ n = 1000; @@ -199,7 +203,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ if( p->pWinDefn ) n++; #endif } - sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); + if( p->pEList ){ + sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set"); + } + n--; #ifndef SQLITE_OMIT_WINDOWFUNC if( p->pWin ){ Window *pX; @@ -395,12 +402,14 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ sqlite3TreeViewPop(pView); return; } - if( pExpr->flags ){ + if( pExpr->flags || pExpr->affExpr ){ if( ExprHasProperty(pExpr, EP_FromJoin) ){ - sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d", - pExpr->flags, pExpr->iRightJoinTable); + sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c iRJT=%d", + pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n', + pExpr->iRightJoinTable); }else{ - sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags); + sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c", + pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n'); } }else{ zFlgs[0] = 0; @@ -527,7 +536,14 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ } case TK_COLLATE: { - sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); + /* COLLATE operators without the EP_Collate flag are intended to + ** emulate collation associated with a table column. These show + ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE + ** operators that appear in the original SQL always have the + ** EP_Collate bit set and appear in treeview output as just "COLLATE" */ + sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s", + !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "", + pExpr->u.zToken, zFlgs); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } @@ -548,10 +564,10 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ #endif } if( pExpr->op==TK_AGG_FUNCTION ){ - sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", - pExpr->op2, pExpr->u.zToken); + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s", + pExpr->op2, pExpr->u.zToken, zFlgs); }else{ - sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); + sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); } if( pFarg ){ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); @@ -628,7 +644,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { const char *zType = "unk"; - switch( pExpr->affinity ){ + switch( pExpr->affExpr ){ case OE_Rollback: zType = "rollback"; break; case OE_Abort: zType = "abort"; break; case OE_Fail: zType = "fail"; break; @@ -669,7 +685,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ sqlite3TreeViewExpr(pView, pExpr->pRight, 0); }else if( zUniOp ){ sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); } sqlite3TreeViewPop(pView); } diff --git a/src/trigger.c b/src/trigger.c index c37f76d..83685a0 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -177,7 +177,11 @@ void sqlite3BeginTrigger( /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken(db, pName); - if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + if( zName==0 ){ + assert( db->mallocFailed ); + goto trigger_cleanup; + } + if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){ goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); @@ -340,6 +344,7 @@ void sqlite3FinishTrigger( Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + assert( pLink!=0 ); pTrig = sqlite3HashInsert(pHash, zName, pTrig); if( pTrig ){ sqlite3OomFault(db); @@ -458,6 +463,9 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep->pIdList = pColumn; pTriggerStep->pUpsert = pUpsert; pTriggerStep->orconf = orconf; + if( pUpsert ){ + sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget); + } }else{ testcase( pColumn ); sqlite3IdListDelete(db, pColumn); @@ -613,10 +621,9 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); assert( iDb>=0 && iDbnDb ); pTable = tableOfTrigger(pTrigger); - assert( pTable ); - assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); + assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION - { + if( pTable ){ int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); @@ -630,7 +637,6 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ /* Generate code to destroy the database record of the trigger. */ - assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", @@ -654,9 +660,11 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); - Trigger **pp; - for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; + if( pTab ){ + Trigger **pp; + for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); + *pp = (*pp)->pNext; + } } sqlite3DeleteTrigger(db, pTrigger); db->mDbFlags |= DBFLAG_SchemaChange; diff --git a/src/update.c b/src/update.c index bbeaa3d..458550b 100644 --- a/src/update.c +++ b/src/update.c @@ -715,28 +715,30 @@ void sqlite3Update( } if( !isView ){ - int addr1 = 0; /* Address of jump instruction */ - /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); + /* If REPLACE conflict handling may have been used, or if the PK of the + ** row is changing, then the GenerateConstraintChecks() above may have + ** moved cursor iDataCur. Reseek it. */ + if( bReplace || chngKey ){ + if( pPk ){ + sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); + }else{ + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); + } + VdbeCoverageNeverTaken(v); + } + /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ - if( bReplace || chngKey ){ - if( pPk ){ - addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); - }else{ - addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); - } - VdbeCoverageNeverTaken(v); - } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); /* If changing the rowid value, or if there are foreign key constraints @@ -766,9 +768,6 @@ void sqlite3Update( sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } #endif - if( bReplace || chngKey ){ - sqlite3VdbeJumpHere(v, addr1); - } if( hasFK ){ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); diff --git a/src/upsert.c b/src/upsert.c index 850ae86..7beb9ff 100644 --- a/src/upsert.c +++ b/src/upsert.c @@ -205,6 +205,7 @@ void sqlite3UpsertDoUpdate( sqlite3 *db = pParse->db; SrcList *pSrc; /* FROM clause for the UPDATE */ int iDataCur; + int i; assert( v!=0 ); assert( pUpsert!=0 ); @@ -221,7 +222,6 @@ void sqlite3UpsertDoUpdate( Index *pPk = sqlite3PrimaryKeyIndex(pTab); int nPk = pPk->nKeyCol; int iPk = pParse->nMem+1; - int i; pParse->nMem += nPk; for(i=0; ipUpsertSrc, 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); + } + } sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet, pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert); pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */ diff --git a/src/util.c b/src/util.c index 764bfe9..7adce4e 100644 --- a/src/util.c +++ b/src/util.c @@ -1498,7 +1498,7 @@ LogEst sqlite3LogEstFromDouble(double x){ #endif /* SQLITE_OMIT_VIRTUALTABLE */ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_ENABLE_STAT4) || \ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* ** Convert a LogEst into an integer. @@ -1516,7 +1516,7 @@ u64 sqlite3LogEstToInt(LogEst x){ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) if( x>60 ) return (u64)LARGEST_INT64; #else - /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input + /* If only SQLITE_ENABLE_STAT4 is on, then the largest input ** possible to this routine is 310, resulting in a maximum x of 31 */ assert( x<=60 ); #endif diff --git a/src/vdbe.c b/src/vdbe.c index d697d6b..777582b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -343,6 +343,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ ** Convert pRec to a text representation. ** ** SQLITE_AFF_BLOB: +** SQLITE_AFF_NONE: ** No-op. pRec is unchanged. */ static void applyAffinity( @@ -482,13 +483,15 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ c = 's'; } *(zCsr++) = c; + *(zCsr++) = 'x'; sqlite3_snprintf(100, zCsr, "%d[", pMem->n); zCsr += sqlite3Strlen30(zCsr); - for(i=0; i<16 && in; i++){ + for(i=0; i<25 && in; i++){ sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); zCsr += sqlite3Strlen30(zCsr); } - for(i=0; i<16 && in; i++){ + *zCsr++ = '|'; + for(i=0; i<25 && in; i++){ char z = pMem->z[i]; if( z<32 || z>126 ) *zCsr++ = '.'; else *zCsr++ = z; @@ -518,7 +521,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); k += sqlite3Strlen30(&zBuf[k]); zBuf[k++] = '['; - for(j=0; j<15 && jn; j++){ + for(j=0; j<25 && jn; j++){ u8 c = pMem->z[j]; if( c>=0x20 && c<0x7f ){ zBuf[k++] = c; @@ -551,7 +554,7 @@ static void memTracePrint(Mem *p){ printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ - printf(" r:%g", p->u.r); + printf(" r:%.17g", p->u.r); #endif }else if( sqlite3VdbeMemIsRowSet(p) ){ printf(" (rowset)"); @@ -1140,7 +1143,6 @@ case OP_Real: { /* same as TK_FLOAT, out2 */ case OP_String8: { /* same as TK_STRING, out2 */ assert( pOp->p4.z!=0 ); pOut = out2Prerelease(p, pOp); - pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); #ifndef SQLITE_OMIT_UTF16 @@ -1164,6 +1166,7 @@ case OP_String8: { /* same as TK_STRING, out2 */ if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } + pOp->opcode = OP_String; assert( rc==SQLITE_OK ); /* Fall through to the next case, OP_String */ } @@ -1831,6 +1834,7 @@ case OP_RealAffinity: { /* in1 */ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemRealify(pIn1); + REGISTER_TRACE(pOp->p1, pIn1); } break; } @@ -2226,9 +2230,14 @@ case OP_Compare: { REGISTER_TRACE(p2+idx, &aMem[p2+idx]); assert( inKeyField ); pColl = pKeyInfo->aColl[i]; - bRev = pKeyInfo->aSortOrder[i]; + bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC); iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); if( iCompare ){ + if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) + && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null)) + ){ + iCompare = -iCompare; + } if( bRev ) iCompare = -iCompare; break; } @@ -2519,11 +2528,6 @@ case OP_Offset: { /* out3 */ ** if the P4 argument is a P4_MEM use the value of the P4 argument as ** the result. ** -** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, -** then the cache of the cursor is reset prior to extracting the column. -** The first OP_Column against a pseudo-table after the value of the content -** register has changed should have this bit set. -** ** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then ** the result is guaranteed to only be used as the argument of a length() ** or typeof() function, respectively. The loading of large blobs can be @@ -2812,15 +2816,27 @@ case OP_Affinity: { assert( pOp->p2>0 ); assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; - while( 1 /*edit-by-break*/ ){ + while( 1 /*exit-by-break*/ ){ assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] ); assert( memIsValid(pIn1) ); applyAffinity(pIn1, zAffinity[0], encoding); if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){ - /* When applying REAL affinity, if the result is still MEM_Int, - ** indicate that REAL is actually desired */ - pIn1->flags |= MEM_IntReal; - pIn1->flags &= ~MEM_Int; + /* When applying REAL affinity, if the result is still an MEM_Int + ** that will fit in 6 bytes, then change the type to MEM_IntReal + ** so that we keep the high-resolution integer value but know that + ** the type really wants to be REAL. */ + testcase( pIn1->u.i==140737488355328LL ); + testcase( pIn1->u.i==140737488355327LL ); + testcase( pIn1->u.i==-140737488355328LL ); + testcase( pIn1->u.i==-140737488355329LL ); + if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){ + pIn1->flags |= MEM_IntReal; + pIn1->flags &= ~MEM_Int; + }else{ + pIn1->u.r = (double)pIn1->u.i; + pIn1->flags |= MEM_Real; + pIn1->flags &= ~MEM_Int; + } } REGISTER_TRACE((int)(pIn1-aMem), pIn1); zAffinity++; @@ -2927,14 +2943,36 @@ case OP_MakeRecord: { #endif /* Loop through the elements that will make up the record to figure - ** out how much space is required for the new record. + ** out how much space is required for the new record. After this loop, + ** the Mem.uTemp field of each term should hold the serial-type that will + ** be used for that term in the generated record: + ** + ** Mem.uTemp value type + ** --------------- --------------- + ** 0 NULL + ** 1 1-byte signed integer + ** 2 2-byte signed integer + ** 3 3-byte signed integer + ** 4 4-byte signed integer + ** 5 6-byte signed integer + ** 6 8-byte signed integer + ** 7 IEEE float + ** 8 Integer constant 0 + ** 9 Integer constant 1 + ** 10,11 reserved for expansion + ** N>=12 and even BLOB + ** N>=13 and odd text + ** + ** The following additional values are computed: + ** nHdr Number of bytes needed for the record header + ** nData Number of bytes of data space needed for the record + ** nZero Zero bytes at the end of the record */ pRec = pLast; do{ assert( memIsValid(pRec) ); - serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); - if( pRec->flags & MEM_Zero ){ - if( serial_type==0 ){ + if( pRec->flags & MEM_Null ){ + if( pRec->flags & MEM_Zero ){ /* Values with MEM_Null and MEM_Zero are created by xColumn virtual ** table methods that never invoke sqlite3_result_xxxxx() while ** computing an unchanging column value in an UPDATE statement. @@ -2942,19 +2980,83 @@ case OP_MakeRecord: { ** so that they can be passed through to xUpdate and have ** a true sqlite3_value_nochange(). */ assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); - serial_type = 10; - }else if( nData ){ - if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + pRec->uTemp = 10; }else{ - nZero += pRec->u.nZero; - len -= pRec->u.nZero; + pRec->uTemp = 0; } + nHdr++; + }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){ + /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ + i64 i = pRec->u.i; + u64 uu; + testcase( pRec->flags & MEM_Int ); + testcase( pRec->flags & MEM_IntReal ); + if( i<0 ){ + uu = ~i; + }else{ + uu = i; + } + nHdr++; + testcase( uu==127 ); testcase( uu==128 ); + testcase( uu==32767 ); testcase( uu==32768 ); + testcase( uu==8388607 ); testcase( uu==8388608 ); + testcase( uu==2147483647 ); testcase( uu==2147483648 ); + testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL ); + if( uu<=127 ){ + if( (i&1)==i && file_format>=4 ){ + pRec->uTemp = 8+(u32)uu; + }else{ + nData++; + pRec->uTemp = 1; + } + }else if( uu<=32767 ){ + nData += 2; + pRec->uTemp = 2; + }else if( uu<=8388607 ){ + nData += 3; + pRec->uTemp = 3; + }else if( uu<=2147483647 ){ + nData += 4; + pRec->uTemp = 4; + }else if( uu<=140737488355327LL ){ + nData += 6; + pRec->uTemp = 5; + }else{ + nData += 8; + if( pRec->flags & MEM_IntReal ){ + /* If the value is IntReal and is going to take up 8 bytes to store + ** as an integer, then we might as well make it an 8-byte floating + ** point value */ + pRec->u.r = (double)pRec->u.i; + pRec->flags &= ~MEM_IntReal; + pRec->flags |= MEM_Real; + pRec->uTemp = 7; + }else{ + pRec->uTemp = 6; + } + } + }else if( pRec->flags & MEM_Real ){ + nHdr++; + nData += 8; + pRec->uTemp = 7; + }else{ + assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) ); + assert( pRec->n>=0 ); + len = (u32)pRec->n; + serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0); + if( pRec->flags & MEM_Zero ){ + serial_type += pRec->u.nZero*2; + if( nData ){ + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + len += pRec->u.nZero; + }else{ + nZero += pRec->u.nZero; + } + } + nData += len; + nHdr += sqlite3VarintLen(serial_type); + pRec->uTemp = serial_type; } - nData += len; - testcase( serial_type==127 ); - testcase( serial_type==128 ); - nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); - pRec->uTemp = serial_type; if( pRec==pData0 ) break; pRec--; }while(1); @@ -3290,7 +3392,7 @@ case OP_AutoCommit: { rc = SQLITE_ERROR; goto abort_due_to_error; } - break; + /*NOTREACHED*/ assert(0); } /* Opcode: Transaction P1 P2 P3 P4 P5 @@ -4028,6 +4130,7 @@ case OP_SeekGT: { /* jump, in3, group */ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( pC->isTable ){ + u16 flags3, newType; /* The BTREE_SEEK_EQ flag is only set on index cursors */ assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 || CORRUPT_DB ); @@ -4036,18 +4139,21 @@ case OP_SeekGT: { /* jump, in3, group */ ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so convert it. */ pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ + flags3 = pIn3->flags; + if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3, 0); } - iKey = sqlite3VdbeIntValue(pIn3); + iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ + newType = pIn3->flags; /* Record the type after applying numeric affinity */ + pIn3->flags = flags3; /* But convert the type back to its original */ /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ - if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - if( (pIn3->flags & MEM_Real)==0 ){ - if( (pIn3->flags & MEM_Null) || oc>=OP_SeekGE ){ - VdbeBranchTaken(1,2); goto jump_to_p2; - break; + if( (newType & (MEM_Int|MEM_IntReal))==0 ){ + if( (newType & MEM_Real)==0 ){ + if( (newType & MEM_Null) || oc>=OP_SeekGE ){ + VdbeBranchTaken(1,2); + goto jump_to_p2; }else{ rc = sqlite3BtreeLast(pC->uc.pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; @@ -4432,23 +4538,27 @@ case OP_SeekRowid: { /* jump, in3 */ pIn3 = &aMem[pOp->p3]; testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_IntReal ); + testcase( pIn3->flags & MEM_Real ); + testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str ); if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - /* Make sure pIn3->u.i contains a valid integer representation of - ** the key value, but do not change the datatype of the register, as - ** other parts of the perpared statement might be depending on the - ** current datatype. */ - u16 origFlags = pIn3->flags; - int isNotInt; - applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); - isNotInt = (pIn3->flags & MEM_Int)==0; - pIn3->flags = origFlags; - if( isNotInt ) goto jump_to_p2; + /* If pIn3->u.i does not contain an integer, compute iKey as the + ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted + ** into an integer without loss of information. Take care to avoid + ** changing the datatype of pIn3, however, as it is used by other + ** parts of the prepared statement. */ + Mem x = pIn3[0]; + applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding); + if( (x.flags & MEM_Int)==0 ) goto jump_to_p2; + iKey = x.u.i; + goto notExistsWithKey; } /* Fall through into OP_NotExists */ case OP_NotExists: /* jump, in3 */ pIn3 = &aMem[pOp->p3]; assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); assert( pOp->p1>=0 && pOp->p1nCursor ); + iKey = pIn3->u.i; +notExistsWithKey: pC = p->apCsr[pOp->p1]; assert( pC!=0 ); #ifdef SQLITE_DEBUG @@ -4459,7 +4569,6 @@ case OP_NotExists: /* jump, in3 */ pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); res = 0; - iKey = pIn3->u.i; rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); assert( rc==SQLITE_OK || res==0 ); pC->movetoTarget = iKey; /* Used by OP_Delete */ @@ -5341,11 +5450,12 @@ case OP_Next: /* jump */ ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ assert( pOp->opcode!=OP_Next || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE - || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found - || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid); + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found + || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid + || pC->seekOp==OP_IfNoHope); assert( pOp->opcode!=OP_Prev || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last + || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope || pC->seekOp==OP_NullRow); rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); @@ -5864,7 +5974,7 @@ case OP_ParseSchema: { initData.pzErrMsg = &p->zErrMsg; initData.mInitFlags = 0; zSql = sqlite3MPrintf(db, - "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid", db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; diff --git a/src/vdbe.h b/src/vdbe.h index 041a91c..e3aaaa1 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -222,10 +222,10 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); # define sqlite3ExplainBreakpoint(A,B) /*no-op*/ #endif void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); -void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); -void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); -void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); -void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); +void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8); +void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); +void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); +void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); int sqlite3VdbeChangeToNoop(Vdbe*, int addr); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 17e057b..bd03553 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -486,7 +486,6 @@ int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); int sqlite3VdbeCursorRestore(VdbeCursor*); u32 sqlite3VdbeSerialTypeLen(u32); u8 sqlite3VdbeOneByteSerialTypeLen(u8); -u32 sqlite3VdbeSerialType(Mem*, int, u32*); u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 83221d9..c7968ee 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -844,7 +844,7 @@ int sqlite3_vtab_nochange(sqlite3_context *p){ */ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ int rc; -#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifndef SQLITE_ENABLE_STAT4 sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; assert( p->pVdbe!=0 ); #else @@ -909,7 +909,7 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#if SQLITE_ENABLE_STAT3_OR_STAT4 +#if SQLITE_ENABLE_STAT4 if( pCtx->pVdbe==0 ) return 0; #else assert( pCtx->pVdbe!=0 ); @@ -943,7 +943,7 @@ void sqlite3_set_auxdata( Vdbe *pVdbe = pCtx->pVdbe; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( pVdbe==0 ) goto failed; #else assert( pVdbe!=0 ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8dd2b42..039812c 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -640,7 +640,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename || opcode==OP_VDestroy - || (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL) + || (opcode==OP_ParseSchema && pOp->p4.z==0) || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -977,16 +977,16 @@ void sqlite3VdbeScanStatus( ** Change the value of the opcode, or P1, P2, P3, or P5 operands ** for a specific instruction. */ -void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){ +void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){ sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode; } -void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ +void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ sqlite3VdbeGetOp(p,addr)->p1 = val; } -void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ +void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ sqlite3VdbeGetOp(p,addr)->p2 = val; } -void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ +void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ @@ -1493,14 +1493,16 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ case P4_KEYINFO: { int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); for(j=0; jnKeyField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : ""; if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; - sqlite3_str_appendf(&x, ",%s%s", - pKeyInfo->aSortOrder[j] ? "-" : "", zColl); + sqlite3_str_appendf(&x, ",%s%s%s", + (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "", + (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "", + zColl); } sqlite3_str_append(&x, ")", 1); break; @@ -1907,8 +1909,11 @@ int sqlite3VdbeList( ** pick up the appropriate opcode. */ int j; i -= p->nOp; + assert( apSub!=0 ); + assert( nSub>0 ); for(j=0; i>=apSub[j]->nOp; j++){ i -= apSub[j]->nOp; + assert( inOp || j+1aOp[i]; } @@ -3430,10 +3435,17 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ ** of SQLite will not understand those serial types. */ +#if 0 /* Inlined into the OP_MakeRecord opcode */ /* ** Return the serial-type for the value stored in pMem. ** ** This routine might convert a large MEM_IntReal value into MEM_Real. +** +** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord +** opcode in the byte-code engine. But by moving this routine in-line, we +** can omit some redundant tests and make that opcode a lot faster. So +** this routine is now only used by the STAT3 logic and STAT3 support has +** ended. The code is kept here for historical reference only. */ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ int flags = pMem->flags; @@ -3494,6 +3506,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ *pLen = n; return ((n*2) + 12 + ((flags&MEM_Str)!=0)); } +#endif /* inlined into OP_MakeRecord */ /* ** The sizes for serial types less than 128 @@ -3802,7 +3815,7 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nKeyField + 1; return p; @@ -3901,7 +3914,7 @@ static int vdbeRecordCompareDebug( if( szHdr1>98307 ) return SQLITE_CORRUPT; d1 = szHdr1; assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); assert( pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ @@ -3932,7 +3945,12 @@ static int vdbeRecordCompareDebug( pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0); if( rc!=0 ){ assert( mem1.szMalloc==0 ); /* See comment below */ - if( pKeyInfo->aSortOrder[i] ){ + if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) + && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null)) + ){ + rc = -rc; + } + if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){ rc = -rc; /* Invert the result for DESC sort order. */ } goto debugCompareEnd; @@ -4308,7 +4326,7 @@ int sqlite3VdbeRecordCompareWithSkip( VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->aSortFlags!=0 ); assert( pPKey2->pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ @@ -4431,8 +4449,14 @@ int sqlite3VdbeRecordCompareWithSkip( } if( rc!=0 ){ - if( pPKey2->pKeyInfo->aSortOrder[i] ){ - rc = -rc; + int sortFlags = pPKey2->pKeyInfo->aSortFlags[i]; + if( sortFlags ){ + if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0 + || ((sortFlags & KEYINFO_ORDER_DESC) + !=(serial_type==0 || (pRhs->flags&MEM_Null))) + ){ + rc = -rc; + } } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); assert( mem1.szMalloc==0 ); /* See comment below */ @@ -4600,7 +4624,11 @@ static int vdbeRecordCompareString( nCmp = MIN( pPKey2->aMem[0].n, nStr ); res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); - if( res==0 ){ + if( res>0 ){ + res = pPKey2->r2; + }else if( res<0 ){ + res = pPKey2->r1; + }else{ res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ @@ -4614,10 +4642,6 @@ static int vdbeRecordCompareString( }else{ res = pPKey2->r1; } - }else if( res>0 ){ - res = pPKey2->r2; - }else{ - res = pPKey2->r1; } } @@ -4649,7 +4673,10 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ ** header size is (12*5 + 1 + 1) bytes. */ if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; - if( p->pKeyInfo->aSortOrder[0] ){ + if( p->pKeyInfo->aSortFlags[0] ){ + if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ + return sqlite3VdbeRecordCompare; + } p->r1 = 1; p->r2 = -1; }else{ @@ -4898,7 +4925,7 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ ** features such as 'now'. */ int sqlite3NotPureFunc(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( pCtx->pVdbe==0 ) return 1; #endif if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){ @@ -4995,7 +5022,7 @@ void sqlite3VdbePreUpdateHook( preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nKeyField = pTab->nCol; - preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; + preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 4279792..d34e3cf 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -355,11 +355,12 @@ int sqlite3_blob_close(sqlite3_blob *pBlob){ sqlite3 *db; if( p ){ + sqlite3_stmt *pStmt = p->pStmt; db = p->db; sqlite3_mutex_enter(db->mutex); - rc = sqlite3_finalize(p->pStmt); sqlite3DbFree(db, p); sqlite3_mutex_leave(db->mutex); + rc = sqlite3_finalize(pStmt); }else{ rc = SQLITE_OK; } diff --git a/src/vdbemem.c b/src/vdbemem.c index af6d41a..820789f 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -232,7 +232,13 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( pMem->szMalloc==0 || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ - pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + if( pMem->db ){ + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + }else{ + pMem->zMalloc = sqlite3Realloc(pMem->z, n); + if( pMem->zMalloc==0 ) sqlite3_free(pMem->z); + pMem->z = pMem->zMalloc; + } bPreserve = 0; }else{ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); @@ -1303,7 +1309,7 @@ struct ValueNewStat4Ctx { ** an sqlite3_value within the UnpackedRecord.a[] array. */ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( p ){ UnpackedRecord *pRec = p->ppRec[0]; @@ -1339,7 +1345,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ } #else UNUSED_PARAMETER(p); -#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ +#endif /* defined(SQLITE_ENABLE_STAT4) */ return sqlite3ValueNew(db); } @@ -1363,7 +1369,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ ** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to ** NULL and an SQLite error code returned. */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 static int valueFromFunction( sqlite3 *db, /* The database connection */ Expr *p, /* The expression to evaluate */ @@ -1446,7 +1452,7 @@ static int valueFromFunction( } #else # define valueFromFunction(a,b,c,d,e,f) SQLITE_OK -#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ +#endif /* defined(SQLITE_ENABLE_STAT4) */ /* ** Extract a value from the supplied expression in the manner described @@ -1475,7 +1481,7 @@ static int valueFromExpr( assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; -#if defined(SQLITE_ENABLE_STAT3_OR_STAT4) +#if defined(SQLITE_ENABLE_STAT4) if( op==TK_REGISTER ) op = pExpr->op2; #else if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; @@ -1568,7 +1574,7 @@ static int valueFromExpr( 0, SQLITE_DYNAMIC); } #endif -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 else if( op==TK_FUNCTION && pCtx!=0 ){ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); } @@ -1585,13 +1591,13 @@ static int valueFromExpr( return rc; no_mem: -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( pCtx==0 || pCtx->pParse->nErr==0 ) #endif sqlite3OomFault(db); sqlite3DbFree(db, zVal); assert( *ppVal==0 ); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 if( pCtx==0 ) sqlite3ValueFree(pVal); #else assert( pCtx==0 ); sqlite3ValueFree(pVal); @@ -1619,56 +1625,7 @@ int sqlite3ValueFromExpr( return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** The implementation of the sqlite_record() function. This function accepts -** a single argument of any type. The return value is a formatted database -** record (a blob) containing the argument value. -** -** This is used to convert the value stored in the 'sample' column of the -** sqlite_stat3 table to the record format SQLite uses internally. -*/ -static void recordFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const int file_format = 1; - u32 iSerial; /* Serial type */ - int nSerial; /* Bytes of space for iSerial as varint */ - u32 nVal; /* Bytes of space required for argv[0] */ - int nRet; - sqlite3 *db; - u8 *aRet; - - UNUSED_PARAMETER( argc ); - iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); - nSerial = sqlite3VarintLen(iSerial); - db = sqlite3_context_db_handle(context); - - nRet = 1 + nSerial + nVal; - aRet = sqlite3DbMallocRawNN(db, nRet); - if( aRet==0 ){ - sqlite3_result_error_nomem(context); - }else{ - aRet[0] = nSerial+1; - putVarint32(&aRet[1], iSerial); - sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); - sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); - sqlite3DbFreeNN(db, aRet); - } -} - -/* -** Register built-in functions used to help read ANALYZE data. -*/ -void sqlite3AnalyzeFunctions(void){ - static FuncDef aAnalyzeTableFuncs[] = { - FUNCTION(sqlite_record, 1, 0, 0, recordFunc), - }; - sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs)); -} - +#ifdef SQLITE_ENABLE_STAT4 /* ** Attempt to extract a value from pExpr and use it to construct *ppVal. ** diff --git a/src/vdbesort.c b/src/vdbesort.c index f909f81..7d60ee5 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -829,7 +829,8 @@ static int vdbeSorterCompareText( ); } }else{ - if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); + if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ res = res * -1; } } @@ -897,7 +898,8 @@ static int vdbeSorterCompareInt( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } - }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ + assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); res = res * -1; } @@ -1012,6 +1014,7 @@ int sqlite3VdbeSorterInit( if( pKeyInfo->nAllField<13 && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0 ){ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; } @@ -1728,13 +1731,16 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list); }else{ /* Launch a background thread for this operation */ - u8 *aMem = pTask->list.aMemory; - void *pCtx = (void*)pTask; + u8 *aMem; + void *pCtx; + assert( pTask!=0 ); assert( pTask->pThread==0 && pTask->bDone==0 ); assert( pTask->list.pList==0 ); assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 ); + aMem = pTask->list.aMemory; + pCtx = (void*)pTask; pSorter->iPrev = (u8)(pTask - pSorter->aTask); pTask->list = pSorter->list; pSorter->list.pList = 0; diff --git a/src/vtab.c b/src/vtab.c index 41e26ef..0852909 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -32,6 +32,9 @@ struct VtabCtx { ** Construct and install a Module object for a virtual table. When this ** routine is called, it is guaranteed that all appropriate locks are held ** and the module is not already part of the connection. +** +** If there already exists a module with zName, replace it with the new one. +** If pModule==0, then delete the module zName if it exists. */ Module *sqlite3VtabCreateModule( sqlite3 *db, /* Database in which module is registered */ @@ -41,25 +44,36 @@ Module *sqlite3VtabCreateModule( void (*xDestroy)(void *) /* Module destructor function */ ){ Module *pMod; - int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); - if( pMod==0 ){ - sqlite3OomFault(db); + Module *pDel; + char *zCopy; + if( pModule==0 ){ + zCopy = (char*)zName; + pMod = 0; }else{ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); + int nName = sqlite3Strlen30(zName); + pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); + if( pMod==0 ){ + sqlite3OomFault(db); + return 0; + } + zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); pMod->zName = zCopy; pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; pMod->pEpoTab = 0; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - assert( pDel==0 || pDel==pMod ); - if( pDel ){ + pMod->nRefModule = 1; + } + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + if( pDel ){ + if( pDel==pMod ){ sqlite3OomFault(db); sqlite3DbFree(db, pDel); pMod = 0; + }else{ + sqlite3VtabEponymousTableClear(db, pDel); + sqlite3VtabModuleUnref(db, pDel); } } return pMod; @@ -80,11 +94,7 @@ static int createModule( int rc = SQLITE_OK; sqlite3_mutex_enter(db->mutex); - if( sqlite3HashFind(&db->aModule, zName) ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); - } + (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); sqlite3_mutex_leave(db->mutex); @@ -123,6 +133,44 @@ int sqlite3_create_module_v2( return createModule(db, zName, pModule, pAux, xDestroy); } +/* +** External API to drop all virtual-table modules, except those named +** on the azNames list. +*/ +int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ + HashElem *pThis, *pNext; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif + for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ + Module *pMod = (Module*)sqliteHashData(pThis); + pNext = sqliteHashNext(pThis); + if( azNames ){ + int ii; + for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} + if( azNames[ii]!=0 ) continue; + } + createModule(db, pMod->zName, 0, 0, 0); + } + return SQLITE_OK; +} + +/* +** Decrement the reference count on a Module object. Destroy the +** module when the reference count reaches zero. +*/ +void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){ + assert( pMod->nRefModule>0 ); + pMod->nRefModule--; + if( pMod->nRefModule==0 ){ + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } + assert( pMod->pEpoTab==0 ); + sqlite3DbFree(db, pMod); + } +} + /* ** Lock the virtual table so that it cannot be disconnected. ** Locks nest. Every lock should have a corresponding unlock. @@ -162,6 +210,7 @@ void sqlite3VtabUnlock(VTable *pVTab){ pVTab->nRef--; if( pVTab->nRef==0 ){ sqlite3_vtab *p = pVTab->pVtab; + sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); if( p ){ p->pModule->xDisconnect(p); } @@ -566,6 +615,7 @@ static int vtabCallConstructor( ** the sqlite3_vtab object if successful. */ memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; + pMod->nRefModule++; pVTable->nRef = 1; if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; diff --git a/src/wal.c b/src/wal.c index 53a9e50..669be95 100644 --- a/src/wal.c +++ b/src/wal.c @@ -3478,6 +3478,7 @@ int sqlite3WalFrames( if( rc ) return rc; iOffset += szFrame; nExtra++; + assert( pLast!=0 ); } } if( bSync ){ @@ -3510,6 +3511,7 @@ int sqlite3WalFrames( iFrame++; rc = walIndexAppend(pWal, iFrame, p->pgno); } + assert( pLast!=0 || nExtra==0 ); while( rc==SQLITE_OK && nExtra>0 ){ iFrame++; nExtra--; diff --git a/src/walker.c b/src/walker.c index eff3585..67ecd8a 100644 --- a/src/walker.c +++ b/src/walker.c @@ -25,9 +25,22 @@ static int walkWindowList(Walker *pWalker, Window *pList){ Window *pWin; for(pWin=pList; pWin; pWin=pWin->pNextWin){ - if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; - if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; + int rc; + rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy); + if( rc ) return WRC_Abort; + rc = sqlite3WalkExprList(pWalker, pWin->pPartition); + 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; + rc = sqlite3WalkExpr(pWalker, pWin->pEnd); + if( NEVER(rc) ) return WRC_Abort; } return WRC_Continue; } @@ -63,18 +76,22 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; assert( pExpr->x.pList==0 || pExpr->pRight==0 ); if( pExpr->pRight ){ + assert( !ExprHasProperty(pExpr, EP_WinFunc) ); pExpr = pExpr->pRight; continue; }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + assert( !ExprHasProperty(pExpr, EP_WinFunc) ); if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else if( pExpr->x.pList ){ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } + }else{ + if( pExpr->x.pList ){ + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + } #ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort; - } + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort; + } #endif + } } break; } @@ -116,8 +133,9 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){ { Parse *pParse = pWalker->pParse; if( pParse && IN_RENAME_OBJECT ){ + /* 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); - assert( rc==WRC_Continue ); return rc; } } diff --git a/src/where.c b/src/where.c index f2ab125..1a43b8d 100644 --- a/src/where.c +++ b/src/where.c @@ -253,7 +253,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) - && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN + && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op + ==TK_COLUMN ){ int j; for(j=0; jnEquiv; j++){ @@ -449,7 +450,7 @@ static int findIndexCol( const char *zColl = pIdx->azColl[iCol]; for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr); if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase @@ -513,7 +514,7 @@ static int isDistinctRedundant( ** current SELECT is a correlated sub-query. */ for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr); if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } @@ -933,6 +934,7 @@ static sqlite3_index_info *allocateIndexInfo( for(i=0; ia[i].pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break; } if( i==n){ nOrderBy = n; @@ -1031,7 +1033,7 @@ static sqlite3_index_info *allocateIndexInfo( for(i=0; ia[i].pExpr; pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; } *pmNoOmit = mNoOmit; @@ -1077,7 +1079,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: @@ -1270,7 +1272,7 @@ static int whereKeyStats( pRec->nField = nField; return i; } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ /* ** If it is not NULL, pTerm is a term that provides an upper or lower @@ -1296,7 +1298,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Return the affinity for a single column of an index. */ @@ -1305,12 +1307,13 @@ char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ if( !pIdx->zColAff ){ if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; } + assert( pIdx->zColAff[iCol]!=0 ); return pIdx->zColAff[iCol]; } #endif -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** This function is called to estimate the number of rows visited by a ** range-scan on a skip-scan index. For example: @@ -1416,7 +1419,7 @@ static int whereRangeSkipScanEst( return rc; } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ /* ** This function is used to estimate the number of rows that will be visited @@ -1469,12 +1472,12 @@ static int whereRangeScanEst( int nOut = pLoop->nOut; LogEst nNew; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; - if( p->nSample>0 && nEqnSampleCol - && OptimizationEnabled(pParse->db, SQLITE_Stat34) + if( p->nSample>0 && ALWAYS(nEqnSampleCol) + && OptimizationEnabled(pParse->db, SQLITE_Stat4) ){ if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; @@ -1572,7 +1575,7 @@ static int whereRangeScanEst( /* TUNING: If both iUpper and iLower are derived from the same ** sample, then assume they are 4x more selective. This brings ** the estimated selectivity more in line with what it would be - ** if estimated without the use of STAT3/4 tables. */ + ** if estimated without the use of STAT4 tables. */ if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); @@ -1621,12 +1624,12 @@ static int whereRangeScanEst( return rc; } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Estimate the number of rows that will be returned based on ** an equality constraint x=VALUE and where that VALUE occurs in ** the histogram data. This only works when x is the left-most -** column of an index and sqlite_stat3 histogram data is available +** column of an index and sqlite_stat4 histogram data is available ** for that index. When pExpr==NULL that means the constraint is ** "x IS NULL" instead of "x=VALUE". ** @@ -1684,9 +1687,9 @@ static int whereEqualScanEst( return rc; } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 /* ** Estimate the number of rows that will be returned based on ** an IN constraint where the right-hand side of the IN operator @@ -1733,7 +1736,7 @@ static int whereInScanEst( assert( pBuilder->nRecValid==nRecValid ); return rc; } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ #ifdef WHERETRACE_ENABLED @@ -2265,11 +2268,12 @@ static void whereLoopOutputAdjust( ){ WhereTerm *pTerm, *pX; Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int i, j, k; + int i, j; LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ + assert( pTerm!=0 ); if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; if( (pTerm->prereqAll & notAllowed)!=0 ) continue; @@ -2290,6 +2294,7 @@ static void whereLoopOutputAdjust( pLoop->nOut--; if( pTerm->eOperator&(WO_EQ|WO_IS) ){ Expr *pRight = pTerm->pExpr->pRight; + int k = 0; testcase( pTerm->pExpr->op==TK_IS ); if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){ k = 10; @@ -2453,7 +2458,7 @@ static int whereLoopAddBtreeIndex( LogEst rCostIdx; LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ int nIn = 0; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 int nRecValid = pBuilder->nRecValid; #endif if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) @@ -2514,8 +2519,6 @@ static int whereLoopAddBtreeIndex( }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ } if( pProbe->hasStat1 ){ LogEst M, logK, safetyMargin; @@ -2611,7 +2614,7 @@ static int whereLoopAddBtreeIndex( ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ assert( pNew->nOut==saved_nOut ); if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4 + /* Adjust nOut using stat4 data. Or, if there is no stat4 ** data, using some other estimate. */ whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); }else{ @@ -2625,13 +2628,13 @@ static int whereLoopAddBtreeIndex( pNew->nOut += pTerm->truthProb; pNew->nOut -= nIn; }else{ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 tRowcnt nOut = 0; if( nInMul==0 && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) - && OptimizationEnabled(db, SQLITE_Stat34) + && OptimizationEnabled(db, SQLITE_Stat4) ){ Expr *pExpr = pTerm->pExpr; if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ @@ -2668,6 +2671,7 @@ static int whereLoopAddBtreeIndex( ** it to pNew->rRun, which is currently set to the cost of the index ** seek only. Then, if this is a non-covering index, add the cost of ** visiting the rows in the main table. */ + assert( pSrc->pTab->szTabRow>0 ); rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ @@ -2693,7 +2697,7 @@ static int whereLoopAddBtreeIndex( whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } pNew->nOut = saved_nOut; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 pBuilder->nRecValid = nRecValid; #endif } @@ -2766,7 +2770,7 @@ static int indexMightHelpWithOrderBy( if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); + Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr); if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ @@ -2797,7 +2801,9 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ } if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr = pTerm->pExpr; + Expr *pExpr; + if( pTerm->wtFlags & TERM_NOPARTIDX ) continue; + pExpr = pTerm->pExpr; if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) ){ @@ -3066,7 +3072,7 @@ static int whereLoopAddBtree( ** plan */ pTab->tabFlags |= TF_StatsUsed; } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 sqlite3Stat4ProbeFree(pBuilder->pRec); pBuilder->nRecValid = 0; pBuilder->pRec = 0; @@ -3694,8 +3700,8 @@ static i8 wherePathSatisfiesOrderBy( if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ if( pLoop->u.vtab.isOrdered ) obSat = obDone; break; - }else{ - pLoop->u.btree.nIdxCol = 0; + }else if( wctrlFlags & WHERE_DISTINCTBY ){ + pLoop->u.btree.nDistinctCol = 0; } iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; @@ -3706,7 +3712,7 @@ static i8 wherePathSatisfiesOrderBy( */ for(i=0; ia[i].pExpr); + pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr); if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, @@ -3743,7 +3749,8 @@ static i8 wherePathSatisfiesOrderBy( assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); assert( pIndex->aiColumn[nColumn-1]==XN_ROWID || !HasRowid(pIndex->pTable)); - isOrderDistinct = IsUniqueIndex(pIndex); + isOrderDistinct = IsUniqueIndex(pIndex) + && (pLoop->wsFlags & WHERE_SKIPSCAN)==0; } /* Loop through all columns of the index and deal with the ones @@ -3761,15 +3768,21 @@ static i8 wherePathSatisfiesOrderBy( u16 eOp = pLoop->aLTerm[j]->eOperator; /* Skip over == and IS and ISNULL terms. (Also skip IN terms when - ** doing WHERE_ORDERBY_LIMIT processing). + ** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL + ** terms imply that the index is not UNIQUE NOT NULL in which case + ** the loop need to be marked as not order-distinct because it can + ** have repeated NULL rows. ** ** If the current term is a column of an ((?,?) IN (SELECT...)) ** expression for which the SELECT returns more than one column, ** check that it is the only column used by this loop. Otherwise, ** if it is one of two or more, none of the columns can be - ** considered to match an ORDER BY term. */ + ** considered to match an ORDER BY term. + */ if( (eOp & eqOpMask)!=0 ){ - if( eOp & WO_ISNULL ){ + if( eOp & (WO_ISNULL|WO_IS) ){ + testcase( eOp & WO_ISNULL ); + testcase( eOp & WO_IS ); testcase( isOrderDistinct ); isOrderDistinct = 0; } @@ -3795,7 +3808,7 @@ static i8 wherePathSatisfiesOrderBy( */ if( pIndex ){ iColumn = pIndex->aiColumn[j]; - revIdx = pIndex->aSortOrder[j]; + revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC; if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; }else{ iColumn = XN_ROWID; @@ -3819,7 +3832,7 @@ static i8 wherePathSatisfiesOrderBy( isMatch = 0; for(i=0; bOnce && ia[i].pExpr); + pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr); testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; @@ -3837,7 +3850,9 @@ static i8 wherePathSatisfiesOrderBy( pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; } - pLoop->u.btree.nIdxCol = j+1; + if( wctrlFlags & WHERE_DISTINCTBY ){ + pLoop->u.btree.nDistinctCol = j+1; + } isMatch = 1; break; } @@ -3845,13 +3860,22 @@ static i8 wherePathSatisfiesOrderBy( /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ - if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0; + if( (rev ^ revIdx)!=(pOrderBy->a[i].sortFlags&KEYINFO_ORDER_DESC) ){ + isMatch = 0; + } }else{ - rev = revIdx ^ pOrderBy->a[i].sortOrder; + rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC); if( rev ) *pRevMask |= MASKBIT(iLoop); revSet = 1; } } + if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){ + if( j==pLoop->u.btree.nEq ){ + pLoop->wsFlags |= WHERE_BIGNULL_SORT; + }else{ + isMatch = 0; + } + } if( isMatch ){ if( iColumn==XN_ROWID ){ testcase( distinctColumns==0 ); @@ -4765,6 +4789,16 @@ WhereInfo *sqlite3WhereBegin( sqlite3DebugPrintf(", limit: %d", iAuxArg); } sqlite3DebugPrintf(")\n"); + if( sqlite3WhereTrace & 0x100 ){ + Select sSelect; + memset(&sSelect, 0, sizeof(sSelect)); + sSelect.selFlags = SF_WhereBegin; + sSelect.pSrc = pTabList; + sSelect.pWhere = pWhere; + sSelect.pOrderBy = pOrderBy; + sSelect.pEList = pResultSet; + sqlite3TreeViewSelect(0, &sSelect, 0); + } } if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ sqlite3WhereClausePrint(sWLB.pWC); @@ -5041,6 +5075,7 @@ WhereInfo *sqlite3WhereBegin( sqlite3VdbeSetP4KeyInfo(pParse, pIx); if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 + && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0 && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED ){ @@ -5158,7 +5193,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ && (pLoop->wsFlags & WHERE_INDEXED)!=0 && (pIdx = pLoop->u.btree.pIndex)->hasStat1 - && (n = pLoop->u.btree.nIdxCol)>0 + && (n = pLoop->u.btree.nDistinctCol)>0 && pIdx->aiRowLogEst[n]>=36 ){ int r1 = pParse->nMem+1; @@ -5182,6 +5217,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ VdbeCoverageIf(v, pLevel->op==OP_Next); VdbeCoverageIf(v, pLevel->op==OP_Prev); VdbeCoverageIf(v, pLevel->op==OP_VNext); + if( pLevel->regBignull ){ + sqlite3VdbeResolveLabel(v, pLevel->addrBignull); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1); + VdbeCoverage(v); + } #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif diff --git a/src/whereInt.h b/src/whereInt.h index 090bbc2..64978cf 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -71,13 +71,15 @@ struct WhereLevel { int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ + int regBignull; /* big-null flag reg. True if a NULL-scan is needed */ + int addrBignull; /* Jump here for next part of big-null scan */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ - int p1, p2; /* Operands of the opcode used to ends the loop */ + int p1, p2; /* Operands of the opcode used to end the loop */ union { /* Information that depends on pWLoop->wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ @@ -128,7 +130,7 @@ struct WhereLoop { u16 nEq; /* Number of equality constraints */ u16 nBtm; /* Size of BTM vector */ u16 nTop; /* Size of TOP vector */ - u16 nIdxCol; /* Index column used for ORDER BY */ + u16 nDistinctCol; /* Index columns used to sort for DISTINCT */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ @@ -279,16 +281,17 @@ struct WhereTerm { #define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */ #define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */ #define TERM_OR_OK 0x40 /* Used during OR-clause processing */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ #else -# define TERM_VNULL 0x00 /* Disabled if not using stat3 */ +# define TERM_VNULL 0x00 /* Disabled if not using stat4 */ #endif #define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ #define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ #define TERM_LIKE 0x400 /* The original LIKE operator */ #define TERM_IS 0x800 /* Term.pExpr is an IS operator */ #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ +#define TERM_NOPARTIDX 0x2000 /* Not for use to enable a partial index */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -399,7 +402,7 @@ struct WhereLoopBuilder { ExprList *pOrderBy; /* ORDER BY clause */ WhereLoop *pNew; /* Template WhereLoop */ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +#ifdef SQLITE_ENABLE_STAT4 UnpackedRecord *pRec; /* Probe for stat4 (if required) */ int nRecValid; /* Number of valid fields currently in pRec */ #endif @@ -586,5 +589,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ +#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #endif /* !defined(SQLITE_WHEREINT_H) */ diff --git a/src/wherecode.c b/src/wherecode.c index a625448..2fbcba1 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -318,9 +318,9 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ ** Code an OP_Affinity opcode to apply the column affinity string zAff ** to the n registers starting at base. ** -** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the -** beginning and end of zAff are ignored. If all entries in zAff are -** SQLITE_AFF_BLOB, then no code gets generated. +** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which +** are no-ops) at the beginning and end of zAff are ignored. If all entries +** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated. ** ** This routine makes its own copy of zAff so that the caller is free ** to modify zAff after this routine returns. @@ -333,15 +333,16 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ } assert( v!=0 ); - /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning - ** and end of the affinity string. + /* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE + ** entries at the beginning and end of the affinity string. */ - while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){ + assert( SQLITE_AFF_NONE0 && zAff[0]<=SQLITE_AFF_BLOB ){ n--; base++; zAff++; } - while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){ + while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){ n--; } @@ -1116,6 +1117,7 @@ typedef struct IdxExprTrans { static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + pExpr->affExpr = sqlite3ExprAffinity(pExpr); pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; @@ -1548,32 +1550,12 @@ Bitmask sqlite3WhereCodeOneLoopStart( u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ int omitTable; /* True if we use the index only */ - + int regBignull = 0; /* big-null flag register */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; assert( nEq>=pLoop->nSkip ); - /* If this loop satisfies a sort order (pOrderBy) request that - ** was passed to this function to implement a "SELECT min(x) ..." - ** query, then the caller will only allow the loop to run for - ** a single iteration. This means that the first row returned - ** should not have a NULL value stored in 'x'. If column 'x' is - ** the first one after the nEq equality constraints in the index, - ** this requires some special handling. - */ - assert( pWInfo->pOrderBy==0 - || pWInfo->pOrderBy->nExpr==1 - || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 ); - if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 - && pWInfo->nOBSat>0 - && (pIdx->nKeyCol>nEq) - ){ - assert( pLoop->nSkip==0 ); - bSeekPastNull = 1; - nExtraReg = 1; - } - /* Find any inequality constraint terms for the start and end ** of the range. */ @@ -1614,6 +1596,25 @@ Bitmask sqlite3WhereCodeOneLoopStart( } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); + /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses + ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS + ** FIRST). In both cases separate ordered scans are made of those + ** index entries for which the column is null and for those for which + ** it is not. For an ASC sort, the non-NULL entries are scanned first. + ** For DESC, NULL entries are scanned first. + */ + if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0 + && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0 + ){ + assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 ); + assert( pRangeEnd==0 && pRangeStart==0 ); + assert( pLoop->nSkip==0 ); + nExtraReg = 1; + bSeekPastNull = 1; + pLevel->regBignull = regBignull = ++pParse->nMem; + pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse); + } + /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). @@ -1636,7 +1637,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( zStartAff && nTop ){ zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); } - addrNxt = pLevel->addrNxt; + addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt); testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); @@ -1670,10 +1671,14 @@ Bitmask sqlite3WhereCodeOneLoopStart( } bSeekPastNull = 0; }else if( bSeekPastNull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - nConstraint++; startEq = 0; + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); start_constraints = 1; + nConstraint++; + }else if( regBignull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + start_constraints = 1; + nConstraint++; } codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){ @@ -1684,6 +1689,11 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); } + if( regBignull ){ + sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); + VdbeComment((v, "NULL-scan pass ctr")); + } + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); @@ -1694,6 +1704,23 @@ Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); + + assert( bSeekPastNull==0 || bStopAtNull==0 ); + if( regBignull ){ + assert( bSeekPastNull==1 || bStopAtNull==1 ); + assert( bSeekPastNull==!bStopAtNull ); + assert( bStopAtNull==startEq ); + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); + op = aStartOp[(nConstraint>1)*4 + 2 + bRev]; + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, + nConstraint-startEq); + VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); + VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); + VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); + VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE); + } } /* Load the value for the inequality constraint at the end of the @@ -1725,8 +1752,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( endEq = 1; } }else if( bStopAtNull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - endEq = 0; + if( regBignull==0 ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + endEq = 0; + } nConstraint++; } sqlite3DbFree(db, zStartAff); @@ -1737,6 +1766,12 @@ Bitmask sqlite3WhereCodeOneLoopStart( /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ + if( regBignull ){ + /* Except, skip the end-of-range check while doing the NULL-scan */ + sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); + VdbeComment((v, "If NULL-scan 2nd pass")); + VdbeCoverage(v); + } op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); @@ -1744,6 +1779,23 @@ Bitmask sqlite3WhereCodeOneLoopStart( testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } + if( regBignull ){ + /* During a NULL-scan, check to see if we have reached the end of + ** the NULLs */ + assert( bSeekPastNull==!bStopAtNull ); + assert( bSeekPastNull+bStopAtNull==1 ); + assert( nConstraint+bSeekPastNull>0 ); + sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2); + VdbeComment((v, "If NULL-scan 1st pass")); + VdbeCoverage(v); + op = aEndOp[bRev*2 + bSeekPastNull]; + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, + nConstraint+bSeekPastNull); + testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); + testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); + testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); + } if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); diff --git a/src/whereexpr.c b/src/whereexpr.c index 9ac940c..a161310 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -84,7 +84,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ }else{ pTerm->truthProb = 1; } - pTerm->pExpr = sqlite3ExprSkipCollate(p); + pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; @@ -117,10 +117,16 @@ static int allowedOp(int op){ ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_Collate flag ** is not commuted. +** +** The return value is extra flags that are added to the WhereTerm object +** after it is commuted. The only extra flag ever added is TERM_NOPARTIDX +** which prevents the term from being used to enable a partial index if +** COLLATE changes have been made. */ -static void exprCommute(Parse *pParse, Expr *pExpr){ +static u16 exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_Collate); u16 expLeft = (pExpr->pLeft->flags & EP_Collate); + u16 wtFlags = 0; assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); if( expRight==expLeft ){ /* Either X and Y both have COLLATE operator or neither do */ @@ -128,11 +134,13 @@ static void exprCommute(Parse *pParse, Expr *pExpr){ /* Both X and Y have COLLATE operators. Make sure X is always ** used by clearing the EP_Collate flag from Y. */ pExpr->pRight->flags &= ~EP_Collate; + wtFlags |= TERM_NOPARTIDX; }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ /* Neither X nor Y have COLLATE operators, but X has a non-default ** collating sequence. So add the EP_Collate marker on X to cause ** it to be searched first. */ pExpr->pLeft->flags |= EP_Collate; + wtFlags |= TERM_NOPARTIDX; } } SWAP(Expr*,pExpr->pRight,pExpr->pLeft); @@ -144,6 +152,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){ assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; } + return wtFlags; } /* @@ -275,6 +284,7 @@ static int isLikeOrGlob( ** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28 ** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07 ** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975 + ** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a */ if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT @@ -284,9 +294,13 @@ static int isLikeOrGlob( double rDummy; isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); if( isNum<=0 ){ - zNew[iTo-1]++; - isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); - zNew[iTo-1]--; + if( iTo==1 && zNew[0]=='-' ){ + isNum = +1; + }else{ + zNew[iTo-1]++; + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); + zNew[iTo-1]--; + } } if( isNum>0 ){ sqlite3ExprDelete(db, pPrefix); @@ -1140,7 +1154,7 @@ static void exprAnalyze( pDup = pExpr; pNew = pTerm; } - exprCommute(pParse, pDup); + pNew->wtFlags |= exprCommute(pParse, pDup); pNew->leftCursor = aiCurCol[0]; pNew->u.leftColumn = aiCurCol[1]; testcase( (prereqLeft | extraRight) != prereqLeft ); @@ -1381,8 +1395,8 @@ static void exprAnalyze( } } -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - /* When sqlite_stat3 histogram data is available an operator of the +#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. @@ -1393,7 +1407,7 @@ static void exprAnalyze( && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 && !ExprHasProperty(pExpr, EP_FromJoin) - && OptimizationEnabled(db, SQLITE_Stat34) + && OptimizationEnabled(db, SQLITE_Stat4) ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; @@ -1418,7 +1432,7 @@ static void exprAnalyze( pNewTerm->prereqAll = pTerm->prereqAll; } } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ +#endif /* SQLITE_ENABLE_STAT4 */ /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. @@ -1451,7 +1465,7 @@ static void exprAnalyze( ** all terms of the WHERE clause. */ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - Expr *pE2 = sqlite3ExprSkipCollate(pExpr); + Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr); pWC->op = op; if( pE2==0 ) return; if( pE2->op!=op ){ diff --git a/src/window.c b/src/window.c index dcd7107..e8dfa6c 100644 --- a/src/window.c +++ b/src/window.c @@ -748,6 +748,8 @@ struct WindowRewrite { static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ struct WindowRewrite *p = pWalker->u.pRewrite; Parse *pParse = pWalker->pParse; + assert( p!=0 ); + assert( p->pWin!=0 ); /* If this function is being called from within a scalar sub-select ** that used by the SELECT statement being processed, only process @@ -847,6 +849,7 @@ static void selectWindowRewriteEList( Walker sWalker; WindowRewrite sRewrite; + assert( pWin!=0 ); memset(&sWalker, 0, sizeof(Walker)); memset(&sRewrite, 0, sizeof(WindowRewrite)); @@ -885,7 +888,7 @@ static ExprList *exprListAppendList( pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); } pList = sqlite3ExprListAppend(pParse, pList, pDup); - if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; + if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags; } } return pList; @@ -931,11 +934,14 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** redundant, remove the ORDER BY from the parent SELECT. */ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0); pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1); - if( pSort && p->pOrderBy ){ + if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){ + int nSave = pSort->nExpr; + pSort->nExpr = p->pOrderBy->nExpr; if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; } + pSort->nExpr = nSave; } /* Assign a cursor number for the ephemeral table used to buffer rows. @@ -959,8 +965,15 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** window function - one for the accumulator, another for interim ** results. */ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList, 0); + ExprList *pArgs = pWin->pOwner->x.pList; + if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ + selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); + pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); + pWin->bExprArgs = 1; + }else{ + pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); + pSublist = exprListAppendList(pParse, pSublist, pArgs, 0); + } if( pWin->pFilter ){ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); @@ -978,7 +991,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ */ if( pSublist==0 ){ pSublist = sqlite3ExprListAppend(pParse, 0, - sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0) + sqlite3Expr(db, TK_INTEGER, "0") ); } @@ -991,7 +1004,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); pSub->selFlags |= SF_Expanded; - pTab2 = sqlite3ResultSetOfSelect(pParse, pSub); + pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); if( pTab2==0 ){ rc = SQLITE_NOMEM; }else{ @@ -1014,11 +1027,24 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ return rc; } +/* +** Unlink the Window object from the Select to which it is attached, +** if it is attached. +*/ +void sqlite3WindowUnlinkFromSelect(Window *p){ + if( p->ppThis ){ + *p->ppThis = p->pNextWin; + if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis; + p->ppThis = 0; + } +} + /* ** Free the Window object passed as the second argument. */ void sqlite3WindowDelete(sqlite3 *db, Window *p){ if( p ){ + sqlite3WindowUnlinkFromSelect(p); sqlite3ExprDelete(db, p->pFilter); sqlite3ExprListDelete(db, p->pPartition); sqlite3ExprListDelete(db, p->pOrderBy); @@ -1196,28 +1222,44 @@ void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ assert( p->op==TK_FUNCTION ); - /* This routine is only called for the parser. If pWin was not - ** allocated due to an OOM, then the parser would fail before ever - ** invoking this routine */ - if( ALWAYS(pWin) ){ - p->y.pWin = pWin; - ExprSetProperty(p, EP_WinFunc); - pWin->pOwner = p; - if( p->flags & EP_Distinct ){ - sqlite3ErrorMsg(pParse, - "DISTINCT is not supported for window functions"); - } + assert( pWin ); + p->y.pWin = pWin; + ExprSetProperty(p, EP_WinFunc); + pWin->pOwner = p; + if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){ + sqlite3ErrorMsg(pParse, + "DISTINCT is not supported for window functions" + ); } }else{ sqlite3WindowDelete(pParse->db, pWin); } } +/* +** Possibly link window pWin into the list at pSel->pWin (window functions +** to be processed as part of SELECT statement pSel). The window is linked +** in if either (a) there are no other windows already linked to this +** SELECT, or (b) the windows already linked use a compatible window frame. +*/ +void sqlite3WindowLink(Select *pSel, Window *pWin){ + 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; + } +} + /* ** Return 0 if the two window objects are identical, or non-zero otherwise. ** Identical window objects can be processed in a single scan. */ -int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ +int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){ if( p1->eFrmType!=p2->eFrmType ) return 1; if( p1->eStart!=p2->eStart ) return 1; if( p1->eEnd!=p2->eEnd ) return 1; @@ -1226,6 +1268,9 @@ int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1; if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1; + if( bFilter ){ + if( sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1) ) return 1; + } return 0; } @@ -1277,8 +1322,8 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ pWin->regApp = pParse->nMem+1; pParse->nMem += 3; if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ - assert( pKeyInfo->aSortOrder[0]==0 ); - pKeyInfo->aSortOrder[0] = 1; + assert( pKeyInfo->aSortFlags[0]==0 ); + pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC; } sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); @@ -1363,6 +1408,108 @@ static int windowArgCount(Window *pWin){ return (pList ? pList->nExpr : 0); } +typedef struct WindowCodeArg WindowCodeArg; +typedef struct WindowCsrAndReg WindowCsrAndReg; + +/* +** See comments above struct WindowCodeArg. +*/ +struct WindowCsrAndReg { + int csr; /* Cursor number */ + int reg; /* First in array of peer values */ +}; + +/* +** A single instance of this structure is allocated on the stack by +** sqlite3WindowCodeStep() and a pointer to it passed to the various helper +** routines. This is to reduce the number of arguments required by each +** helper function. +** +** regArg: +** Each window function requires an accumulator register (just as an +** ordinary aggregate function does). This variable is set to the first +** in an array of accumulator registers - one for each window function +** in the WindowCodeArg.pMWin list. +** +** eDelete: +** The window functions implementation sometimes caches the input rows +** that it processes in a temporary table. If it is not zero, this +** variable indicates when rows may be removed from the temp table (in +** order to reduce memory requirements - it would always be safe just +** to leave them there). Possible values for eDelete are: +** +** WINDOW_RETURN_ROW: +** An input row can be discarded after it is returned to the caller. +** +** WINDOW_AGGINVERSE: +** An input row can be discarded after the window functions xInverse() +** callbacks have been invoked in it. +** +** WINDOW_AGGSTEP: +** An input row can be discarded after the window functions xStep() +** callbacks have been invoked in it. +** +** start,current,end +** Consider a window-frame similar to the following: +** +** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) +** +** The windows functions implmentation caches the input rows in a temp +** table, sorted by "a, b" (it actually populates the cache lazily, and +** aggressively removes rows once they are no longer required, but that's +** a mere detail). It keeps three cursors open on the temp table. One +** (current) that points to the next row to return to the query engine +** once its window function values have been calculated. Another (end) +** points to the next row to call the xStep() method of each window function +** on (so that it is 2 groups ahead of current). And a third (start) that +** points to the next row to call the xInverse() method of each window +** function on. +** +** Each cursor (start, current and end) consists of a VDBE cursor +** (WindowCsrAndReg.csr) and an array of registers (starting at +** WindowCodeArg.reg) that always contains a copy of the peer values +** read from the corresponding cursor. +** +** Depending on the window-frame in question, all three cursors may not +** be required. In this case both WindowCodeArg.csr and reg are set to +** 0. +*/ +struct WindowCodeArg { + Parse *pParse; /* Parse context */ + Window *pMWin; /* First in list of functions being processed */ + Vdbe *pVdbe; /* VDBE object */ + int addrGosub; /* OP_Gosub to this address to return one row */ + int regGosub; /* Register used with OP_Gosub(addrGosub) */ + int regArg; /* First in array of accumulator registers */ + int eDelete; /* See above */ + + WindowCsrAndReg start; + WindowCsrAndReg current; + WindowCsrAndReg end; +}; + +/* +** Generate VM code to read the window frames peer values from cursor csr into +** an array of registers starting at reg. +*/ +static void windowReadPeerValues( + WindowCodeArg *p, + int csr, + int reg +){ + Window *pMWin = p->pMWin; + ExprList *pOrderBy = pMWin->pOrderBy; + if( pOrderBy ){ + Vdbe *v = sqlite3GetVdbe(p->pParse); + ExprList *pPart = pMWin->pPartition; + int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); + int i; + for(i=0; inExpr; i++){ + sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i); + } + } +} + /* ** Generate VM code to invoke either xStep() (if bInverse is 0) or ** xInverse (if bInverse is non-zero) for each window function in the @@ -1383,20 +1530,27 @@ static int windowArgCount(Window *pWin){ ** number of rows in the current partition. */ static void windowAggStep( - Parse *pParse, + WindowCodeArg *p, Window *pMWin, /* Linked list of window functions */ int csr, /* Read arguments from this cursor */ int bInverse, /* True to invoke xInverse instead of xStep */ int reg /* Array of registers */ ){ + Parse *pParse = p->pParse; Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; int regArg; - int nArg = windowArgCount(pWin); + int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin); int i; + assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED ); + + /* All OVER clauses in the same window function aggregate step must + ** be the same. */ + assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)==0 ); + for(i=0; izName!=nth_valueName ){ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); @@ -1434,14 +1588,30 @@ static void windowAggStep( int addrIf = 0; if( pWin->pFilter ){ int regTmp; - assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr ); - assert( nArg || pWin->pOwner->x.pList==0 ); + assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr ); + assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 ); regTmp = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, regTmp); } + + if( pWin->bExprArgs ){ + int iStart = sqlite3VdbeCurrentAddr(v); + VdbeOp *pOp, *pEnd; + + 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++){ + if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){ + pOp->p1 = csr; + } + } + } if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl; assert( nArg>0 ); @@ -1452,32 +1622,14 @@ static void windowAggStep( bInverse, regArg, pWin->regAccum); sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); + if( pWin->bExprArgs ){ + sqlite3ReleaseTempRange(pParse, regArg, nArg); + } if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); } } } -typedef struct WindowCodeArg WindowCodeArg; -typedef struct WindowCsrAndReg WindowCsrAndReg; -struct WindowCsrAndReg { - int csr; - int reg; -}; - -struct WindowCodeArg { - Parse *pParse; - Window *pMWin; - Vdbe *pVdbe; - int regGosub; - int addrGosub; - int regArg; - int eDelete; - - WindowCsrAndReg start; - WindowCsrAndReg current; - WindowCsrAndReg end; -}; - /* ** Values that may be passed as the second argument to windowCodeOp(). */ @@ -1485,28 +1637,6 @@ struct WindowCodeArg { #define WINDOW_AGGINVERSE 2 #define WINDOW_AGGSTEP 3 -/* -** Generate VM code to read the window frames peer values from cursor csr into -** an array of registers starting at reg. -*/ -static void windowReadPeerValues( - WindowCodeArg *p, - int csr, - int reg -){ - Window *pMWin = p->pMWin; - ExprList *pOrderBy = pMWin->pOrderBy; - if( pOrderBy ){ - Vdbe *v = sqlite3GetVdbe(p->pParse); - ExprList *pPart = pMWin->pPartition; - int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); - int i; - for(i=0; inExpr; i++){ - sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i); - } - } -} - /* ** Generate VM code to invoke either xValue() (bFin==0) or xFinalize() ** (bFin==1) for each window function in the linked list starting at @@ -1567,8 +1697,12 @@ static void windowFullScan(WindowCodeArg *p){ int lblNext; int lblBrk; int addrNext; - int csr = pMWin->csrApp; + int csr; + VdbeModuleComment((v, "windowFullScan begin")); + + assert( pMWin!=0 ); + csr = pMWin->csrApp; nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); lblNext = sqlite3VdbeMakeLabel(pParse); @@ -1623,7 +1757,7 @@ static void windowFullScan(WindowCodeArg *p){ if( addrEq ) sqlite3VdbeJumpHere(v, addrEq); } - windowAggStep(pParse, pMWin, csr, 0, p->regArg); + windowAggStep(p, pMWin, csr, 0, p->regArg); sqlite3VdbeResolveLabel(v, lblNext); sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext); @@ -1638,6 +1772,7 @@ static void windowFullScan(WindowCodeArg *p){ } windowAggFinal(p, 1); + VdbeModuleComment((v, "windowFullScan end")); } /* @@ -1812,34 +1947,46 @@ static void windowIfNewPeer( /* ** This function is called as part of generating VM programs for RANGE ** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for -** the ORDER BY term in the window, it generates code equivalent to: +** the ORDER BY term in the window, and that argument op is OP_Ge, it generates +** code equivalent to: ** ** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl; ** -** A special type of arithmetic is used such that if csr.peerVal is not -** a numeric type (real or integer), then the result of the addition is -** a copy of csr1.peerVal. +** The value of parameter op may also be OP_Gt or OP_Le. In these cases the +** operator in the above pseudo-code is replaced with ">" or "<=", respectively. +** +** If the sort-order for the ORDER BY term in the window is DESC, then the +** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is +** subtracted. And the comparison operator is inverted to - ">=" becomes "<=", +** ">" becomes "<", and so on. So, with DESC sort order, if the argument op +** is OP_Ge, the generated code is equivalent to: +** +** 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 +** or subtraction is a a copy of csr1.peerVal. */ static void windowCodeRangeTest( WindowCodeArg *p, - int op, /* OP_Ge or OP_Gt */ - int csr1, - int regVal, - int csr2, - int lbl + int op, /* OP_Ge, OP_Gt, or OP_Le */ + int csr1, /* Cursor number for cursor 1 */ + int regVal, /* Register containing non-negative number */ + int csr2, /* Cursor number for cursor 2 */ + int lbl /* Jump destination if condition is true */ ){ Parse *pParse = p->pParse; Vdbe *v = sqlite3GetVdbe(pParse); - int reg1 = sqlite3GetTempReg(pParse); - int reg2 = sqlite3GetTempReg(pParse); - int arith = OP_Add; - int addrGe; - - int regString = ++pParse->nMem; + ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */ + int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */ + int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */ + int regString = ++pParse->nMem; /* Reg. for constant value '' */ + int arith = OP_Add; /* OP_Add or OP_Subtract */ + int addrGe; /* Jump destination */ assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); - assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 ); - if( p->pMWin->pOrderBy->a[0].sortOrder ){ + assert( pOrderBy && pOrderBy->nExpr==1 ); + if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){ switch( op ){ case OP_Ge: op = OP_Le; break; case OP_Gt: op = OP_Lt; break; @@ -1848,27 +1995,95 @@ static void windowCodeRangeTest( arith = OP_Subtract; } + /* Read the peer-value from each cursor into a register */ windowReadPeerValues(p, csr1, reg1); windowReadPeerValues(p, csr2, reg2); - /* Check if the peer value for csr1 value is a text or blob by comparing - ** it to the smallest possible string - ''. If it is, jump over the - ** OP_Add or OP_Subtract operation and proceed directly to the comparison. */ + 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 + ** (and adding that capability causes a performance regression), so + ** instead if the BIGNULL flag is set then cases where either reg1 or + ** reg2 are NULL are handled separately in the following block. The code + ** generated is equivalent to: + ** + ** if( reg1 IS NULL ){ + ** if( op==OP_Ge ) goto lbl; + ** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl; + ** if( op==OP_Le && reg2 IS NULL ) goto lbl; + ** }else if( reg2 IS NULL ){ + ** if( op==OP_Le ) goto lbl; + ** } + ** + ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is + ** not taken, control jumps over the comparison operator coded below this + ** block. */ + if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){ + /* This block runs if reg1 contains a NULL. */ + int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v); + switch( op ){ + case OP_Ge: + sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl); + break; + case OP_Gt: + sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl); + VdbeCoverage(v); + break; + case OP_Le: + sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); + VdbeCoverage(v); + break; + default: assert( op==OP_Lt ); /* no-op */ break; + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); + + /* 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); + } + } + + /* 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); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le ); testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge); testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt); testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le); testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt); - sqlite3ReleaseTempReg(pParse, reg1); sqlite3ReleaseTempReg(pParse, reg2); + + VdbeModuleComment((v, "CodeRangeTest: end")); } /* @@ -1888,9 +2103,7 @@ static int windowCodeOp( Window *pMWin = p->pMWin; int ret = 0; Vdbe *v = p->pVdbe; - int addrIf = 0; int addrContinue = 0; - int addrGoto = 0; int bPeer = (pMWin->eFrmType!=TK_ROWS); int lblDone = sqlite3VdbeMakeLabel(pParse); @@ -1923,7 +2136,7 @@ static int windowCodeOp( ); } }else{ - addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1); + sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1); VdbeCoverage(v); } } @@ -1932,6 +2145,25 @@ static int windowCodeOp( windowAggFinal(p, 0); } addrContinue = sqlite3VdbeCurrentAddr(v); + + /* 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). */ + if( pMWin->eStart==pMWin->eEnd && regCountdown + && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE + ){ + 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); + sqlite3ReleaseTempReg(pParse, regRowid1); + sqlite3ReleaseTempReg(pParse, regRowid2); + assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ); + } + switch( op ){ case WINDOW_RETURN_ROW: csr = p->current.csr; @@ -1946,7 +2178,7 @@ static int windowCodeOp( assert( pMWin->regEndRowid ); sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1); }else{ - windowAggStep(pParse, pMWin, csr, 1, p->regArg); + windowAggStep(p, pMWin, csr, 1, p->regArg); } break; @@ -1958,7 +2190,7 @@ static int windowCodeOp( assert( pMWin->regEndRowid ); sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1); }else{ - windowAggStep(pParse, pMWin, csr, 0, p->regArg); + windowAggStep(p, pMWin, csr, 0, p->regArg); } break; } @@ -1976,7 +2208,7 @@ static int windowCodeOp( sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer); VdbeCoverage(v); if( bPeer ){ - addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone); } } @@ -1992,8 +2224,6 @@ static int windowCodeOp( sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange); } sqlite3VdbeResolveLabel(v, lblDone); - if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); - if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); return ret; } @@ -2009,6 +2239,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName); + pNew->zBase = sqlite3DbStrDup(db, p->zBase); pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); pNew->pFunc = p->pFunc; pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); @@ -2017,9 +2248,11 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew->eEnd = p->eEnd; pNew->eStart = p->eStart; pNew->eExclude = p->eExclude; + pNew->regResult = p->regResult; pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); pNew->pOwner = pOwner; + pNew->bImplicitFrame = p->bImplicitFrame; } } return pNew; @@ -2343,7 +2576,7 @@ static int windowExprGtZero(Parse *pParse, Expr *pExpr){ ** regEnd = ** regStart = ** }else{ -** if( (csrEnd.key + regEnd) <= csrCurrent.key ){ +** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ ** AGGSTEP ** } ** while( (csrStart.key + regStart) < csrCurrent.key ){ @@ -2416,8 +2649,6 @@ void sqlite3WindowCodeStep( int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ int addrInteger = 0; /* Address of OP_Integer */ int addrEmpty; /* Address of OP_Rewind in flush: */ - int regStart = 0; /* Value of PRECEDING */ - int regEnd = 0; /* Value of FOLLOWING */ int regNew; /* Array of registers holding new input row */ int regRecord; /* regNew array in record form */ int regRowid; /* Rowid for regRecord in eph table */ @@ -2426,6 +2657,8 @@ void sqlite3WindowCodeStep( int regFlushPart = 0; /* Register for "Gosub flush_partition" */ WindowCodeArg s; /* Context object for sub-routines */ int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */ + int regStart = 0; /* Value of PRECEDING */ + int regEnd = 0; /* Value of FOLLOWING */ assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED @@ -2556,14 +2789,14 @@ void sqlite3WindowCodeStep( if( regStart ){ sqlite3ExprCode(pParse, pMWin->pStart, regStart); - windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); + windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0)); } if( regEnd ){ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); - windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); + windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0)); } - if( pMWin->eStart==pMWin->eEnd && regStart ){ + if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){ int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le); int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd); VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound */ diff --git a/test/affinity2.test b/test/affinity2.test index 9838bd6..6ad257a 100644 --- a/test/affinity2.test +++ b/test/affinity2.test @@ -14,6 +14,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix affinity2 do_execsql_test affinity2-100 { CREATE TABLE t1( @@ -58,4 +59,78 @@ do_execsql_test affinity2-300 { SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid; } {1 1 1 0 2 1 1 1 3 0 1 1} +#------------------------------------------------------------------------- +do_execsql_test 400 { + CREATE TABLE ttt(c0, c1); + CREATE INDEX ii ON ttt(CAST(c0 AS NUMERIC)); + INSERT INTO ttt VALUES('abc', '-1'); +} +do_execsql_test 410 { + SELECT * FROM ttt WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid; +} {abc -1} +do_execsql_test 420 { + SELECT * FROM ttt INDEXED BY ii WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid; +} {abc -1} + +do_execsql_test 430 { + CREATE TABLE t3(a, b, c INTEGER); + CREATE INDEX t3ac ON t3(a, c-1); + INSERT INTO t3 VALUES(1, 1, 1); + INSERT INTO t3 VALUES(2, 1, 0); + INSERT INTO t3 VALUES(3, 1, 1); + INSERT INTO t3 VALUES(4, 1, 0); + INSERT INTO t3 VALUES(5, 1, 1); +} +do_execsql_test 440 { + SELECT * FROM t3 WHERE c='0' ORDER BY a; +} {2 1 0 4 1 0} + +# 2019-08-22 ticket https://sqlite.org/src/info/d99f1ffe836c591ac57f +# False positive in sqlite3ExprNeedsNoAffinityChange() +# +do_execsql_test 500 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 TEXT UNIQUE, c1); + INSERT INTO t0(c0) VALUES (-1); + SELECT quote(- x'ce'), quote(t0.c0), quote(- x'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 501 { + SELECT * FROM t0 WHERE - x'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 502 { + SELECT quote(+-+x'ce'), quote(t0.c0), quote(+-+x'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 503 { + SELECT * FROM t0 WHERE +-+x'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 504 { + SELECT quote(- 'ce'), quote(t0.c0), quote(- 'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 505 { + SELECT * FROM t0 WHERE - 'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 506 { + SELECT quote(+-+'ce'), quote(t0.c0), quote(+-+'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 507 { + SELECT * FROM t0 WHERE +-+'ce' >= t0.c0; +} {-1 {}} + +# 2019-08-30 ticket https://www.sqlite.org/src/info/40812aea1fde9594 +# +# Due to some differences in floating point computations, these tests do not +# work under valgrind. +# +if {![info exists ::G(valgrind)]} { + do_execsql_test 600 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL UNIQUE); + INSERT INTO t0(c0) VALUES (3175546974276630385); + SELECT 3175546974276630385 < c0 FROM t0; + } {1} + do_execsql_test 601 { + SELECT 1 FROM t0 WHERE 3175546974276630385 < c0; + } {1} +} + finish_test diff --git a/test/aggnested.test b/test/aggnested.test index 91de63b..d712c84 100644 --- a/test/aggnested.test +++ b/test/aggnested.test @@ -1,4 +1,4 @@ -# 2012 August 23 +# 2012-08-23 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -232,6 +232,34 @@ do_test aggnested-3.16 { GROUP BY id1; } } {12 2 34 4} + +# 2019-08-31 +# Problem found by dbsqlfuzz +# +do_execsql_test aggnested-4.1 { + DROP TABLE IF EXISTS aa; + DROP TABLE IF EXISTS bb; + CREATE TABLE aa(x INT); INSERT INTO aa(x) VALUES(123); + CREATE TABLE bb(y INT); INSERT INTO bb(y) VALUES(456); + SELECT (SELECT sum(x+(SELECT y)) FROM bb) FROM aa; +} {579} +do_execsql_test aggnested-4.2 { + SELECT (SELECT sum(x+y) FROM bb) FROM aa; +} {579} +do_execsql_test aggnested-4.3 { + DROP TABLE IF EXISTS tx; + DROP TABLE IF EXISTS ty; + CREATE TABLE tx(x INT); + INSERT INTO tx VALUES(1),(2),(3),(4),(5); + CREATE TABLE ty(y INT); + INSERT INTO ty VALUES(91),(92),(93); + SELECT min((SELECT count(y) FROM ty)) FROM tx; +} {3} +do_execsql_test aggnested-4.4 { + SELECT max((SELECT a FROM (SELECT count(*) AS a FROM ty) AS s)) FROM tx; +} {3} + + finish_test diff --git a/test/alter.test b/test/alter.test index d20e5eb..a82456d 100644 --- a/test/alter.test +++ b/test/alter.test @@ -856,7 +856,6 @@ do_test alter-14.2 { set system_table_list {1 sqlite_master} catchsql ANALYZE ifcapable analyze { lappend system_table_list 2 sqlite_stat1 } -ifcapable stat3 { lappend system_table_list 3 sqlite_stat3 } ifcapable stat4 { lappend system_table_list 4 sqlite_stat4 } foreach {tn tbl} $system_table_list { diff --git a/test/altertab.test b/test/altertab.test index 602f753..2eed636 100644 --- a/test/altertab.test +++ b/test/altertab.test @@ -594,4 +594,3 @@ do_execsql_test 18.2.2 { } {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1))}} finish_test - diff --git a/test/altertab3.test b/test/altertab3.test index 863da72..948a351 100644 --- a/test/altertab3.test +++ b/test/altertab3.test @@ -20,6 +20,7 @@ ifcapable !altertable { return } + ifcapable windowfunc { do_execsql_test 1.0 { CREATE TABLE t1(a, b); @@ -237,5 +238,148 @@ do_execsql_test 10.2 { ) IN () OR t1.a=5} } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 11.1 { + CREATE TABLE t1( + a,b,c,d,e,f,g,h,j,jj,jjb,k,aa,bb,cc,dd,ee DEFAULT 3.14, + ff DEFAULT('hiccup'),Wg NOD NULL DEFAULT(false) + ); + + CREATE TRIGGER b AFTER INSERT ON t1 WHEN new.a BEGIN + SELECT a, sum() w3 FROM t1 + WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM abc)); + END; +} + +do_catchsql_test 11.2 { + ALTER TABLE t1 RENAME TO t1x; +} {1 {error in trigger b: no such table: abc}} + +do_execsql_test 11.3 { + DROP TRIGGER b; + CREATE TRIGGER b AFTER INSERT ON t1 WHEN new.a BEGIN + SELECT a, sum() w3 FROM t1 + WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM t1)); + END; +} {} + +do_execsql_test 11.4 { + ALTER TABLE t1 RENAME TO t1x; + SELECT sql FROM sqlite_master WHERE name = 'b'; +} { +{CREATE TRIGGER b AFTER INSERT ON "t1x" WHEN new.a BEGIN + SELECT a, sum() w3 FROM "t1x" + WINDOW b AS (ORDER BY NOT EXISTS(SELECT 1 FROM "t1x")); + END} +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 12.1 { +CREATE TABLE t1(a,b,c,d,e,f,g,h,j,jj,Zjj,k,aQ,bb,cc,dd,ee DEFAULT 3.14, +ff DEFAULT('hiccup'),gg NOD NULL DEFAULT(false)); +CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN + +SELECT b () OVER , dense_rank() OVER d, d () OVER w1 +FROM t1 +WINDOW +w1 AS +( w1 ORDER BY d +ROWS BETWEEN 2 NOT IN(SELECT a, sum(d) w2,max(d)OVER FROM t1 +WINDOW +w1 AS +(PARTITION BY d +ROWS BETWEEN '' PRECEDING AND false FOLLOWING), +d AS +(PARTITION BY b ORDER BY d +ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +) PRECEDING AND 1 FOLLOWING), +w2 AS +(PARTITION BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), +w3 AS +(PARTITION BY b ORDER BY d +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +; +SELECT a, sum(d) w2,max(d)OVER FROM t1 +WINDOW +w1 AS +(PARTITION BY d +ROWS BETWEEN '' PRECEDING AND false FOLLOWING), +d AS +(PARTITION BY b ORDER BY d +ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +; + +END; +} + +do_execsql_test 12.2 { + ALTER TABLE t1 RENAME TO t1x; +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 13.1 { + CREATE TABLE t1(a); + CREATE TRIGGER r1 INSERT ON t1 BEGIN + SELECT a(*) OVER (ORDER BY (SELECT 1)) FROM t1; + END; +} + +do_execsql_test 13.2 { + ALTER TABLE t1 RENAME TO t1x; +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 14.1 { + CREATE TABLE t1(a); + CREATE TABLE t2(b); + CREATE TRIGGER AFTER INSERT ON t1 BEGIN + SELECT sum() FILTER (WHERE (SELECT sum() FILTER (WHERE 0)) AND a); + END; +} + +do_catchsql_test 14.2 { + ALTER TABLE t1 RENAME TO t1x; +} {1 {error in trigger AFTER: no such column: a}} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 16.1 { + CREATE TABLE t1(x); + CREATE TRIGGER AFTER INSERT ON t1 BEGIN + SELECT (WITH t2 AS (WITH t3 AS (SELECT true) + SELECT * FROM t3 ORDER BY true COLLATE nocase) + SELECT 11); + + WITH t4 AS (SELECT * FROM t1) SELECT 33; + END; +} +do_execsql_test 16.2 { + ALTER TABLE t1 RENAME TO t1x; +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 17.1 { + CREATE TABLE t1(a,b,c); + CREATE TRIGGER AFTER INSERT ON t1 WHEN new.a NOT NULL BEGIN + SELECT a () FILTER (WHERE a>0) FROM t1; + END; +} + +do_execsql_test 17.2 { + ALTER TABLE t1 RENAME TO t1x; + ALTER TABLE t1x RENAME a TO aaa; + SELECT sql FROM sqlite_master WHERE type='trigger'; +} { +{CREATE TRIGGER AFTER INSERT ON "t1x" WHEN new.aaa NOT NULL BEGIN + SELECT a () FILTER (WHERE aaa>0) FROM "t1x"; + END} +} + finish_test diff --git a/test/analyze.test b/test/analyze.test index 683542f..ca6c9b0 100644 --- a/test/analyze.test +++ b/test/analyze.test @@ -288,7 +288,7 @@ do_test analyze-4.3 { } {} # Verify that DROP TABLE and DROP INDEX remove entries from the -# sqlite_stat1, sqlite_stat3 and sqlite_stat4 tables. +# sqlite_stat1 and sqlite_stat4 tables. # do_test analyze-5.0 { execsql { @@ -306,13 +306,12 @@ do_test analyze-5.0 { SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} -ifcapable stat4||stat3 { - ifcapable stat4 {set stat sqlite_stat4} else {set stat sqlite_stat3} +ifcapable stat4 { do_test analyze-5.1 { - execsql " - SELECT DISTINCT idx FROM $stat ORDER BY 1; - SELECT DISTINCT tbl FROM $stat ORDER BY 1; - " + execsql { + SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; + SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; + } } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} } do_test analyze-5.2 { @@ -322,12 +321,12 @@ do_test analyze-5.2 { SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t3i1 t3i3 t4i1 t4i2 t3 t4} -ifcapable stat4||stat3 { +ifcapable stat4 { do_test analyze-5.3 { - execsql " - SELECT DISTINCT idx FROM $stat ORDER BY 1; - SELECT DISTINCT tbl FROM $stat ORDER BY 1; - " + execsql { + SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; + SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; + } } {t3i1 t3i3 t4i1 t4i2 t3 t4} } do_test analyze-5.4 { @@ -337,12 +336,12 @@ do_test analyze-5.4 { SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t4i1 t4i2 t4} -ifcapable stat4||stat3 { +ifcapable stat4 { do_test analyze-5.5 { - execsql " - SELECT DISTINCT idx FROM $stat ORDER BY 1; - SELECT DISTINCT tbl FROM $stat ORDER BY 1; - " + execsql { + SELECT DISTINCT idx FROM sqlite_stat4 ORDER BY 1; + SELECT DISTINCT tbl FROM sqlite_stat4 ORDER BY 1; + } } {t4i1 t4i2 t4} } diff --git a/test/analyze3.test b/test/analyze3.test index b7b324a..8cc344e 100644 --- a/test/analyze3.test +++ b/test/analyze3.test @@ -18,7 +18,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix analyze3 -ifcapable !stat4&&!stat3 { +ifcapable !stat4 { finish_test return } @@ -100,11 +100,7 @@ do_test analyze3-1.1.1 { ANALYZE; } - ifcapable stat4 { - execsql { SELECT count(*)>0 FROM sqlite_stat4; } - } else { - execsql { SELECT count(*)>0 FROM sqlite_stat3; } - } + execsql { SELECT count(*)>0 FROM sqlite_stat4; } } {1} do_execsql_test analyze3-1.1.x { diff --git a/test/analyze5.test b/test/analyze5.test index ac175c0..e58457a 100644 --- a/test/analyze5.test +++ b/test/analyze5.test @@ -17,7 +17,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !stat4&&!stat3 { +ifcapable !stat4 { finish_test return } @@ -67,39 +67,21 @@ do_test analyze5-1.0 { CREATE INDEX t1z ON t1(z); -- integers 0, 1, 2, and 3 ANALYZE; } - ifcapable stat4 { - db eval { - SELECT DISTINCT lindex(test_decode(sample),0) - FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt; - } - } else { - db eval { - SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt; - } + db eval { + SELECT DISTINCT lindex(test_decode(sample),0) + FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt; } } {alpha bravo charlie delta} do_test analyze5-1.1 { - ifcapable stat4 { - db eval { - SELECT DISTINCT lower(lindex(test_decode(sample), 0)) - FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1 - } - } else { - db eval { - SELECT lower(sample) FROM sqlite_stat3 WHERE idx='t1v' ORDER BY 1 - } + db eval { + SELECT DISTINCT lower(lindex(test_decode(sample), 0)) + FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1 } } {alpha bravo charlie delta} -ifcapable stat4 { - do_test analyze5-1.2 { - db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1} - } {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8} -} else { - do_test analyze5-1.2 { - db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1} - } {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4} -} +do_test analyze5-1.2 { + db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1} +} {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8} # Verify that range queries generate the correct row count estimates # diff --git a/test/analyze6.test b/test/analyze6.test index 34d00f5..b6353f2 100644 --- a/test/analyze6.test +++ b/test/analyze6.test @@ -17,7 +17,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !stat4&&!stat3 { +ifcapable !stat4 { finish_test return } diff --git a/test/analyze7.test b/test/analyze7.test index d6da6c1..b3dba02 100644 --- a/test/analyze7.test +++ b/test/analyze7.test @@ -82,7 +82,7 @@ do_test analyze7-3.1 { do_test analyze7-3.2.1 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;} } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/} -ifcapable stat4||stat3 { +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 { @@ -99,7 +99,7 @@ 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=?)*/} -ifcapable {!stat4 && !stat3} { +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=?)*/} diff --git a/test/analyze8.test b/test/analyze8.test index daa83ef..7c61652 100644 --- a/test/analyze8.test +++ b/test/analyze8.test @@ -10,13 +10,13 @@ #*********************************************************************** # # This file implements tests for SQLite library. The focus of the tests -# in this file is testing the capabilities of sqlite_stat3. +# in this file is testing the capabilities of sqlite_stat4. # set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !stat4&&!stat3 { +ifcapable !stat4 { finish_test return } diff --git a/test/analyzeA.test b/test/analyzeA.test deleted file mode 100644 index afcbe84..0000000 --- a/test/analyzeA.test +++ /dev/null @@ -1,186 +0,0 @@ -# 2013 August 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 automated tests used to verify that the current build -# (which must be either ENABLE_STAT3 or ENABLE_STAT4) works with both stat3 -# and stat4 data. -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl -set testprefix analyzeA - -ifcapable !stat4&&!stat3 { - finish_test - return -} - -# Populate the stat3 table according to the current contents of the db -# -proc populate_stat3 {{bDropTable 1}} { - # Open a second connection on database "test.db" and run ANALYZE. If this - # is an ENABLE_STAT3 build, this is all that is required to create and - # populate the sqlite_stat3 table. - # - sqlite3 db2 test.db - execsql { ANALYZE } - - # Now, if this is an ENABLE_STAT4 build, create and populate the - # sqlite_stat3 table based on the stat4 data gathered by the ANALYZE - # above. Then drop the sqlite_stat4 table. - # - ifcapable stat4 { - db2 func lindex lindex - execsql { - PRAGMA writable_schema = on; - CREATE TABLE sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample); - INSERT INTO sqlite_stat3 - SELECT DISTINCT tbl, idx, - lindex(neq,0), lindex(nlt,0), lindex(ndlt,0), test_extract(sample, 0) - FROM sqlite_stat4; - } db2 - if {$bDropTable} { execsql {DROP TABLE sqlite_stat4} db2 } - execsql { PRAGMA writable_schema = off } - } - - # Modify the database schema cookie to ensure that the other connection - # reloads the schema. - # - execsql { - CREATE TABLE obscure_tbl_nm(x); - DROP TABLE obscure_tbl_nm; - } db2 - db2 close -} - -# Populate the stat4 table according to the current contents of the db -# -proc populate_stat4 {{bDropTable 1}} { - sqlite3 db2 test.db - execsql { ANALYZE } - - ifcapable stat3 { - execsql { - PRAGMA writable_schema = on; - CREATE TABLE sqlite_stat4(tbl,idx,neq,nlt,ndlt,sample); - INSERT INTO sqlite_stat4 - SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample) - FROM sqlite_stat3; - } db2 - if {$bDropTable} { execsql {DROP TABLE sqlite_stat3} db2 } - execsql { PRAGMA writable_schema = off } - } - - # Modify the database schema cookie to ensure that the other connection - # reloads the schema. - # - execsql { - CREATE TABLE obscure_tbl_nm(x); - DROP TABLE obscure_tbl_nm; - } db2 - db2 close -} - -# Populate the stat4 table according to the current contents of the db. -# Leave deceptive data in the stat3 table. This data should be ignored -# in favour of that from the stat4 table. -# -proc populate_both {} { - ifcapable stat4 { populate_stat3 0 } - ifcapable stat3 { populate_stat4 0 } - - sqlite3 db2 test.db - execsql { - PRAGMA writable_schema = on; - UPDATE sqlite_stat3 SET idx = - CASE idx WHEN 't1b' THEN 't1c' ELSE 't1b' - END; - PRAGMA writable_schema = off; - CREATE TABLE obscure_tbl_nm(x); - DROP TABLE obscure_tbl_nm; - } db2 - db2 close -} - -foreach {tn analyze_cmd} { - 1 populate_stat4 - 2 populate_stat3 - 3 populate_both -} { - reset_db - do_test 1.$tn.1 { - execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT) } - for {set i 0} {$i < 100} {incr i} { - set c [expr int(pow(1.1,$i)/100)] - set b [expr 125 - int(pow(1.1,99-$i))/100] - execsql {INSERT INTO t1 VALUES($i, $b, $c)} - } - } {} - - execsql { CREATE INDEX t1b ON t1(b) } - execsql { CREATE INDEX t1c ON t1(c) } - $analyze_cmd - - do_execsql_test 1.$tn.2.1 { SELECT count(*) FROM t1 WHERE b=31 } 1 - do_execsql_test 1.$tn.2.2 { SELECT count(*) FROM t1 WHERE c=0 } 49 - do_execsql_test 1.$tn.2.3 { SELECT count(*) FROM t1 WHERE b=125 } 49 - do_execsql_test 1.$tn.2.4 { SELECT count(*) FROM t1 WHERE c=16 } 1 - - do_eqp_test 1.$tn.2.5 { - SELECT * FROM t1 WHERE b = 31 AND c = 0; - } {SEARCH TABLE t1 USING INDEX t1b (b=?)} - do_eqp_test 1.$tn.2.6 { - SELECT * FROM t1 WHERE b = 125 AND c = 16; - } {SEARCH TABLE t1 USING INDEX t1c (c=?)} - - do_execsql_test 1.$tn.3.1 { - SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50 - } {6} - do_execsql_test 1.$tn.3.2 { - SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 50 - } {90} - do_execsql_test 1.$tn.3.3 { - SELECT count(*) FROM t1 WHERE b BETWEEN 75 AND 125 - } {90} - do_execsql_test 1.$tn.3.4 { - SELECT count(*) FROM t1 WHERE c BETWEEN 75 AND 125 - } {6} - - do_eqp_test 1.$tn.3.5 { - SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50 - } {SEARCH TABLE t1 USING INDEX t1b (b>? AND b? AND c? AND b? AND b? AND c? AND c90} { set a $i } else { set a NULL } - set b [expr $i % 5] - execsql "INSERT INTO t3 VALUES($a, $b)" - } - execsql ANALYZE -} {} -do_eqp_test 10.1.3 { - SELECT * FROM t3 WHERE a IS NULL AND b = 2 -} {/t3 USING INDEX t3b/} -do_eqp_test 10.1.4 { - SELECT * FROM t3 WHERE a IS NOT NULL AND b = 2 -} {/t3 USING INDEX t3a/} - -#------------------------------------------------------------------------- -# Check that stat3 data is used correctly with non-default collation -# sequences. -# -foreach {tn schema} { - 1 { - CREATE TABLE t4(a COLLATE nocase, b); - CREATE INDEX t4a ON t4(a); - CREATE INDEX t4b ON t4(b); - } - 2 { - CREATE TABLE t4(a, b); - CREATE INDEX t4a ON t4(a COLLATE nocase); - CREATE INDEX t4b ON t4(b); - } -} { - drop_all_tables - do_test 11.$tn.1 { execsql $schema } {} - - do_test 11.$tn.2 { - for {set i 0} {$i < 100} {incr i} { - if { ($i % 10)==0 } { set a ABC } else { set a DEF } - set b [expr $i % 5] - execsql { INSERT INTO t4 VALUES($a, $b) } - } - execsql ANALYZE - } {} - - do_eqp_test 11.$tn.3 { - SELECT * FROM t4 WHERE a = 'def' AND b = 3; - } {/t4 USING INDEX t4b/} - - if {$tn==1} { - set sql "SELECT * FROM t4 WHERE a = 'abc' AND b = 3;" - do_eqp_test 11.$tn.4 $sql {/t4 USING INDEX t4a/} - } else { - - set sql "SELECT * FROM t4 WHERE a = 'abc' COLLATE nocase AND b = 3;" - do_eqp_test 11.$tn.5 $sql {/t4 USING INDEX t4a/} - - set sql "SELECT * FROM t4 WHERE a COLLATE nocase = 'abc' AND b = 3;" - do_eqp_test 11.$tn.6 $sql {/t4 USING INDEX t4a/} - } -} - -#------------------------------------------------------------------------- -# Test that nothing untoward happens if the stat3 table contains entries -# for indexes that do not exist. Or NULL values in the idx column. -# Or NULL values in any of the other columns. -# -drop_all_tables -do_execsql_test 15.1 { - CREATE TABLE x1(a, b, UNIQUE(a, b)); - INSERT INTO x1 VALUES(1, 2); - INSERT INTO x1 VALUES(3, 4); - INSERT INTO x1 VALUES(5, 6); - ANALYZE; - INSERT INTO sqlite_stat3 VALUES(NULL, NULL, NULL, NULL, NULL, NULL); -} -db close -sqlite3 db test.db -do_execsql_test 15.2 { SELECT * FROM x1 } {1 2 3 4 5 6} - -do_execsql_test 15.3 { - INSERT INTO sqlite_stat3 VALUES(42, 42, 42, 42, 42, 42); -} -db close -sqlite3 db test.db -do_execsql_test 15.4 { SELECT * FROM x1 } {1 2 3 4 5 6} - -do_execsql_test 15.5 { - UPDATE sqlite_stat1 SET stat = NULL; -} -db close -sqlite3 db test.db -do_execsql_test 15.6 { SELECT * FROM x1 } {1 2 3 4 5 6} - -do_execsql_test 15.7 { - ANALYZE; - UPDATE sqlite_stat1 SET tbl = 'no such tbl'; -} -db close -sqlite3 db test.db -do_execsql_test 15.8 { SELECT * FROM x1 } {1 2 3 4 5 6} - -do_execsql_test 15.9 { - ANALYZE; - UPDATE sqlite_stat3 SET neq = NULL, nlt=NULL, ndlt=NULL; -} -db close -sqlite3 db test.db -do_execsql_test 15.10 { SELECT * FROM x1 } {1 2 3 4 5 6} - -# This is just for coverage.... -do_execsql_test 15.11 { - ANALYZE; - UPDATE sqlite_stat1 SET stat = stat || ' unordered'; -} -db close -sqlite3 db test.db -do_execsql_test 15.12 { SELECT * FROM x1 } {1 2 3 4 5 6} - -#------------------------------------------------------------------------- -# Test that allocations used for sqlite_stat3 samples are included in -# the quantity returned by SQLITE_DBSTATUS_SCHEMA_USED. -# -set one [string repeat x 1000] -set two [string repeat x 2000] -do_test 16.1 { - reset_db - execsql { - CREATE TABLE t1(a, UNIQUE(a)); - INSERT INTO t1 VALUES($one); - ANALYZE; - } - set nByte [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] - - reset_db - execsql { - CREATE TABLE t1(a, UNIQUE(a)); - INSERT INTO t1 VALUES($two); - ANALYZE; - } - set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] - - expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050} -} {1} - -#------------------------------------------------------------------------- -# Test that stat3 data may be used with partial indexes. -# -do_test 17.1 { - reset_db - execsql { - CREATE TABLE t1(a, b, c, d); - CREATE INDEX i1 ON t1(a, b) WHERE d IS NOT NULL; - INSERT INTO t1 VALUES(-1, -1, -1, NULL); - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; - } - - for {set i 0} {$i < 32} {incr i} { - execsql { INSERT INTO t1 VALUES($i%2, $b, $i/2, 'abc') } - } - execsql {ANALYZE main.t1} -} {} - -do_catchsql_test 17.1.2 { - ANALYZE temp.t1; -} {1 {no such table: temp.t1}} - -do_eqp_test 17.2 { - SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; -} {/USING INDEX i1/} -do_eqp_test 17.3 { - SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; -} {/USING INDEX i1/} - -do_execsql_test 17.4 { - CREATE INDEX i2 ON t1(c) WHERE d IS NOT NULL; - ANALYZE main.i2; -} -do_eqp_test 17.5 { - SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; -} {/USING INDEX i1/} -do_eqp_test 17.6 { - SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=0 AND c=10; -} {/USING INDEX i2/} - -#------------------------------------------------------------------------- -# -do_test 18.1 { - reset_db - execsql { - CREATE TABLE t1(a, b); - CREATE INDEX i1 ON t1(a, b); - } - for {set i 0} {$i < 9} {incr i} { - execsql { - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - INSERT INTO t1 VALUES($i, 0); - } - } - execsql ANALYZE - execsql { SELECT count(*) FROM sqlite_stat3 } -} {9} - -#------------------------------------------------------------------------- -# For coverage. -# -ifcapable view { - do_test 19.1 { - reset_db - execsql { - CREATE TABLE t1(x, y); - CREATE INDEX i1 ON t1(x, y); - CREATE VIEW v1 AS SELECT * FROM t1; - ANALYZE; - } - } {} -} -ifcapable auth { - proc authproc {op args} { - if {$op == "SQLITE_ANALYZE"} { return "SQLITE_DENY" } - return "SQLITE_OK" - } - do_test 19.2 { - reset_db - db auth authproc - execsql { - CREATE TABLE t1(x, y); - CREATE VIEW v1 AS SELECT * FROM t1; - } - catchsql ANALYZE - } {1 {not authorized}} -} - -#------------------------------------------------------------------------- -# -reset_db -proc r {args} { expr rand() } -db func r r -db func lrange lrange -do_test 20.1 { - execsql { - CREATE TABLE t1(a,b,c,d); - CREATE INDEX i1 ON t1(a,b,c,d); - } - for {set i 0} {$i < 16} {incr i} { - execsql { - INSERT INTO t1 VALUES($i, r(), r(), r()); - INSERT INTO t1 VALUES($i, $i, r(), r()); - INSERT INTO t1 VALUES($i, $i, $i, r()); - INSERT INTO t1 VALUES($i, $i, $i, $i); - INSERT INTO t1 VALUES($i, $i, $i, $i); - INSERT INTO t1 VALUES($i, $i, $i, r()); - INSERT INTO t1 VALUES($i, $i, r(), r()); - INSERT INTO t1 VALUES($i, r(), r(), r()); - } - } -} {} -do_execsql_test 20.2 { ANALYZE } -for {set i 0} {$i<16} {incr i} { - set val $i - do_execsql_test 20.3.$i { - SELECT count(*) FROM sqlite_stat3 WHERE sample=$val - } {1} -} - -finish_test diff --git a/test/analyzeC.test b/test/analyzeC.test index 02faa9c..2a0a897 100644 --- a/test/analyzeC.test +++ b/test/analyzeC.test @@ -132,6 +132,20 @@ do_execsql_test 4.3 { SELECT count(a) FROM t1; } {/.*INDEX t1ca.*/} +# 2019-08-15. +# Ticket https://www.sqlite.org/src/tktview/e4598ecbdd18bd82945f602901 +# The sz=N parameter in the sqlite_stat1 table needs to have a value of +# 2 or more to avoid a division by zero in the query planner. +# +do_execsql_test 4.4 { + DROP TABLE IF EXISTS t44; + CREATE TABLE t44(a PRIMARY KEY); + INSERT INTO sqlite_stat1 VALUES('t44',null,'sz=0'); + ANALYZE sqlite_master; + SELECT 0 FROM t44 WHERE a IN(1,2,3); +} {} + + # The sz=NNN parameter works even if there is other extraneous text # in the sqlite_stat1.stat column. diff --git a/test/auth.test b/test/auth.test index 354acba..cc48fdb 100644 --- a/test/auth.test +++ b/test/auth.test @@ -2450,11 +2450,7 @@ ifcapable compound&&subquery { ifcapable stat4 { set stat4 "sqlite_stat4 " } else { - ifcapable stat3 { - set stat4 "sqlite_stat3 " - } else { - set stat4 "" - } + set stat4 "" } do_test auth-5.2 { execsql { diff --git a/test/check.test b/test/check.test index dcd3c18..e23043e 100644 --- a/test/check.test +++ b/test/check.test @@ -123,6 +123,11 @@ do_test check-2.1 { y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) ); + CREATE TABLE t2n( + x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ), + y NUMERIC CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), + z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) + ); PRAGMA writable_schema = 0; } } {} @@ -146,9 +151,17 @@ do_test check-2.4 { } } {1 {CHECK constraint failed: one}} do_test check-2.5 { + # The 5 gets automatically promoted to 5.0 because the column type is REAL catchsql { INSERT INTO t2 VALUES(NULL, 5, NULL); } +} {0 {}} +do_test check-2.5b { + # This time the column type is NUMERIC, so not automatic promption to REAL + # occurs and the constraint fails. + catchsql { + INSERT INTO t2n VALUES(NULL, 5, NULL); + } } {1 {CHECK constraint failed: two}} do_test check-2.6 { catchsql { @@ -195,6 +208,7 @@ do_test check-2.cleanup { execsql { DROP TABLE IF EXISTS t2b; DROP TABLE IF EXISTS t2c; + DROP TABLE IF EXISTS t2n; } } {} @@ -495,4 +509,34 @@ do_execsql_test 10.1 { PRAGMA integrity_check; } {ok} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 11.0 { + CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ; +} +do_execsql_test 11.1 { + INSERT INTO t1 VALUES (NULL); +} +do_execsql_test 11.2 { + INSERT INTO t1 VALUES (NULL); +} + +do_execsql_test 11.3 { + CREATE TABLE t2(b, a CHECK( + CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END) + ); +} +do_execsql_test 11.4 { + INSERT INTO t2(a) VALUES('abc'); +} +do_execsql_test 11.5 { + INSERT INTO t2(b, a) VALUES(1, 'abc'||''); +} +do_execsql_test 11.6 { + INSERT INTO t2(b, a) VALUES(2, 'abc'); +} + +finish_test + + finish_test diff --git a/test/checkfault.test b/test/checkfault.test new file mode 100644 index 0000000..3b18a64 --- /dev/null +++ b/test/checkfault.test @@ -0,0 +1,41 @@ +# 2019 July 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 contains fault-injection test cases for the +# sqlite3_db_cacheflush API. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix cffault +source $testdir/malloc_common.tcl + +do_execsql_test 1.0 { + CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ; + CREATE TABLE t2(b, a CHECK( + CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END) + ); +} + +do_faultsim_test 1.1 -faults oom* -body { + execsql { INSERT INTO t1 VALUES ('ABCDEFG') } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 1.2 -faults oom* -body { + execsql { INSERT INTO t2(a) VALUES('abc') } +} -test { + faultsim_test_result {0 {}} +} + + +finish_test diff --git a/test/close.test b/test/close.test index 99bc725..107c7a7 100644 --- a/test/close.test +++ b/test/close.test @@ -79,4 +79,11 @@ do_test 1.4.4 { sqlite3_finalize $STMT } {SQLITE_OK} +do_test 1.5 { + set DB [sqlite3_open test.db] + sqlite3_blob_open $DB main t1 x 2 0 BLOB + sqlite3_close_v2 $DB + sqlite3_blob_close $BLOB +} {} + finish_test diff --git a/test/colname.test b/test/colname.test index f314f94..5fa0b60 100644 --- a/test/colname.test +++ b/test/colname.test @@ -399,6 +399,12 @@ ifcapable vtab { SELECT name FROM pragma_table_info('t2'); } {Bbb} } +do_execsql_test colname-9.330 { -- added 2019-08-10 to invalidate + DROP TABLE IF EXISTS t1; -- a couple assert()s that were + CREATE TABLE t1(a); -- added by ticket 3b44500725 + INSERT INTO t1 VALUES(17),(2),(99),(-3),(7); + SELECT (SELECT avg(a) UNION SELECT min(a) OVER()) FROM t1; +} {17} # Issue detected by OSSFuzz on 2017-12-24 (Christmas Eve) # caused by check-in https://sqlite.org/src/info/6b2ff26c25 diff --git a/test/conflict3.test b/test/conflict3.test index 751a442..413e824 100644 --- a/test/conflict3.test +++ b/test/conflict3.test @@ -366,5 +366,73 @@ do_execsql_test 12.3 { SELECT * FROM t2; } {111 111B 112 112} +#------------------------------------------------------------------------- +ifcapable trigger { + reset_db + do_execsql_test 13.1.0 { + PRAGMA recursive_triggers = true; + CREATE TABLE t0 (c0 UNIQUE, c1 UNIQUE); + CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN + DELETE FROM t0; + END; + + INSERT INTO t0 VALUES(1, NULL); + INSERT INTO t0 VALUES(0, NULL); + } + + do_execsql_test 13.1.1 { + UPDATE OR REPLACE t0 SET c1 = 1; + } + + integrity_check 13.1.2 + + do_execsql_test 13.1.3 { + SELECT * FROM t0 + } {} + + do_execsql_test 13.2.0 { + CREATE TABLE t2 (a PRIMARY KEY, b UNIQUE, c UNIQUE) WITHOUT ROWID; + CREATE TRIGGER tr3 AFTER DELETE ON t2 BEGIN + DELETE FROM t2; + END; + + INSERT INTO t2 VALUES(1, 1, 1); + INSERT INTO t2 VALUES(2, 2, 2); + } + + do_execsql_test 13.2.1 { + UPDATE OR REPLACE t2 SET c = 0; + } + + integrity_check 13.2.2 + + do_execsql_test 13.2.3 { + SELECT * FROM t2 + } {} + + do_execsql_test 13.3.0 { + CREATE TABLE t1(a, b); + CREATE TABLE log(x); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES(1, 2); + + CREATE TRIGGER tb BEFORE UPDATE ON t1 BEGIN + DELETE FROM t1; + END; + CREATE TRIGGER ta AFTER UPDATE ON t1 BEGIN + INSERT INTO log VALUES('fired!'); + END; + + UPDATE t1 SET b=3; + } + + do_execsql_test 13.3.1 { + SELECT * FROM t1; + } {} + do_execsql_test 13.3.2 { + SELECT * FROM log; + } {} +} finish_test + diff --git a/test/corruptL.test b/test/corruptL.test index 53a68a0..b0ad66d 100644 --- a/test/corruptL.test +++ b/test/corruptL.test @@ -228,6 +228,7 @@ do_test 2.0 { }]} {} do_execsql_test 2.1 { + PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking INSERT INTO t1(b) VALUES(X'a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6ac8ae0d0e7c3175946e62ba2b'); } @@ -376,10 +377,14 @@ do_test 4.0 { | end crash-6b48ba69806134.db }]} {} +set res {1 {database disk image is malformed}} +ifcapable oversize_cell_check { + set res {1 {no such table: t3}} +} do_catchsql_test 4.1 { + PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking INSERT INTO t3 SELECT * FROM t2; -} {1 {database disk image is malformed}} - +} $res #------------------------------------------------------------------------- reset_db @@ -605,7 +610,7 @@ do_test 6.0 { | 3872: 75 65 6e 63 65 04 43 52 45 41 54 45 20 54 41 42 uence.CREATE TAB | 3888: 4c 45 20 73 71 6c 69 74 65 5f 73 65 71 75 65 6e LE sqlite_sequen | 3904: 63 65 28 6e 61 6d 65 2c 73 65 71 29 81 04 01 07 ce(name,seq).... -| 3920: 17 11 11 01 81 73 74 61 c2 6c 65 74 31 74 31 02 .....sta.let1t1. +| 3920: 17 11 11 01 81 73 74 61 62 6c 65 74 31 74 31 02 .....stablet1t1. | 3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 CREATE TABLE t1( | 3952: 61 20 52 45 41 4c 20 4e 4f 54 20 4e 55 4c 4c 20 a REAL NOT NULL | 3968: 44 45 46 41 55 4c 54 28 32 35 2b 33 32 29 2c 62 DEFAULT(25+32),b @@ -833,10 +838,14 @@ do_test 8.0 { | end a.db }]} {} - +set res {1 {database disk image is malformed}} +ifcapable oversize_cell_check { + set res {1 {no such table: t3}} +} do_catchsql_test 8.1 { + PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking INSERT INTO t3 SELECT * FROM t2; -} {1 {database disk image is malformed}} +} $res #------------------------------------------------------------------------- reset_db @@ -1004,6 +1013,7 @@ do_test 10.0 { }]} {} do_catchsql_test 10.1 { + PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking SELECT * FROM t1 WHERE a<='2019-05-09' ORDER BY a DESC; } {1 {database disk image is malformed}} @@ -1057,6 +1067,7 @@ do_test 11.0 { }]} {} do_catchsql_test 11.1 { + PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking DELETE FROM t3 WHERE x IN (SELECT x FROM t4); } {1 {database disk image is malformed}} diff --git a/test/corruptM.test b/test/corruptM.test new file mode 100644 index 0000000..15fc8d6 --- /dev/null +++ b/test/corruptM.test @@ -0,0 +1,186 @@ +# 2019-08-12 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Check to ensure that the type, name, and tbl_name fields of the +# sqlite_master table are validated and errors are reported if they +# are inconsistent with the sql. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix corruptM + +# These tests deal with corrupt database files +# +database_may_be_corrupt + +proc open_db2_and_catchsql {sql} { + set rc [catch { sqlite3 db2 test.db } msg] + if {$rc} { + return [list $rc $msg] + } + set res [catchsql $sql db2] + db2 close + set res +} + +db close +forcedelete test.db +sqlite3 db test.db +do_execsql_test corruptM-100 { + CREATE TABLE t1(a,b,c); + INSERT INTO t1 VALUES(111,222,333); + CREATE INDEX i1 ON t1(b); + CREATE VIEW v2 AS SELECT 15,22; + CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT 5; END; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_execsql_test corruptM-101 { + PRAGMA writable_schema=on; + UPDATE sqlite_master SET tbl_name=NULL WHERE name='t1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 {} | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-102 { + open_db2_and_catchsql { + PRAGMA quick_check; + } +} {1 {malformed database schema (t1)}} + +do_execsql_test corruptM-110 { + UPDATE sqlite_master SET tbl_name='tx' WHERE name='t1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 tx | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-111 { + open_db2_and_catchsql { + PRAGMA quick_check; + } +} {1 {malformed database schema (t1)}} +do_execsql_test corruptM-112 { + UPDATE sqlite_master SET tbl_name='t1', type='tabl' WHERE name='t1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {tabl t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-113 { + open_db2_and_catchsql { + PRAGMA quick_check; + } +} {1 {malformed database schema (t1)}} +do_execsql_test corruptM-114 { + UPDATE sqlite_master SET tbl_name='t9',type='table',name='t9'WHERE name='t1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t9 t9 | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-114 { + open_db2_and_catchsql { + PRAGMA quick_check; + } +} {1 {malformed database schema (t9)}} + +do_execsql_test corruptM-120 { + UPDATE sqlite_master SET name='t1',tbl_name='T1' WHERE name='t9'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-121 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {0 {ok 111 222 333 15 22}} + +do_execsql_test corruptM-130 { + UPDATE sqlite_master SET type='view' WHERE name='t1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {view t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-131 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (t1)}} + +do_execsql_test corruptM-140 { + UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='t1'; + UPDATE sqlite_master SET tbl_name='tx' WHERE name='i1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 tx | view v2 v2 | trigger r1 t1 |} +do_test corruptM-141 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (i1)}} + +do_execsql_test corruptM-150 { + UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='i1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | table i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-151 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (i1)}} + +do_execsql_test corruptM-160 { + UPDATE sqlite_master SET type='view', tbl_name='t1' WHERE name='i1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | view i1 t1 | view v2 v2 | trigger r1 t1 |} +do_test corruptM-161 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (i1)}} + +do_execsql_test corruptM-170 { + UPDATE sqlite_master SET type='index', tbl_name='t1' WHERE name='i1'; + UPDATE sqlite_master SET type='table', tbl_name='v2' WHERE name='v2'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 t1 | table v2 v2 | trigger r1 t1 |} +do_test corruptM-171 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (v2)}} + +do_execsql_test corruptM-180 { + UPDATE sqlite_master SET type='view',name='v3',tbl_name='v3' WHERE name='v2'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 t1 | view v3 v3 | trigger r1 t1 |} +do_test corruptM-181 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (v3)}} + +do_execsql_test corruptM-190 { + UPDATE sqlite_master SET type='view',name='v2',tbl_name='v2' WHERE name='v3'; + UPDATE sqlite_master SET type='view' WHERE name='r1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 t1 | view v2 v2 | view r1 t1 |} +do_test corruptM-191 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (r1)}} +do_execsql_test corruptM-192 { + UPDATE sqlite_master SET type='trigger',tbl_name='v2' WHERE name='r1'; + SELECT type, name, tbl_name, '|' FROM sqlite_master; +} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 v2 |} +do_test corruptM-193 { + open_db2_and_catchsql { + PRAGMA quick_check; + SELECT * FROM t1, v2; + } +} {1 {malformed database schema (r1)}} + +finish_test diff --git a/test/dbfuzz001.test b/test/dbfuzz001.test index 77df86b..7ef4cd2 100644 --- a/test/dbfuzz001.test +++ b/test/dbfuzz001.test @@ -305,7 +305,7 @@ do_test dbfuzz001-310 { | 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 74 65 6c 03 62 74 (......=tatel.bt +| 432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74 (......=tablet2t | 448: 32 32 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 22CREATE 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 diff --git a/test/dbfuzz2.c b/test/dbfuzz2.c index 025204d..804222c 100644 --- a/test/dbfuzz2.c +++ b/test/dbfuzz2.c @@ -211,6 +211,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ if( mxCb>0 ){ sqlite3_progress_handler(db, 10, progress_handler, 0); } +#ifdef SQLITE_TESTCTRL_PRNG_SEED + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db); +#endif for(i=0; i=1 ){ printf("%s\n", azSql[i]); diff --git a/test/dbstatus.test b/test/dbstatus.test index 564b9c5..8d5d834 100644 --- a/test/dbstatus.test +++ b/test/dbstatus.test @@ -63,7 +63,7 @@ proc lookaside {db} { } } -ifcapable stat4||stat3 { +ifcapable stat4 { set STAT3 1 } else { set STAT3 0 diff --git a/test/distinct2.test b/test/distinct2.test index 31ab355..c42a1c9 100644 --- a/test/distinct2.test +++ b/test/distinct2.test @@ -229,5 +229,77 @@ do_execsql_test 1020 { SELECT DISTINCT a FROM t1, t2 WHERE x=b; } {1 1} +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 2000 { + CREATE TABLE t0 (c0, c1, c2, PRIMARY KEY (c0, c1)); + CREATE TABLE t1 (c2); + INSERT INTO t0(c2) VALUES (0),(1),(3),(4),(5),(6),(7),(8),(9),(10),(11); + INSERT INTO t0(c1) VALUES ('a'); + INSERT INTO t1(c2) VALUES (0); +} +do_execsql_test 2010 { + SELECT DISTINCT t0.c0, t1._rowid_, t0.c1 FROM t1 CROSS JOIN t0 ORDER BY t0.c0; +} {{} 1 {} {} 1 a} +do_execsql_test 1.2 { + ANALYZE; +} +do_execsql_test 2020 { + SELECT DISTINCT t0.c0, t1._rowid_, t0.c1 FROM t1 CROSS JOIN t0 ORDER BY t0.c0; +} {{} 1 {} {} 1 a} + + +do_execsql_test 2030 { + CREATE TABLE t2(a, b, c); + CREATE INDEX t2ab ON t2(a, b); + + WITH c(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<64) + INSERT INTO t2 SELECT 'one', i%2, 'one' FROM c; + + WITH c(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM c WHERE i<64) + INSERT INTO t2 SELECT 'two', i%2, 'two' FROM c; + + CREATE TABLE t3(x INTEGER PRIMARY KEY); + INSERT INTO t3 VALUES(1); + + ANALYZE; +} +do_execsql_test 2040 { + SELECT DISTINCT a, b, x FROM t3 CROSS JOIN t2 ORDER BY a; +} { + one 0 1 + one 1 1 + two 0 1 + two 1 1 +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3000 { + CREATE TABLE t0 (c0, c1 NOT NULL DEFAULT 1, c2, PRIMARY KEY (c0, c1)); + INSERT INTO t0(c2) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); + INSERT INTO t0(c2) VALUES('a'); +} + +do_execsql_test 3010 { + SELECT DISTINCT * FROM t0 WHERE NULL IS t0.c0; +} { + {} 1 {} + {} 1 a +} + +do_execsql_test 3020 { + ANALYZE; +} + +do_execsql_test 3030 { + SELECT DISTINCT * FROM t0 WHERE NULL IS c0; +} { + {} 1 {} + {} 1 a +} finish_test + diff --git a/test/filter1.test b/test/filter1.test new file mode 100644 index 0000000..9309b74 --- /dev/null +++ b/test/filter1.test @@ -0,0 +1,188 @@ +# 2018 May 8 +# +# 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 filter1 + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9); +} + +do_execsql_test 1.1 { SELECT sum(a) FROM t1; } 45 +do_execsql_test 1.2 { SELECT sum(a) FILTER( WHERE a<5 ) FROM t1; } 10 + +do_execsql_test 1.3 { + SELECT sum(a) FILTER( WHERE a>9 ), + sum(a) FILTER( WHERE a>8 ), + sum(a) FILTER( WHERE a>7 ), + sum(a) FILTER( WHERE a>6 ), + sum(a) FILTER( WHERE a>5 ), + sum(a) FILTER( WHERE a>4 ), + sum(a) FILTER( WHERE a>3 ), + sum(a) FILTER( WHERE a>2 ), + sum(a) FILTER( WHERE a>1 ), + sum(a) FILTER( WHERE a>0 ) + FROM t1; +} {{} 9 17 24 30 35 39 42 44 45} + +do_execsql_test 1.4 { + SELECT max(a) FILTER (WHERE (a % 2)==0) FROM t1 +} {8} + +do_execsql_test 1.5 { + SELECT min(a) FILTER (WHERE a>4) FROM t1 +} {5} + +do_execsql_test 1.6 { + SELECT count(*) FILTER (WHERE a!=5) FROM t1 +} {8} + +do_execsql_test 1.7 { + SELECT min(a) FILTER (WHERE a>3) FROM t1 GROUP BY (a%2) ORDER BY 1; +} {4 5} + +do_execsql_test 1.8 { + CREATE VIEW vv AS + SELECT sum(a) FILTER( WHERE a>9 ), + sum(a) FILTER( WHERE a>8 ), + sum(a) FILTER( WHERE a>7 ), + sum(a) FILTER( WHERE a>6 ), + sum(a) FILTER( WHERE a>5 ), + sum(a) FILTER( WHERE a>4 ), + sum(a) FILTER( WHERE a>3 ), + sum(a) FILTER( WHERE a>2 ), + sum(a) FILTER( WHERE a>1 ), + sum(a) FILTER( WHERE a>0 ) + FROM t1; + SELECT * FROM vv; +} {{} 9 17 24 30 35 39 42 44 45} + + +#------------------------------------------------------------------------- +# Test some errors: +# +# .1 FILTER on a non-aggregate function, +# .2 Window function in FILTER clause, +# .3 Aggregate function in FILTER clause, +# +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(a); + INSERT INTO t1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9); +} + +do_catchsql_test 2.1 { + SELECT upper(a) FILTER (WHERE a=1) FROM t1 +} {1 {FILTER may not be used with non-aggregate upper()}} + +do_catchsql_test 2.2 { + SELECT sum(a) FILTER (WHERE 1 - max(a) OVER () > 0) FROM t1 +} {1 {misuse of window function max()}} + +do_catchsql_test 2.3 { + SELECT sum(a) FILTER (WHERE 1 - count(a)) FROM t1 +} {1 {misuse of aggregate function count()}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1, 1); +} +do_execsql_test 3.1 { + SELECT b, max(a) FILTER (WHERE b='x') FROM t1; +} {1 {}} + +do_execsql_test 3.2 { + CREATE TABLE t2(a, b, c); + INSERT INTO t2 VALUES(1, 2, 3); + INSERT INTO t2 VALUES(1, 3, 4); + INSERT INTO t2 VALUES(2, 5, 6); + INSERT INTO t2 VALUES(2, 7, 8); +} +do_execsql_test 3.3 { + SELECT a, c, max(b) FILTER (WHERE c='x') FROM t2 GROUP BY a; +} {1 3 {} 2 6 {}} + +do_execsql_test 3.4 { + DELETE FROM t2; + INSERT INTO t2 VALUES(1, 5, 'x'); + INSERT INTO t2 VALUES(1, 2, 3); + INSERT INTO t2 VALUES(1, 4, 'x'); + INSERT INTO t2 VALUES(2, 5, 6); + INSERT INTO t2 VALUES(2, 7, 8); +} +do_execsql_test 3.5 { + SELECT a, c, max(b) FILTER (WHERE c='x') FROM t2 GROUP BY a; +} {1 x 5 2 6 {}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES('a', 0, 5); + INSERT INTO t1 VALUES('a', 1, 10); + INSERT INTO t1 VALUES('a', 0, 15); + + INSERT INTO t1 VALUES('b', 0, 5); + INSERT INTO t1 VALUES('b', 1, 1000); + INSERT INTO t1 VALUES('b', 0, 5); + + INSERT INTO t1 VALUES('c', 0, 1); + INSERT INTO t1 VALUES('c', 1, 2); + INSERT INTO t1 VALUES('c', 0, 3); +} + +do_execsql_test 4.1 { + SELECT avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY h; +} {2.0 5.0 10.0} +do_execsql_test 4.2 { + SELECT avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY (h+1.0); +} {2.0 5.0 10.0} +do_execsql_test 4.3 { + SELECT a, avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY avg(c); +} {c 2.0 a 10.0 b 5.0} +do_execsql_test 4.4 { + SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2 +} {c 2.0 b 5.0 a 10.0} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(1, 3); +} + +do_execsql_test 5.1 { + SELECT count(*) FILTER (WHERE b>2) FROM (SELECT * FROM t1) +} {1} + +do_execsql_test 5.2 { + SELECT count(*) FILTER (WHERE b>2) OVER () FROM (SELECT * FROM t1) +} {1 1} + +do_execsql_test 5.3 { + SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1) +} {0 1} + +finish_test + diff --git a/test/filter2.tcl b/test/filter2.tcl new file mode 100644 index 0000000..f3871f8 --- /dev/null +++ b/test/filter2.tcl @@ -0,0 +1,132 @@ +# 2018 May 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. +# +#*********************************************************************** +# + +source [file join [file dirname $argv0] pg_common.tcl] + +#========================================================================= + + +start_test filter2 "2019 July 2" + +ifcapable !windowfunc + +execsql_test 1.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER); + INSERT INTO t1 VALUES + (1, 7), (2, 3), (3, 5), (4, 30), (5, 26), (6, 23), (7, 27), + (8, 3), (9, 17), (10, 26), (11, 33), (12, 25), (13, NULL), (14, 47), + (15, 36), (16, 13), (17, 45), (18, 31), (19, 11), (20, 36), (21, 37), + (22, 21), (23, 22), (24, 14), (25, 16), (26, 3), (27, 7), (28, 29), + (29, 50), (30, 38), (31, 3), (32, 36), (33, 12), (34, 4), (35, 46), + (36, 3), (37, 48), (38, 23), (39, NULL), (40, 24), (41, 5), (42, 46), + (43, 11), (44, NULL), (45, 18), (46, 25), (47, 15), (48, 18), (49, 23); +} + +execsql_test 1.1 { SELECT sum(b) FROM t1 } + +execsql_test 1.2 { SELECT sum(b) FILTER (WHERE a<10) FROM t1 } + +execsql_test 1.3 { SELECT count(DISTINCT b) FROM t1 } + +execsql_test 1.4 { SELECT count(DISTINCT b) FILTER (WHERE a!=19) FROM t1 } + +execsql_test 1.5 { + SELECT min(b) FILTER (WHERE a>19), + min(b) FILTER (WHERE a>0), + max(a+b) FILTER (WHERE a>19), + max(b+a) FILTER (WHERE a BETWEEN 10 AND 40) + FROM t1; +} + +execsql_test 1.6 { + SELECT min(b), + min(b), + max(a+b), + max(b+a) + FROM t1 + GROUP BY (a%10) + ORDER BY 1, 2, 3, 4; +} + +execsql_test 1.7 { + SELECT min(b) FILTER (WHERE a>19), + min(b) FILTER (WHERE a>0), + max(a+b) FILTER (WHERE a>19), + max(b+a) FILTER (WHERE a BETWEEN 10 AND 40) + FROM t1 + GROUP BY (a%10) + ORDER BY 1, 2, 3, 4; +} + +execsql_test 1.8 { + SELECT sum(a+b) FILTER (WHERE a=NULL) FROM t1 +} + +execsql_test 1.9 { + SELECT (a%5) FROM t1 GROUP BY (a%5) + HAVING sum(b) FILTER (WHERE b<20) > 34 + ORDER BY 1 +} + +execsql_test 1.10 { + SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb + FROM t1 + GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34 + ORDER BY 1 +} + +execsql_test 1.11 { + SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb + FROM t1 + GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34 + ORDER BY 2 +} + +execsql_test 1.12 { + SELECT (a%5), + sum(b) FILTER (WHERE b<20) AS bbb, + count(distinct b) FILTER (WHERE b<20 OR a=13) AS ccc + FROM t1 GROUP BY (a%5) + ORDER BY 2 +} + +execsql_test 1.13 { + SELECT + string_agg(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=0), + string_agg(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=1), + count(*) FILTER (WHERE b%2!=0), + count(*) FILTER (WHERE b%2!=1) + FROM t1; +} + +execsql_float_test 1.14 { + SELECT + avg(b) FILTER (WHERE b>a), + avg(b) FILTER (WHERE b19), + min(b) FILTER (WHERE a>0), + max(a+b) FILTER (WHERE a>19), + max(b+a) FILTER (WHERE a BETWEEN 10 AND 40) + FROM t1; +} {3 3 88 85} + +do_execsql_test 1.6 { + SELECT min(b), + min(b), + max(a+b), + max(b+a) + FROM t1 + GROUP BY (a%10) + ORDER BY 1, 2, 3, 4; +} {3 3 58 58 3 3 66 66 3 3 71 71 3 3 88 88 4 4 61 61 5 5 54 54 + 7 7 85 85 11 11 79 79 16 16 81 81 24 24 68 68} + +do_execsql_test 1.7 { + SELECT min(b) FILTER (WHERE a>19), + min(b) FILTER (WHERE a>0), + max(a+b) FILTER (WHERE a>19), + max(b+a) FILTER (WHERE a BETWEEN 10 AND 40) + FROM t1 + GROUP BY (a%10) + ORDER BY 1, 2, 3, 4; +} {3 3 58 58 3 3 71 39 4 4 38 61 7 7 85 85 11 5 54 45 16 16 81 81 + 18 3 66 61 21 3 88 68 23 11 79 79 24 24 68 68} + +do_execsql_test 1.8 { + SELECT sum(a+b) FILTER (WHERE a=NULL) FROM t1 +} {{}} + +do_execsql_test 1.9 { + SELECT (a%5) FROM t1 GROUP BY (a%5) + HAVING sum(b) FILTER (WHERE b<20) > 34 + ORDER BY 1 +} {3 4} + +do_execsql_test 1.10 { + SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb + FROM t1 + GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34 + ORDER BY 1 +} {3 49 4 46} + +do_execsql_test 1.11 { + SELECT (a%5), sum(b) FILTER (WHERE b<20) AS bbb + FROM t1 + GROUP BY (a%5) HAVING sum(b) FILTER (WHERE b<20) >34 + ORDER BY 2 +} {4 46 3 49} + +do_execsql_test 1.12 { + SELECT (a%5), + sum(b) FILTER (WHERE b<20) AS bbb, + count(distinct b) FILTER (WHERE b<20 OR a=13) AS ccc + FROM t1 GROUP BY (a%5) + ORDER BY 2 +} {2 25 3 0 34 2 1 34 4 4 46 4 3 49 5} + +do_execsql_test 1.13 { + SELECT + group_concat(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=0), + group_concat(CAST(b AS TEXT), '_') FILTER (WHERE b%2!=1), + count(*) FILTER (WHERE b%2!=0), + count(*) FILTER (WHERE b%2!=1) + FROM t1; +} {7_3_5_23_27_3_17_33_25_47_13_45_31_11_37_21_3_7_29_3_3_23_5_11_25_15_23 30_26_26_36_36_22_14_16_50_38_36_12_4_46_48_24_46_18_18 27 19} + + +do_test 1.14 { + set myres {} + foreach r [db eval {SELECT + avg(b) FILTER (WHERE b>a), + avg(b) FILTER (WHERE b([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + incr i + } + set {} {} +} {} + +do_execsql_test 1.15 { + SELECT + a/5, + sum(b) FILTER (WHERE a%5=0), + sum(b) FILTER (WHERE a%5=1), + sum(b) FILTER (WHERE a%5=2), + sum(b) FILTER (WHERE a%5=3), + sum(b) FILTER (WHERE a%5=4) + FROM t1 GROUP BY (a/5) ORDER BY 1; +} {0 {} 7 3 5 30 1 26 23 27 3 17 2 26 33 25 {} 47 3 36 13 45 31 11 + 4 36 37 21 22 14 5 16 3 7 29 50 6 38 3 36 12 4 7 46 3 48 23 {} + 8 24 5 46 11 {} 9 18 25 15 18 23} + +finish_test diff --git a/test/filterfault.test b/test/filterfault.test new file mode 100644 index 0000000..a8cde1f --- /dev/null +++ b/test/filterfault.test @@ -0,0 +1,44 @@ +# 2018 May 8 +# +# 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 filterfault + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c, d); + INSERT INTO t1 VALUES(1, 2, 3, 4); + INSERT INTO t1 VALUES(5, 6, 7, 8); + INSERT INTO t1 VALUES(9, 10, 11, 12); +} +faultsim_save_and_close + +do_faultsim_test 1 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + execsql { + SELECT sum(a) FILTER (WHERE b<5), + count() FILTER (WHERE d!=c) + FROM t1 GROUP BY c ORDER BY 1; + } +} -test { + faultsim_test_result {0 {{} 1 {} 1 1 1}} +} + + +finish_test diff --git a/test/fkey8.test b/test/fkey8.test index 42f997f..085190e 100644 --- a/test/fkey8.test +++ b/test/fkey8.test @@ -229,4 +229,3 @@ do_execsql_test 5.3 { } {ok} finish_test - diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test index 8c1a14a..3aecc29 100644 --- a/test/fts3corrupt4.test +++ b/test/fts3corrupt4.test @@ -26,6 +26,7 @@ ifcapable !fts3 { } sqlite3_fts3_may_be_corrupt 1 +database_may_be_corrupt do_execsql_test 1.0 { BEGIN; @@ -2146,6 +2147,7 @@ do_test 14.0 { }]} {} do_execsql_test 14.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; } @@ -3048,6 +3050,7 @@ do_test 19.0 { }]} {} do_catchsql_test 19.1 { + PRAGMA writable_schema = 1; SELECT rowid,a,c,snippet(t1,85101090932165,-1,10) FROM t1 WHERE a MATCH 'rtree'; } {1 {database disk image is malformed}} @@ -3249,6 +3252,7 @@ do_test 20.0 { }]} {} do_execsql_test 20.1 { + PRAGMA writable_schema = 1; BEGIN; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; @@ -3471,8 +3475,8 @@ do_test 21.0 { | end crash-18cc014e42e828.db }]} {} -breakpoint do_catchsql_test 21.1 { + PRAGMA writable_schema = 1; SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*'; } {1 {database disk image is malformed}} @@ -3693,6 +3697,7 @@ do_test 22.0 { }]} {} do_catchsql_test 22.1 { + PRAGMA writable_schema = 1; SELECT snippet(t1,'', '', '--',-1,01)==0 FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1'; } {0 {0 0 0 0 0 0 0}} @@ -3912,6 +3917,7 @@ do_test 23.0 { }]} {} do_catchsql_test 23.1 { + PRAGMA writable_schema = 1; SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j'; } {1 {database disk image is malformed}} @@ -4130,6 +4136,7 @@ do_test 24.0 { }]} {} do_catchsql_test 24.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT '4hE'+x FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; } {0 {}} @@ -4373,6 +4380,7 @@ do_test 25.0 { }]} {} do_catchsql_test 25.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237) INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ; } {0 {}} @@ -4607,6 +4615,7 @@ do_test 26.0 { }]} {} do_execsql_test 26.1 { + PRAGMA writable_schema = 1; SELECT count(*) FROM ( SELECT t1, (t1) FROM t1 WHERE b MATCH 'x' ) @@ -4825,6 +4834,7 @@ do_test 27.0 { }]} {} do_catchsql_test 27.2 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x GLOB 2.16770 FROM x) INSERT INTO t1(a) SELECT randomblob(3000) FROM t2 ; } {0 {}} @@ -5057,6 +5067,7 @@ do_test 28.0 { }]} {} do_catchsql_test 28.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; } {0 {}} @@ -5094,5 +5105,445 @@ do_catchsql_test 28.1 { INSERT INTO t1(t1) SELECT x FROM t2; } {0 {}} -finish_test +#------------------------------------------------------------------------- +# +reset_db +do_test 29.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-53f41622dd3bf6.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 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 54 69 72 .5tablet1_segTir +| 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 4d 54 45 47 45 52 2c 73 74 61 ,idx IMTEGER,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 67 64 69 72 egdir_1t1_segdir +| 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 39 4d cid INTEGER PR9M +| 3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20 ARY KEY, 'c0a', +| 3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 12 06 'c1b', 'c2c')8.. +| 3984: 17 11 11 08 5f 74 61 6b 3c 65 74 31 74 31 43 52 ...._tak.$.. +| 80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .H.............. +| 2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 72 7f 00 .........?%..r.. +| 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 21 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 46 20 46 54 53 VTAB ENABLF 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 55 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45 BLU 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 56 4d 41 58 20 4d 45 4d 4f 52 59 RTREEVMAX MEMORY +| 3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c =50000000 OMIT L +| 3056: 4f 42 43 20 45 58 54 45 4e 53 49 4f 4e 20 54 48 OBC EXTENSION TH +| 3072: 52 45 41 44 53 41 46 45 3d 40 18 24 05 00 25 0f READSAFE=@.$..%. +| 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 31 58 4e 4f 43 41 53 45 17 22 DSAFE=1XNOCASE.. +| 3136: 05 00 25 0f 17 54 48 52 45 41 44 43 41 46 45 3d ..%..THREADCAFE= +| 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 48 MIT LOAD EXTENSH +| 3216: cf 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 .NXNOCASE....3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3.. +| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 30 30 MAX MEMORY-50000 +| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 +| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500 +| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....% +| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB +| 3376: 49 4e 41 52 49 18 1a 05 0d a5 0f 19 45 4e 41 42 INARI.......ENAB +| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f be 31 53 45 17 LE RTREEXNO.1SE. +| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 51 ...%..ENABLE RTQ +| 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 37 f8 52 54 52 49 4d 18 14 05 00 25 MSYS7.RTRIM....% +| 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 3e 31 58 4e 4f 43 41 53 45 17 LE JSO>1XNOCASE. +| 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: 48 c0 47 45 4f 50 4f 4c 40 58 4e 4f 43 41 53 45 H.GEOPOL@XNOCASE +| 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 51 49 4d 17 0f 05 00 23 OPOLYXRTQIM....# +| 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 4d 41 52 59 17 0b LE FTS4XBIMARY.. +| 3776: 05 00 23 0f 19 45 4e 31 42 4c 45 20 46 1a 53 34 ..#..EN1BLE F.S4 +| 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 96 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 T.T VTABXRTRIM.. +| 3920: 05 00 17 0f 1e e4 45 42 55 47 58 42 49 4e 41 52 ......EBUGXBINAR +| 3936: 59 11 05 05 00 17 0e 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 01 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 40 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 4f 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMOILER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM +| page 4 offset 12288 +| 0: 0d 00 00 01 00 10 00 00 00 00 00 00 00 00 00 00 ................ +| 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 4d 03 25 15 00 00 04 .%....sysM.%.... +| 3200: 6e 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03 nmit.%....rtree. +| 3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03 %....threadsafe. +| 3232: 25 0e 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 bd .....20160609... +| 3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05 .........4...... +| 3312: 00 01 06 00 00 01 35 09 01 04 00 01 04 00 02 04 ......5......... +| 3328: 00 01 07 30 30 e6 30 30 30 30 09 1c 04 00 01 04 ...00.0000...... +| 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 04 01 02 02 10 03 01 02 02 ................ +| 3376: 00 0f 71 02 12 00 03 01 02 02 00 03 01 65 02 00 ..q..........e.. +| 3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 ................ +| 3408: 01 0d a2 00 03 01 02 02 00 00 08 63 3b 6d 70 69 ...........c;mpi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64 ler............d +| 3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 bstat........... +| 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 02 .enable?........ +| 3488: 00 01 02 00 01 02 00 01 01 f0 01 02 00 01 02 00 ................ +| 3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 ................ +| 3520: 02 00 01 02 00 01 02 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 03 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 00 01 03 00 01 06 65 6f 70 6f 6c 79 09 .........eopoly. +| 3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31 ...........json1 +| 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 01 f0 ................ +| 3760: 03 01 02 02 05 93 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 8a 72 65 65 09 19 03 00 01 03 00 11 03 00 .r.ree.......... +| 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 75 61 62 09 07 04 .........vuab... +| 3904: 00 01 04 00 01 04 00 00 61 78 b4 01 01 01 01 02 ........ax...... +| 3920: 00 01 01 01 02 00 00 f1 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 01 ff 01 01 01 02 00 01 01 01 ................ +| 3984: 02 00 01 01 01 02 00 01 01 01 02 09 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 02 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 11 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 1f 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 e9 10 d6 0f c7 ................ +| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =1.............. +| end crash-53f41622dd3bf6.db +}]} {} +do_catchsql_test 29.1 { + PRAGMA writable_schema = 1; + INSERT INTO t1(a) SELECT X'819192E578DE3F'; + UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*'; + INSERT INTO t1(b) VALUES(x'78'); + INSERT INTO t1(t1) SELECT x FROM t2; +} {1 {database disk image is malformed}} + +#------------------------------------------------------------------------- +# +reset_db +do_test 30.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 28672 pagesize 4096 filename crash-e6e3857edf9b26.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 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 62 2c 72 6f 6f 74 ock INTEGEb,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 67 64 69 72 egdir_1t1_segdir +| 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 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06 'c1b', '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 00 00 ...t.[.@.$...... +| 2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7e f0 .........?%...~. +| 2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e .COMPILER=gcc-5. +| 2912: 34 23 00 20 32 30 31 36 30 36 30 39 20 44 45 42 4#. 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 42 92 4c 45 20 46 54 53 VTAB ENB.LE 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 1f 4a 53 4f 4e 31 20 45 4e 41 42 4c 49 BLE.JSON1 ENABLI +| 3008: 00 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 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c =50000000 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 88 4e 4f 43 41 53 45 17 22 DSAFE=0.NOCASE.. +| 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 20 05 00 33 0f 17 ONXNOCASE. ..3.. +| 3232: 4f 4d 49 54 20 4c 4f 41 54 20 45 58 54 45 4e 53 OMIT LOAT EXTENS +| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 04 00 33 0f 19 IONXRTRIM....3.. +| 3264: 82 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 .AX MEMORY=50000 +| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3 +| 3328: 0f 17 4d 41 58 20 4d 45 4d fa 52 59 3d 35 30 20 ..MAX MEM.RY=50 +| 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 53 52 45 45 58 42 ..ENABLE RSREEXB +| 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 53 41 53 45 17 LE RTREEXNOSASE. +| 3408: 19 05 00 25 0f 17 45 4e 42 42 4c 45 20 52 54 52 ...%..ENBBLE 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 5a 53 35 58 42 49 NABLE MEMSZS5XBI +| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 3c NARY....)..ENAB< +| 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 31 42 4c 45 20 47 45 4e 50 4f 4c 59 58 42 49 N1BLE GENPOLYXBI +| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e f2 1e 4c NARY....)..EN..L +| 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 3c NARY....#..ENAB< +| 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 43 4c 45 20 46 54 53 35 ..#..ENACLE FTS5 +| 3792: 58 4e 4f 43 40 53 45 16 0a 05 00 23 0f 17 45 4e XNOC@SE....#..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 55 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAU 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 62 49 4d 11 06 TAT VTABXRTbIM.. +| 3920: 05 00 17 0f 19 44 45 42 54 47 58 42 49 4e 41 52 .....DEBTGXBINAR +| 3936: 59 11 05 05 00 17 0f 19 54 45 42 55 47 58 4e 4f Y.......TEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG +| 3968: 68 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d hRTRIM'...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 4f 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XOOCASE&...C..C +| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4. +| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM +| page 4 offset 12288 +| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 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 14 00 e8 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 f2 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 6d 70 69 ...........compi +| 3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64 ler............d +| 3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01 bstat........... +| 3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00 .ebug........... +| 3472: 06 65 6e 60 62 6c 65 3f 07 02 00 01 02 00 01 01 .en`ble?........ +| 3488: ff f1 b1 00 00 02 3f 01 01 f0 f1 02 00 57 02 00 ......?......W.. +| 3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 10 01 ................ +| 3520: 02 00 01 02 00 01 02 00 01 02 01 01 02 00 01 02 ................ +| 3536: 00 01 02 00 00 f2 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 03 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 00 01 03 00 01 06 65 6f 70 6f 6c 79 09 .........eopoly. +| 3616: 10 03 00 01 03 00 01 03 00 00 b3 6a 73 6f 6e 31 ...........json1 +| 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 cc 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 62 65 65 09 19 03 00 01 03 00 01 03 00 .rtbee.......... +| 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 01 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 02 02 00 00 04 76 74 61 62 09 07 04 .........vtab... +| 3904: 00 01 03 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 01 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 da 00 01 01 01 02 00 01 01 ................ +| 4048: 01 02 00 01 01 01 01 ff ff 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 01 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: 01 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .o.............. +| end crash-e6e3857edf9b26.db +}]} {} + +do_execsql_test 30.1 { + UPDATE t1 SET b=a; +} + +do_catchsql_test 30.2 { + SELECT (matchinfo(null)) FROM t1 WHERE t1 MATCH 'ee*e*e*e*e*e*e*Re*e*e*e**' +} {1 {database disk image is malformed}} + +finish_test diff --git a/test/fts3corrupt5.test b/test/fts3corrupt5.test index d60a8c0..a8a3b01 100644 --- a/test/fts3corrupt5.test +++ b/test/fts3corrupt5.test @@ -57,4 +57,3 @@ foreach {tn val q bCorrupt} { } finish_test - diff --git a/test/fts3expr5.test b/test/fts3expr5.test index 8673abb..1317bef 100644 --- a/test/fts3expr5.test +++ b/test/fts3expr5.test @@ -64,4 +64,3 @@ do_test 2.2 { } {1 {Error parsing expression}} finish_test - diff --git a/test/fts3snippet.test b/test/fts3snippet.test index ebcdb8c..976c8c8 100644 --- a/test/fts3snippet.test +++ b/test/fts3snippet.test @@ -561,7 +561,31 @@ do_test 4.3 { }] } {64} +#------------------------------------------------------------------------- +# Request a snippet from a query with more than 64 phrases. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t5 USING fts3(x); + INSERT INTO t5 VALUES('a1 a2 a3'); + INSERT INTO t5 VALUES('a4 a5 a6'); + INSERT INTO t5 VALUES('a70 a71 a72'); +} +do_execsql_test 5.1 { + SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH + 'a1 OR a2 OR a3 OR a4 OR a5 OR a6 OR a7 OR a8 OR a9 OR a10 OR ' || + 'a11 OR a12 OR a13 OR a14 OR a15 OR a16 OR a17 OR a18 OR a19 OR a10 OR ' || + 'a21 OR a22 OR a23 OR a24 OR a25 OR a26 OR a27 OR a28 OR a29 OR a20 OR ' || + 'a31 OR a32 OR a33 OR a34 OR a35 OR a36 OR a37 OR a38 OR a39 OR a30 OR ' || + 'a41 OR a42 OR a43 OR a44 OR a45 OR a46 OR a47 OR a48 OR a49 OR a40 OR ' || + 'a51 OR a52 OR a53 OR a54 OR a55 OR a56 OR a57 OR a58 OR a59 OR a50 OR ' || + 'a61 OR a62 OR a63 OR a64 OR a65 OR a66 OR a67 OR a68 OR a69 OR a60 OR ' || + 'a71 OR a72 OR a73 OR a74 OR a75 OR a76 OR a77 OR a78 OR a79 OR a70' +} { + {[a1] [a2] [a3]} + {[a4] [a5] [a6]} + {[a70] [a71] [a72]} +} set sqlite_fts3_enable_parentheses 0 finish_test diff --git a/test/fts4merge5.test b/test/fts4merge5.test new file mode 100644 index 0000000..1fad778 --- /dev/null +++ b/test/fts4merge5.test @@ -0,0 +1,58 @@ +# 2019 October 02 +# +# 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 script is testing the FTS4 module. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix fts4merge5 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +source $testdir/genesis.tcl + +do_execsql_test 1.1 { + CREATE TABLE t1(docid, words); +} +fts_kjv_genesis + +do_execsql_test 1.2 { + CREATE VIRTUAL TABLE x1 USING fts3; + INSERT INTO x1(x1) VALUES('nodesize=64'); + INSERT INTO x1(x1) VALUES('maxpending=64'); +} + +do_execsql_test 1.3 { + INSERT INTO x1(docid, content) SELECT * FROM t1; +} + +for {set tn 1} {1} {incr tn} { + set tc1 [db total_changes] + do_execsql_test 1.4.$tn.1 { + INSERT INTO x1(x1) VALUES('merge=1,2'); + } + set tc2 [db total_changes] + + if {($tc2 - $tc1)<2} break + + do_execsql_test 1.4.$tn.1 { + INSERT INTO x1(x1) VALUES('integrity-check'); + } +} + + + +finish_test diff --git a/test/fts4record.test b/test/fts4record.test new file mode 100644 index 0000000..f1a3eaf --- /dev/null +++ b/test/fts4record.test @@ -0,0 +1,120 @@ +# 2019 September 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. +# +#************************************************************************* +# This file implements regression tests for SQLite library. The +# focus of this script is testing the FTS4 module. +# +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/fts3_common.tcl +set testprefix fts4record + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +sqlite3_fts3_may_be_corrupt 1 + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts4(x); + INSERT INTO t1 VALUES('terma terma terma termb'); +} + +do_execsql_test 1.1 { + SELECT quote(root) FROM t1_segdir +} { + X'00057465726D6105010203030004016203010500' +} + +proc make_record_wrapper {args} { make_fts3record $args } +db func record make_record_wrapper + +do_execsql_test 1.2 { + select quote( + record(0, 5, 'terma', 5, 1, 2, 3, 3, 0, + 4, 1, 'b' , 3, 1, 5, 0 + ) ); +} { + X'00057465726D6105010203030004016203010500' +} + +do_execsql_test 1.3.1 { + UPDATE t1_segdir SET root = + record(0, 5, 'terma', 5, 1, 2, 3, 3, 0, + 4, 1, 'b' , 3, 1, 5, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 + ); +} + +do_catchsql_test 1.3.2 { + SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*' +} {1 {database disk image is malformed}} + +do_execsql_test 1.4.1 { + UPDATE t1_segdir SET root = + record(0, 5, 'terma', 5, 1, 2, 3, 3, 0, + 4, 1, 'b' , 4, 1, 5, + 256, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 + ); +} + +do_catchsql_test 1.4.2 { + SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*' +} {1 {database disk image is malformed}} + +do_execsql_test 1.4.3 { + SELECT quote(root) FROM t1_segdir +} { + X'00057465726D610501020303000401620401058002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100' +} + +do_execsql_test 1.5.1 { + UPDATE t1_segdir SET root = + record(0, 5, 'terma', 5, 1, 2, 3, 3, 0, + 4, 1, 'b' , 4, 1, 5, + 256, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 + ); +} + +do_catchsql_test 1.4.2 { + SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*' +} {1 {database disk image is malformed}} + +do_execsql_test 1.4.3 { + SELECT quote(root) FROM t1_segdir +} { + X'00057465726D610501020303000401620401058002010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100' +} + + +do_execsql_test 1.5.1 { + UPDATE t1_segdir SET root = + X'00057465726D61050102030300040162040105FF00010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100' +} + +do_catchsql_test 1.5.2 { + SELECT snippet(t1) FROM t1 WHERE t1 MATCH 'term*' +} {1 {database disk image is malformed}} + +do_catchsql_test 1.5.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +finish_test diff --git a/test/fts4rename.test b/test/fts4rename.test index 1c711e7..c647d69 100644 --- a/test/fts4rename.test +++ b/test/fts4rename.test @@ -41,4 +41,3 @@ do_catchsql_test 1.3 { } {0 {}} finish_test - diff --git a/test/func.test b/test/func.test index 579bad8..7315af3 100644 --- a/test/func.test +++ b/test/func.test @@ -1419,7 +1419,45 @@ do_execsql_test func-32.150 { SELECT test_frombind(x.a,y.b,x.c,:123,y.e,x.f,$xyz+y.f) FROM t1 x, t1 y; } {8} - +# 2019-08-15 +# Direct-only functions. +# +proc testdirectonly {x} {return [expr {$x*2}]} +do_test func-33.1 { + db func testdirectonly -directonly testdirectonly + db eval {SELECT testdirectonly(15)} +} {30} +do_catchsql_test func-33.2 { + CREATE VIEW v33(y) AS SELECT testdirectonly(15); + SELECT * FROM v33; +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.3 { + SELECT * FROM (SELECT testdirectonly(15)) AS v33; +} {30} +do_execsql_test func-33.4 { + WITH c(x) AS (SELECT testdirectonly(15)) + SELECT * FROM c; +} {30} +do_catchsql_test func-33.5 { + WITH c(x) AS (SELECT * FROM v33) + SELECT * FROM c; +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.10 { + CREATE TABLE t33a(a,b); + CREATE TABLE t33b(x,y); + CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN + INSERT INTO t33b(x,y) VALUES(testdirectonly(new.a),new.b); + END; +} {} +do_catchsql_test func-33.11 { + INSERT INTO t33a VALUES(1,2); +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.20 { + ALTER TABLE t33a RENAME COLUMN a TO aaa; + SELECT sql FROM sqlite_master WHERE name='r1'; +} {{CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN + INSERT INTO t33b(x,y) VALUES(testdirectonly(new.aaa),new.b); + END}} finish_test diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 4096f84..4d52aed 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -1805,6 +1805,9 @@ int main(int argc, char **argv){ sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag); } +#endif +#ifdef SQLITE_TESTCTRL_PRNG_SEED + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db); #endif do{ runSql(db, (char*)pSql->a, runFlags); diff --git a/test/fuzzdata7.db b/test/fuzzdata7.db index 262a22107f442158de0bee9e54b860e1b80f6b22..8706be40d11d54231c2e2098f76172e4b59ef494 100644 GIT binary patch delta 121219 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

    A<&ae-?*+Vyt-lMK0mi) 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%0AI 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Η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

    NQkYfBK;xv*eO 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 diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 4452d295b8f141d6fc93bee6249dc969fc1467af..80c1ad007919e3b04f7753ad29c6f551539178a0 100644 GIT binary patch delta 71846 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%0A0Mb4Vj}ZQg&G=!yT;{TH=qQoXa^N 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 GbpAhRm|kZ9 delta 24180 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 N "X==Y" optimization +# was working. But we have now taken that optimization out. +#do_execsql_test in4-3.44 { +# EXPLAIN +# SELECT * FROM t3 WHERE x IN (10); +#} {~/OpenEphemeral/} do_execsql_test in4-3.45 { SELECT * FROM t3 WHERE x NOT IN (10,11,99999); } {1 1 1} @@ -326,7 +329,7 @@ do_execsql_test in4-6.1 { do_execsql_test in4-6.1-eqp { EXPLAIN QUERY PLAN SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); -} {~/SCAN/} +} {~/SCAN TABLE t6a/} do_execsql_test in4-6.2 { SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b); } {3 4 4 44} diff --git a/test/in5.test b/test/in5.test index a5ea7c1..6680641 100644 --- a/test/in5.test +++ b/test/in5.test @@ -248,5 +248,22 @@ do_execsql_test 9.1 { SELECT * FROM t9 WHERE a IN (44, 45, 44, 45) } {44 45} +#------------------------------------------------------------------------- +# Test that ticket c7a117190 is fixed. +# +reset_db +do_execsql_test 9.0 { + CREATE TABLE t0(c0); + CREATE VIEW v0(c0) AS SELECT LOWER(CAST('1e500' AS TEXT)) FROM t0; + INSERT INTO t0(c0) VALUES (NULL); +} + +do_execsql_test 9.1 { + SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500')); +} {1e500} + +do_execsql_test 9.2 { + SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500'); +} {1e500} finish_test diff --git a/test/index6.test b/test/index6.test index b271954..976c49f 100644 --- a/test/index6.test +++ b/test/index6.test @@ -159,7 +159,7 @@ do_test index6-2.2 { SELECT * FROM t2 WHERE a=5; } } {/.* TABLE t2 USING INDEX t2a1 .*/} -ifcapable stat4||stat3 { +ifcapable stat4 { execsql ANALYZE do_test index6-2.3stat4 { execsql { @@ -437,5 +437,48 @@ do_execsql_test index6-14.2 { SELECT * FROM t0 WHERE CASE c0 WHEN 0 THEN 0 ELSE 1 END; } {{} row} -finish_test +# 2019-08-30 +# Ticket https://www.sqlite.org/src/info/a6408d42b9f44462 +# Ticket https://www.sqlite.org/src/info/fba33c8b1df6a915 +# https://sqlite.org/src/info/bac716244fddac1fe841 +# +do_execsql_test index6-15.1 { + DROP TABLE t0; + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES (NULL); + CREATE INDEX i0 ON t0(1) WHERE c0 NOT NULL; + SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) IS FALSE; +} {1} +do_execsql_test index6-15.2 { + SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) BETWEEN FALSE AND TRUE; +} {1} +do_execsql_test index6-15.3 { + SELECT 1 FROM t0 WHERE TRUE BETWEEN (t0.c0 IS FALSE) AND TRUE; +} {1} +do_execsql_test index6-15.4 { + SELECT 1 FROM t0 WHERE FALSE BETWEEN FALSE AND (t0.c0 IS FALSE); +} {1} +do_execsql_test index6-15.5 { + SELECT 1 FROM t0 WHERE (c0 IS FALSE) IN (FALSE); +} {1} +# 2019-09-03 +# Ticket https://sqlite.org/src/info/767a8cbc6d20bd68 +do_execsql_test index6-16.1 { + DROP TABLE t0; + CREATE TABLE t0(c0 COLLATE NOCASE, c1); + CREATE INDEX i0 ON t0(0) WHERE c0 >= c1; + INSERT INTO t0 VALUES('a', 'B'); + SELECT c1 <= c0, c0 >= c1 FROM t0; +} {1 0} +do_execsql_test index6-16.2 { + SELECT 2 FROM t0 WHERE c0 >= c1; +} {} +do_execsql_test index6-16.3 { + SELECT 3 FROM t0 WHERE c1 <= c0; +} {3} + + + + +finish_test diff --git a/test/index7.test b/test/index7.test index 33abbaf..f57792e 100644 --- a/test/index7.test +++ b/test/index7.test @@ -203,7 +203,7 @@ do_test index7-2.2 { SELECT * FROM t2 WHERE a=5; } } {/.* TABLE t2 USING COVERING INDEX t2a1 .*/} -ifcapable stat4||stat3 { +ifcapable stat4 { do_test index7-2.3stat4 { execsql { EXPLAIN QUERY PLAN diff --git a/test/indexexpr1.test b/test/indexexpr1.test index e93dcc0..6b134db 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -445,5 +445,42 @@ do_execsql_test indexexpr-1620 { SELECT b FROM t1 WHERE lower(a)='01234' ORDER BY +b; } {} +# 2019-08-09 https://www.sqlite.org/src/info/9080b6227fabb466 +# ExprImpliesExpr theorem prover bug: +# "(NULL IS FALSE) IS FALSE" does not imply "NULL IS NULL" +# +do_execsql_test indexexpr-1700 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES (0); + CREATE INDEX i0 ON t0(NULL > c0) WHERE (NULL NOT NULL); + SELECT * FROM t0 WHERE ((NULL IS FALSE) IS FALSE); +} {0} + +# 2019-09-02 https://www.sqlite.org/src/tktview/57af00b6642ecd6848 +# When the expression of an an index-on-expression references a +# table column of type REAL that is actually holding an MEM_IntReal +# value, be sure to use the REAL value and not the INT value when +# computing the expression. +# +ifcapable like_match_blobs { + do_execsql_test indexexpr-1800 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL, c1 TEXT); + CREATE INDEX i0 ON t0(+c0, c0); + INSERT INTO t0(c0) VALUES(0); + SELECT CAST(+ t0.c0 AS BLOB) LIKE 0 FROM t0; + } {0} + do_execsql_test indexexpr-1810 { + SELECT CAST(+ t0.c0 AS BLOB) LIKE '0.0' FROM t0; + } {1} + do_execsql_test indexexpr-1820 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x REAL); + CREATE INDEX t1x ON t1(x, +x); + INSERT INTO t1(x) VALUES(2); + SELECT +x FROM t1 WHERE x=2; + } {2.0} +} finish_test diff --git a/test/indexexpr2.test b/test/indexexpr2.test index a3a685f..5d387c7 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -295,6 +295,82 @@ do_execsql_test 7.3 { REINDEX; } {} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 8.0 { + CREATE TABLE t0(c0); + CREATE INDEX i0 ON t0(c0) WHERE c0 NOT NULL; + INSERT INTO t0(c0) VALUES (NULL); +} +do_execsql_test 8.1.1 { + SELECT * FROM t0 WHERE ~('' BETWEEN t0.c0 AND TRUE); +} {{}} +do_execsql_test 8.1.2 { + SELECT ~('' BETWEEN t0.c0 AND TRUE) FROM t0; +} {-1} + +foreach {tn expr} { + 1 " 0 == (34 BETWEEN c0 AND 33)" + 2 " 1 != (34 BETWEEN c0 AND 33)" + 3 "-1 < (34 BETWEEN c0 AND 33)" + 4 "-1 <= (34 BETWEEN c0 AND 33)" + 5 " 1 > (34 BETWEEN c0 AND 33)" + 6 " 1 >= (34 BETWEEN c0 AND 33)" + 7 " 1 - (34 BETWEEN c0 AND 33)" + 8 "-1 + (34 BETWEEN c0 AND 33)" + 9 " 1 | (34 BETWEEN c0 AND 33)" + 10 " 1 << (34 BETWEEN c0 AND 33)" + 11 " 1 >> (34 BETWEEN c0 AND 33)" + 12 " 1 || (34 BETWEEN c0 AND 33)" +} { + do_execsql_test 8.3.$tn.1 "SELECT * FROM t0 WHERE $expr ORDER BY c0" { {} } + do_execsql_test 8.3.$tn.2 "SELECT ($expr) IS TRUE FROM t0" { 1 } +} + +do_execsql_test 8.4 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2), (3, 4); + CREATE TABLE t2(x, y); +} + +foreach {tn expr} { + 1 " 0 == (a=0 AND y=1)" + 2 " 1 != (a=0 AND y=1)" + 3 "-1 < (a=0 AND y=1)" + 4 "-1 <= (a=0 AND y=1)" + 5 " 1 > (a=0 AND y=1)" + 6 " 1 >= (a=0 AND y=1)" + 7 " 1 - (a=0 AND y=1)" + 8 "-1 + (a=0 AND y=1)" + 9 " 1 | (a=0 AND y=1)" + 10 "1 << (a=0 AND y=1)" + 11 "1 >> (a=0 AND y=1)" + 12 "1 || (a=0 AND y=1)" + + 13 " 0 == (10 BETWEEN y AND b)" + 14 " 1 != (10 BETWEEN y AND b)" + 15 "-1 < (10 BETWEEN y AND b)" + 16 "-1 <= (10 BETWEEN y AND b)" + 17 " 1 > (10 BETWEEN y AND b)" + 18 " 1 >= (10 BETWEEN y AND b)" + 19 " 1 - (10 BETWEEN y AND b)" + 20 "-1 + (10 BETWEEN y AND b)" + 21 " 1 | (10 BETWEEN y AND b)" + 22 " 1 << (10 BETWEEN y AND b)" + 23 " 1 >> (10 BETWEEN y AND b)" + 24 " 1 || (10 BETWEEN y AND b)" + + 25 " 1 || (10 BETWEEN y AND b)" +} { + do_execsql_test 8.5.$tn.1 " + SELECT * FROM t1 LEFT JOIN t2 WHERE $expr + " {1 2 {} {} 3 4 {} {}} + + do_execsql_test 8.5.$tn.2 " + SELECT ($expr) IS TRUE FROM t1 LEFT JOIN t2 + " {1 1} +} finish_test + diff --git a/test/insert.test b/test/insert.test index 01c7016..397a0e6 100644 --- a/test/insert.test +++ b/test/insert.test @@ -460,4 +460,20 @@ do_execsql_test insert-14.1 { integrity_check insert-99.0 +# 2019-08-12. +# +do_execsql_test insert-15.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT); + CREATE INDEX i1 ON t1(b); + CREATE TABLE t2(a, b); + INSERT INTO t2 VALUES(4, randomblob(31000)); + INSERT INTO t2 VALUES(4, randomblob(32000)); + INSERT INTO t2 VALUES(4, randomblob(33000)); + REPLACE INTO t1 SELECT a, b FROM t2; + SELECT a, length(b) FROM t1; +} {4 33000} + + finish_test diff --git a/test/instr.test b/test/instr.test index 2caf3bc..d23d66c 100644 --- a/test/instr.test +++ b/test/instr.test @@ -257,4 +257,25 @@ do_execsql_test instr-1.64 { SELECT instr(a, b) FROM x1; } 0 +# 2019-09-16 ticket https://www.sqlite.org/src/info/587791f92620090e +# +do_execsql_test instr-2.0 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 PRIMARY KEY, c1); + INSERT INTO t0(c0) VALUES (x'bb'), (0); + SELECT COUNT(*) FROM t0 WHERE INSTR(x'aabb', t0.c0) ORDER BY t0.c0, t0.c1; +} {1} +do_execsql_test instr-2.1 { + SELECT quote(c0) FROM t0 WHERE INSTR(x'aabb', t0.c0) ORDER BY t0.c0, t0.c1; +} {X'BB'} +do_execsql_test instr-2.2 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES('text'),(x'bb'); + SELECT quote(x) FROM t1 WHERE instr(x'aabb',x); +} {X'BB'} +do_execsql_test instr-2.3 { + SELECT quote(x) FROM t1 WHERE x>'zzz' AND instr(x'aabb',x); +} {X'BB'} + finish_test diff --git a/test/intarray.test b/test/intarray.test index 049f117..2250027 100644 --- a/test/intarray.test +++ b/test/intarray.test @@ -47,12 +47,12 @@ do_test intarray-1.1 { } } {table ia1 table ia2 table ia3 table ia4} -# Verify the inability to DROP and recreate an intarray virtual table. +# Verify the ability to DROP and recreate an intarray virtual table. do_test intarray-1.1b { db eval {DROP TABLE ia1} - set rc [catch {sqlite3_intarray_create db ia1} msg] - lappend rc $msg -} {1 SQLITE_MISUSE} + set rc [catch {sqlite3_intarray_create db ia1} ia1] + lappend rc $ia1 +} {/0 [0-9A-Z]+/} do_test intarray-1.2 { db eval { diff --git a/test/intreal.test b/test/intreal.test index cf2c3b7..1a3db0a 100644 --- a/test/intreal.test +++ b/test/intreal.test @@ -82,5 +82,17 @@ do_execsql_test 2.6 { ); } [list a $D] +# 2019-07-29 ticket ba2f4585cf495231 +# +db close +sqlite3 db :memory: +do_execsql_test 3.0 { + CREATE TABLE t0 (c0 REAL, c1); + CREATE UNIQUE INDEX i0 ON t0(c1, 0 | c0); + INSERT INTO t0(c0) VALUES (4750228396194493326), (0); + UPDATE OR REPLACE t0 SET c0 = 'a', c1 = ''; + SELECT * FROM t0 ORDER BY t0.c1; + PRAGMA integrity_check; +} {a {} ok} finish_test diff --git a/test/join.test b/test/join.test index f613df8..6821862 100644 --- a/test/join.test +++ b/test/join.test @@ -812,11 +812,16 @@ do_execsql_test join-15.105 { FROM t1 LEFT JOIN t2 WHERE a IN (1,3,x,y); } {1 2 {} {} x 3 4 {} {} x} -do_execsql_test join-15.106 { +do_execsql_test join-15.106a { SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE NOT ( 'x'='y' AND t2.y=1 ); } {1 2 {} {} x 3 4 {} {} x} +do_execsql_test join-15.106b { + SELECT *, 'x' + FROM t1 LEFT JOIN t2 + WHERE ~ ( 'x'='y' AND t2.y=1 ); +} {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.107 { SELECT *, 'x' FROM t1 LEFT JOIN t2 @@ -864,4 +869,41 @@ do_execsql_test join-16.100 { WHERE (b IS NOT NULL)=0; } {1 {}} +# 2019-08-17 ticket https://sqlite.org/src/tktview/6710d2f7a13a299728ab +# Ensure that constants that derive from the right-hand table of a LEFT JOIN +# are never factored out, since they are not really constant. +# +do_execsql_test join-17.100 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(0),(1); + SELECT * FROM t1 LEFT JOIN (SELECT abs(1) AS y FROM t1) ON x WHERE NOT(y='a'); +} {1 1 1 1} +do_execsql_test join-17.110 { + SELECT * FROM t1 LEFT JOIN (SELECT abs(1)+2 AS y FROM t1) ON x + WHERE NOT(y='a'); +} {1 3 1 3} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test join-18.1 { + CREATE TABLE t0(a); + CREATE TABLE t1(b); + CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0; + INSERT INTO t1 VALUES (1); +} {} + +do_execsql_test join-18.2 { + SELECT * FROM v0 WHERE NOT(v0.a IS FALSE); +} {{}} + +do_execsql_test join-18.3 { + SELECT * FROM t1 LEFT JOIN t0 WHERE NOT(a IS FALSE); +} {1 {}} + +do_execsql_test join-18.4 { + SELECT NOT(v0.a IS FALSE) FROM v0 +} {1} + finish_test + diff --git a/test/json104.test b/test/json104.test index 23864d5..e56e7ed 100644 --- a/test/json104.test +++ b/test/json104.test @@ -153,5 +153,3 @@ do_execsql_test 405 { finish_test - - diff --git a/test/like.test b/test/like.test index 75ddf9c..0fc8025 100644 --- a/test/like.test +++ b/test/like.test @@ -1114,4 +1114,3 @@ do_execsql_test 16.2 { } {{ 1-}} finish_test - diff --git a/test/like3.test b/test/like3.test index f64fb63..0705315 100644 --- a/test/like3.test +++ b/test/like3.test @@ -207,6 +207,19 @@ do_execsql_test like3-5.410 { SELECT * FROM t0 WHERE t0.c0 LIKE '.1%'; } {.1%} +# 2019-09-03 +# Ticket https://www.sqlite.org/src/info/0f0428096f +do_execsql_test like3-5.420 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 UNIQUE); + INSERT INTO t0(c0) VALUES(-1); + SELECT * FROM t0 WHERE t0.c0 GLOB '-*'; +} {-1} +do_execsql_test like3-5.421 { + SELECT t0.c0 GLOB '-*' FROM t0; +} {1} + + # 2019-02-27 # Verify that the LIKE optimization works with an ESCAPE clause when diff --git a/test/mallocA.test b/test/mallocA.test index a78073d..ff91d2a 100644 --- a/test/mallocA.test +++ b/test/mallocA.test @@ -96,24 +96,6 @@ do_faultsim_test 6.2 -faults oom* -body { } -test { faultsim_test_result [list 0 {1 2}] } -ifcapable stat3 { - do_test 6.3-prep { - execsql { - PRAGMA writable_schema = 1; - CREATE TABLE sqlite_stat4 AS - SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample) AS sample - FROM sqlite_stat3; - } - } {} - do_faultsim_test 6.3 -faults oom* -body { - execsql { - ANALYZE sqlite_master; - SELECT rowid FROM t1 WHERE a='abc' AND b<'y'; - } - } -test { - faultsim_test_result [list 0 {1 2}] - } -} do_execsql_test 7.0 { PRAGMA cache_size = 5; diff --git a/test/minmax4.test b/test/minmax4.test index 8063538..775fee8 100644 --- a/test/minmax4.test +++ b/test/minmax4.test @@ -19,6 +19,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix minmax4 ifcapable !compound { finish_test @@ -148,6 +149,88 @@ do_test minmax4-2.7 { } } {1 1 {} 2 2 2 3 3 5 5} +#------------------------------------------------------------------------- +foreach {tn sql} { + 1 { CREATE INDEX i1 ON t1(a) } + 2 { CREATE INDEX i1 ON t1(a DESC) } + 3 { } +} { + reset_db + do_execsql_test 3.$tn.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(NULL, 1); + } + execsql $sql + do_execsql_test 3.$tn.1 { + SELECT min(a), b FROM t1; + } {{} 1} + do_execsql_test 3.$tn.2 { + SELECT min(a), b FROM t1 WHERE a<50; + } {{} {}} + do_execsql_test 3.$tn.3 { + INSERT INTO t1 VALUES(2, 2); + } + do_execsql_test 3.$tn.4 { + SELECT min(a), b FROM t1; + } {2 2} + do_execsql_test 3.$tn.5 { + SELECT min(a), b FROM t1 WHERE a<50; + } {2 2} +} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE t0 (c0, c1); + CREATE INDEX i0 ON t0(c1, c1 + 1 DESC); + INSERT INTO t0(c0) VALUES (1); +} +do_execsql_test 4.1 { + SELECT MIN(t0.c1), t0.c0 FROM t0 WHERE t0.c1 ISNULL; +} {{} 1} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1 (a, b); + INSERT INTO t1 VALUES(123, NULL); + CREATE INDEX i1 ON t1(a, b DESC); +} +do_execsql_test 5.1 { + SELECT MIN(a) FROM t1 WHERE a=123; +} {123} + +#------------------------------------------------------------------------- +# Tests for ticket f8a7060ece. +# +reset_db +do_execsql_test 6.1.0 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(NULL, 1, 'x'); + CREATE INDEX i1 ON t1(a); +} +do_execsql_test 6.1.1 { + SELECT min(a), b, c FROM t1 WHERE c='x'; +} {{} 1 x} +do_execsql_test 6.1.2 { + INSERT INTO t1 VALUES(1, 2, 'y'); +} {} +do_execsql_test 6.1.3 { + SELECT min(a), b, c FROM t1 WHERE c='x'; +} {{} 1 x} + +do_execsql_test 6.2.0 { + CREATE TABLE t0(c0 UNIQUE, c1); + INSERT INTO t0(c1) VALUES (0); + INSERT INTO t0(c0) VALUES (0); + CREATE VIEW v0(c0, c1) AS + SELECT t0.c1, t0.c0 FROM t0 WHERE CAST(t0.rowid AS INT) = 1; +} +do_execsql_test 6.2.1 { + SELECT c0, c1 FROM v0; +} {0 {}} +do_execsql_test 6.2.2 { + SELECT v0.c0, MIN(v0.c1) FROM v0; +} {0 {}} finish_test diff --git a/test/nulls1.test b/test/nulls1.test new file mode 100644 index 0000000..98fc6ab --- /dev/null +++ b/test/nulls1.test @@ -0,0 +1,253 @@ +# 2019 August 10 +# +# 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 nulls1 + +do_execsql_test 1.0 { + DROP TABLE IF EXISTS t3; + CREATE TABLE t3(a INTEGER); + INSERT INTO t3 VALUES(NULL), (10), (30), (20), (NULL); +} {} + +for {set a 0} {$a < 3} {incr a} { + foreach {tn limit} { + 1 "" + 2 "LIMIT 10" + } { + do_execsql_test 1.$a.$tn.1 " + SELECT a FROM t3 ORDER BY a nULLS FIRST $limit + " {{} {} 10 20 30} + + do_execsql_test 1.$a.$tn.2 " + SELECT a FROM t3 ORDER BY a nULLS LAST $limit + " {10 20 30 {} {}} + + do_execsql_test 1.$a.$tn.3 " + SELECT a FROM t3 ORDER BY a DESC nULLS FIRST $limit + " {{} {} 30 20 10} + + do_execsql_test 1.$a.$tn.4 " + SELECT a FROM t3 ORDER BY a DESC nULLS LAST $limit + " {30 20 10 {} {}} + } + + switch $a { + 0 { + execsql { CREATE INDEX i1 ON t3(a) } + } + 1 { + execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t3(a DESC) } + } + } +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t2(a, b, c); + CREATE INDEX i2 ON t2(a, b); + INSERT INTO t2 VALUES(1, 1, 1); + INSERT INTO t2 VALUES(1, NULL, 2); + INSERT INTO t2 VALUES(1, NULL, 3); + INSERT INTO t2 VALUES(1, 4, 4); +} + +do_execsql_test 2.1 { + SELECT * FROM t2 WHERE a=1 ORDER BY b NULLS LAST +} { + 1 1 1 1 4 4 1 {} 2 1 {} 3 +} + +do_execsql_test 2.2 { + SELECT * FROM t2 WHERE a=1 ORDER BY b DESC NULLS FIRST +} { + 1 {} 3 + 1 {} 2 + 1 4 4 + 1 1 1 +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a, b, c, d, UNIQUE (b)); +} +foreach {tn sql err} { + 1 { CREATE INDEX i1 ON t1(a ASC NULLS LAST) } LAST + 2 { CREATE INDEX i1 ON t1(a ASC NULLS FIRST) } FIRST + 3 { CREATE INDEX i1 ON t1(a, b ASC NULLS LAST) } LAST + 4 { CREATE INDEX i1 ON t1(a, b ASC NULLS FIRST) } FIRST + 5 { CREATE INDEX i1 ON t1(a DESC NULLS LAST) } LAST + 6 { CREATE INDEX i1 ON t1(a DESC NULLS FIRST) } FIRST + 7 { CREATE INDEX i1 ON t1(a, b DESC NULLS LAST) } LAST + 8 { CREATE INDEX i1 ON t1(a, b DESC NULLS FIRST) } FIRST + 9 { CREATE TABLE t2(a, b, PRIMARY KEY(a DESC, b NULLS FIRST)) } FIRST + 10 { CREATE TABLE t2(a, b, UNIQUE(a DESC NULLS FIRST, b)) } FIRST + 11 { INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS LAST) DO UPDATE SET a = a+1 } LAST + 12 { + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS FIRST) DO UPDATE SET a = a+1; + END + } FIRST +} { + do_catchsql_test 3.1.$tn $sql "1 {unsupported use of NULLS $err}" +} + +do_execsql_test 3.2 { + CREATE TABLE first(nulls, last); + INSERT INTO first(last, nulls) VALUES(100,200), (300,400), (200,300); + SELECT * FROM first ORDER BY nulls; +} { + 200 100 + 300 200 + 400 300 +} + +#------------------------------------------------------------------------- +# +ifcapable vtab { + register_echo_module db + do_execsql_test 4.0 { + CREATE TABLE tx(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON tx(b); + INSERT INTO tx VALUES(1, 1, 1); + INSERT INTO tx VALUES(2, NULL, 2); + INSERT INTO tx VALUES(3, 3, 3); + INSERT INTO tx VALUES(4, NULL, 4); + INSERT INTO tx VALUES(5, 5, 5); + CREATE VIRTUAL TABLE te USING echo(tx); + } + + do_execsql_test 4.1 { + SELECT * FROM tx ORDER BY b NULLS FIRST; + } {2 {} 2 4 {} 4 1 1 1 3 3 3 5 5 5} + do_execsql_test 4.2 { + SELECT * FROM te ORDER BY b NULLS FIRST; + } {2 {} 2 4 {} 4 1 1 1 3 3 3 5 5 5} + + do_execsql_test 4.3 { + SELECT * FROM tx ORDER BY b NULLS LAST; + } {1 1 1 3 3 3 5 5 5 2 {} 2 4 {} 4} + do_execsql_test 4.4 { + SELECT * FROM te ORDER BY b NULLS LAST; + } {1 1 1 3 3 3 5 5 5 2 {} 2 4 {} 4} +} + +#------------------------------------------------------------------------- +# +do_execsql_test 5.0 { + CREATE TABLE t4(a, b, c); + INSERT INTO t4 VALUES(1, 1, 11); + INSERT INTO t4 VALUES(1, 2, 12); + INSERT INTO t4 VALUES(1, NULL, 1); + + INSERT INTO t4 VALUES(2, NULL, 1); + INSERT INTO t4 VALUES(2, 2, 12); + INSERT INTO t4 VALUES(2, 1, 11); + + INSERT INTO t4 VALUES(3, NULL, 1); + INSERT INTO t4 VALUES(3, 2, 12); + INSERT INTO t4 VALUES(3, NULL, 3); +} + +do_execsql_test 5.1 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + 1 1 11 1 2 12 1 {} 1 + 2 1 11 2 2 12 2 {} 1 + 3 2 12 3 {} 1 3 {} 3 +} +do_execsql_test 5.2 { + CREATE INDEX t4ab ON t4(a, b); + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + 1 1 11 1 2 12 1 {} 1 + 2 1 11 2 2 12 2 {} 1 + 3 2 12 3 {} 1 3 {} 3 +} +do_eqp_test 5.3 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + QUERY PLAN + `--SEARCH TABLE t4 USING INDEX t4ab (a=?) +} + +do_execsql_test 5.4 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST +} { + 3 {} 3 3 {} 1 3 2 12 + 2 {} 1 2 2 12 2 1 11 + 1 {} 1 1 2 12 1 1 11 +} +do_eqp_test 5.5 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST +} { + QUERY PLAN + `--SEARCH TABLE t4 USING INDEX t4ab (a=?) +} + +#------------------------------------------------------------------------- +# +do_execsql_test 6.0 { + CREATE TABLE t5(a, b, c); + WITH s(i) AS ( + VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200 + ) + INSERT INTO t5 SELECT i%2, CASE WHEN (i%10)==0 THEN NULL ELSE i END, i FROM s; +} + +set res1 [db eval { SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c }] +set res2 [db eval { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +}] + +do_execsql_test 6.1.1 { + CREATE INDEX t5ab ON t5(a, b, c); + SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c; +} $res1 +do_eqp_test 6.1.2 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c; +} { + QUERY PLAN + `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?) +} +do_execsql_test 6.2.1 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +} $res2 +do_eqp_test 6.2.2 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +} { + QUERY PLAN + `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?) +} + +#------------------------------------------------------------------------- +do_execsql_test 7.0 { + CREATE TABLE t71(a, b, c); + CREATE INDEX t71abc ON t71(a, b, c); + + SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c NULLS LAST; + SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c DESC NULLS FIRST; + + SELECT * FROM t71 ORDER BY a NULLS LAST; + SELECT * FROM t71 ORDER BY a DESC NULLS FIRST; +} + +finish_test + + diff --git a/test/orderbyA.test b/test/orderbyA.test new file mode 100644 index 0000000..4400f4e --- /dev/null +++ b/test/orderbyA.test @@ -0,0 +1,147 @@ +# 2019-09-21 +# +# 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. +# +# Specifically, it tests cases where the expressions in a GROUP BY +# clause are the same as those in the ORDER BY clause. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix orderbyA + +proc do_sortcount_test {tn sql cnt res} { + set eqp [execsql "EXPLAIN QUERY PLAN $sql"] + set rcnt [regexp -all {USE TEMP} $eqp] + uplevel [list do_test $tn.1 [list set {} $rcnt] $cnt] + uplevel [list do_execsql_test $tn.2 $sql $res] +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES('one', 1, 11); + INSERT INTO t1 VALUES('three', 7, 11); + INSERT INTO t1 VALUES('one', 2, 11); + INSERT INTO t1 VALUES('one', 3, 11); + INSERT INTO t1 VALUES('two', 4, 11); + INSERT INTO t1 VALUES('two', 6, 11); + INSERT INTO t1 VALUES('three', 8, 11); + INSERT INTO t1 VALUES('two', 5, 11); + INSERT INTO t1 VALUES('three', 9, 11); +} + +foreach {tn idx} { + 1 {} + 2 {CREATE INDEX i1 ON t1(a)} + 3 {CREATE INDEX i1 ON t1(a DESC)} +} { + execsql { DROP INDEX IF EXISTS i1 } + execsql $idx + + # $match is the number of temp-table sorts we expect if the GROUP BY + # can use the same sort order as the ORDER BY. $nomatch is the number + # of expected sorts if the GROUP BY and ORDER BY are not compatible. + set match 1 + set nomatch 2 + if {$tn>=2} { + set match 0 + set nomatch 1 + } + + do_sortcount_test 1.$tn.1.1 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a + } $match {one 6 three 24 two 15} + do_sortcount_test 1.$tn.1.2 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC + } $match {two 15 three 24 one 6} + + do_sortcount_test 1.$tn.2.1 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||'' + } $nomatch {one 6 three 24 two 15} + do_sortcount_test 1.$tn.2.2 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a||'' DESC + } $nomatch {two 15 three 24 one 6} + + do_sortcount_test 1.$tn.3.1 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a NULLS LAST + } $nomatch {one 6 three 24 two 15} + do_sortcount_test 1.$tn.3.2 { + SELECT a, sum(b) FROM t1 GROUP BY a ORDER BY a DESC NULLS FIRST + } $nomatch {two 15 three 24 one 6} +} + +#------------------------------------------------------------------------- +do_execsql_test 2.0 { + CREATE TABLE t2(a, b, c); + INSERT INTO t2 VALUES(1, 'one', 1); + INSERT INTO t2 VALUES(1, 'two', 2); + INSERT INTO t2 VALUES(1, 'one', 3); + INSERT INTO t2 VALUES(1, 'two', 4); + INSERT INTO t2 VALUES(1, 'one', 5); + INSERT INTO t2 VALUES(1, 'two', 6); + + INSERT INTO t2 VALUES(2, 'one', 7); + INSERT INTO t2 VALUES(2, 'two', 8); + INSERT INTO t2 VALUES(2, 'one', 9); + INSERT INTO t2 VALUES(2, 'two', 10); + INSERT INTO t2 VALUES(2, 'one', 11); + INSERT INTO t2 VALUES(2, 'two', 12); + + INSERT INTO t2 VALUES(NULL, 'one', 13); + INSERT INTO t2 VALUES(NULL, 'two', 14); + INSERT INTO t2 VALUES(NULL, 'one', 15); + INSERT INTO t2 VALUES(NULL, 'two', 16); + INSERT INTO t2 VALUES(NULL, 'one', 17); + INSERT INTO t2 VALUES(NULL, 'two', 18); +} + +foreach {tn idx} { + 1 {} + + 2 { CREATE INDEX i2 ON t2(a, b) } + 3 { CREATE INDEX i2 ON t2(a DESC, b DESC) } + + 4 { CREATE INDEX i2 ON t2(a, b DESC) } + 5 { CREATE INDEX i2 ON t2(a DESC, b) } +} { + execsql { DROP INDEX IF EXISTS i2 } + execsql $idx + + + set nSort [expr ($tn==2 || $tn==3) ? 0 : 1] + do_sortcount_test 2.$tn.1.1 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b; + } $nSort {{} one 45 {} two 48 1 one 9 1 two 12 2 one 27 2 two 30} + do_sortcount_test 2.$tn.1.2 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b DESC; + } $nSort {2 two 30 2 one 27 1 two 12 1 one 9 {} two 48 {} one 45} + + set nSort [expr ($tn==4 || $tn==5) ? 0 : 1] + do_sortcount_test 2.$tn.2.1 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC; + } $nSort { {} two 48 {} one 45 1 two 12 1 one 9 2 two 30 2 one 27 } + do_sortcount_test 2.$tn.2.2 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b; + } $nSort { 2 one 27 2 two 30 1 one 9 1 two 12 {} one 45 {} two 48 } + + # ORDER BY can never piggyback on the GROUP BY sort if it uses + # non-standard NULLS behaviour. + set nSort [expr $tn==1 ? 2 : 1] + do_sortcount_test 2.$tn.3.1 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a, b DESC NULLS FIRST; + } $nSort { {} two 48 {} one 45 1 two 12 1 one 9 2 two 30 2 one 27 } + do_sortcount_test 2.$tn.3.2 { + SELECT a, b, sum(c) FROM t2 GROUP BY a, b ORDER BY a DESC, b NULLS LAST; + } $nSort { 2 one 27 2 two 30 1 one 9 1 two 12 {} one 45 {} two 48 } +} + + +finish_test diff --git a/test/permutations.test b/test/permutations.test index 007aec1..5163c2a 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -126,6 +126,7 @@ set allquicktests [test_set $alltests -exclude { walcrash2.test e_fkey.test backup.test fts4merge.test fts4merge2.test fts4merge4.test fts4check.test + fts4merge5.test fts3cov.test fts3snippet.test fts3corrupt2.test fts3an.test fts3defer.test fts4langid.test fts3sort.test fts5unicode.test @@ -455,8 +456,8 @@ test_suite "coverage-analyze" -description { Coverage tests for file analyze.c. } -files { analyze3.test analyze4.test analyze5.test analyze6.test - analyze7.test analyze8.test analyze9.test analyzeA.test - analyze.test analyzeB.test mallocA.test + analyze7.test analyze8.test analyze9.test + analyze.test mallocA.test } test_suite "coverage-sorter" -description { @@ -624,7 +625,7 @@ test_suite "utf16" -description { } -files { alter.test alter3.test analyze.test analyze3.test analyze4.test analyze5.test analyze6.test - analyze7.test analyze8.test analyze9.test analyzeA.test analyzeB.test + analyze7.test analyze8.test analyze9.test auth.test bind.test blob.test capi2.test capi3.test collate1.test collate2.test collate3.test collate4.test collate5.test collate6.test conflict.test date.test delete.test expr.test fkey1.test func.test diff --git a/test/pg_common.tcl b/test/pg_common.tcl index bbc52eb..b3f35cd 100644 --- a/test/pg_common.tcl +++ b/test/pg_common.tcl @@ -70,8 +70,8 @@ proc execsql {sql} { proc execsql_test {tn sql} { set res [execsql $sql] set sql [string map {string_agg group_concat} $sql] - set sql [string map [list {NULLS FIRST} {}] $sql] - set sql [string map [list {NULLS LAST} {}] $sql] + # set sql [string map [list {NULLS FIRST} {}] $sql] + # set sql [string map [list {NULLS LAST} {}] $sql] puts $::fd "do_execsql_test $tn {" puts $::fd " [string trim $sql]" puts $::fd "} {$res}" diff --git a/test/pragma.test b/test/pragma.test index 9257ce4..1881a5c 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -1859,10 +1859,11 @@ do_test 23.1 { CREATE INDEX i1 ON t1(b,c); CREATE INDEX i2 ON t1(c,d); CREATE INDEX i2x ON t1(d COLLATE nocase, c DESC); + CREATE INDEX i3 ON t1(d,b+c,c); CREATE TABLE t2(x INTEGER REFERENCES t1); } db2 eval {SELECT name FROM sqlite_master} -} {t1 i1 i2 i2x t2} +} {t1 i1 i2 i2x i3 t2} do_test 23.2a { db eval { DROP INDEX i2; @@ -1889,13 +1890,14 @@ do_test 23.2b { # means left-most. Key columns come before auxiliary columns.) # # (The second column of output from PRAGMA index_xinfo is...) -# EVIDENCE-OF: R-40889-06838 The rank of the column within the table +# EVIDENCE-OF: R-06603-49335 The rank of the column within the table # being indexed, or -1 if the index-column is the rowid of the table -# being indexed. +# being indexed and -2 if the index is on an expression. # # (The third column of output from PRAGMA index_xinfo is...) -# EVIDENCE-OF: R-22751-28901 The name of the column being indexed, or -# NULL if the index-column is the rowid of the table being indexed. +# EVIDENCE-OF: R-40641-22898 The name of the column being indexed, or +# NULL if the index-column is the rowid of the table being indexed or an +# expression. # # (The fourth column of output from PRAGMA index_xinfo is...) # EVIDENCE-OF: R-11847-09179 1 if the index-column is sorted in reverse @@ -1915,6 +1917,9 @@ do_test 23.2c { do_test 23.2d { db2 eval {PRAGMA index_xinfo(i2x)} } {0 3 d 0 nocase 1 1 2 c 1 BINARY 1 2 -1 {} 0 BINARY 0} +do_test 23.2e { + db2 eval {PRAGMA index_xinfo(i3)} +} {0 3 d 0 BINARY 1 1 -2 {} 0 BINARY 1 2 2 c 0 BINARY 1 3 -1 {} 0 BINARY 0} # EVIDENCE-OF: R-64103-17776 PRAGMA schema.index_list(table-name); This # pragma returns one row for each index associated with the given table. @@ -1936,6 +1941,7 @@ do_test 23.2d { # do_test 23.3 { db eval { + DROP INDEX IF EXISTS i3; CREATE INDEX i3 ON t1(d,b,c); } capture_pragma db2 out {PRAGMA index_list(t1)} diff --git a/test/pragma5.test b/test/pragma5.test index d2c5800..f16e462 100644 --- a/test/pragma5.test +++ b/test/pragma5.test @@ -11,9 +11,9 @@ # This file implements regression tests for SQLite library. # # This file implements tests for the PRAGMA command. Specifically, -# those pragmas enabled at build time by setting: +# those pragmas that are not disabled at build time by setting: # -# -DSQLITE_INTROSPECTION_PRAGMAS +# -DSQLITE_OMIT_INTROSPECTION_PRAGMAS # set testdir [file dirname $argv0] diff --git a/test/releasetest.tcl b/test/releasetest.tcl index 997e5ea..37f00eb 100755 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -412,6 +412,8 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} { # skip over "value is outside range" errors if {[regexp {value .* is outside the range of representable} $line]} { # noop + } elseif {[regexp {overflow: .* cannot be represented} $line]} { + # noop } else { incr ::NERRCASE if {$rc==0} { diff --git a/test/releasetest_data.tcl b/test/releasetest_data.tcl index 6b6c2a8..bd3f108 100644 --- a/test/releasetest_data.tcl +++ b/test/releasetest_data.tcl @@ -1,7 +1,43 @@ - -# This file contains Configuration data used by "wapptest.tcl" and -# "releasetest.tcl". +# 2019 August 01 # +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file implements a program that produces scripts (either shell scripts +# or batch files) to implement a particular test that is part of the SQLite +# release testing procedure. For example, to run veryquick.test with a +# specified set of -D compiler switches. +# +# A "configuration" is a set of options passed to [./configure] and [make] +# to build the SQLite library in a particular fashion. A "platform" is a +# list of tests; most platforms are named after the hardware/OS platform +# that the tests will be run on as part of the release procedure. Each +# "test" is a combination of a configuration and a makefile target (e.g. +# "fulltest"). The program may be invoked as follows: +# +set USAGE { +$argv0 platforms + List available platforms. + +$argv0 tests ?-nodebug? PLATFORM + List tests in a specified platform. If the -nodebug switch is + specified, synthetic debug/ndebug configurations are omitted. Each + test is a combination of a configuration and a makefile target. + +$argv0 script ?-msvc? CONFIGURATION TARGET + Given a configuration and make target, return a bash (or, if -msvc + is specified, batch) script to execute the test. The first argument + passed to the script must be a directory containing SQLite source code. + +$argv0 configurations + List available configurations. +} # Omit comments (text between # and \n) in a long multi-line string. # @@ -158,8 +194,6 @@ array set ::Configs [strip_comments { -DHAVE_LOCALTIME_R=1 -DHAVE_PREAD=1 -DHAVE_PWRITE=1 - -DHAVE_USLEEP=1 - -DHAVE_USLEEP=1 -DHAVE_UTIME=1 -DSQLITE_DEFAULT_CACHE_SIZE=1000 -DSQLITE_DEFAULT_CKPTFULLFSYNC=1 @@ -172,7 +206,6 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS3_TOKENIZER=1 - if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1 -DSQLITE_ENABLE_PERSIST_WAL=1 -DSQLITE_ENABLE_PURGEABLE_PCACHE=1 -DSQLITE_ENABLE_RTREE=1 @@ -212,7 +245,6 @@ array set ::Configs [strip_comments { "No-lookaside" { -DSQLITE_TEST_REALLOC_STRESS=1 -DSQLITE_OMIT_LOOKASIDE=1 - -DHAVE_USLEEP=1 } "Valgrind" { -DSQLITE_ENABLE_STAT4 @@ -222,22 +254,34 @@ array set ::Configs [strip_comments { --enable-json1 } + "Windows-Memdebug" { + MEMDEBUG=1 + DEBUG=3 + } + "Windows-Win32Heap" { + WIN32HEAP=1 + DEBUG=4 + } + # The next group of configurations are used only by the # Failure-Detection platform. They are all the same, but we need # different names for them all so that they results appear in separate # subdirectories. # - Fail0 {-O0} - Fail2 {-O0} - Fail3 {-O0} - Fail4 {-O0} + Fail0 {-O0} + Fail2 {-O0} + Fail3 {-O0} + Fail4 {-O0} FuzzFail1 {-O0} FuzzFail2 {-O0} }] +if {$tcl_platform(os)=="Darwin"} { + lappend Configs(Apple -DSQLITE_ENABLE_LOCKING_STYLE=1 +} array set ::Platforms [strip_comments { Linux-x86_64 { - "Check-Symbols" checksymbols + "Check-Symbols*" checksymbols "Fast-One" "fuzztest test" "Debug-One" "mptest test" "Have-Not" test @@ -253,7 +297,7 @@ array set ::Platforms [strip_comments { "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} "Device-One" fulltest "Default" "threadtest fulltest" - "Valgrind" valgrindtest + "Valgrind*" valgrindtest } Linux-i686 { "Devkit" test @@ -276,11 +320,15 @@ array set ::Platforms [strip_comments { "Windows NT-intel" { "Stdcall" test "Have-Not" test + "Windows-Memdebug*" test + "Windows-Win32Heap*" test "Default" "mptest fulltestonly" } "Windows NT-amd64" { "Stdcall" test "Have-Not" test + "Windows-Memdebug*" test + "Windows-Win32Heap*" test "Default" "mptest fulltestonly" } @@ -289,120 +337,24 @@ array set ::Platforms [strip_comments { # correctly identifies failures. # Failure-Detection { - Fail0 "TEST_FAILURE=0 test" - Sanitize "TEST_FAILURE=1 test" - Fail2 "TEST_FAILURE=2 valgrindtest" - Fail3 "TEST_FAILURE=3 valgrindtest" - Fail4 "TEST_FAILURE=4 test" - FuzzFail1 "TEST_FAILURE=5 test" - FuzzFail2 "TEST_FAILURE=5 valgrindtest" + Fail0* "TEST_FAILURE=0 test" + Sanitize* "TEST_FAILURE=1 test" + Fail2* "TEST_FAILURE=2 valgrindtest" + Fail3* "TEST_FAILURE=3 valgrindtest" + Fail4* "TEST_FAILURE=4 test" + FuzzFail1* "TEST_FAILURE=5 test" + FuzzFail2* "TEST_FAILURE=5 valgrindtest" } }] -proc make_test_suite {msvc withtcl name testtarget config} { - - # Tcl variable $opts is used to build up the value used to set the - # OPTS Makefile variable. Variable $cflags holds the value for - # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but - # CFLAGS is only passed to gcc. - # - set makeOpts "" - set cflags [expr {$msvc ? "-Zi" : "-g"}] - set opts "" - set title ${name}($testtarget) - set configOpts $withtcl - set skip 0 - - regsub -all {#[^\n]*\n} $config \n config - foreach arg $config { - if {$skip} { - set skip 0 - continue - } - if {[regexp {^-[UD]} $arg]} { - lappend opts $arg - } elseif {[regexp {^[A-Z]+=} $arg]} { - lappend testtarget $arg - } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} { - # Arguments of the form 'if:os=="Linux"' will cause the subsequent - # argument to be skipped if the $tcl_platform(os) is not "Linux", for - # example... - set skip [expr !(\$::tcl_platform($key)$tail)] - } elseif {[regexp {^--(enable|disable)-} $arg]} { - if {$msvc} { - if {$arg eq "--disable-amalgamation"} { - lappend makeOpts USE_AMALGAMATION=0 - continue - } - if {$arg eq "--disable-shared"} { - lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 - continue - } - if {$arg eq "--enable-fts5"} { - lappend opts -DSQLITE_ENABLE_FTS5 - continue - } - if {$arg eq "--enable-json1"} { - lappend opts -DSQLITE_ENABLE_JSON1 - continue - } - if {$arg eq "--enable-shared"} { - lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 - continue - } - } - lappend configOpts $arg - } else { - if {$msvc} { - if {$arg eq "-g"} { - lappend cflags -Zi - continue - } - if {[regexp -- {^-O(\d+)$} $arg all level]} then { - lappend makeOpts OPTIMIZATIONS=$level - continue - } - } - lappend cflags $arg - } - } - - # Disable sync to make testing faster. - # - lappend opts -DSQLITE_NO_SYNC=1 - - # Some configurations already set HAVE_USLEEP; in that case, skip it. - # - if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} { - lappend opts -DHAVE_USLEEP=1 - } - - # Add the define for this platform. - # - if {$::tcl_platform(platform)=="windows"} { - lappend opts -DSQLITE_OS_WIN=1 - } else { - lappend opts -DSQLITE_OS_UNIX=1 - } - - # Set the sub-directory to use. - # - set dir [string tolower [string map {- _ " " _ "(" _ ")" _} $name]] - - # Join option lists into strings, using space as delimiter. - # - set makeOpts [join $makeOpts " "] - set cflags [join $cflags " "] - set opts [join $opts " "] - - return [list $title $dir $configOpts $testtarget $makeOpts $cflags $opts] -} - # Configuration verification: Check that each entry in the list of configs # specified for each platforms exists. # foreach {key value} [array get ::Platforms] { foreach {v t} $value { + if {[string range $v end end]=="*"} { + set v [string range $v 0 end-1] + } if {0==[info exists ::Configs($v)]} { puts stderr "No such configuration: \"$v\"" exit -1 @@ -410,3 +362,248 @@ foreach {key value} [array get ::Platforms] { } } +proc usage {} { + global argv0 + puts stderr [subst $::USAGE] + exit 1 +} + +proc is_prefix {p str min} { + set n [string length $p] + if {$n<$min} { return 0 } + if {[string range $str 0 [expr $n-1]]!=$p} { return 0 } + return 1 +} + +proc main_configurations {} { + foreach k [lsort [array names ::Configs]] { + puts $k + } +} + +proc main_platforms {} { + foreach k [lsort [array names ::Platforms]] { + puts "\"$k\"" + } +} + +proc main_script {args} { + set bMsvc 0 + set nArg [llength $args] + if {$nArg==3} { + if {![is_prefix [lindex $args 0] -msvc 2]} usage + set bMsvc 1 + } elseif {$nArg<2 || $nArg>3} { + usage + } + set config [lindex $args end-1] + set target [lindex $args end] + + set opts [list] ;# OPTS value + set cflags [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value + set makeOpts [list] ;# Extra args for [make] + set configOpts [list] ;# Extra args for [configure] + + if {$::tcl_platform(platform)=="windows" || $bMsvc} { + lappend opts -DSQLITE_OS_WIN=1 + } else { + lappend opts -DSQLITE_OS_UNIX=1 + } + + # Figure out if this is a synthetic ndebug or debug configuration. + # + set bRemoveDebug 0 + if {[string match *-ndebug $config]} { + set bRemoveDebug 1 + set config [string range $config 0 end-7] + } + if {[string match *-debug $config]} { + lappend opts -DSQLITE_DEBUG + lappend opts -DSQLITE_EXTRA_IFNULLROW + set config [string range $config 0 end-6] + } + + # Ensure that the named configuration exists. + # + if {![info exists ::Configs($config)]} { + puts stderr "No such config: $config" + exit 1 + } + + # Loop through the parameters of the nominated configuration, updating + # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as + # follows: + # + # 1. If the parameter begins with a "*", discard it. + # + # 2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or + # -DSQLITE_DEBUG=1, discard it + # + # 3. If the parameter begins with "-D", add it to $opts. + # + # 4. If the parameter begins with "--" add it to $configOpts. Unless + # this command is preparing a script for MSVC - then add an + # equivalent to $makeOpts or $opts. + # + # 5. If the parameter begins with "-" add it to $cflags. If in MSVC + # mode and the parameter is an -O option, instead add + # an OPTIMIZATIONS= switch to $makeOpts. + # + # 6. If none of the above apply, add the parameter to $makeOpts + # + foreach param $::Configs($config) { + if {[string range $param 0 0]=="*"} continue + + if {$bRemoveDebug} { + if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1" + || $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1" + } { + continue + } + } + + if {[string range $param 0 1]=="-D"} { + lappend opts $param + continue + } + + if {[string range $param 0 1]=="--"} { + if {$bMsvc} { + switch -- $param { + --disable-amalgamation { + lappend makeOpts USE_AMALGAMATION=0 + } + --disable-shared { + lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 + } + --enable-fts5 { + lappend opts -DSQLITE_ENABLE_FTS5 + } + --enable-json1 { + lappend opts -DSQLITE_ENABLE_JSON1 + } + --enable-shared { + lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 + } + --enable-session { + lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK + lappend opts -DSQLITE_ENABLE_SESSION + } + default { + error "Cannot translate $param for MSVC" + } + } + } else { + lappend configOpts $param + } + + continue + } + + if {[string range $param 0 0]=="-"} { + if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} { + lappend makeOpts OPTIMIZATIONS=$level + } else { + lappend cflags $param + } + continue + } + + lappend makeOpts $param + } + + # Some configurations specify -DHAVE_USLEEP=0. For all others, add + # -DHAVE_USLEEP=1. + # + if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} { + lappend opts -DHAVE_USLEEP=1 + } + + if {$bMsvc==0} { + puts {set -e} + puts {} + puts {if [ "$#" -ne 1 ] ; then} + puts { echo "Usage: $0 " } + puts { exit -1 } + puts {fi } + puts {SRCDIR=$1} + puts {} + puts "TCL=\"[::tcl::pkgconfig get libdir,install]\"" + + puts "\$SRCDIR/configure --with-tcl=\$TCL $configOpts" + puts {} + puts {OPTS=" -DSQLITE_NO_SYNC=1"} + foreach o $opts { + puts "OPTS=\"\$OPTS $o\"" + } + puts {} + puts "CFLAGS=\"$cflags\"" + puts {} + puts "make $target \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts" + } else { + + puts {set SRCDIR=%1} + set makecmd "nmake /f %SRCDIR%\\Makefile.msc TOP=%SRCDIR% $target " + append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts" + + puts "set TMP=%CD%" + puts $makecmd + } +} + +proc main_tests {args} { + set bNodebug 0 + set nArg [llength $args] + if {$nArg==2} { + if {[is_prefix [lindex $args 0] -nodebug 2]} { + set bNodebug 1 + } elseif {[is_prefix [lindex $args 0] -debug 2]} { + set bNodebug 0 + } else usage + } elseif {$nArg==0 || $nArg>2} { + usage + } + set p [lindex $args end] + if {![info exists ::Platforms($p)]} { + puts stderr "No such platform: $p" + exit 1 + } + + foreach {config target} $::Platforms($p) { + set bNosynthetic 0 + if {[string range $config end end]=="*"} { + set bNosynthetic 1 + set config [string range $config 0 end-1] + } + puts "$config \"$target\"" + if {$bNodebug==0 && $bNosynthetic==0} { + set iHas [string first SQLITE_DEBUG $::Configs($config)] + set dtarget test + if {$target=="tcltest"} { + set dtarget tcltest + } + if {$iHas>=0} { + puts "$config-ndebug \"$dtarget\"" + } else { + puts "$config-debug \"$dtarget\"" + } + } + } +} + +if {[llength $argv]==0} { usage } +set cmd [lindex $argv 0] +set n [expr [llength $argv]-1] +if {[string match ${cmd}* configurations] && $n==0} { + main_configurations +} elseif {[string match ${cmd}* script]} { + main_script {*}[lrange $argv 1 end] +} elseif {[string match ${cmd}* platforms] && $n==0} { + main_platforms +} elseif {[string match ${cmd}* tests]} { + main_tests {*}[lrange $argv 1 end] +} else { + usage +} + + diff --git a/test/rowvalue.test b/test/rowvalue.test index 2a2f8a9..e859024 100644 --- a/test/rowvalue.test +++ b/test/rowvalue.test @@ -557,4 +557,17 @@ do_execsql_test 21.0 { SELECT * FROM t1 WHERE (a,b) IN (VALUES(1,2)); } {1 2} +# 2019-08-09: Multi-column subquery on the RHS of an IN operator. +# +do_execsql_test 22.100 { + SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1) IN (SELECT 3,4); + SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1) IN (SELECT 5,6); + SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1) IN (SELECT 3,4); + SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1) IN (SELECT 5,6); + SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1 DESC) IN (SELECT 3,4); + SELECT (SELECT 3,4 UNION SELECT 5,6 ORDER BY 1 DESC) IN (SELECT 5,6); + SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1 DESC) IN (SELECT 3,4); + SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1 DESC) IN (SELECT 5,6); +} {1 0 1 0 0 1 0 1} + finish_test diff --git a/test/rowvalue7.test b/test/rowvalue7.test index f6764f3..03591af 100644 --- a/test/rowvalue7.test +++ b/test/rowvalue7.test @@ -55,4 +55,14 @@ do_catchsql_test 2.2 { UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a); } {1 {3 columns assigned 2 values}} +# 2019-08-26 +# ticket https://www.sqlite.org/src/info/78acc9d40f0786e8 +# +do_catchsql_test 3.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,2); + UPDATE t1 SET (a,a,a,b)=(SELECT 99,100); +} {1 {4 columns assigned 2 values}} + finish_test diff --git a/test/schema.test b/test/schema.test index afca39e..c7daef2 100644 --- a/test/schema.test +++ b/test/schema.test @@ -209,17 +209,29 @@ ifcapable utf16 { #--------------------------------------------------------------------- # Tests 8.1 and 8.2 check that prepared statements are invalidated when -# the authorization function is set. +# the authorization function is set to a non-null function. Tests 8.11 +# and 8.12 verify that no invalidations occur when the authorizer is +# cleared. # ifcapable auth { + proc noop_auth {args} {return SQLITE_OK} do_test schema-8.1 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + db auth noop_auth + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-8.2 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} + do_test schema-8.11 { set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] db auth {} sqlite3_step $::STMT - } {SQLITE_ERROR} - do_test schema-8.3 { + } {SQLITE_ROW} + do_test schema-8.12 { sqlite3_finalize $::STMT - } {SQLITE_SCHEMA} + } {SQLITE_OK} + } #--------------------------------------------------------------------- diff --git a/test/select1.test b/test/select1.test index 468f118..27191ca 100644 --- a/test/select1.test +++ b/test/select1.test @@ -1100,4 +1100,69 @@ do_execsql_test select1-17.3 { UNION ALL SELECT * FROM t2 WHERE y=3 ORDER BY y,z LIMIT 4); } {1 2 3} +# 2019-07-24 Ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311 +# +do_execsql_test select1-18.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(c); + CREATE TABLE t2(x PRIMARY KEY, y); + INSERT INTO t1(c) VALUES(123); + INSERT INTO t2(x) VALUES(123); + SELECT x FROM t2, t1 WHERE x BETWEEN c AND null OR x AND + x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim + FROM t2, t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)) AND null + OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND null + OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)) AND null + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c)))) AND x IN (c) + ), t1 WHERE x BETWEEN c AND null + OR x AND x IN (c))); +} {} +do_execsql_test select1-18.2 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(c); + CREATE TABLE t2(x PRIMARY KEY, y); + INSERT INTO t1(c) VALUES(123); + INSERT INTO t2(x) VALUES(123); + SELECT x FROM t2, t1 WHERE x BETWEEN c AND (c+1) OR x AND + x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x COLLATE rtrim + FROM t2, t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)) AND (c+1) + OR NOT EXISTS(SELECT -4.81 FROM t1, t2 WHERE x BETWEEN c AND (c+1) + OR x AND x IN ((SELECT x FROM (SELECT x FROM t2, t1 + WHERE x BETWEEN (SELECT x FROM (SELECT x BETWEEN c AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)) AND (c+1) + OR x AND x IN (c)), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c)))) AND x IN (c) + ), t1 WHERE x BETWEEN c AND (c+1) + OR x AND x IN (c))); +} {123} +do_execsql_test select1-18.3 { + SELECT 1 FROM t1 WHERE ( + SELECT 2 FROM t2 WHERE ( + SELECT 3 FROM ( + SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0))) + ) WHERE x>c OR x=c + ) + ); +} {1} +do_execsql_test select1-18.4 { + SELECT 1 FROM t1, t2 WHERE ( + SELECT 3 FROM ( + SELECT x FROM t2 WHERE x=c OR x=(SELECT x FROM (VALUES(0))) + ) WHERE x>c OR x=c + ); +} {1} + finish_test diff --git a/test/skipscan1.test b/test/skipscan1.test index 6aaf533..da9df8f 100644 --- a/test/skipscan1.test +++ b/test/skipscan1.test @@ -234,7 +234,6 @@ do_execsql_test skipscan1-5.2 { ANALYZE; DELETE FROM sqlite_stat1; DROP TABLE IF EXISTS sqlite_stat4; - DROP TABLE IF EXISTS sqlite_stat3; INSERT INTO sqlite_stat1 VALUES('t5','t5i1','2702931 3 2 2 2 2'); INSERT INTO sqlite_stat1 VALUES('t5','t5i2','2702931 686 2 2 2'); ANALYZE sqlite_master; @@ -373,4 +372,30 @@ do_execsql_test skipscan1-2.3 { SELECT a,b,c,d,'|' FROM t6 WHERE d<>99 AND b=345 ORDER BY a DESC; } {} +# 2019-07-29 Ticket ced41c7c7d6b4d36 +# A skipscan query is not order-distinct +# +db close +sqlite3 db :memory: +do_execsql_test skipscan1-3.1 { + CREATE TABLE t1 (c1, c2, c3, c4, PRIMARY KEY(c4, c3)); + INSERT INTO t1 VALUES(3,0,1,NULL); + INSERT INTO t1 VALUES(0,4,1,NULL); + INSERT INTO t1 VALUES(5,6,1,NULL); + INSERT INTO t1 VALUES(0,4,1,NULL); + ANALYZE sqlite_master; + INSERT INTO sqlite_stat1 VALUES('t1','sqlite_autoindex_t1_1','18 18 6'); + ANALYZE sqlite_master; + SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|' + FROM t1 WHERE t1.c3 = 1; +} {3 0 1 NULL | 0 4 1 NULL | 5 6 1 NULL |} +do_eqp_test skipscan1-3.2 { + SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|' + FROM t1 WHERE t1.c3 = 1; +} { + QUERY PLAN + |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?) + `--USE TEMP B-TREE FOR DISTINCT +} + finish_test diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 3197374..92425ae 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -42,7 +42,7 @@ do_test tcl-1.1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, config, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg @@ -789,7 +789,7 @@ do_test 17.6.2 { do_test 17.6.3 { list [catch { db function xyz -n object ret } msg] $msg -} {1 {bad option "-n": must be -argcount, -deterministic or -returntype}} +} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, or -returntype}} # 2019-02-28: The "bind_fallback" command. # diff --git a/test/tempdb2.test b/test/tempdb2.test index d814f84..37cb4b3 100644 --- a/test/tempdb2.test +++ b/test/tempdb2.test @@ -97,4 +97,3 @@ do_execsql_test 2.2 { } "[int2str 1001][int2str 1001][int2str 1001]" finish_test - diff --git a/test/tkt-18458b1a.test b/test/tkt-18458b1a.test new file mode 100644 index 0000000..996ca88 --- /dev/null +++ b/test/tkt-18458b1a.test @@ -0,0 +1,53 @@ +# 2019 September 10 +# +# 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. In particular, +# that problems related to ticket [18458b1a] have been fixed. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tkt-18458b1a + +foreach tn {1 2} { + reset_db + if {$tn==1} { + # Disable the flattener and push-down optimizations + optimization_control db query-flattener 0 + optimization_control db push-down 0 + } else { + # Enable them + optimization_control db query-flattener 1 + optimization_control db push-down 1 + } + + db cache size 0 + + do_execsql_test $tn.1.1 { + CREATE TABLE t0(c0 COLLATE NOCASE); + INSERT INTO t0(c0) VALUES ('B'); + CREATE VIEW v0(c0, c1) AS SELECT DISTINCT t0.c0, 'a' FROM t0; + } + + do_execsql_test $tn.1.2 { + SELECT count(*) FROM v0 WHERE c1 >= c0; + } 1 + + do_execsql_test $tn.1.3 { + SELECT count(*) FROM v0 WHERE NOT NOT (c1 >= c0); + } 1 + + do_execsql_test $tn.1.4 { + SELECT count(*) FROM v0 WHERE ((c1 >= c0) OR 0+0); + } 1 +} + +finish_test + diff --git a/test/tkt-3a77c9714e.test b/test/tkt-3a77c9714e.test index b7d366f..734dff3 100644 --- a/test/tkt-3a77c9714e.test +++ b/test/tkt-3a77c9714e.test @@ -1,4 +1,4 @@ -# 2011 December 06 +# 2011-12-06 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -68,5 +68,19 @@ do_execsql_test 2.2 { ) } {FACTORING FACTOR SWIMMING SWIMM} +# Similar problem discovered by dbsqlfuzz on 2019-09-18 +# +do_execsql_test 3.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(i INT PRIMARY KEY, a, b); + INSERT INTO t1 VALUES(NULL,'one','i'); + CREATE INDEX i1a ON t1(a); + CREATE INDEX i1b ON t1(b); + SELECT (SELECT 1 + FROM (SELECT 1 FROM t1 WHERE a=1 OR b='i') + WHERE a='o' + OR b IN (SELECT a=('b' IN (SELECT 'a')))) + FROM t1; +} {{}} finish_test diff --git a/test/tkt-a7debbe0.test b/test/tkt-a7debbe0.test new file mode 100644 index 0000000..974f6d6 --- /dev/null +++ b/test/tkt-a7debbe0.test @@ -0,0 +1,103 @@ +# 2019 September 10 +# +# 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. In particular, +# that problems related to ticket a7debbe0ad1 have been fixed. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tkt-a7debbe0 + +foreach tn {1 2} { + reset_db + if {$tn==1} { + # Disable the flattener + optimization_control db query-flattener 0 + } else { + # Enable the flattener + optimization_control db query-flattener 1 + } + + do_execsql_test $tn.1.0 { + CREATE TABLE t0(xyz INTEGER); + INSERT INTO t0(xyz) VALUES(456); + CREATE VIEW v2(a, B) AS + SELECT 'a', 'B' COLLATE NOCASE FROM t0; + CREATE TABLE t2(a, B COLLATE NOCASE); + INSERT INTO t2 VALUES('a', 'B'); + CREATE VIEW v3(a, B) AS + SELECT 'a' COLLATE BINARY, 'B' COLLATE NOCASE FROM t0; + + CREATE VIEW v4(a, B) AS + SELECT 'a', +CAST('B' COLLATE NOCASE AS TEXT) FROM t0; + + CREATE VIEW v5(a, B) AS + SELECT 'a', ('B' COLLATE NOCASE) || '' FROM t0; + } + + # Table t2 and views v2 through v5 should all be equivalent. + do_execsql_test $tn.1.1.1 { SELECT a >= B FROM t2; } 1 + do_execsql_test $tn.1.1.2 { SELECT 'a' >= 'B' COLLATE NOCASE } 0 + do_execsql_test $tn.1.1.3 { SELECT a >= B FROM v2 } 1 + do_execsql_test $tn.1.1.4 { SELECT a >= B FROM v3 } 1 + do_execsql_test $tn.1.1.5 { SELECT a >= B FROM v4 } 1 + do_execsql_test $tn.1.1.6 { SELECT a >= B FROM v5 } 1 + + do_execsql_test $tn.1.2.1 { SELECT B < a FROM t2 } 0 + do_execsql_test $tn.1.2.2 { SELECT 'B' COLLATE NOCASE < 'a' } 0 + do_execsql_test $tn.1.2.3 { SELECT B < a FROM v2 } 0 + do_execsql_test $tn.1.2.4 { SELECT B < a FROM v3 } 0 + do_execsql_test $tn.1.2.5 { SELECT a < B FROM v4 } 0 + do_execsql_test $tn.1.2.6 { SELECT a < B FROM v5 } 0 + + #------------------------------------------------------------------------- + do_execsql_test $tn.2.0 { + CREATE TABLE t5(a, b COLLATE NOCASE); + INSERT INTO t5 VALUES(1, 'XYZ'); + } + + # Result should be 0, as column "xyz" from the sub-query has implicit + # collation sequence BINARY. + do_execsql_test $tn.2.1 { + SELECT xyz==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5; + } {0} + + # Result should be 1, as literal 'xyz' has no collation sequence, so + # the comparison uses the implicit collation sequence of the RHS - NOCASE. + do_execsql_test $tn.2.2 { + SELECT 'xyz'==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5; + } {1} + + #----------------------------------------------------------------------- + # The test case submitted with the ticket. + # + do_execsql_test $tn.3.0 { + DROP TABLE t0; + DROP VIEW v2; + + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES(''); + CREATE VIEW v2(c0, c1) AS + SELECT 'B' COLLATE NOCASE, 'a' FROM t0 ORDER BY t0.c0; + SELECT SUM(count) FROM ( + SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2 + ); + } 1 + + # The result is 1, as the collation used is the implicit collation sequence + # of v2.c1 - BINARY. + do_execsql_test $tn.3.1 { + SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2; + } 1 +} + +finish_test + diff --git a/test/tkt-b75a9ca6b0.test b/test/tkt-b75a9ca6b0.test index 8fceb43..f5ae10e 100644 --- a/test/tkt-b75a9ca6b0.test +++ b/test/tkt-b75a9ca6b0.test @@ -60,7 +60,7 @@ foreach {tn q res eqp} [subst -nocommands { {1 3 2 2 3 1} {$idxscan*$sort} 8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC" - {3 1 2 2 1 3} {$idxscan*$sort} + {3 1 2 2 1 3} {$idxscan} 9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC" {1 3 2 2 3 1} {$idxscan} diff --git a/test/tkt-cbd054fa6b.test b/test/tkt-cbd054fa6b.test index 2951233..86248ca 100644 --- a/test/tkt-cbd054fa6b.test +++ b/test/tkt-cbd054fa6b.test @@ -16,7 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !stat4&&!stat3 { +ifcapable !stat4 { finish_test return } @@ -55,19 +55,12 @@ do_test tkt-cbd05-1.1 { } {10} do_test tkt-cbd05-1.2 { db eval { ANALYZE; } - ifcapable stat4 { - db eval { - PRAGMA writable_schema = 1; - CREATE VIEW vvv AS - SELECT tbl,idx,neq,nlt,ndlt,test_extract(sample,0) AS sample - FROM sqlite_stat4; - PRAGMA writable_schema = 0; - } - } else { - db eval { - CREATE VIEW vvv AS - SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat3; - } + db eval { + PRAGMA writable_schema = 1; + CREATE VIEW vvv AS + SELECT tbl,idx,neq,nlt,ndlt,test_extract(sample,0) AS sample + FROM sqlite_stat4; + PRAGMA writable_schema = 0; } } {} do_test tkt-cbd05-1.3 { diff --git a/test/trigger1.test b/test/trigger1.test index 8946cd8..ddb40e3 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -768,4 +768,18 @@ do_execsql_test trigger1-19.1 { SELECT * FROM t19; } {1 2 2} +# 2019-08-26 Chromium sqlite3_fts3_lpm_fuzzer find. +# +db close +sqlite3 db :memory: +do_execsql_test trigger1-20.1 { + CREATE TABLE t20_1(x); + ATTACH ':memory:' AS aux; + CREATE TABLE aux.t20_2(y); + CREATE TABLE aux.t20_3(z); + CREATE TEMP TRIGGER r20_3 AFTER INSERT ON t20_2 BEGIN UPDATE t20_3 SET z=z+1; END; + DETACH aux; + DROP TRIGGER r20_3; +} {} + finish_test diff --git a/test/triggerC.test b/test/triggerC.test index d5fd884..a2a0603 100644 --- a/test/triggerC.test +++ b/test/triggerC.test @@ -1072,4 +1072,3 @@ do_catchsql_test 17.1 { finish_test - diff --git a/test/upsert1.test b/test/upsert1.test index 0d13cd8..006af43 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -210,5 +210,15 @@ do_execsql_test upsert1-780 { SELECT * FROM t1; } {1 2 33 4 5} +# 2019-08-30 ticket https://sqlite.org/src/info/5a3dba8104421320 +do_execsql_test upsert1-800 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL UNIQUE, c1); + CREATE UNIQUE INDEX test800i0 ON t0(0 || c1); + INSERT INTO t0(c0, c1) VALUES (1, 2), (2, 1); + INSERT INTO t0(c0) VALUES (1) ON CONFLICT(c0) DO UPDATE SET c1=excluded.c0; + PRAGMA integrity_check; + REINDEX; +} {ok} finish_test diff --git a/test/view.test b/test/view.test index 8a60f86..b3f50dc 100644 --- a/test/view.test +++ b/test/view.test @@ -38,6 +38,18 @@ do_test view-1.1 { SELECT * FROM v1 ORDER BY a; } } {1 2 4 5 7 8} +do_test view-1.1.100 { + db config enable_view off + catchsql { + SELECT * FROM v1 ORDER BY a; + } +} {1 {access to view "v1" prohibited}} +do_test view-1.1.110 { + db config enable_view on + catchsql { + SELECT * FROM v1 ORDER BY a; + } +} {0 {1 2 4 5 7 8}} do_test view-1.2 { catchsql { ROLLBACK; @@ -724,4 +736,55 @@ do_execsql_test view-26.1 { 1 1 3 3 } +#------------------------------------------------------------------------- +reset_db +do_execsql_test view-27.0 { + CREATE TABLE t0(c0 TEXT, c1); + INSERT INTO t0(c0, c1) VALUES (-1, 0); + CREATE VIEW v0(c0, c1) AS SELECT t0.c0, AVG(t0.c1) FROM t0; +} + +do_execsql_test view-27.1 { + SELECT c0, typeof(c0), c1, typeof(c1) FROM v0; +} { + -1 text + 0.0 real +} + +do_execsql_test view-27.2 { SELECT c0'8James'" {4 2 6 1 5} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James} - - 1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} - - 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%} - - 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%} - - 1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} -} { - set echo_module {} - do_execsql_test 18.$tn.1 $sql $res - do_test 18.$tn.2 { lrange $::echo_module 2 end } $filter +ifcapable !icu { + foreach {tn sql res filter} { + 1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James} + + 1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} + + 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%} + + 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%} + + 1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} + } { + set echo_module {} + do_execsql_test 18.$tn.1 $sql $res + do_test 18.$tn.2 { lrange $::echo_module 2 end } $filter + } } do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON } @@ -1342,7 +1352,7 @@ foreach {tn sql res filter} { do_execsql_test 18.2.x { PRAGMA case_sensitive_like = OFF } #------------------------------------------------------------------------- -# Test that an existing module may not be overridden. +# Test that it is ok to override and existing module. # do_test 19.1 { sqlite3 db2 test.db @@ -1350,7 +1360,7 @@ do_test 19.1 { } SQLITE_OK do_test 19.2 { register_echo_module [sqlite3_connection_pointer db2] -} SQLITE_MISUSE +} SQLITE_OK do_test 19.3 { db2 close } {} diff --git a/test/vtabH.test b/test/vtabH.test index 78b156c..f1a0466 100644 --- a/test/vtabH.test +++ b/test/vtabH.test @@ -30,36 +30,38 @@ do_execsql_test 1.0 { CREATE VIRTUAL TABLE e6 USING echo(t6); } -foreach {tn sql expect} { - 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { - xBestIndex - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} - xFilter - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} - 8ABC 8abd 8abc +ifcapable !icu { + foreach {tn sql expect} { + 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + 8ABC 8abd 8abc + } + + 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + 8abc 8abd 8abc + } + 3 "SELECT * FROM e6 WHERE b LIKE '8e/'" { + xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} + xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/ + } + 4 "SELECT * FROM e6 WHERE b GLOB '8e/'" { + xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} + xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/ + } + } { + do_test 1.$tn { + set echo_module {} + execsql $sql + set ::echo_module + } [list {*}$expect] } - - 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { - xBestIndex - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} - xFilter - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} - 8abc 8abd 8abc - } - 3 "SELECT * FROM e6 WHERE b LIKE '8e/'" { - xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/ - } - 4 "SELECT * FROM e6 WHERE b GLOB '8e/'" { - xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/ - } -} { - do_test 1.$tn { - set echo_module {} - execsql $sql - set ::echo_module - } [list {*}$expect] } diff --git a/test/walvfs.test b/test/walvfs.test index cb8005c..8ffc6f9 100644 --- a/test/walvfs.test +++ b/test/walvfs.test @@ -426,4 +426,3 @@ db close db2 close tvfs delete finish_test - diff --git a/test/wapptest.tcl b/test/wapptest.tcl index 65bf988..201078e 100755 --- a/test/wapptest.tcl +++ b/test/wapptest.tcl @@ -5,10 +5,6 @@ exec wapptclsh "$0" ${1+"$@"} # package required wapp source [file join [file dirname [info script]] wapp.tcl] -# Read the data from the releasetest_data.tcl script. -# -source [file join [file dirname [info script]] releasetest_data.tcl] - # Variables set by the "control" form: # # G(platform) - User selected platform. @@ -69,6 +65,15 @@ proc wapptest_run {} { wapptest_output [string repeat * 70] } +proc releasetest_data {args} { + global G + set rtd [file join $G(srcdir) test releasetest_data.tcl] + set fd [open "|[info nameofexecutable] $rtd $args" r+] + set ret [read $fd] + close $fd + return $ret +} + # Generate the text for the box at the top of the UI. The current SQLite # version, according to fossil, along with a warning if there are # uncommitted changes in the checkout. @@ -108,7 +113,9 @@ proc set_test_array {} { global G if { $G(state)=="config" } { set G(test_array) [list] - foreach {config target} $::Platforms($G(platform)) { + set debug "-debug" + if {$G(debug)==0} { set debug "-nodebug"} + foreach {config target} [releasetest_data tests $debug $G(platform)] { # If using MSVC, do not run sanitize or valgrind tests. Or the # checksymbols test. @@ -136,22 +143,6 @@ proc set_test_array {} { } lappend G(test_array) [dict create config $config target $target] - - set exclude [list checksymbols valgrindtest fuzzoomtest] - if {$G(debug) && !($target in $exclude)} { - set debug_idx [lsearch -glob $::Configs($config) -DSQLITE_DEBUG*] - set xtarget $target - regsub -all {fulltest[a-z]*} $xtarget test xtarget - if {$debug_idx<0} { - lappend G(test_array) [ - dict create config $config-(Debug) target $xtarget - ] - } else { - lappend G(test_array) [ - dict create config $config-(NDebug) target $xtarget - ] - } - } } } } @@ -313,51 +304,33 @@ proc slave_fileevent {name} { } # Return the contents of the "slave script" - the script run by slave -# processes to actually perform the test. It does two things: -# -# 1. Reads and [exec]s the contents of file wapptest_configure.sh. -# 2. Reads and [exec]s the contents of file wapptest_make.sh. -# -# Step 1 is omitted if the test uses MSVC (which does not use configure). +# processes to actually perform the test. All it does is execute the +# test script already written to disk (wapptest_cmd.sh or wapptest_cmd.bat). # proc wapptest_slave_script {} { global G - set res { - proc readfile {filename} { - set fd [open $filename] - set data [read $fd] - close $fd - return $data - } + if {$G(msvc)==0} { + set dir [file join .. $G(srcdir)] + set res [subst -nocommands { + set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ] + exit [set rc] + }] + } else { + set dir [file nativename [file normalize $G(srcdir)]] + set dir [string map [list "\\" "\\\\"] $dir] + set res [subst -nocommands { + set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ] + exit [set rc] + }] } - if {$G(msvc)==0} { - append res { - set cfg [readfile wapptest_configure.sh] - set rc [catch { exec {*}$cfg >& test.log } msg] - if {$rc==0} { - set make [readfile wapptest_make.sh] - set rc [catch { exec {*}$make >>& test.log }] - } - } - } else { - append res { - set make [readfile wapptest_make.sh] - set rc [catch { exec {*}$make >>& test.log }] - } - } - - append res { exit $rc } - set res } # Launch a slave process to run a test. # -proc slave_launch { - name wtcl title dir configOpts testtarget makeOpts cflags opts -} { +proc slave_launch {name target dir} { global G catch { file mkdir $dir } msg @@ -366,28 +339,18 @@ proc slave_launch { } set G(test.$name.dir) $dir - # Write the configure command to wapptest_configure.sh. This file - # is empty if using MSVC - MSVC does not use configure. + # Write the test command to wapptest_cmd.sh|bat. # - set fd1 [open [file join $dir wapptest_configure.sh] w] - if {$G(msvc)==0} { - puts $fd1 "[file join .. $G(srcdir) configure] $wtcl $configOpts" + set ext sh + if {$G(msvc)} { set ext bat } + set fd1 [open [file join $dir wapptest_cmd.$ext] w] + if {$G(msvc)} { + puts $fd1 [releasetest_data script -msvc $name $target] + } else { + puts $fd1 [releasetest_data script $name $target] } close $fd1 - # Write the make command to wapptest_make.sh. Using nmake for MSVC and - # make for all other systems. - # - set makecmd "make" - if {$G(msvc)} { - set nativedir [file nativename $G(srcdir)] - set nativedir [string map [list "\\" "\\\\"] $nativedir] - set makecmd "nmake /f [file join $nativedir Makefile.msc] TOP=$nativedir" - } - set fd2 [open [file join $dir wapptest_make.sh] w] - puts $fd2 "$makecmd $makeOpts $testtarget \"CFLAGS=$cflags\" \"OPTS=$opts\"" - close $fd2 - # Write the wapptest_run.tcl script to the test directory. To run the # commands in the other two files. # @@ -448,30 +411,12 @@ proc do_some_stuff {} { } { set target [dict get $j target] + set dir [string tolower [string map {" " _ "-" _} $name]] set G(test.$name.start) [clock seconds] - set wtcl "" - if {$G(tcl)!=""} { set wtcl "--with-tcl=$G(tcl)" } + set G(test.$name.log) [file join $dir test.log] - # If this configuration is named -(Debug) or -(NDebug), - # then add or remove the SQLITE_DEBUG option from the base - # configuration before running the test. - if {[regexp -- {(.*)-(\(.*\))} $name -> head tail]} { - set opts $::Configs($head) - if {$tail=="(Debug)"} { - append opts " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1" - } else { - regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $opts { } opts - regsub { *-DSQLITE_DEBUG[^ ]* *} $opts { } opts - } - } else { - set opts $::Configs($name) - } + slave_launch $name $target $dir - set L [make_test_suite $G(msvc) $wtcl $name $target $opts] - set G(test.$name.log) [file join [lindex $L 1] test.log] - slave_launch $name $wtcl {*}$L - - set G(test.$name.log) [file join [lindex $L 1] test.log] incr nLaunch -1 } } @@ -517,7 +462,7 @@ proc generate_main_page {{extra {}}} { } # Build the "platform" select widget. - set lOpt [array names ::Platforms] + set lOpt [releasetest_data platforms] generate_select_widget Platform control_platform $lOpt $G(platform) # Build the "test" select widget. @@ -880,13 +825,18 @@ for {set i 0} {$i < [llength $argv]} {incr i} { } } +wapptest_init for {set i 0} {$i < [llength $lTestArg]} {incr i} { - switch -- [lindex $lTestArg $i] { + set opt [lindex $lTestArg $i] + if {[string range $opt 0 1]=="--"} { + set opt [string range $opt 1 end] + } + switch -- $opt { -platform { if {$i==[llength $lTestArg]-1} { wapptest_usage } incr i set arg [lindex $lTestArg $i] - set lPlatform [array names ::Platforms] + set lPlatform [releasetest_data platforms] if {[lsearch $lPlatform $arg]<0} { puts stderr "No such platform: $arg. Platforms are: $lPlatform" exit -1 @@ -937,7 +887,6 @@ for {set i 0} {$i < [llength $lTestArg]} {incr i} { } } -wapptest_init if {$G(noui)==0} { wapp-start $lWappArg } else { diff --git a/test/where.test b/test/where.test index 264866f..26bf3a0 100644 --- a/test/where.test +++ b/test/where.test @@ -1538,5 +1538,37 @@ do_catchsql_test where-25.5 { ON CONFLICT(c) DO UPDATE SET b=NULL } {1 {corrupt database}} -finish_test +# 2019-08-21 Ticket https://www.sqlite.org/src/info/d9f584e936c7a8d0 +# +db close +sqlite3 db :memory: +do_execsql_test where-26.1 { + CREATE TABLE t0(c0 INTEGER PRIMARY KEY, c1 TEXT); + INSERT INTO t0(c0, c1) VALUES (1, 'a'); + CREATE TABLE t1(c0 INT PRIMARY KEY, c1 TEXT); + INSERT INTO t1(c0, c1) VALUES (1, 'a'); + SELECT * FROM t0 WHERE '-1' BETWEEN 0 AND t0.c0; +} {1 a} +do_execsql_test where-26.2 { + SELECT * FROM t1 WHERE '-1' BETWEEN 0 AND t1.c0; +} {1 a} +do_execsql_test where-26.3 { + SELECT * FROM t0 WHERE '-1'>=0 AND '-1'<=t0.c0; +} {1 a} +do_execsql_test where-26.4 { + SELECT * FROM t1 WHERE '-1'>=0 AND '-1'<=t1.c0; +} {1 a} +do_execsql_test where-26.5 { + SELECT '-1' BETWEEN 0 AND t0.c0 FROM t0; +} {1} +do_execsql_test where-26.6 { + SELECT '-1' BETWEEN 0 AND t1.c0 FROM t1; +} {1} +do_execsql_test where-26.7 { + SELECT '-1'>=0 AND '-1'<=t0.c0 FROM t0; +} {1} +do_execsql_test where-26.8 { + SELECT '-1'>=0 AND '-1'<=t1.c0 FROM t1; +} {1} +finish_test diff --git a/test/where9.test b/test/where9.test index 7a019d3..b274609 100644 --- a/test/where9.test +++ b/test/where9.test @@ -787,7 +787,7 @@ do_test where9-6.8.2 { } {1 {no query solution}} set solution_possible 0 -ifcapable stat4||stat3 { +ifcapable stat4 { if {[permutation] != "no_optimization"} { set solution_possible 1 } } if $solution_possible { @@ -860,11 +860,6 @@ do_test where9-7.0 { INSERT INTO t6 SELECT * FROM t5; ANALYZE t5; } - ifcapable stat3 { - sqlite3 db2 test.db - db2 eval { DROP TABLE IF EXISTS sqlite_stat3 } - db2 close - } } {} do_test where9-7.1.1 { count_steps { diff --git a/test/whereG.test b/test/whereG.test index d2e6a4e..595de11 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -266,5 +266,47 @@ do_execsql_test 7.3 { SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2; } {1 3 1 4 9 3 9 4} +# 2019-08-22 +# Ticket https://www.sqlite.org/src/info/7e07a3dbf5a8cd26 +# +do_execsql_test 8.1 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0 (c0); + INSERT INTO t0(c0) VALUES ('a'); + SELECT LIKELY(t0.rowid) <= '0' FROM t0; +} {1} +do_execsql_test 8.2 { + SELECT * FROM t0 WHERE LIKELY(t0.rowid) <= '0'; +} {a} +do_execsql_test 8.3 { + SELECT (t0.rowid) <= '0' FROM t0; +} {0} +do_execsql_test 8.4 { + SELECT * FROM t0 WHERE (t0.rowid) <= '0'; +} {} +do_execsql_test 8.5 { + SELECT unlikely(t0.rowid) <= '0', likelihood(t0.rowid,0.5) <= '0' FROM t0; +} {1 1} +do_execsql_test 8.6 { + SELECT * FROM t0 WHERE unlikely(t0.rowid) <= '0'; +} {a} +do_execsql_test 8.7 { + SELECT * FROM t0 WHERE likelihood(t0.rowid, 0.5) <= '0'; +} {a} +do_execsql_test 8.8 { + SELECT unlikely(t0.rowid <= '0'), + likely(t0.rowid <= '0'), + likelihood(t0.rowid <= '0',0.5) + FROM t0; +} {0 0 0} +do_execsql_test 8.9 { + SELECT * FROM t0 WHERE unlikely(t0.rowid <= '0'); +} {} +do_execsql_test 8.10 { + SELECT * FROM t0 WHERE likelihood(t0.rowid <= '0', 0.5); +} {} + + + finish_test diff --git a/test/wild001.test b/test/wild001.test deleted file mode 100644 index 7fe1404..0000000 --- a/test/wild001.test +++ /dev/null @@ -1,311 +0,0 @@ -# 2013-07-01 -# -# 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 is a test case from content taken "from the wild". In this -# particular instance, the query was provided with permission by -# Elan Feingold on 2013-06-27. His message on the SQLite mailing list -# on that date reads: -# -#------------------------------------------------------------------------------ -# > Can you send (1) the schema (2) the query that is giving problems, and (3) -# > the content of the sqlite_stat1 table after you have run ANALYZE? If you -# > can combine all of the above into a script, that would be great! -# > -# > If you send (1..3) above and you give us written permission to include the -# > query in our test suite, that would be off-the-chain terrific. -# -# Please find items 1..3 in this file: http://www.plexapp.com/elan/sqlite_bug.txt -# -# You have our permission to include the query in your test suite. -# -# Thanks for an amazing product. -#----------------------------------------------------------------------------- -# -# This test case merely creates the schema and populates SQLITE_STAT1 and -# SQLITE_STAT3 then runs an EXPLAIN QUERY PLAN to ensure that the right plan -# is discovered. This test case may need to be adjusted for future revisions -# of the query planner manage to select a better query plan. The query plan -# shown here is known to be very fast with the original data. -# -# This test should work the same with and without SQLITE_ENABLE_STAT3 -# -############################################################################### - -set testdir [file dirname $argv0] -source $testdir/tester.tcl - -ifcapable !stat3 { - finish_test - return -} - -do_execsql_test wild001.01 { - CREATE TABLE "items" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "secid" integer, "parent_id" integer, "metadata_type" integer, "guid" varchar(255), "media_item_count" integer, "title" varchar(255), "title_sort" varchar(255) COLLATE NOCASE, "original_title" varchar(255), "studio" varchar(255), "rating" float, "rating_count" integer, "tagline" varchar(255), "summary" text, "trivia" text, "quotes" text, "content_rating" varchar(255), "content_rating_age" integer, "index" integer, "absolute_index" integer, "duration" integer, "user_thumb_url" varchar(255), "user_art_url" varchar(255), "user_banner_url" varchar(255), "user_music_url" varchar(255), "user_fields" varchar(255), "tags_genre" varchar(255), "tags_collection" varchar(255), "tags_director" varchar(255), "tags_writer" varchar(255), "tags_star" varchar(255), "originally_available_at" datetime, "available_at" datetime, "expires_at" datetime, "refreshed_at" datetime, "year" integer, "added_at" datetime, "created_at" datetime, "updated_at" datetime, "deleted_at" datetime, "tags_country" varchar(255), "extra_data" varchar(255), "hash" varchar(255)); - CREATE INDEX "i_secid" ON "items" ("secid" ); - CREATE INDEX "i_parent_id" ON "items" ("parent_id" ); - CREATE INDEX "i_created_at" ON "items" ("created_at" ); - CREATE INDEX "i_index" ON "items" ("index" ); - CREATE INDEX "i_title" ON "items" ("title" ); - CREATE INDEX "i_title_sort" ON "items" ("title_sort" ); - CREATE INDEX "i_guid" ON "items" ("guid" ); - CREATE INDEX "i_metadata_type" ON "items" ("metadata_type" ); - CREATE INDEX "i_deleted_at" ON "items" ("deleted_at" ); - CREATE INDEX "i_secid_ex1" ON "items" ("secid", "metadata_type", "added_at" ); - CREATE INDEX "i_hash" ON "items" ("hash" ); - CREATE TABLE "settings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "account_id" integer, "guid" varchar(255), "rating" float, "view_offset" integer, "view_count" integer, "last_viewed_at" datetime, "created_at" datetime, "updated_at" datetime); - CREATE INDEX "s_account_id" ON "settings" ("account_id" ); - CREATE INDEX "s_guid" ON "settings" ("guid" ); - ANALYZE; - INSERT INTO sqlite_stat1 VALUES('settings','s_guid','4740 1'); - INSERT INTO sqlite_stat1 VALUES('settings','s_account_id','4740 4740'); - INSERT INTO sqlite_stat1 VALUES('items','i_hash','27316 2'); - INSERT INTO sqlite_stat1 VALUES('items','i_secid_ex1','27316 6829 4553 3'); - INSERT INTO sqlite_stat1 VALUES('items','i_deleted_at','27316 27316'); - INSERT INTO sqlite_stat1 VALUES('items','i_metadata_type','27316 6829'); - INSERT INTO sqlite_stat1 VALUES('items','i_guid','27316 2'); - INSERT INTO sqlite_stat1 VALUES('items','i_title_sort','27316 2'); - INSERT INTO sqlite_stat1 VALUES('items','i_title','27316 2'); - INSERT INTO sqlite_stat1 VALUES('items','i_index','27316 144'); - INSERT INTO sqlite_stat1 VALUES('items','i_created_at','27316 2'); - INSERT INTO sqlite_stat1 VALUES('items','i_parent_id','27316 15'); - INSERT INTO sqlite_stat1 VALUES('items','i_secid','27316 6829'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,150,150,'com.plexapp.agents.thetvdb://153021/2/9?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,198,198,'com.plexapp.agents.thetvdb://194031/1/10?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,526,526,'com.plexapp.agents.thetvdb://71256/12/92?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,923,923,'com.plexapp.agents.thetvdb://71256/15/16?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1008,1008,'com.plexapp.agents.thetvdb://71256/15/93?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1053,1053,'com.plexapp.agents.thetvdb://71256/16/21?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1068,1068,'com.plexapp.agents.thetvdb://71256/16/35?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1235,1235,'com.plexapp.agents.thetvdb://71256/17/44?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1255,1255,'com.plexapp.agents.thetvdb://71256/17/62?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1573,1573,'com.plexapp.agents.thetvdb://71663/20/9?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1580,1580,'com.plexapp.agents.thetvdb://71663/21/16?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2000,2000,'com.plexapp.agents.thetvdb://73141/9/8?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2107,2107,'com.plexapp.agents.thetvdb://73244/6/17?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2256,2256,'com.plexapp.agents.thetvdb://74845/4/7?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2408,2408,'com.plexapp.agents.thetvdb://75978/2/21?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2634,2634,'com.plexapp.agents.thetvdb://79126/1/1?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2962,2962,'com.plexapp.agents.thetvdb://79274/3/94?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3160,3160,'com.plexapp.agents.thetvdb://79274/5/129?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3161,3161,'com.plexapp.agents.thetvdb://79274/5/12?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3688,3688,'com.plexapp.agents.thetvdb://79274/8/62?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3714,3714,'com.plexapp.agents.thetvdb://79274/8/86?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4002,4002,'com.plexapp.agents.thetvdb://79590/13/17?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4215,4215,'com.plexapp.agents.thetvdb://80727/3/6?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4381,4381,'com.plexapp.agents.thetvdb://83462/3/24?lang=en'); - INSERT INTO sqlite_stat3 VALUES('settings','s_account_id',4740,0,0,1); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,1879,1879,'1113f632ccd52ec8b8d7ca3d6d56da4701e48018'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,2721,2721,'1936154b97bb5567163edaebc2806830ae419ccf'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,3035,3035,'1c122331d4b7bfa0dc2c003ab5fb4f7152b9987a'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,3393,3393,'1f81bdbc9acc3321dc592b1a109ca075731b549a'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,6071,6070,'393cf7713efb4519c7a3d1d5403f0d945d15a16a'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,7462,7461,'4677dd37011f8bd9ae7fbbdd3af6dcd8a5b4ab2d'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8435,8434,'4ffa339485334e81a5e12e03a63b6508d76401cf'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8716,8714,'52a093852e6599dd5004857b7ff5b5b82c7cdb25'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,9107,9104,'561183e39f866d97ec728e9ff16ac4ad01466111'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,10942,10939,'66e99b72e29610f49499ae09ee04a376210d1f08'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,12143,12139,'71f0602427e173dc2c551535f73fdb6885fe4302'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,14962,14958,'8ca8e4dfba696019830c19ab8a32c7ece9d8534b'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15179,15174,'8ebf1a5cf33f8ada1fc5853ac06ac4d7e074f825'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15375,15370,'908bc211bebdf21c79d2d2b54ebaa442ac1f5cae'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18215,18210,'ab29e4e18ec5a14fef95aa713d69e31c045a22c1'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18615,18610,'ae84c008cc0c338bf4f28d798a88575746452f6d'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18649,18644,'aec7c901353e115aa5307e94018ba7507bec3a45'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,19517,19512,'b75025fbf2e9c504e3c1197ff1b69250402a31f8'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,21251,21245,'c7d32f0e3a8f3a0a3dbd00833833d2ccee62f0fd'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,23616,23610,'dd5ff61479a9bd4100de802515d9dcf72d46f07a'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24287,24280,'e3db00034301b7555419d4ef6f64769298d5845e'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24949,24942,'ea336abd197ecd7013854a25a4f4eb9dea7927c6'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,25574,25567,'f018ea5182ec3f32768ca1c3cefbf3ad160ec20b'); - INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,26139,26132,'f53709a8d81c12cb0f4f8d58004a25dd063de67c'); - INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',25167,0,0,2); - INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',736,25167,1,3); - INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',15,25903,2,4); - INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',1398,25918,3,5); - INSERT INTO sqlite_stat3 VALUES('items','i_deleted_at',27316,0,0,NULL); - INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',2149,0,0,1); - INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',411,2149,1,2); - INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',1440,2560,2,3); - INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',23316,4000,3,4); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,215,215,'com.plexapp.agents.imdb://tt0065702?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,711,711,'com.plexapp.agents.imdb://tt0198781?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,987,986,'com.plexapp.agents.imdb://tt0454876?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1004,1002,'com.plexapp.agents.imdb://tt0464154?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1056,1053,'com.plexapp.agents.imdb://tt0499549?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1120,1116,'com.plexapp.agents.imdb://tt0903624?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1250,1245,'com.plexapp.agents.imdb://tt1268799?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1270,1264,'com.plexapp.agents.imdb://tt1320261?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1376,1369,'com.plexapp.agents.imdb://tt1772341?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,3035,3027,'com.plexapp.agents.thetvdb://153021/3/14?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6071,6063,'com.plexapp.agents.thetvdb://71173/1/18?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6342,6334,'com.plexapp.agents.thetvdb://71256/13/4?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,9107,9099,'com.plexapp.agents.thetvdb://72389/2/19?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,11740,11732,'com.plexapp.agents.thetvdb://73893/2/13?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,12143,12135,'com.plexapp.agents.thetvdb://73976/4/23?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,15179,15171,'com.plexapp.agents.thetvdb://75897/16/12?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17408,17400,'com.plexapp.agents.thetvdb://76808/2/16?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17984,17976,'com.plexapp.agents.thetvdb://77068/1/16?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,18215,18207,'com.plexapp.agents.thetvdb://77259/1/1?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,21251,21243,'com.plexapp.agents.thetvdb://78957/8/2?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,24287,24279,'com.plexapp.agents.thetvdb://80337/5/8?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25513,25505,'com.plexapp.agents.thetvdb://82226/6?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25548,25540,'com.plexapp.agents.thetvdb://82339/2/10?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,26770,26762,'com.plexapp.agents.thetvdb://86901/1/3?lang=en'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1524,0,0,''); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',2,3034,1391,'Attack of the Giant Squid'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',51,4742,2895,'Brad Sherwood'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',11,4912,2996,'Brian Williams'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',39,5847,3857,'Chip Esten'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,6071,4015,'Chuck Versus the DeLorean'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,7625,5436,'Denny Siegel'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',30,8924,6618,'Episode 1'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',29,9015,6629,'Episode 2'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',32,9082,6643,'Episode 3'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',28,9135,6654,'Episode 4'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',26,9183,6665,'Episode 5'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',27,9229,6677,'Episode 6'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',22,9266,6688,'Episode 7'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',20,9298,6699,'Episode 8'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',55,11750,8817,'Greg Proops'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,12143,9120,'Hardware Jungle'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',33,14712,11435,'Kathy Greenwood'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',3,15179,11840,'Last Call'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,18215,14601,'Nature or Nurture?'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,18241,14623,'Neil DeGrasse Tyson'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',68,19918,16144,'Pilot'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',7,21251,17298,'Reza Aslan'); - INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,24287,20035,'Technoviking'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1524,0,0,''); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,3035,1429,'Anderson Can''t Dance'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',51,4782,2991,'Brad Sherwood'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',11,4936,3079,'Brian Williams'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',39,5694,3783,'Chip Esten'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,6071,4100,'Clive Warren'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',12,7144,5078,'Denny Siegel'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',30,8249,6097,'Episode 1'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',29,8340,6108,'Episode 2'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',32,8407,6122,'Episode 3'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',28,8460,6133,'Episode 4'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',26,8508,6144,'Episode 5'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',27,8554,6156,'Episode 6'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',22,8591,6167,'Episode 7'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',20,8623,6178,'Episode 8'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,9107,6537,'Fat Albert and the Cosby Kids'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',55,10539,7843,'Greg Proops'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,12143,9276,'Iron Age Remains'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',33,13118,10143,'Kathy Greenwood'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,15179,11972,'Mink'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',68,17411,14035,'Pilot'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',2,18214,14727,'Reflections'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',4,21250,17481,'The Apartment'); - INSERT INTO sqlite_stat3 VALUES('items','i_title',1,24287,20283,'The Simpsons Already Did It'); - INSERT INTO sqlite_stat3 VALUES('items','i_index',4315,95,2,1); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1553,4410,3,2); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1485,5963,4,3); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1414,7448,5,4); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1367,8862,6,5); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1328,10229,7,6); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1161,11557,8,7); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1108,12718,9,8); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1033,13826,10,9); - INSERT INTO sqlite_stat3 VALUES('items','i_index',1014,14859,11,10); - INSERT INTO sqlite_stat3 VALUES('items','i_index',929,15873,12,11); - INSERT INTO sqlite_stat3 VALUES('items','i_index',906,16802,13,12); - INSERT INTO sqlite_stat3 VALUES('items','i_index',844,17708,14,13); - INSERT INTO sqlite_stat3 VALUES('items','i_index',690,18552,15,14); - INSERT INTO sqlite_stat3 VALUES('items','i_index',655,19242,16,15); - INSERT INTO sqlite_stat3 VALUES('items','i_index',625,19897,17,16); - INSERT INTO sqlite_stat3 VALUES('items','i_index',579,20522,18,17); - INSERT INTO sqlite_stat3 VALUES('items','i_index',555,21101,19,18); - INSERT INTO sqlite_stat3 VALUES('items','i_index',526,21656,20,19); - INSERT INTO sqlite_stat3 VALUES('items','i_index',501,22182,21,20); - INSERT INTO sqlite_stat3 VALUES('items','i_index',459,22683,22,21); - INSERT INTO sqlite_stat3 VALUES('items','i_index',439,23142,23,22); - INSERT INTO sqlite_stat3 VALUES('items','i_index',315,23581,24,23); - INSERT INTO sqlite_stat3 VALUES('items','i_index',192,24177,26,25); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1851,0,0,NULL); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',373,1857,2,'2011-10-22 14:54:39'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',595,2230,3,'2011-10-22 14:54:41'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',337,2825,4,'2011-10-22 14:54:43'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',361,3378,8,'2011-10-22 14:54:54'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',160,3739,9,'2011-10-22 14:54:56'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',315,4000,11,'2011-10-22 14:54:59'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',321,4334,13,'2011-10-22 14:55:02'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1292,4723,16,'2011-10-22 14:55:06'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,6015,17,'2011-10-22 14:55:07'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,9107,2677,'2012-09-04 18:07:50'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',313,9717,3270,'2012-10-18 16:50:21'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',450,10030,3271,'2012-10-18 16:50:22'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',389,10668,3275,'2012-10-18 16:50:26'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',796,11057,3276,'2012-10-18 16:51:06'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,12041,3280,'2012-10-19 19:52:37'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',135,13281,4186,'2013-02-19 00:56:10'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1063,13416,4187,'2013-02-19 00:56:11'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',797,14479,4188,'2013-02-19 00:56:13'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',147,15276,4189,'2013-02-19 00:56:15'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',346,15423,4190,'2013-02-19 00:56:16'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,18215,6436,'2013-05-05 14:09:54'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',2,21251,8122,'2013-05-24 15:25:45'); - INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,24287,11116,'2013-05-26 14:17:39'); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2560,0,0,NULL); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',18,3022,31,2350); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',10,6068,285,8150); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',158,6346,315,8949); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',34,9094,562,18831); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',20,12139,794,22838); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',134,14033,886,24739); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',159,14167,887,24740); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14326,888,24741); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14487,889,24742); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,14648,890,24743); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',157,14772,891,24744); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',126,15043,894,24747); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',40,15169,895,24748); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15243,898,24753); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',138,15404,899,24754); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',160,15542,900,24755); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15702,901,24756); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15863,902,24757); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,16024,903,24758); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',155,16148,904,24759); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',26,18208,1043,29704); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2,21251,1282,32952); - INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',13,24279,1583,36068); - INSERT INTO sqlite_stat3 VALUES('items','i_secid',25167,0,0,2); - INSERT INTO sqlite_stat3 VALUES('items','i_secid',736,25167,1,3); - INSERT INTO sqlite_stat3 VALUES('items','i_secid',15,25903,2,4); - INSERT INTO sqlite_stat3 VALUES('items','i_secid',1398,25918,3,5); - ANALYZE sqlite_master; - - explain query plan - select items.title - from items - join items as child on child.parent_id=items.id - join items as grandchild on grandchild.parent_id=child.id - join settings - on settings.guid=grandchild.guid - and settings.account_id=1 - where items.metadata_type=2 - and items.secid=2 - and settings.last_viewed_at is not null - group by items.id - order by settings.last_viewed_at desc - limit 10; -} [list \ - 0 0 3 {SEARCH TABLE settings USING INDEX s_account_id (account_id=?)} \ - 0 1 2 {SEARCH TABLE items AS grandchild USING INDEX i_guid (guid=?)} \ - 0 2 1 {SEARCH TABLE items AS child USING INTEGER PRIMARY KEY (rowid=?)} \ - 0 3 0 {SEARCH TABLE items USING INTEGER PRIMARY KEY (rowid=?)} \ - 0 0 0 {USE TEMP B-TREE FOR GROUP BY} \ - 0 0 0 {USE TEMP B-TREE FOR ORDER BY}] - - -finish_test diff --git a/test/window1.test b/test/window1.test index 6815738..7a41e72 100644 --- a/test/window1.test +++ b/test/window1.test @@ -257,6 +257,9 @@ do_catchsql_test 7.1.6 { do_catchsql_test 7.1.7 { SELECT max(x) OVER abc FROM t1 WINDOW def AS (ORDER BY y); } {1 {no such window: abc}} +do_catchsql_test 7.1.8 { + SELECT row_number(x) OVER () FROM t1 +} {1 {wrong number of arguments to function row_number()}} do_execsql_test 7.2 { SELECT @@ -1167,6 +1170,68 @@ do_execsql_test 29.2 { 11 K cc 'xyz' K | } +# 2019-07-18 +# Check-in [7ef7b23cbb1b9ace] (which was itself a fix for ticket +# https://www.sqlite.org/src/info/1be72aab9) introduced a new problem +# if the LHS of a BETWEEN operator is a WINDOW function. The problem +# was found by (the recently enhanced) dbsqlfuzz. +# +do_execsql_test 30.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES('BB','aa',399); + SELECT + count () OVER win1 NOT BETWEEN 'a' AND 'mmm', + count () OVER win3 + FROM t1 + WINDOW win1 AS (ORDER BY a GROUPS BETWEEN 4 PRECEDING AND 1 FOLLOWING + EXCLUDE CURRENT ROW), + win2 AS (PARTITION BY b ORDER BY a), + win3 AS (win2 RANGE BETWEEN 5.2 PRECEDING AND true PRECEDING ); +} {1 1} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 31.1 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(c, d); + CREATE TABLE t3(e, f); + + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1, 1); + INSERT INTO t3 VALUES(1, 1); +} + +do_execsql_test 31.2 { + SELECT d IN (SELECT sum(c) OVER (ORDER BY e+c) FROM t3) FROM ( + SELECT * FROM t2 + ); +} {1} + +do_execsql_test 31.3 { + SELECT d IN (SELECT sum(c) OVER (PARTITION BY d ORDER BY e+c) FROM t3) FROM ( + SELECT * FROM t2 + ); +} {1} + +do_catchsql_test 31.3 { + SELECT d IN ( + SELECT sum(c) OVER ( ROWS BETWEEN d FOLLOWING AND UNBOUNDED FOLLOWING) + FROM t3 + ) + FROM ( + SELECT * FROM t2 + ); +} {1 {frame starting offset must be a non-negative integer}} + +do_catchsql_test 31.3 { + SELECT d IN ( + SELECT sum(c) OVER ( ROWS BETWEEN CURRENT ROW AND c FOLLOWING) + FROM t3 + ) + FROM ( + SELECT * FROM t2 + ); +} {1 {frame ending offset must be a non-negative integer}} + finish_test - - diff --git a/test/window2.tcl b/test/window2.tcl index 093d693..5edc536 100644 --- a/test/window2.tcl +++ b/test/window2.tcl @@ -424,7 +424,29 @@ execsql_float_test 4.9 { WINDOW win AS (ORDER BY 1); } +execsql_test 4.10 { + SELECT count(*) OVER (ORDER BY b) FROM t1 +} +execsql_test 4.11 { + SELECT count(distinct a) FILTER (WHERE b='odd') FROM t1 +} + +========== + +execsql_test 5.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x INTEGER, y INTEGER); + INSERT INTO t1 VALUES(10, 1); + INSERT INTO t1 VALUES(20, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(2, 4); + INSERT INTO t1 VALUES(1, 5); +} + +execsql_float_test 5.1 { + SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z; +} finish_test diff --git a/test/window2.test b/test/window2.test index 4bed0cd..5f028eb 100644 --- a/test/window2.test +++ b/test/window2.test @@ -893,4 +893,41 @@ do_test 4.9 { set {} {} } {} +do_execsql_test 4.10 { + SELECT count(*) OVER (ORDER BY b) FROM t1 +} {3 3 3 6 6 6} + +do_execsql_test 4.11 { + SELECT count(distinct a) FILTER (WHERE b='odd') FROM t1 +} {3} + +#========================================================================== + +do_execsql_test 5.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x INTEGER, y INTEGER); + INSERT INTO t1 VALUES(10, 1); + INSERT INTO t1 VALUES(20, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(2, 4); + INSERT INTO t1 VALUES(1, 5); +} {} + + +do_test 5.1 { + set myres {} + foreach r [db eval {SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;}] { + lappend myres [format %.4f [set r]] + } + set res2 {7.2000 8.7500 10.0000 11.0000 15.0000} + set i 0 + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + incr i + } + set {} {} +} {} + finish_test diff --git a/test/window4.tcl b/test/window4.tcl index a0229db..1b2b2ef 100644 --- a/test/window4.tcl +++ b/test/window4.tcl @@ -385,6 +385,26 @@ execsql_test 11.4 { ) sub; } +execsql_test 12.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER); + INSERT INTO t2 VALUES(1), (2), (3); +} + +execsql_test 12.1 { + SELECT (SELECT min(a) OVER ()) FROM t2 +} + +execsql_float_test 12.2 { + SELECT (SELECT avg(a)) FROM t2 ORDER BY 1 +} + +execsql_float_test 12.3 { + SELECT + (SELECT avg(a) UNION SELECT min(a) OVER ()) + FROM t2 GROUP BY a + ORDER BY 1 +} finish_test diff --git a/test/window4.test b/test/window4.test index 1fb5b5d..6951a23 100644 --- a/test/window4.test +++ b/test/window4.test @@ -1324,4 +1324,51 @@ do_execsql_test 11.4 { ) sub; } {0 1 2} +do_execsql_test 12.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER); + INSERT INTO t2 VALUES(1), (2), (3); +} {} + +do_execsql_test 12.1 { + SELECT (SELECT min(a) OVER ()) FROM t2 +} {1 2 3} + + +do_test 12.2 { + set myres {} + foreach r [db eval {SELECT (SELECT avg(a)) FROM t2 ORDER BY 1}] { + lappend myres [format %.4f [set r]] + } + set res2 {2.0000} + set i 0 + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + incr i + } + set {} {} +} {} + + +do_test 12.3 { + set myres {} + foreach r [db eval {SELECT + (SELECT avg(a) UNION SELECT min(a) OVER ()) + FROM t2 GROUP BY a + ORDER BY 1}] { + lappend myres [format %.4f [set r]] + } + set res2 {1.0000 2.0000 3.0000} + set i 0 + foreach r [set myres] r2 [set res2] { + if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { + error "list element [set i] does not match: got=[set r] expected=[set r2]" + } + incr i + } + set {} {} +} {} + finish_test diff --git a/test/window6.test b/test/window6.test index d732dea..c6889c7 100644 --- a/test/window6.test +++ b/test/window6.test @@ -368,4 +368,3 @@ do_execsql_test 11.4.1 { } finish_test - diff --git a/test/window7.test b/test/window7.test index fd04e23..441e2b1 100644 --- a/test/window7.test +++ b/test/window7.test @@ -41,54 +41,146 @@ do_execsql_test 1.0 { do_execsql_test 1.1 { SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1; -} {0 550 1 460 2 470 3 480 4 490 5 500 6 510 7 520 8 530 9 540} +} {0 550 1 460 2 470 3 480 4 490 5 500 6 510 7 520 8 530 + 9 540} do_execsql_test 1.2 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.3 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.4 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 + 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 + 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 + 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 + 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 + 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 + 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 + 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 + 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 + 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.5 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.6 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 + 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 + 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 + 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 + 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 + 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 + 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 + 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 + 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 + 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.7 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 + 0 1010 0 1010 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 + 1 1480 1 1480 1 1480 1 1480 2 1960 2 1960 2 1960 2 1960 + 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 3 1900 3 1900 + 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 + 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 + 4 1940 4 1940 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 + 5 1980 5 1980 5 1980 5 1980 6 2020 6 2020 6 2020 6 2020 + 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 7 2060 7 2060 + 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.8.1 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 + 0 1010 0 1010 1 930 1 930 1 930 1 930 1 930 1 930 1 930 + 1 930 1 930 1 930 2 950 2 950 2 950 2 950 2 950 2 950 + 2 950 2 950 2 950 2 950 3 970 3 970 3 970 3 970 3 970 + 3 970 3 970 3 970 3 970 3 970 4 990 4 990 4 990 4 990 + 4 990 4 990 4 990 4 990 4 990 4 990 5 1010 5 1010 5 1010 + 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 6 1030 + 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 + 6 1030 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 + 7 1050 7 1050 7 1050 8 1070 8 1070 8 1070 8 1070 8 1070 + 8 1070 8 1070 8 1070 8 1070 8 1070 9 540 9 540 9 540 9 540 + 9 540 9 540 9 540 9 540 9 540 9 540} do_execsql_test 1.8.2 { SELECT a, sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 + 1 1010 1 1010 1 1010 2 930 2 930 2 930 2 930 2 930 2 930 + 2 930 2 930 2 930 2 930 3 950 3 950 3 950 3 950 3 950 + 3 950 3 950 3 950 3 950 3 950 4 970 4 970 4 970 4 970 + 4 970 4 970 4 970 4 970 4 970 4 970 5 990 5 990 5 990 + 5 990 5 990 5 990 5 990 5 990 5 990 5 990 6 1010 6 1010 + 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 + 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 + 7 1030 7 1030 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 + 8 1050 8 1050 8 1050 8 1050 9 1070 9 1070 9 1070 9 1070 + 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070} finish_test diff --git a/test/window8.tcl b/test/window8.tcl index df1fd78..a8333f1 100644 --- a/test/window8.tcl +++ b/test/window8.tcl @@ -197,30 +197,67 @@ execsql_test 4.2.1 { ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } - execsql_test 4.2.2 { + SELECT sum(b) OVER ( + ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.2.3 { SELECT sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.2.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} execsql_test 4.3.1 { SELECT sum(b) OVER ( ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.3.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} execsql_test 4.4.1 { SELECT sum(b) OVER ( ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } - execsql_test 4.4.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.4.3 { SELECT sum(b) OVER ( ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.4.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.5.1 { + SELECT sum(b) OVER ( + ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} +execsql_test 4.5.2 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS FIRST RANGE + BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} ========== @@ -248,6 +285,17 @@ foreach {tn ex} { 6 { ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING } 7 { ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING } + + 8 { RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 9 { ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 10 { PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 11 { ORDER BY a NULLS LAST GROUPS 6 PRECEDING } + 12 { ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING } + 13 { ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING } + 14 { ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING } } { execsql_test 5.$tn.$tn2.1 " SELECT max(c) OVER win, @@ -293,6 +341,84 @@ execsql_test 6.2 { FROM t2 } +========== + +execsql_test 7.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER, b INTEGER); + + INSERT INTO t2 VALUES(1, 65); + INSERT INTO t2 VALUES(2, NULL); + INSERT INTO t2 VALUES(3, NULL); + INSERT INTO t2 VALUES(4, NULL); + INSERT INTO t2 VALUES(5, 66); + INSERT INTO t2 VALUES(6, 67); +} + +foreach {tn f ex} { + 1 sum "" + 2 min "" + 3 sum "EXCLUDE CURRENT ROW" + 4 max "EXCLUDE CURRENT ROW" +} { +execsql_test 7.$tn.1 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +" +execsql_test 7.$tn.2 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.3 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +" +execsql_test 7.$tn.4 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.5 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +" + +execsql_test 7.$tn.6 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.7 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +" +execsql_test 7.$tn.8 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +" +execsql_test 7.$tn.9 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +" +} + + finish_test diff --git a/test/window8.test b/test/window8.test index 829bd0b..ed720eb 100644 --- a/test/window8.test +++ b/test/window8.test @@ -3522,33 +3522,76 @@ do_execsql_test 4.1.2 { do_execsql_test 4.2.1 { SELECT sum(b) OVER ( ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ) FROM t1 ORDER BY 1 NULLS FIRST; } {{} {} 6 6 6} do_execsql_test 4.2.2 { + SELECT sum(b) OVER ( + ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 {} {}} + +do_execsql_test 4.2.3 { SELECT sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ) FROM t1 ORDER BY 1 NULLS FIRST; } {{} {} 6 6 6} +do_execsql_test 4.2.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 {} {}} + do_execsql_test 4.3.1 { SELECT sum(b) OVER ( - ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; } {6 6 6 15 15} +do_execsql_test 4.3.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {9 9 15 15 15} + do_execsql_test 4.4.1 { SELECT sum(b) OVER ( - ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; } {3 6 9 9 12} do_execsql_test 4.4.2 { SELECT sum(b) OVER ( - ORDER BY a DESC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; } {5 6 8 9 10} +do_execsql_test 4.4.3 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; +} {5 6 8 9 10} + +do_execsql_test 4.4.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {5 6 8 9 10} + +do_execsql_test 4.5.1 { + SELECT sum(b) OVER ( + ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {9 9 15 15 15} + +do_execsql_test 4.5.2 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS FIRST RANGE + BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 15 15} + #========================================================================== do_execsql_test 5.0 { @@ -3564,7 +3607,7 @@ do_execsql_test 5.1.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 @@ -3587,7 +3630,7 @@ do_execsql_test 5.1.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 @@ -3609,9 +3652,9 @@ do_execsql_test 5.1.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 979 102 44 979 102 44 @@ -3633,9 +3676,9 @@ do_execsql_test 5.1.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 8400 65 9 8400 65 9 @@ -3659,7 +3702,7 @@ do_execsql_test 5.1.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {777 113 5 777 113 5 777 113 5 777 113 5 777 113 5 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 @@ -3683,7 +3726,7 @@ do_execsql_test 5.1.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 @@ -3703,8 +3746,8 @@ do_execsql_test 5.1.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 21 934 158 21 934 158 21 934 158 21 @@ -3726,8 +3769,8 @@ do_execsql_test 5.1.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 7840 15 3 7840 15 3 7840 15 3 7840 15 3 7840 15 3 7840 15 3 @@ -3750,8 +3793,8 @@ do_execsql_test 5.1.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 160 158 2 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 @@ -3773,8 +3816,8 @@ do_execsql_test 5.1.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 @@ -3795,8 +3838,8 @@ do_execsql_test 5.1.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 158 158 1 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -3818,8 +3861,8 @@ do_execsql_test 5.1.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 @@ -3840,9 +3883,9 @@ do_execsql_test 5.1.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 @@ -3864,9 +3907,335 @@ do_execsql_test 5.1.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 + 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 + 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 + 9745 70 70 9745 71 71 9745 72 72 10504 65 65 10504 66 66 + 10504 67 67 10504 68 68 11215 64 64 11920 63 63 12603 62 62 + 13274 60 60 13274 61 61 13941 59 59 14608 55 55 14608 56 56 + 14608 57 57 14608 58 58 15241 54 54 15870 53 53 16499 52 52 + 17126 49 49 17126 50 50 17126 51 51 17733 44 44 17733 45 45 + 17733 46 46 17733 47 47 17733 48 48 18176 42 42 18176 43 43 + 18597 40 40 18597 41 41 18996 39 39 19395 37 37 19395 38 38 + 19788 36 36 20181 35 35 20536 34 34 20891 30 30 20891 31 31 + 20891 32 32 20891 33 33 21226 28 28 21226 29 29 21535 27 27 + 21830 26 26 22087 22 22 22087 23 23 22087 24 24 22087 25 25 + 22334 21 21 22573 17 17 22573 18 18 22573 19 19 22573 20 20 + 22796 11 11 22796 12 12 22796 13 13 22796 14 14 22796 15 15 + 22796 16 16 22929 10 10 23042 9 9 23155 1 1 23155 2 2 23155 3 3 + 23155 4 4 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.1.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83} + +do_execsql_test 5.1.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.1.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 + 899 113 16 899 113 16 899 113 16 899 113 16 979 102 44 979 102 44 + 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 + 979 102 44 979 102 44 979 102 44 979 102 49 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 56 979 102 56 979 102 56 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 62 979 102 62 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 102 75 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 + 979 113 25 979 113 25 979 113 25 979 113 33 979 113 33 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33} + +do_execsql_test 5.1.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2050 84 11 2050 84 11 2050 84 11 2050 84 11 2050 84 11 2050 84 11 + 4997 75 10 4997 75 10 4997 75 10 4997 75 10 4997 75 10 4997 75 10 + 4997 75 10 4997 75 10 4997 75 10 7337 68 9 7337 68 9 7337 68 9 + 7337 68 9 7337 68 9 7337 68 9 7337 68 9 10450 59 8 10450 59 8 + 10450 59 8 10450 59 8 10450 59 8 10450 59 8 10450 59 8 10450 59 8 + 10450 59 8 11714 51 7 11714 51 7 11714 51 7 11714 51 7 11714 51 7 + 11714 51 7 11714 51 7 11714 51 7 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 14195 35 5 14195 35 5 14195 35 5 14195 35 5 + 14195 35 5 15999 28 4 15999 28 4 15999 28 4 15999 28 4 15999 28 4 + 15999 28 4 15999 28 4 17365 22 3 17365 22 3 17365 22 3 17365 22 3 + 17365 22 3 17365 22 3 20846 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.1.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {777 113 5 777 113 5 777 113 5 777 113 5 777 113 5 805 250 7 + 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 + 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 + 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 + 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 + 840 247 13 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 870 158 0 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 9 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 + 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 938 148 8 + 938 148 8 938 148 8 938 148 8 938 148 8 938 148 8 938 148 8 + 938 148 8 959 224 7 959 224 7 959 224 7 959 224 7 959 224 7 + 959 224 7 959 224 7 979 133 9 979 133 9 979 133 9 979 133 9 + 979 133 9 979 133 9 979 133 9 979 133 9 979 133 9} + +do_execsql_test 5.1.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 + 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 1264 1 1 + 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 + 1366 1 1 1366 1 1 1366 1 1 1366 1 1 1519 1 1 1519 1 1 1519 1 1 + 1519 1 1 1519 1 1 1804 1 1 1804 1 1 1804 1 1 1804 1 1 1804 1 1 + 1804 1 1 1804 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 + 2050 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 + 2309 1 1 2309 1 1 2340 1 1 2340 1 1 2340 1 1 2340 1 1 2340 1 1 + 2340 1 1 2340 1 1 2947 1 1 2947 1 1 2947 1 1 2947 1 1 2947 1 1 + 2947 1 1 2947 1 1 2947 1 1 2947 1 1 3113 1 1 3113 1 1 3113 1 1 + 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1} + +do_execsql_test 5.1.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 21 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 58 959 102 58 959 102 58 959 102 58 + 959 102 58 959 102 58 959 102 58 959 102 58 959 113 39 959 113 39 + 959 113 39 959 113 39 959 113 39 959 158 34 959 158 34 959 158 34 + 959 158 34 959 158 34 959 158 34 959 158 34 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 53 979 102 53 + 979 102 53 979 102 53 979 102 53 979 102 53 979 102 53 979 102 56 + 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 56 979 102 56 979 102 59 979 102 59 979 102 59 979 102 59 + 979 102 59 979 102 59 979 102 59 979 102 59 979 102 59} + +do_execsql_test 5.1.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 + 2309 1 1 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 7156 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 + 8960 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 + 8960 28 4 10479 35 5 10479 35 5 10479 35 5 10479 35 5 10479 35 5 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 12368 68 9 + 12368 68 9 12368 68 9 12368 68 9 12368 68 9 12368 68 9 12368 68 9 + 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12705 51 7 + 12705 51 7 12705 51 7 13509 59 8 13509 59 8 13509 59 8 13509 59 8 + 13509 59 8 13509 59 8 13509 59 8 13509 59 8 13509 59 8 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 13949 75 10 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 14195 84 11 + 14195 84 11 14195 84 11 14195 84 11 14195 84 11 14195 84 11} + +do_execsql_test 5.1.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 160 158 2 + 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 + 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 + 257 252 3 295 295 1 309 309 1 336 330 3 336 330 3 336 330 3 + 346 346 1 355 354 2 355 354 2 355 354 2 399 393 4 399 393 4 + 399 393 4 399 393 4 399 393 4 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 2 480 480 2 574 572 2 574 572 2 607 607 1 + 618 618 2 618 618 2 634 627 4 634 627 4 634 627 4 634 627 4 + 634 629 3 652 652 1 667 660 2 671 667 3 671 667 3 671 667 3 + 671 667 3 683 683 1 711 705 2 716 705 3 716 711 2 730 726 2 + 730 726 2 762 759 2 768 759 4 768 762 3 768 762 3 777 777 1 + 792 786 3 794 786 4 794 786 4 794 790 3 805 805 1 822 822 1 + 845 839 5 845 839 5 845 839 5 845 839 5 845 839 5 870 870 2 + 870 870 2 870 870 2 899 899 1 911 911 1 934 929 2 938 929 4 + 938 934 3 938 934 3 963 959 2 963 959 2 979 979 1} + +do_execsql_test 5.1.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 + {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 + {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 85 72 + {} 85 72 133 4 3 223 10 8 223 11 9 226 2 2 226 2 2 239 12 10 + 239 13 11 239 14 12 247 15 13 257 18 16 257 19 17 295 20 18 + 309 21 19 335 22 20 335 23 21 335 24 22 421 35 30 443 37 32 + 504 16 14 504 17 15 607 42 36 683 56 47 710 26 24 710 27 25 + 710 27 25 711 59 50 759 62 53 759 63 54 777 66 56 805 71 61 + 899 81 68 911 82 69 929 83 70 929 84 71 979 89 75 1334 51 43 + 1416 57 48 1416 58 49 1584 29 26 1584 29 26 1584 31 27 1584 32 28 + 1584 32 28 1891 49 41 1922 87 73 1922 88 74 2005 52 44 2005 52 44 + 2005 54 45 2005 55 46 2518 45 38 2518 46 39 2518 46 39 2518 48 40 + 2523 73 63 2523 73 63 2523 75 64 2523 76 65 2523 77 66} + +do_execsql_test 5.1.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 158 158 1 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 1 355 355 1 393 393 2 393 393 2 + 398 398 1 399 399 1 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 2 480 480 2 572 572 1 574 574 1 607 607 1 + 618 618 2 618 618 2 627 627 1 629 629 1 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 1 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 2 768 768 2 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 2 839 839 2 840 840 1 844 844 1 845 845 1 870 870 2 + 870 870 2 870 870 2 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 2 938 938 2 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.1.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 + {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 + {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 43 37 {} 43 37 {} 49 41 {} 50 42 {} 51 43 {} 54 45 + {} 59 50 {} 60 51 {} 61 52 {} 63 54 {} 64 55 {} 64 55 {} 67 57 + {} 68 58 {} 69 59 {} 70 60 {} 72 62 {} 75 64 {} 76 65 {} 78 67 + {} 78 67 {} 78 67 {} 84 71 {} 85 72 {} 85 72 133 4 3 223 10 8 + 226 2 2 226 2 2 239 14 12 247 15 13 257 19 17 295 20 18 + 309 21 19 335 23 21 421 35 30 443 37 32 607 42 36 627 45 38 + 633 48 40 671 55 46 683 56 47 705 57 48 710 27 25 710 27 25 + 711 58 49 759 62 53 777 66 56 786 29 26 786 29 26 798 32 28 + 798 32 28 805 71 61 845 77 66 899 81 68 911 82 69 929 83 70 + 959 87 73 963 88 74 979 89 75 1258 46 39 1258 46 39 1334 52 44 + 1334 52 44 1678 73 63 1678 73 63} + +do_execsql_test 5.1.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 + 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 + 979 238 72 979 239 71 979 247 70 979 250 69 979 252 68 979 256 67 + 979 257 66 979 295 65 979 309 64 979 330 63 979 335 62 979 336 61 + 979 346 60 979 354 59 979 355 57 979 355 58 979 393 56 979 393 57 + 979 398 55 979 399 53 979 399 54 979 412 53 979 421 52 979 430 51 + 979 443 50 979 480 48 979 480 49 979 572 47 979 574 46 979 607 45 + 979 618 43 979 618 44 979 627 42 979 629 40 979 629 41 979 633 40 + 979 634 39 979 652 38 979 660 37 979 667 35 979 667 36 979 670 35 + 979 671 34 979 683 33 979 705 32 979 711 31 979 716 30 979 726 29 + 979 730 28 979 759 27 979 762 26 979 768 24 979 768 25 979 777 23 + 979 786 22 979 790 21 979 792 20 979 794 19 979 805 18 979 822 17 + 979 839 15 979 839 16 979 840 14 979 844 13 979 845 12 979 870 9 + 979 870 10 979 870 11 979 899 9 979 911 8 979 929 7} + +do_execsql_test 5.1.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 @@ -3891,7 +4260,7 @@ do_execsql_test 5.2.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 @@ -3914,7 +4283,7 @@ do_execsql_test 5.2.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {22176 1 1 22192 1 1 22196 1 1 22226 1 1 22244 1 1 22256 1 1 22310 1 1 22316 1 1 22316 1 1 22350 1 1 22378 1 1 22396 1 1 22444 1 1 22450 1 1 22472 1 1 22484 1 1 22488 1 1 22488 1 1 @@ -3936,9 +4305,9 @@ do_execsql_test 5.2.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {839 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 234 8 963 113 24 979 102 43 @@ -3960,9 +4329,9 @@ do_execsql_test 5.2.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2048 81 11 2108 81 11 2108 81 11 2690 81 11 2834 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 4482 74 10 4616 74 10 4844 74 10 4866 74 10 5287 74 10 5287 74 10 5287 74 10 7421 65 9 7437 65 9 @@ -3986,7 +4355,7 @@ do_execsql_test 5.2.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {667 158 0 671 250 6 759 158 5 768 113 4 777 113 4 777 113 4 777 113 4 777 252 4 792 247 12 805 250 6 805 250 6 805 250 6 805 250 6 805 250 6 805 398 6 822 158 5 822 158 5 822 158 5 @@ -4010,7 +4379,7 @@ do_execsql_test 5.2.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {295 1 1 335 1 1 607 1 1 667 1 1 742 1 1 759 1 1 845 1 1 890 1 1 929 1 1 959 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 @@ -4030,8 +4399,8 @@ do_execsql_test 5.2.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {667 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 355 0 911 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 20 934 158 20 934 158 20 934 158 20 @@ -4053,8 +4422,8 @@ do_execsql_test 5.2.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {1383 1 1 1421 1 1 1651 1 1 1695 1 1 2050 1 1 2050 1 1 3448 7 2 3732 7 2 4050 7 2 4120 7 2 4136 7 2 4359 7 2 4359 7 2 4359 7 2 7129 15 3 7135 15 3 7207 15 3 7441 15 3 7447 15 3 7447 15 3 @@ -4077,8 +4446,8 @@ do_execsql_test 5.2.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 @@ -4100,8 +4469,8 @@ do_execsql_test 5.2.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 {} 34 29 {} 35 30 {} 36 31 {} 37 32 {} 38 33 {} 38 33 {} 40 34 @@ -4122,8 +4491,8 @@ do_execsql_test 5.2.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4144,8 +4513,8 @@ do_execsql_test 5.2.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 {} 23 21 {} 24 22 @@ -4165,9 +4534,9 @@ do_execsql_test 5.2.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 @@ -4189,9 +4558,334 @@ do_execsql_test 5.2.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 + 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 + 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 + 9727 66 66 9745 69 69 9745 70 70 9745 72 72 10504 65 65 + 10504 67 67 10504 68 68 11215 64 64 11844 62 62 11920 63 63 + 13274 60 60 13274 61 61 13897 58 58 13903 57 57 13925 56 56 + 13937 55 55 13941 59 59 15203 53 53 15241 54 54 15832 52 52 + 17100 48 48 17104 46 46 17104 47 47 17106 45 45 17126 49 49 + 17126 50 50 17126 51 51 17569 42 42 17733 44 44 18176 43 43 + 18597 40 40 18597 41 41 18952 37 37 18996 39 39 19395 38 38 + 19760 35 35 19788 36 36 20492 32 32 20492 33 33 20498 30 30 + 20536 34 34 20833 29 29 20871 28 28 20891 31 31 21180 27 27 + 21752 23 23 21830 26 26 22025 21 21 22087 22 22 22087 24 24 + 22087 25 25 22278 20 20 22316 19 19 22549 15 15 22557 14 14 + 22573 17 17 22573 18 18 22706 10 10 22796 11 11 22796 12 12 + 22796 13 13 22796 16 16 23022 4 4 23042 2 2 23042 3 3 23042 9 9 + 23155 1 1 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.2.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 113 82} + +do_execsql_test 5.2.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {22176 1 1 22192 1 1 22196 1 1 22226 1 1 22244 1 1 22256 1 1 + 22310 1 1 22316 1 1 22316 1 1 22350 1 1 22378 1 1 22396 1 1 + 22444 1 1 22450 1 1 22472 1 1 22484 1 1 22488 1 1 22488 1 1 + 22522 1 1 22526 1 1 22526 1 1 22528 1 1 22548 1 1 22712 1 1 + 22734 1 1 22756 1 1 22756 1 1 22762 1 1 22762 1 1 22800 1 1 + 22800 1 1 22820 1 1 22846 1 1 22860 1 1 22898 1 1 22908 1 1 + 22916 1 1 22932 1 1 23022 1 1 23042 1 1 23042 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.2.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {667 158 0 870 113 8 870 158 0 870 158 0 870 158 0 870 158 0 + 870 355 0 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 + 899 113 8 899 113 8 899 113 15 899 113 15 899 113 15 899 113 15 + 899 113 15 899 113 15 899 113 15 899 158 8 963 113 24 979 102 43 + 979 102 43 979 102 43 979 102 43 979 102 43 979 102 43 979 102 43 + 979 102 43 979 102 43 979 102 43 979 102 48 979 102 48 979 102 48 + 979 102 48 979 102 48 979 102 55 979 102 55 979 102 55 979 102 55 + 979 102 55 979 102 55 979 102 55 979 102 61 979 102 61 979 102 61 + 979 102 61 979 102 61 979 102 61 979 102 74 979 102 74 979 102 74 + 979 102 74 979 102 74 979 102 74 979 102 74 979 102 74 979 102 74 + 979 102 74 979 102 74 979 102 74 979 102 74 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 113 24 979 113 24 979 113 24 979 113 24 979 113 24 979 113 24 + 979 113 24 979 113 24 979 113 32 979 113 32 979 113 32 979 113 32 + 979 113 32 979 113 32 979 113 32 979 113 32 979 113 43} + +do_execsql_test 5.2.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {1383 84 11 1421 84 11 1651 84 11 1695 84 11 2050 84 11 2050 84 11 + 4098 75 10 4158 75 10 4158 75 10 4740 75 10 4884 75 10 4997 75 10 + 4997 75 10 4997 75 10 4997 75 10 6532 68 9 6666 68 9 6894 68 9 + 6916 68 9 7337 68 9 7337 68 9 7337 68 9 9471 59 8 9487 59 8 + 9767 59 8 10095 59 8 10317 59 8 10450 59 8 10450 59 8 10450 59 8 + 10450 59 8 10785 51 7 11379 51 7 11714 51 7 11714 51 7 11714 51 7 + 11714 51 7 11714 51 7 11714 51 7 12009 40 6 12381 40 6 12676 40 6 + 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 13418 35 5 13566 35 5 14082 35 5 14195 35 5 + 14195 35 5 15040 28 4 15154 28 4 15999 28 4 15999 28 4 15999 28 4 + 15999 28 4 15999 28 4 16606 22 3 16758 22 3 17365 22 3 17365 22 3 + 17365 22 3 17365 22 3 20135 9 2 20141 9 2 20213 9 2 20447 9 2 + 20453 9 2 20453 9 2 20599 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 22244 1 1 22528 1 1 22846 1 1 + 22916 1 1 22932 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.2.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {667 158 0 671 250 6 759 158 5 768 113 4 777 113 4 777 113 4 + 777 113 4 777 252 4 792 247 12 805 250 6 805 250 6 805 250 6 + 805 250 6 805 250 6 805 398 6 822 158 5 822 158 5 822 158 5 + 822 158 5 822 346 5 839 113 8 840 247 12 840 247 12 840 247 12 + 840 247 12 840 247 12 840 247 12 840 247 12 840 247 12 840 247 12 + 840 247 12 840 247 12 840 393 12 845 224 6 870 102 10 870 158 0 + 870 158 0 870 158 0 870 158 0 870 355 0 899 113 8 899 113 8 + 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 234 8 + 911 223 7 929 148 7 934 223 7 934 223 7 934 223 7 934 223 7 + 934 223 7 934 223 7 934 239 7 938 102 10 938 102 10 938 102 10 + 938 102 10 938 102 10 938 102 10 938 102 10 938 102 10 938 102 10 + 938 148 7 938 148 7 938 148 7 938 148 7 938 148 7 938 148 7 + 938 160 7 938 208 10 959 224 6 959 224 6 959 224 6 959 224 6 + 959 224 6 959 238 6 963 133 8 979 133 8 979 133 8 979 133 8 + 979 133 8 979 133 8 979 133 8 979 133 8 979 330 8} + +do_execsql_test 5.2.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {295 1 1 335 1 1 607 1 1 667 1 1 742 1 1 759 1 1 845 1 1 + 890 1 1 929 1 1 959 1 1 962 1 1 962 1 1 962 1 1 962 1 1 + 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 + 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 1366 1 1 + 1366 1 1 1383 1 1 1398 1 1 1406 1 1 1421 1 1 1519 1 1 1519 1 1 + 1535 1 1 1651 1 1 1669 1 1 1682 1 1 1695 1 1 1804 1 1 1804 1 1 + 1804 1 1 1804 1 1 1804 1 1 1897 1 1 1919 1 1 2000 1 1 2048 1 1 + 2050 1 1 2050 1 1 2070 1 1 2086 1 1 2108 1 1 2108 1 1 2134 1 1 + 2150 1 1 2309 1 1 2309 1 1 2309 1 1 2340 1 1 2340 1 1 2340 1 1 + 2430 1 1 2690 1 1 2758 1 1 2770 1 1 2776 1 1 2834 1 1 2848 1 1 + 2947 1 1 2947 1 1 2947 1 1 2947 1 1 2980 1 1 3082 1 1 3088 1 1 + 3088 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3234 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1} + +do_execsql_test 5.2.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {911 223 7 934 158 26 934 158 26 934 158 26 934 158 26 934 158 26 + 934 158 33 934 223 7 934 223 7 934 223 7 934 223 7 934 223 7 + 934 223 7 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 + 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 + 934 223 20 934 223 20 934 223 26 934 239 7 959 102 49 959 102 49 + 959 102 49 959 102 49 959 102 49 959 102 49 959 102 49 959 102 49 + 959 102 49 959 102 49 959 102 57 959 102 57 959 102 57 959 102 57 + 959 102 57 959 102 57 959 102 57 959 102 57 959 113 38 959 113 38 + 959 113 38 959 113 38 959 113 49 959 158 33 959 158 33 959 158 33 + 959 158 33 959 158 33 959 158 33 959 158 38 963 102 58 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 979 102 52 + 979 102 52 979 102 52 979 102 52 979 102 52 979 102 52 979 102 52 + 979 102 55 979 102 55 979 102 55 979 102 55 979 102 55 979 102 55 + 979 102 55 979 102 55 979 102 55 979 102 58 979 102 58 979 102 58 + 979 102 58 979 102 58 979 102 58 979 102 58 979 102 58} + +do_execsql_test 5.2.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {1398 1 1 1682 1 1 2000 1 1 2070 1 1 2086 1 1 2309 1 1 2309 1 1 + 2309 1 1 5079 9 2 5085 9 2 5157 9 2 5391 9 2 5397 9 2 5397 9 2 + 5543 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 6397 22 3 6549 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 + 8001 28 4 8115 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 + 8960 28 4 9702 35 5 9850 35 5 10366 35 5 10479 35 5 10479 35 5 + 10774 40 6 11146 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11563 68 9 + 11697 68 9 11776 51 7 11925 68 9 11947 68 9 12368 68 9 12368 68 9 + 12368 68 9 12370 51 7 12530 59 8 12546 59 8 12705 51 7 12705 51 7 + 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12826 59 8 + 13050 75 10 13110 75 10 13110 75 10 13154 59 8 13376 59 8 + 13509 59 8 13509 59 8 13509 59 8 13509 59 8 13528 84 11 + 13566 84 11 13692 75 10 13796 84 11 13836 75 10 13840 84 11 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 14195 84 11 + 14195 84 11} + +do_execsql_test 5.2.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 + 113 113 1 158 158 1 160 158 1 160 158 2 223 223 1 224 224 1 + 238 234 2 239 234 2 239 238 2 252 250 2 256 252 2 257 247 4 + 257 247 4 257 250 3 335 330 2 336 330 2 336 335 2 355 354 1 + 355 354 2 355 355 1 399 393 3 399 393 3 399 393 3 399 393 3 + 399 393 4 480 480 1 480 480 1 572 572 1 574 574 1 618 618 1 + 618 618 1 633 629 2 634 627 3 634 627 3 634 627 4 634 629 3 + 667 667 1 670 667 2 671 667 2 671 667 2 671 667 3 711 711 1 + 711 711 1 716 705 2 726 726 1 730 730 1 762 762 1 768 759 3 + 768 762 2 768 762 2 792 790 2 792 790 2 794 786 3 794 786 3 + 844 839 4 845 839 4 845 839 4 845 839 4 845 839 4 870 870 1 + 870 870 1 870 870 2 934 934 1 938 929 3 938 934 2 938 934 2 + 959 959 1 963 963 1} + +do_execsql_test 5.2.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 + {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 + {} 34 29 {} 35 30 {} 36 31 {} 37 32 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 42 36 {} 43 37 {} 43 37 {} 50 42 {} 56 47 {} 60 51 + {} 61 52 {} 62 53 {} 64 55 {} 64 55 {} 66 56 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 71 61 {} 72 62 {} 78 67 {} 78 67 {} 78 67 + {} 81 68 {} 82 69 {} 83 70 {} 85 72 {} 85 72 {} 89 75 113 2 2 + 113 2 2 223 11 9 239 12 10 239 13 11 257 18 16 335 22 20 + 335 24 22 355 27 25 355 27 25 504 16 14 504 17 15 705 58 49 + 710 26 24 711 57 48 711 59 50 759 63 54 929 84 71 959 88 74 + 963 87 73 1185 32 28 1185 32 28 1191 29 26 1191 29 26 1334 51 43 + 1334 55 46 1338 52 44 1338 52 44 1584 31 27 1678 77 66 1684 73 63 + 1684 73 63 1885 48 40 1889 46 39 1889 46 39 1891 45 38 1891 49 41 + 2005 54 45 2523 75 64 2523 76 65} + +do_execsql_test 5.2.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 + 113 113 1 158 158 0 158 158 1 355 355 0 355 355 1 393 393 1 + 393 393 1 399 399 0 399 399 1 480 480 1 480 480 1 618 618 1 + 618 618 1 629 629 0 629 629 1 667 667 0 667 667 1 768 768 1 + 768 768 1 839 839 1 839 839 1 870 870 1 870 870 1 870 870 2 + 938 938 1 938 938 1} + +do_execsql_test 5.2.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 + {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 + {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 {} 23 21 {} 24 22 + {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 35 30 {} 36 31 {} 37 32 + {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 {} 43 37 + {} 45 38 {} 48 40 {} 49 41 {} 50 42 {} 51 43 {} 54 45 {} 55 46 + {} 56 47 {} 57 48 {} 58 49 {} 59 50 {} 60 51 {} 61 52 {} 62 53 + {} 63 54 {} 64 55 {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 + {} 70 60 {} 71 61 {} 72 62 {} 75 64 {} 76 65 {} 77 66 {} 78 67 + {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 {} 84 71 {} 85 72 + {} 85 72 {} 87 73 {} 88 74 {} 89 75 113 2 2 113 2 2 355 27 25 + 355 27 25 393 29 26 393 29 26 399 32 28 399 32 28 629 46 39 + 629 46 39 667 52 44 667 52 44 839 73 63 839 73 63} + +do_execsql_test 5.2.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 + 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 + 979 234 72 979 238 71 979 239 70 979 247 69 979 250 68 979 252 67 + 979 256 66 979 257 65 979 295 64 979 309 63 979 330 63 979 335 61 + 979 336 60 979 346 59 979 354 58 979 355 56 979 355 58 979 393 55 + 979 393 56 979 398 54 979 399 52 979 399 53 979 412 52 979 421 51 + 979 430 50 979 443 49 979 480 47 979 480 48 979 572 46 979 574 46 + 979 607 44 979 618 42 979 618 43 979 627 41 979 629 40 979 629 40 + 979 633 39 979 634 38 979 652 37 979 660 36 979 667 34 979 667 35 + 979 670 34 979 671 33 979 683 32 979 705 31 979 711 30 979 716 29 + 979 726 28 979 730 27 979 759 26 979 762 25 979 768 23 979 768 24 + 979 777 22 979 786 21 979 790 20 979 792 19 979 794 18 979 805 17 + 979 822 16 979 839 15 979 839 15 979 840 13 979 844 12 979 845 11 + 979 870 8 979 870 9 979 870 10 979 899 8 979 911 7} + +do_execsql_test 5.2.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 @@ -4216,7 +4910,7 @@ do_execsql_test 5.3.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4237,7 +4931,7 @@ do_execsql_test 5.3.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4256,9 +4950,9 @@ do_execsql_test 5.3.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 @@ -4280,9 +4974,9 @@ do_execsql_test 5.3.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 5287 65 9 5287 65 9 5287 65 9 @@ -4306,7 +5000,7 @@ do_execsql_test 5.3.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4328,7 +5022,7 @@ do_execsql_test 5.3.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4347,8 +5041,8 @@ do_execsql_test 5.3.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 @@ -4370,8 +5064,8 @@ do_execsql_test 5.3.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 @@ -4393,8 +5087,8 @@ do_execsql_test 5.3.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4416,8 +5110,8 @@ do_execsql_test 5.3.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 {} 27 25 {} 27 25 {} 34 29 {} 35 30 {} 36 31 @@ -4438,8 +5132,8 @@ do_execsql_test 5.3.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4459,8 +5153,8 @@ do_execsql_test 5.3.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 @@ -4480,9 +5174,9 @@ do_execsql_test 5.3.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 @@ -4504,9 +5198,324 @@ do_execsql_test 5.3.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 + 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 + 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 + 9727 66 66 9745 69 69 9745 70 70 9745 72 72 10504 65 65 + 10504 67 67 10504 68 68 11215 64 64 11844 62 62 11920 63 63 + 13274 60 60 13274 61 61 13897 58 58 13903 57 57 13925 56 56 + 13937 55 55 13941 59 59 15203 53 53 15241 54 54 15832 52 52 + 17100 48 48 17104 46 46 17104 47 47 17106 45 45 17126 49 49 + 17126 50 50 17126 51 51 17569 42 42 17733 44 44 18176 43 43 + 18597 40 40 18597 41 41 18952 37 37 18996 39 39 19395 38 38 + 19760 35 35 19788 36 36 20492 32 32 20492 33 33 20498 30 30 + 20536 34 34 20833 29 29 20871 28 28 20891 31 31 21180 27 27 + 21752 23 23 21830 26 26 22025 21 21 22087 22 22 22087 24 24 + 22087 25 25 22278 20 20 22316 19 19 22549 15 15 22557 14 14 + 22573 17 17 22573 18 18 22706 10 10 22796 11 11 22796 12 12 + 22796 13 13 22796 16 16 23022 4 4 23042 2 2 23042 3 3 23042 9 9 + 23155 1 1 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.3.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1} + +do_execsql_test 5.3.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 870 158 0 + 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 870 158 0 870 158 0 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 + 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 + 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 + 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 113 25 979 113 25 979 113 25 + 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33} + +do_execsql_test 5.3.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 84 11 {} 84 11 {} 84 11 {} 84 11 {} 84 11 {} 84 11 + 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2050 75 10 + 2050 75 10 2050 75 10 2050 75 10 4997 68 9 4997 68 9 4997 68 9 + 4997 68 9 4997 68 9 4997 68 9 4997 68 9 7337 59 8 7337 59 8 + 7337 59 8 7337 59 8 7337 59 8 7337 59 8 7337 59 8 7337 59 8 + 7337 59 8 10450 51 7 10450 51 7 10450 51 7 10450 51 7 10450 51 7 + 10450 51 7 10450 51 7 10450 51 7 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 12676 35 5 12676 35 5 12676 35 5 12676 35 5 + 12676 35 5 14195 28 4 14195 28 4 14195 28 4 14195 28 4 14195 28 4 + 14195 28 4 14195 28 4 15999 22 3 15999 22 3 15999 22 3 15999 22 3 + 15999 22 3 15999 22 3 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17365 9 2 20846 1 1 20846 1 1 20846 1 1 + 20846 1 1 20846 1 1 20846 1 1 20846 1 1 20846 1 1} + +do_execsql_test 5.3.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1} + +do_execsql_test 5.3.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 + 934 158 27 934 158 27 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 113 39 959 113 39 959 113 39 959 113 39 + 959 113 39 959 113 39 959 113 39 959 113 39 959 113 39 959 113 39 + 959 113 39 959 158 34 959 158 34 959 158 34 959 158 34 959 158 34 + 979 102 46 979 102 46 979 102 46 979 102 46 979 102 46 979 102 46 + 979 102 46 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 + 979 102 47 979 102 47 979 102 47 979 102 47 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49} + +do_execsql_test 5.3.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 5790 22 3 + 5790 22 3 5790 22 3 5790 22 3 5790 22 3 5790 22 3 7156 28 4 + 7156 28 4 7156 28 4 7156 28 4 7156 28 4 7156 28 4 7156 28 4 + 8960 35 5 8960 35 5 8960 35 5 8960 35 5 8960 35 5 10028 68 9 + 10028 68 9 10028 68 9 10028 68 9 10028 68 9 10028 68 9 10028 68 9 + 10396 59 8 10396 59 8 10396 59 8 10396 59 8 10396 59 8 10396 59 8 + 10396 59 8 10396 59 8 10396 59 8 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 11002 75 10 11002 75 10 11002 75 10 + 11002 75 10 11002 75 10 11002 75 10 11002 75 10 11002 75 10 + 11002 75 10 11441 51 7 11441 51 7 11441 51 7 11441 51 7 + 11441 51 7 11441 51 7 11441 51 7 11441 51 7 12145 84 11 + 12145 84 11 12145 84 11 12145 84 11 12145 84 11 12145 84 11} + +do_execsql_test 5.3.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 158 158 1 160 160 1 160 160 1 223 223 1 224 224 1 + 238 234 2 239 234 2 239 238 2 252 250 2 256 252 2 257 247 4 + 257 247 4 257 250 3 335 330 2 336 330 2 336 335 2 354 354 1 + 354 354 1 355 355 1 398 393 3 398 393 3 399 393 3 399 398 2 + 399 398 2 572 572 1 574 574 1 633 629 2 634 627 3 634 627 3 + 634 627 3 634 629 3 667 667 1 670 667 2 671 667 2 671 670 2 + 671 670 2 711 711 1 711 711 1 716 705 2 726 726 1 730 730 1 + 762 762 1 762 762 1 762 762 1 768 759 3 792 790 2 792 790 2 + 794 786 3 794 786 3 844 839 4 845 839 4 845 839 4 845 840 3 + 845 840 3 934 934 1 934 934 1 934 934 1 938 929 3 959 959 1 + 963 963 1} + +do_execsql_test 5.3.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 + {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 + {} 23 21 {} 25 23 {} 27 25 {} 27 25 {} 34 29 {} 35 30 {} 36 31 + {} 37 32 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 + {} 43 37 {} 50 42 {} 56 47 {} 60 51 {} 61 52 {} 62 53 {} 64 55 + {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 {} 70 60 {} 71 61 + {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 + {} 85 72 {} 85 72 {} 89 75 223 11 9 239 12 10 239 13 11 + 257 18 16 335 22 20 335 24 22 504 16 14 504 17 15 671 52 44 + 671 52 44 705 58 49 710 26 24 711 57 48 711 59 50 759 63 54 + 786 32 28 786 32 28 798 29 26 798 29 26 845 73 63 845 73 63 + 929 84 71 959 88 74 963 87 73 1260 46 39 1260 46 39 1334 51 43 + 1334 55 46 1584 31 27 1678 77 66 1885 48 40 1891 45 38 1891 49 41 + 2005 54 45 2523 75 64 2523 76 65} + +do_execsql_test 5.3.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 + {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 + {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 + {} 23 21 {} 24 22 {} 25 23 {} 26 24 {} 27 25 {} 27 25 {} 29 26 + {} 29 26 {} 31 27 {} 32 28 {} 32 28 {} 34 29 {} 35 30 {} 36 31 + {} 37 32 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 + {} 43 37 {} 45 38 {} 46 39 {} 46 39 {} 48 40 {} 49 41 {} 50 42 + {} 51 43 {} 52 44 {} 52 44 {} 54 45 {} 55 46 {} 56 47 {} 57 48 + {} 58 49 {} 59 50 {} 60 51 {} 61 52 {} 62 53 {} 63 54 {} 64 55 + {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 {} 70 60 {} 71 61 + {} 72 62 {} 73 63 {} 73 63 {} 75 64 {} 76 65 {} 77 66 {} 78 67 + {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 {} 84 71 {} 85 72 + {} 85 72 {} 87 73 {} 88 74 {} 89 75} + +do_execsql_test 5.3.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 + 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 + 979 234 72 979 238 71 979 239 70 979 247 69 979 250 68 979 252 67 + 979 256 66 979 257 65 979 295 64 979 309 63 979 330 63 979 335 61 + 979 336 60 979 346 59 979 354 58 979 355 56 979 355 58 979 393 55 + 979 393 56 979 398 54 979 399 52 979 399 53 979 412 52 979 421 51 + 979 430 50 979 443 49 979 480 47 979 480 48 979 572 46 979 574 46 + 979 607 44 979 618 42 979 618 43 979 627 41 979 629 40 979 629 40 + 979 633 39 979 634 38 979 652 37 979 660 36 979 667 34 979 667 35 + 979 670 34 979 671 33 979 683 32 979 705 31 979 711 30 979 716 29 + 979 726 28 979 730 27 979 759 26 979 762 25 979 768 23 979 768 24 + 979 777 22 979 786 21 979 790 20 979 792 19 979 794 18 979 805 17 + 979 822 16 979 839 15 979 839 15 979 840 13 979 844 12 979 845 11 + 979 870 8 979 870 9 979 870 10 979 899 8 979 911 7} + +do_execsql_test 5.3.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 @@ -4531,7 +5540,7 @@ do_execsql_test 5.4.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4554,7 +5563,7 @@ do_execsql_test 5.4.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4573,9 +5582,9 @@ do_execsql_test 5.4.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {113 113 1 234 234 1 257 257 1 336 336 1 354 354 1 768 768 1 839 839 1 839 839 1 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 17 899 113 17 899 113 17 @@ -4597,9 +5606,9 @@ do_execsql_test 5.4.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 81 11 {} 81 11 {} 81 11 {} 81 11 113 81 11 257 81 11 839 81 11 839 81 11 899 81 11 2947 74 10 2947 74 10 2947 74 10 3368 74 10 3390 74 10 3618 74 10 3752 74 10 5287 65 9 5287 65 9 @@ -4623,7 +5632,7 @@ do_execsql_test 5.4.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4647,7 +5656,7 @@ do_execsql_test 5.4.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4666,8 +5675,8 @@ do_execsql_test 5.4.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {158 158 0 355 355 0 399 399 0 629 629 0 667 667 0 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 870 0 911 158 1 934 158 1 934 158 9 934 158 9 934 158 9 934 158 9 @@ -4689,8 +5698,8 @@ do_execsql_test 5.4.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 355 1 1 399 1 1 629 1 1 667 1 1 2050 7 2 2050 7 2 2050 7 2 2273 7 2 2289 7 2 2359 7 2 2677 7 2 2961 7 2 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 @@ -4713,8 +5722,8 @@ do_execsql_test 5.4.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 160 158 1 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 @@ -4736,8 +5745,8 @@ do_execsql_test 5.4.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 @@ -4758,8 +5767,8 @@ do_execsql_test 5.4.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4781,8 +5790,8 @@ do_execsql_test 5.4.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 @@ -4803,9 +5812,9 @@ do_execsql_test 5.4.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 @@ -4827,9 +5836,331 @@ do_execsql_test 5.4.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 + 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 + 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 + 9745 70 70 9745 71 71 9745 72 72 10504 65 65 10504 66 66 + 10504 67 67 10504 68 68 11215 64 64 11920 63 63 12603 62 62 + 13274 60 60 13274 61 61 13941 59 59 14608 55 55 14608 56 56 + 14608 57 57 14608 58 58 15241 54 54 15870 53 53 16499 52 52 + 17126 49 49 17126 50 50 17126 51 51 17733 44 44 17733 45 45 + 17733 46 46 17733 47 47 17733 48 48 18176 42 42 18176 43 43 + 18597 40 40 18597 41 41 18996 39 39 19395 37 37 19395 38 38 + 19788 36 36 20181 35 35 20536 34 34 20891 30 30 20891 31 31 + 20891 32 32 20891 33 33 21226 28 28 21226 29 29 21535 27 27 + 21830 26 26 22087 22 22 22087 23 23 22087 24 24 22087 25 25 + 22334 21 21 22573 17 17 22573 18 18 22573 19 19 22573 20 20 + 22796 11 11 22796 12 12 22796 13 13 22796 14 14 22796 15 15 + 22796 16 16 22929 10 10 23042 9 9 23155 1 1 23155 2 2 23155 3 3 + 23155 4 4 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.4.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 113 1 1 113 1 1 133 1 1 223 1 1 239 1 1 247 1 1 257 1 1 + 295 1 1 309 1 1 335 1 1 355 1 1 355 1 1 393 1 1 393 1 1 + 399 1 1 399 1 1 421 1 1 443 1 1 607 1 1 627 1 1 629 1 1 + 629 1 1 633 1 1 667 1 1 667 1 1 671 1 1 683 1 1 705 1 1 + 711 1 1 759 1 1 777 1 1 805 1 1 839 1 1 839 1 1 845 1 1 + 899 1 1 911 1 1 929 1 1 959 1 1 963 1 1 979 1 1} + +do_execsql_test 5.4.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {158 158 0 355 355 0 399 399 0 629 629 0 667 667 0 870 113 1 + 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 + 870 158 1 870 870 0 899 113 10 899 113 10 899 113 10 899 113 10 + 899 113 10 899 113 10 899 113 10 899 113 17 899 113 17 899 113 17 + 899 113 17 899 113 17 899 113 17 899 113 17 899 158 1 963 113 17 + 979 102 34 979 102 45 979 102 45 979 102 45 979 102 45 979 102 45 + 979 102 50 979 102 50 979 102 50 979 102 50 979 102 50 979 102 50 + 979 102 50 979 102 57 979 102 57 979 102 57 979 102 57 979 102 57 + 979 102 57 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 + 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 + 979 102 63 979 102 63 979 102 76 979 102 76 979 102 76 979 102 76 + 979 102 76 979 102 76 979 102 76 979 102 76 979 113 17 979 113 26 + 979 113 26 979 113 26 979 113 26 979 113 26 979 113 26 979 113 26 + 979 113 26 979 113 34 979 113 34 979 113 34 979 113 34 979 113 34 + 979 113 34 979 113 34 979 113 34 979 113 34 979 113 34} + +do_execsql_test 5.4.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 84 11 {} 84 11 355 84 11 399 84 11 629 84 11 667 84 11 + 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2163 75 10 2307 75 10 + 2889 75 10 2889 75 10 2949 75 10 4997 68 9 4997 68 9 4997 68 9 + 5418 68 9 5440 68 9 5668 68 9 5802 68 9 7337 59 8 7337 59 8 + 7337 59 8 7337 59 8 7470 59 8 7692 59 8 8020 59 8 8300 59 8 + 8316 59 8 10450 51 7 10450 51 7 10450 51 7 10450 51 7 10450 51 7 + 10450 51 7 10785 51 7 11379 51 7 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 + 12009 40 6 12381 40 6 12676 35 5 12676 35 5 12789 35 5 13305 35 5 + 13453 35 5 14195 28 4 14195 28 4 14195 28 4 14195 28 4 14195 28 4 + 15040 28 4 15154 28 4 15999 22 3 15999 22 3 15999 22 3 15999 22 3 + 16606 22 3 16758 22 3 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17612 9 2 17758 9 2 17758 9 2 17764 9 2 + 17998 9 2 18070 9 2 18076 9 2 20846 1 1 20846 1 1 20846 1 1 + 21069 1 1 21085 1 1 21155 1 1 21473 1 1 21757 1 1} + +do_execsql_test 5.4.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 113 1 1 113 1 1 133 1 1 223 1 1 239 1 1 247 1 1 257 1 1 + 295 1 1 309 1 1 335 1 1 355 1 1 355 1 1 393 1 1 393 1 1 + 399 1 1 399 1 1 421 1 1 443 1 1 607 1 1 627 1 1 629 1 1 + 629 1 1 633 1 1 667 1 1 667 1 1 671 1 1 683 1 1 705 1 1 + 711 1 1 759 1 1 777 1 1 805 1 1 839 1 1 839 1 1 845 1 1 + 899 1 1 911 1 1 929 1 1 959 1 1 963 1 1 979 1 1} + +do_execsql_test 5.4.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {223 223 1 239 239 1 309 309 1 572 572 1 627 627 1 870 870 1 + 911 911 1 934 158 22 934 158 28 934 158 28 934 158 28 934 158 28 + 934 158 28 934 158 28 934 223 9 934 223 9 934 223 9 934 223 9 + 934 223 9 934 223 9 934 223 9 934 223 9 934 223 9 934 223 9 + 934 223 9 934 223 9 934 223 9 934 223 22 934 223 22 934 223 22 + 934 223 22 934 223 22 934 934 1 959 102 40 959 102 51 959 102 51 + 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 + 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 + 959 102 51 959 113 35 959 113 40 959 113 40 959 113 40 959 113 40 + 959 113 40 959 113 40 959 113 40 959 113 40 959 113 40 959 113 40 + 959 158 28 959 158 35 959 158 35 959 158 35 959 158 35 963 102 51 + 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 + 979 102 47 979 102 48 979 102 48 979 102 48 979 102 48 979 102 48 + 979 102 48 979 102 48 979 102 48 979 102 48 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 51} + +do_execsql_test 5.4.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 223 1 1 239 1 1 309 1 1 627 1 1 911 1 1 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2556 9 2 + 2702 9 2 2702 9 2 2708 9 2 2942 9 2 3014 9 2 3020 9 2 5790 22 3 + 5790 22 3 5790 22 3 5790 22 3 6397 22 3 6549 22 3 7156 28 4 + 7156 28 4 7156 28 4 7156 28 4 7156 28 4 8001 28 4 8115 28 4 + 8960 35 5 8960 35 5 9073 35 5 9589 35 5 9737 35 5 10028 68 9 + 10028 68 9 10028 68 9 10396 59 8 10396 59 8 10396 59 8 10396 59 8 + 10449 68 9 10471 68 9 10479 40 6 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10529 59 8 + 10699 68 9 10751 59 8 10774 40 6 10833 68 9 11002 75 10 + 11002 75 10 11002 75 10 11002 75 10 11079 59 8 11115 75 10 + 11146 40 6 11259 75 10 11359 59 8 11375 59 8 11441 51 7 + 11441 51 7 11441 51 7 11441 51 7 11441 51 7 11441 51 7 11776 51 7 + 11841 75 10 11841 75 10 11901 75 10 12145 84 11 12145 84 11 + 12370 51 7 12500 84 11 12544 84 11 12774 84 11 12812 84 11} + +do_execsql_test 5.4.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 160 158 1 + 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 + 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 + 257 252 3 295 295 1 309 309 1 336 330 3 336 330 3 336 330 3 + 346 346 1 355 354 1 355 354 2 355 354 2 399 393 3 399 393 3 + 399 393 3 399 393 4 399 393 4 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 574 572 2 574 572 2 607 607 1 + 618 618 1 618 618 1 634 627 3 634 627 4 634 627 4 634 627 4 + 634 629 3 652 652 1 667 660 2 671 667 2 671 667 3 671 667 3 + 671 667 3 683 683 1 711 705 2 716 705 3 716 711 2 730 726 2 + 730 726 2 762 759 2 768 759 4 768 762 2 768 762 2 777 777 1 + 792 786 3 794 786 4 794 786 4 794 790 3 805 805 1 822 822 1 + 845 839 4 845 839 4 845 839 5 845 839 5 845 839 5 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 934 929 2 938 929 4 + 938 934 2 938 934 2 963 959 2 963 959 2 979 979 1} + +do_execsql_test 5.4.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 + {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 + {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 85 72 + {} 85 72 113 2 2 113 2 2 133 4 3 223 10 8 223 11 9 239 12 10 + 239 13 11 239 14 12 247 15 13 257 18 16 257 19 17 295 20 18 + 309 21 19 335 22 20 335 23 21 335 24 22 355 27 25 355 27 25 + 421 35 30 443 37 32 504 16 14 504 17 15 607 42 36 683 56 47 + 710 26 24 711 59 50 759 62 53 759 63 54 777 66 56 805 71 61 + 899 81 68 911 82 69 929 83 70 929 84 71 979 89 75 1185 32 28 + 1185 32 28 1191 29 26 1191 29 26 1334 51 43 1338 52 44 1338 52 44 + 1416 57 48 1416 58 49 1584 31 27 1684 73 63 1684 73 63 1889 46 39 + 1889 46 39 1891 49 41 1922 87 73 1922 88 74 2005 54 45 2005 55 46 + 2518 45 38 2518 48 40 2523 75 64 2523 76 65 2523 77 66} + +do_execsql_test 5.4.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 + {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 + {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 43 37 {} 43 37 {} 49 41 {} 50 42 {} 51 43 {} 54 45 + {} 59 50 {} 60 51 {} 61 52 {} 63 54 {} 64 55 {} 64 55 {} 67 57 + {} 68 58 {} 69 59 {} 70 60 {} 72 62 {} 75 64 {} 76 65 {} 78 67 + {} 78 67 {} 78 67 {} 84 71 {} 85 72 {} 85 72 113 2 2 113 2 2 + 133 4 3 223 10 8 239 14 12 247 15 13 257 19 17 295 20 18 + 309 21 19 335 23 21 355 27 25 355 27 25 393 29 26 393 29 26 + 399 32 28 399 32 28 421 35 30 443 37 32 607 42 36 627 45 38 + 629 46 39 629 46 39 633 48 40 667 52 44 667 52 44 671 55 46 + 683 56 47 705 57 48 711 58 49 759 62 53 777 66 56 805 71 61 + 839 73 63 839 73 63 845 77 66 899 81 68 911 82 69 929 83 70 + 959 87 73 963 88 74 979 89 75} + +do_execsql_test 5.4.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 + 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 + 979 238 72 979 239 71 979 247 70 979 250 69 979 252 68 979 256 67 + 979 257 66 979 295 65 979 309 64 979 330 63 979 335 62 979 336 61 + 979 346 60 979 354 59 979 355 57 979 355 58 979 393 56 979 393 57 + 979 398 55 979 399 53 979 399 54 979 412 53 979 421 52 979 430 51 + 979 443 50 979 480 48 979 480 49 979 572 47 979 574 46 979 607 45 + 979 618 43 979 618 44 979 627 42 979 629 40 979 629 41 979 633 40 + 979 634 39 979 652 38 979 660 37 979 667 35 979 667 36 979 670 35 + 979 671 34 979 683 33 979 705 32 979 711 31 979 716 30 979 726 29 + 979 730 28 979 759 27 979 762 26 979 768 24 979 768 25 979 777 23 + 979 786 22 979 790 21 979 792 20 979 794 19 979 805 18 979 822 17 + 979 839 15 979 839 16 979 840 14 979 844 13 979 845 12 979 870 9 + 979 870 10 979 870 11 979 899 9 979 911 8 979 929 7} + +do_execsql_test 5.4.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 @@ -4860,16 +6191,282 @@ do_execsql_test 6.0 { do_execsql_test 6.1 { SELECT group_concat(a, '.') OVER ( - ORDER BY b RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING + ORDER BY b NULLS FIRST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING ) FROM t2 } {A.B A.B {}} do_execsql_test 6.2 { SELECT group_concat(a, '.') OVER ( - ORDER BY b DESC RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING + ORDER BY b DESC NULLS LAST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING ) FROM t2 } {{} A.B A.B} +#========================================================================== + +do_execsql_test 7.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER, b INTEGER); + + INSERT INTO t2 VALUES(1, 65); + INSERT INTO t2 VALUES(2, NULL); + INSERT INTO t2 VALUES(3, NULL); + INSERT INTO t2 VALUES(4, NULL); + INSERT INTO t2 VALUES(5, 66); + INSERT INTO t2 VALUES(6, 67); +} {} + +do_execsql_test 7.1.1 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {9 9 9 9 9 9} + +do_execsql_test 7.1.2 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.3 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.4 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.5 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.6 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 9 9 9} + +do_execsql_test 7.1.7 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.8 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.9 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.2.1 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {2 2 2 2 2 2} + +do_execsql_test 7.2.2 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.3 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.4 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.5 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.6 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 2 2 2} + +do_execsql_test 7.2.7 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.8 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.9 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.3.1 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {9 9 9 9 9 9} + +do_execsql_test 7.3.2 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.3 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.4 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.5 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.6 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 9 9 9} + +do_execsql_test 7.3.7 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.8 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.9 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.4.1 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {4 4 4 4 4 4} + +do_execsql_test 7.4.2 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.3 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.4 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.5 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.6 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 4 4 4} + +do_execsql_test 7.4.7 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.8 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.9 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {4 4 4 {} {} {}} + finish_test diff --git a/test/window9.test b/test/window9.test index 5a32a75..6f2f2d9 100644 --- a/test/window9.test +++ b/test/window9.test @@ -98,5 +98,139 @@ do_execsql_test 2.2.2 { SELECT b=='2', rank() OVER (ORDER BY a) FROM t1 } {1 1 0 2} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a); + CREATE TABLE t2(a,b,c); +} + +do_execsql_test 3.1 { + SELECT EXISTS(SELECT 1 FROM t1 ORDER BY sum(a) OVER ()) FROM t1; +} + +do_execsql_test 3.2 { + SELECT sum(a) OVER () FROM t2 + ORDER BY EXISTS(SELECT 1 FROM t2 ORDER BY sum(a) OVER ()); +} + +do_catchsql_test 3.3 { + SELECT a, sum(a) OVER (ORDER BY a DESC) FROM t2 + ORDER BY EXISTS( + SELECT 1 FROM t2 ORDER BY sum(a) OVER (ORDER BY a) + ) OVER (ORDER BY a); +} {1 {near "OVER": syntax error}} + +do_catchsql_test 3.4 { + SELECT y, y+1, y+2 FROM ( + SELECT c IN ( + SELECT min(a) OVER (), + (abs(row_number() OVER())+22)/19, + max(a) OVER () FROM t1 + ) AS y FROM t2 + ); +} {1 {sub-select returns 3 columns - expected 1}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE t1(a, b TEXT); + INSERT INTO t1 VALUES('A', 1), ('A', 2), ('2', 1), ('2', 2); +} + +do_execsql_test 4.1.1 { + SELECT b, b=count(*), '1,2' FROM t1 GROUP BY b; +} {1 0 1,2 2 1 1,2} +do_execsql_test 4.1.2 { + SELECT b, b=count(*), group_concat(b) OVER () FROM t1 GROUP BY b; +} {1 0 1,2 2 1 1,2} + +#-------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1(a, b, c, d, e); + CREATE INDEX i1 ON t1(a, b, c, d, e); +} + +foreach {tn sql} { + 1 { + SELECT + sum(e) OVER (), + sum(e) OVER (ORDER BY a), + sum(e) OVER (PARTITION BY a ORDER BY b), + sum(e) OVER (PARTITION BY a, b ORDER BY c), + sum(e) OVER (PARTITION BY a, b, c ORDER BY d) + FROM t1; + } + 2 { + SELECT sum(e) OVER (PARTITION BY a ORDER BY b) FROM t1 ORDER BY a; + } +} { + do_test 5.1.$tn { + execsql "EXPLAIN QUERY PLAN $sql" + } {~/ORDER/} +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES (0); +} + +do_execsql_test 6.1 { + SELECT * FROM t0 WHERE + EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) >=1 AND + EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) <=1; +} {0} + +do_execsql_test 6.2 { + SELECT * FROM t0 WHERE EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) + BETWEEN 1 AND 1; +} {0} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 7.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES(10, 1); + INSERT INTO t1 VALUES(20, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(2, 4); + INSERT INTO t1 VALUES(1, 5); +} {} + + +do_execsql_test 7.1 { + SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z +} { + 7.2 8.75 10.0 11.0 15.0 +} + +do_execsql_test 7.2 { + SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY (z IS y); +} { + 10.0 15.0 11.0 8.75 7.2 +} + +do_execsql_test 7.3 { + SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY (y IS z); +} { + 10.0 15.0 11.0 8.75 7.2 +} + +do_execsql_test 7.4 { + SELECT avg(x) OVER (ORDER BY y) z FROM t1 ORDER BY z + 0.0; +} { + 7.2 8.75 10.0 11.0 15.0 +} + finish_test diff --git a/test/windowA.test b/test/windowA.test new file mode 100644 index 0000000..e94ae57 --- /dev/null +++ b/test/windowA.test @@ -0,0 +1,309 @@ +# 2019-08-30 +# +# 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 RANGE BETWEEN and especially with NULLS LAST +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix windowA + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), d FLOAT); + INSERT INTO t1 VALUES + (1, 'A', 5.4), + (2, 'B', 5.55), + (3, 'C', 8.0), + (4, 'D', 10.25), + (5, 'E', 10.26), + (6, 'N', NULL), + (7, 'N', NULL); +} {} + +do_execsql_test 1.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ +] + +do_execsql_test 1.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 EDCBANN \ + 3 C 8.0 EDCBANN \ + 2 B 5.55 CBANN \ + 1 A 5.4 BANN \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 EDCBA \ + 4 D 10.25 EDCBA \ + 3 C 8.0 EDCBA \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ +] + +do_execsql_test 1.5 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 CB \ + 1 A 5.4 BA \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.6 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 CB \ + 1 A 5.4 BA \ +] + +do_execsql_test 2.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 EDCBA \ + 1 A 5.4 EDCBA \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 NNED \ + 4 D 10.25 NNEDC \ + 3 C 8.0 NNEDC \ + 2 B 5.55 NNEDCBA \ + 1 A 5.4 NNEDCBA \ +] + +do_execsql_test 2.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 EDCBANN \ + 3 C 8.0 EDCBANN \ + 2 B 5.55 EDCBANN \ + 1 A 5.4 EDCBANN \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 NNEDCBA \ + 4 D 10.25 NNEDCBA \ + 3 C 8.0 NNEDCBA \ + 2 B 5.55 NNEDCBA \ + 1 A 5.4 NNEDCBA \ +] + +do_execsql_test 2.5 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 EDCB \ + 1 A 5.4 EDCBA \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.6 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 NNE \ + 4 D 10.25 NNED \ + 3 C 8.0 NNEDC \ + 2 B 5.55 NNEDCB \ + 1 A 5.4 NNEDCBA \ +] + + +do_execsql_test 3.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 DC \ + 3 C 8.0 C \ + 2 B 5.55 BA \ + 1 A 5.4 A \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 3.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 ED \ + 4 D 10.25 DC \ + 3 C 8.0 C \ + 2 B 5.55 BA \ + 1 A 5.4 A \ +] + +do_execsql_test 3.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 DCBANN \ + 3 C 8.0 CBANN \ + 2 B 5.55 BANN \ + 1 A 5.4 ANN \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 3.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 EDCBA \ + 4 D 10.25 DCBA \ + 3 C 8.0 CBA \ + 2 B 5.55 BA \ + 1 A 5.4 A \ +] + +do_execsql_test 4.0 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND 0.5 PRECEDING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 {} \ + 4 D 10.25 {} \ + 3 C 8.0 ED \ + 2 B 5.55 C \ + 1 A 5.4 {} \ +] + + +finish_test diff --git a/test/windowB.test b/test/windowB.test new file mode 100644 index 0000000..321c481 --- /dev/null +++ b/test/windowB.test @@ -0,0 +1,339 @@ +# 2019-08-30 +# +# 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 RANGE BETWEEN and especially with NULLS LAST +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix windowB + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(NULL, 1); + INSERT INTO t1 VALUES(NULL, 2); + INSERT INTO t1 VALUES(NULL, 3); +} {} + +foreach {tn win} { + 1 { ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 2 { ORDER BY a NULLS LAST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 3 { ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 4 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + + 5 { ORDER BY a NULLS LAST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING } + 6 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING } + + 7 { ORDER BY a NULLS LAST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING } + 8 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING } +} { + do_execsql_test 1.$tn " + SELECT sum(b) OVER win FROM t1 + WINDOW win AS ( $win ) + " {6 6 6} +} + +do_execsql_test 1.2 { + SELECT sum(b) OVER win FROM t1 + WINDOW win AS ( + ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) +} {6 6 6} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, NULL); + INSERT INTO t1 VALUES(2, 45); + INSERT INTO t1 VALUES(3, 66.2); + INSERT INTO t1 VALUES(4, 'hello world'); + INSERT INTO t1 VALUES(5, 'hello world'); + INSERT INTO t1 VALUES(6, X'1234'); + INSERT INTO t1 VALUES(7, X'1234'); + INSERT INTO t1 VALUES(8, NULL); +} + +foreach {tn win} { + 1 "ORDER BY b RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING" + 2 "ORDER BY b RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING" + 3 "ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING" + 4 "ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING" +} { + do_execsql_test 2.1.$tn " + SELECT a, sum(a) OVER win FROM t1 + WINDOW win AS ( $win ) + ORDER BY 1 + " {1 9 2 {} 3 {} 4 9 5 9 6 13 7 13 8 9} +} + +#------------------------------------------------------------------------- +ifcapable json1 { + reset_db + do_execsql_test 3.0 { + CREATE TABLE testjson(id INTEGER PRIMARY KEY, j TEXT, x TEXT); + INSERT INTO testjson VALUES(1, '{"a":1}', 'a'); + INSERT INTO testjson VALUES(2, '{"b":2}', 'b'); + INSERT INTO testjson VALUES(3, '{"c":3}', 'c'); + INSERT INTO testjson VALUES(4, '{"d":4}', 'd'); + } + + do_execsql_test 3.1 { + SELECT json_group_array(json(j)) FROM testjson; + } { + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.2 { + SELECT json_group_array(json(j)) OVER (ORDER BY id) FROM testjson; + } { + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.3 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + EXCLUDE TIES + ) FROM testjson; + } { + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.4 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM testjson; + } { + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"b":2},{"c":3},{"d":4}]} + {[{"c":3},{"d":4}]} + } + + do_execsql_test 3.5 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson; + } { + {[]} + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"b":2},{"c":3}]} + } + + do_execsql_test 3.5a { + UPDATE testjson SET j = replace(j,char(125),',"e":9'||char(125)); + SELECT j FROM testjson; + } { + {{"a":1,"e":9}} + {{"b":2,"e":9}} + {{"c":3,"e":9}} + {{"d":4,"e":9}} + } + do_execsql_test 3.5b { + SELECT group_concat(x,'') OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson ORDER BY id; + } {bc cd d {}} + do_execsql_test 3.5c { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson; + } { + {[{"b":2,"e":9},{"c":3,"e":9}]} + {[{"c":3,"e":9},{"d":4,"e":9}]} + {[{"d":4,"e":9}]} + {[]} + } + do_execsql_test 3.5d { + SELECT json_group_object(x,json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson; + } { + {{"b":{"b":2,"e":9},"c":{"c":3,"e":9}}} + {{"c":{"c":3,"e":9},"d":{"d":4,"e":9}}} + {{"d":{"d":4,"e":9}}} + {{}} + } + + do_execsql_test 3.7b { + SELECT group_concat(x,'') FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson; + } {{} a a c} + + do_execsql_test 3.7c { + SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {[]} + {[{"a":1,"e":9}]} + {[{"a":1,"e":9}]} + {[{"c":3,"e":9}]} + } + do_execsql_test 3.7d { + SELECT json_group_object(x,json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {{}} + {{"a":{"a":1,"e":9}}} + {{"a":{"a":1,"e":9}}} + {{"c":{"c":3,"e":9}}} + } +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE x(a); + INSERT INTO x VALUES(1); + INSERT INTO x VALUES(2); +} + +do_execsql_test 4.1 { + WITH y AS ( + SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION BY a) + ) + SELECT * FROM y; +} { + 1 1 +} + +do_catchsql_test 4.2 { + WITH y AS ( + SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION + BY fake_column)) + SELECT * FROM y; +} {1 {no such column: fake_column}} + +do_catchsql_test 4.3 { + SELECT 1 WINDOW win AS (PARTITION BY fake_column); +} {0 1} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1(a, c); + CREATE INDEX i1 ON t1(a); + + INSERT INTO t1 VALUES(0, 421); + INSERT INTO t1 VALUES(1, 844); + INSERT INTO t1 VALUES(2, 1001); +} + +do_execsql_test 5.1 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING + ) FROM t1; +} {0 {} 1 {} 2 {}} + +do_execsql_test 5.2 { + INSERT INTO t1 VALUES(NULL, 123); + INSERT INTO t1 VALUES(NULL, 111); + INSERT INTO t1 VALUES('xyz', 222); + INSERT INTO t1 VALUES('xyz', 333); + + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING + ) FROM t1; +} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555} + +do_execsql_test 5.3 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING + ) FROM t1; +} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555} + +do_execsql_test 5.4 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 0 PRECEDING AND 3 PRECEDING EXCLUDE NO OTHERS + ) FROM t1; +} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555} + +do_execsql_test 5.5 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING EXCLUDE NO OTHERS + ) FROM t1; +} {{} 234 {} 234 0 {} 1 {} 2 {} xyz 555 xyz 555} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t1(a, c); + CREATE INDEX i1 ON t1(a); + + INSERT INTO t1 VALUES(7, 997); + INSERT INTO t1 VALUES(8, 997); + INSERT INTO t1 VALUES('abc', 1001); +} +do_execsql_test 6.1 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING + ) FROM t1; +} {7 {} 8 {} abc 1001} +do_execsql_test 6.2 { + SELECT a, sum(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING EXCLUDE NO OTHERS + ) FROM t1; +} {7 {} 8 {} abc 1001} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 7.0 { + CREATE TABLE t1(a, c); + CREATE INDEX i1 ON t1(a); + + INSERT INTO t1 VALUES(NULL, 46); + INSERT INTO t1 VALUES(NULL, 45); + INSERT INTO t1 VALUES(7, 997); + INSERT INTO t1 VALUES(7, 1000); + INSERT INTO t1 VALUES(8, 997); + INSERT INTO t1 VALUES(8, 1000); + INSERT INTO t1 VALUES('abc', 1001); + INSERT INTO t1 VALUES('abc', 1004); + INSERT INTO t1 VALUES('xyz', 3333); +} + +do_execsql_test 7.1 { + SELECT a, max(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING + ) FROM t1; +} {{} 46 {} 46 7 {} 7 {} 8 {} 8 {} abc 1004 abc 1004 xyz 3333} +do_execsql_test 7.2 { + SELECT a, min(c) OVER ( + ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 0 FOLLOWING + ) FROM t1; +} {{} 45 {} 45 7 {} 7 {} 8 {} 8 {} abc 1001 abc 1001 xyz 3333} + +do_execsql_test 7.3 { + SELECT a, max(c) OVER ( + ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING + ) FROM t1; +} {{} 46 {} 46 7 {} 7 {} 8 {} 8 {} abc 1004 abc 1004 xyz 3333} +do_execsql_test 7.4 { + SELECT a, min(c) OVER ( + ORDER BY a RANGE BETWEEN 0 PRECEDING AND 2 PRECEDING + ) FROM t1; +} {{} 45 {} 45 7 {} 7 {} 8 {} 8 {} abc 1001 abc 1001 xyz 3333} + +finish_test diff --git a/test/windowerr.tcl b/test/windowerr.tcl index 272ce6b..294e68d 100644 --- a/test/windowerr.tcl +++ b/test/windowerr.tcl @@ -64,6 +64,9 @@ errorsql_test 3.2 { WINDOW win AS (ROWS BETWEEN 10 PRECEDING AND x'ABCD' FOLLOWING) } +errorsql_test 3.3 { + SELECT row_number(a) OVER () FROM t1; +} finish_test diff --git a/test/windowerr.test b/test/windowerr.test index 9a4f0a6..40d994d 100644 --- a/test/windowerr.test +++ b/test/windowerr.test @@ -108,4 +108,9 @@ do_test 3.2 { catch { execsql { WINDOW win AS (ROWS BETWEEN 10 PRECEDING AND x'ABCD' FOLLOWING) } } } 1 +# PG says ERROR: function row_number(integer) does not exist +do_test 3.3 { catch { execsql { + SELECT row_number(a) OVER () FROM t1; +} } } 1 + finish_test diff --git a/test/windowfault.test b/test/windowfault.test index 41c4bb6..e037c46 100644 --- a/test/windowfault.test +++ b/test/windowfault.test @@ -224,4 +224,26 @@ do_faultsim_test 9 -end 25 -faults tmpread -body { catch {db close} tvfs delete +reset_db +do_execsql_test 10.0 { + CREATE TABLE t1(a, b, c, d); + CREATE TABLE t2(a, b, c, d); +} + +do_faultsim_test 1 -faults oom* -prep { +} -body { + execsql { + SELECT row_number() OVER win + FROM t1 + WINDOW win AS ( + ORDER BY ( + SELECT percent_rank() OVER win2 FROM t2 + WINDOW win2 AS (ORDER BY a) + ) + ) + } +} -test { + faultsim_test_result {0 {}} +} + finish_test diff --git a/test/without_rowid1.test b/test/without_rowid1.test index 3832239..23fae11 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -17,6 +17,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix without_rowid1 +proc do_execsql_test_if_vtab {tn sql {res {}}} { + ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] } +} + # Create and query a WITHOUT ROWID table. # do_execsql_test without_rowid1-1.0 { @@ -31,6 +35,10 @@ do_execsql_test without_rowid1-1.0 { integrity_check without_rowid1-1.0ic +do_execsql_test_if_vtab without_rowid1-1.0ixi { + SELECT name, key FROM pragma_index_xinfo('t1'); +} {c 1 a 1 b 0 d 0} + do_execsql_test without_rowid1-1.1 { SELECT *, '|' FROM t1 ORDER BY +c, a; } {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic juliet flipper command | journal sherman gamma patriot |} @@ -98,11 +106,6 @@ do_execsql_test without_rowid1-1.50 { ANALYZE; SELECT * FROM sqlite_stat1 ORDER BY idx; } {t1 t1 {4 2 1} t1 t1bd {4 2 2}} -ifcapable stat3 { - do_execsql_test without_rowid1-1.51 { - SELECT DISTINCT tbl, idx FROM sqlite_stat3 ORDER BY idx; - } {t1 t1 t1 t1bd} -} ifcapable stat4 { do_execsql_test without_rowid1-1.52 { SELECT DISTINCT tbl, idx FROM sqlite_stat4 ORDER BY idx; @@ -120,6 +123,9 @@ do_execsql_test 2.1.2 { UPDATE t4 SET a = 'ABC'; SELECT * FROM t4; } {ABC def} +do_execsql_test_if_vtab 2.1.3 { + SELECT name, coll, key FROM pragma_index_xinfo('t4'); +} {a nocase 1 b BINARY 0} do_execsql_test 2.2.1 { DROP TABLE t4; @@ -133,12 +139,22 @@ do_execsql_test 2.2.2 { SELECT * FROM t4; } {xyz ABC} +do_execsql_test_if_vtab 2.2.3 { + SELECT name, coll, key FROM pragma_index_xinfo('t4'); +} {a nocase 1 b BINARY 0} + + do_execsql_test 2.3.1 { CREATE TABLE t5 (a, b, PRIMARY KEY(b, a)) WITHOUT ROWID; INSERT INTO t5(a, b) VALUES('abc', 'def'); UPDATE t5 SET a='abc', b='def'; } {} +do_execsql_test_if_vtab 2.3.2 { + SELECT name, coll, key FROM pragma_index_xinfo('t5'); +} {b BINARY 1 a BINARY 1} + + do_execsql_test 2.4.1 { CREATE TABLE t6 ( a COLLATE nocase, b, c UNIQUE, PRIMARY KEY(b, a) @@ -153,6 +169,11 @@ do_execsql_test 2.4.2 { SELECT * FROM t6 ORDER BY c; } {ABC def ghi ABC def ghi} +do_execsql_test_if_vtab 2.4.3 { + SELECT name, coll, key FROM pragma_index_xinfo('t6'); +} {b BINARY 1 a nocase 1 c BINARY 0} + + #------------------------------------------------------------------------- # Unless the destination table is completely empty, the xfer optimization # is disabled for WITHOUT ROWID tables. The following tests check for diff --git a/test/without_rowid6.test b/test/without_rowid6.test index 3f9fe41..567acfa 100644 --- a/test/without_rowid6.test +++ b/test/without_rowid6.test @@ -16,6 +16,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +proc do_execsql_test_if_vtab {tn sql {res {}}} { + ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] } +} + do_execsql_test without_rowid6-100 { CREATE TABLE t1(a,b,c,d,e, PRIMARY KEY(a,b,c,a,b,c,d,a,b,c)) WITHOUT ROWID; CREATE INDEX t1a ON t1(b, b); @@ -24,6 +28,9 @@ do_execsql_test without_rowid6-100 { INSERT INTO t1(a,b,c,d,e) SELECT i, i+1000, printf('x%dy',i), 0, 0 FROM c; ANALYZE; } {} +do_execsql_test_if_vtab without_rowid6-101 { + SELECT name, key FROM pragma_index_xinfo('t1'); +} {a 1 b 1 c 1 d 1 e 0} do_execsql_test without_rowid6-110 { SELECT c FROM t1 WHERE a=123; } {x123y} @@ -51,6 +58,9 @@ do_execsql_test without_rowid6-200 { INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); SELECT a FROM t1 WHERE b>3 ORDER BY b; } {4 1} +do_execsql_test_if_vtab without_rowid6-201 { + SELECT name, key FROM pragma_index_xinfo('t1'); +} {b 1 a 0 c 0} do_execsql_test without_rowid6-210 { EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>3 ORDER BY b; @@ -105,6 +115,9 @@ do_execsql_test without_rowid6-500 { INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); SELECT a FROM t1 WHERE b>3 ORDER BY b; } {4 1} +do_execsql_test_if_vtab without_rowid6-501 { + SELECT name, key FROM pragma_index_xinfo('t1'); +} {b 1 c 1 a 0} do_execsql_test without_rowid6-510 { EXPLAIN QUERY PLAN SELECT a FROM t1 WHERE b>3 ORDER BY b; diff --git a/test/without_rowid7.test b/test/without_rowid7.test new file mode 100644 index 0000000..56e9fb4 --- /dev/null +++ b/test/without_rowid7.test @@ -0,0 +1,60 @@ +# 2019 July 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 without_rowid7 + +proc do_execsql_test_if_vtab {tn sql {res {}}} { + ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] } +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b COLLATE nocase, PRIMARY KEY(a, a, b)) WITHOUT ROWID; +} + +do_catchsql_test 1.1 { + INSERT INTO t1 VALUES(1, 'one'), (1, 'ONE'); +} {1 {UNIQUE constraint failed: t1.a, t1.b}} + + +do_execsql_test 2.0 { + CREATE TABLE t2(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID; +} + +do_execsql_test 2.1 { + INSERT INTO t2 VALUES(1, 'one'); + SELECT b FROM t2; +} {one} + +do_execsql_test 2.2a { + PRAGMA index_info(t2); +} {0 0 a 1 0 a} +do_execsql_test_if_vtab 2.2b { + SELECT *, '|' FROM pragma_index_info('t2'); +} {0 0 a | 1 0 a |} +do_execsql_test 2.3a { + PRAGMA index_xinfo(t2); +} {0 0 a 0 nocase 1 1 0 a 0 BINARY 1 2 1 b 0 BINARY 0} +do_execsql_test_if_vtab 2.3b { + SELECT *, '|' FROM pragma_index_xinfo('t2'); +} {0 0 a 0 nocase 1 | 1 0 a 0 BINARY 1 | 2 1 b 0 BINARY 0 |} + +do_execsql_test 2.4 { + CREATE TABLE t3(a, b, PRIMARY KEY(a COLLATE nocase, a)); + PRAGMA index_info(t3); +} {} + + + +finish_test diff --git a/tool/lemon.c b/tool/lemon.c index 4416f67..6efc6af 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -4153,6 +4153,7 @@ void ReportTable( struct rule *rp; struct acttab *pActtab; int i, j, n, sz; + int nLookAhead; int szActionType; /* sizeof(YYACTIONTYPE) */ int szCodeType; /* sizeof(YYCODETYPE) */ const char *name; @@ -4403,13 +4404,29 @@ void ReportTable( if( la<0 ) la = lemp->nsymbol; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", la); - if( j==9 || i==n-1 ){ + if( j==9 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } + /* Add extra entries to the end of the yy_lookahead[] table so that + ** yy_shift_ofst[]+iToken will always be a valid index into the array, + ** even for the largest possible value of yy_shift_ofst[] and iToken. */ + nLookAhead = lemp->nterminal + lemp->nactiontab; + while( interminal); + if( j==9 ){ + fprintf(out, "\n"); lineno++; + j = 0; + }else{ + j++; + } + i++; + } + if( j>0 ){ fprintf(out, "\n"); lineno++; } fprintf(out, "};\n"); lineno++; /* Output the yy_shift_ofst[] table */ @@ -4489,7 +4506,9 @@ void ReportTable( */ if( lemp->has_fallback ){ int mx = lemp->nterminal - 1; - while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } + /* 2019-08-28: Generate fallback entries for every token to avoid + ** having to do a range check on the index */ + /* while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } */ lemp->tablesize += (mx+1)*szCodeType; for(i=0; i<=mx; i++){ struct symbol *p = lemp->symbols[i]; diff --git a/tool/lempar.c b/tool/lempar.c index 94c0a31..f75ad51 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -521,15 +521,18 @@ static YYACTIONTYPE yy_find_shift_action( do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); - /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ + assert( i<=YY_ACTTAB_COUNT ); + assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ + assert( i<(int)YY_NLOOKAHEAD ); + if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", @@ -544,16 +547,8 @@ static YYACTIONTYPE yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 - ){ + assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); + if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -567,6 +562,7 @@ static YYACTIONTYPE yy_find_shift_action( #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ + assert( i>=0 && i Date: Mon, 28 Oct 2019 16:38:12 -0400 Subject: [PATCH 18/24] relocate struct definitions to support validation changes --- src/crypto.c | 2 +- src/crypto.h | 45 +++++++++++++++++++++++++++++++++++++++----- src/crypto_impl.c | 48 ----------------------------------------------- 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index d1ec2d6..4a1d6cc 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -105,7 +105,7 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef if( sqlite3StrICmp(zLeft, "cipher_license")==0 && !zRight ){ if(ctx) { char *license_result = sqlite3_mprintf("%d", ctx - ? sqlcipher_license_key_status(ctx) + ? sqlcipher_license_key_status(ctx->provider) : SQLITE_ERROR); codec_vdbe_return_string(pParse, "cipher_license", license_result, P4_DYNAMIC); } diff --git a/src/crypto.h b/src/crypto.h index 0fdbb67..22c91c8 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -192,7 +192,46 @@ static int cipher_isHex(const unsigned char *hex, int sz){ } /* extensions defined in crypto_impl.c */ -typedef struct codec_ctx codec_ctx; +/* the default implementation of SQLCipher uses a cipher_ctx + to keep track of read / write state separately. The following + struct and associated functions are defined here */ +typedef struct { + int derive_key; + int pass_sz; + unsigned char *key; + unsigned char *hmac_key; + unsigned char *pass; + char *keyspec; +} cipher_ctx; + + +typedef struct { + int store_pass; + int kdf_iter; + int fast_kdf_iter; + int kdf_salt_sz; + int key_sz; + int iv_sz; + int block_sz; + int page_sz; + int keyspec_sz; + int reserve_sz; + int hmac_sz; + int plaintext_header_sz; + int hmac_algorithm; + int kdf_algorithm; + unsigned int skip_read_hmac; + unsigned int need_kdf_salt; + unsigned int flags; + unsigned char *kdf_salt; + unsigned char *hmac_kdf_salt; + unsigned char *buffer; + Btree *pBt; + cipher_ctx *read_ctx; + cipher_ctx *write_ctx; + sqlcipher_provider *provider; + void *provider_ctx; +} codec_ctx ; /* crypto.c functions */ int sqlcipher_codec_pragma(sqlite3*, int, Parse*, const char *, const char*); @@ -268,10 +307,6 @@ void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value); int sqlcipher_codec_fips_status(codec_ctx *ctx); const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx); -int sqlcipher_codec_hmac_sha1(const codec_ctx *ctx, const unsigned char *hmac_key, int key_sz, - unsigned char* in, int in_sz, unsigned char *in2, int in2_sz, - unsigned char *out); - int sqlcipher_set_default_plaintext_header_size(int size); int sqlcipher_get_default_plaintext_header_size(void); int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size); diff --git a/src/crypto_impl.c b/src/crypto_impl.c index edd492c..48899fb 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -59,47 +59,6 @@ static volatile sqlite3_mem_methods default_mem_methods; static sqlite3_mutex* sqlcipher_provider_mutex = NULL; static sqlcipher_provider *default_provider = NULL; -/* the default implementation of SQLCipher uses a cipher_ctx - to keep track of read / write state separately. The following - struct and associated functions are defined here */ -typedef struct { - int derive_key; - int pass_sz; - unsigned char *key; - unsigned char *hmac_key; - unsigned char *pass; - char *keyspec; -} cipher_ctx; - - -struct codec_ctx { - int store_pass; - int kdf_iter; - int fast_kdf_iter; - int kdf_salt_sz; - int key_sz; - int iv_sz; - int block_sz; - int page_sz; - int keyspec_sz; - int reserve_sz; - int hmac_sz; - int plaintext_header_sz; - int hmac_algorithm; - int kdf_algorithm; - unsigned int skip_read_hmac; - unsigned int need_kdf_salt; - unsigned int flags; - unsigned char *kdf_salt; - unsigned char *hmac_kdf_salt; - unsigned char *buffer; - Btree *pBt; - cipher_ctx *read_ctx; - cipher_ctx *write_ctx; - sqlcipher_provider *provider; - void *provider_ctx; -}; - static int sqlcipher_mem_init(void *pAppData) { return default_mem_methods.xInit(pAppData); } @@ -1591,12 +1550,5 @@ const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx) { return ctx->provider->get_provider_version(ctx->provider_ctx); } -int sqlcipher_codec_hmac_sha1(const codec_ctx *ctx, const unsigned char *hmac_key, int key_sz, - unsigned char* in, int in_sz, unsigned char *in2, int in2_sz, - unsigned char *out) { - return ctx->provider->hmac(ctx->provider_ctx, SQLCIPHER_HMAC_SHA1, (unsigned char *)hmac_key, key_sz, in, in_sz, in2, in2_sz, out); -} - - #endif /* END SQLCIPHER */ From 924e0ef0f85208e86aa20249614eb54d0ce85563 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Thu, 31 Oct 2019 08:56:05 -0400 Subject: [PATCH 19/24] update version to 4.3.0 --- CHANGELOG.md | 15 ++++++++++++++- SQLCipher.podspec.json | 4 ++-- src/crypto.h | 2 +- test/sqlcipher-pragmas.test | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c64588a..71a74a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # SQLCipher Change Log All notable changes to this project will be documented in this file. +## [4.3.0] - (November 2019 - [4.3.0 changes]) +- Updates baseline to upstream SQLite 3.30.1 +- PRAGMA key now returns text result value "ok" after execution +- Adjusts backup API so that encrypted to encrypted backups are permitted +- Adds NSS crypto provider implementation +- Fixes OpenSSL provider compatibility with BoringSSL +- Separates memory related traces to reduce verbosity of logging +- Fixes output of PRAGMA cipher_integrity_check on big endian platforms +- Cryptograpic provider interface cleanup +- Resolves miscellaneous build warnings + ## [4.2.0] - (May 2019 - [4.2.0 changes]) - Adds PRAGMA cipher_integrity_check to perform independent verification of page HMACs - Updates baseline to upstream SQLite 3.28.0 @@ -145,7 +156,9 @@ All notable changes to this project will be documented in this file. ### Security - Change KDF iteration length from 4,000 to 64,000 -[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v4.2.0...prerelease +[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v4.3.0...prerelease +[4.3.0]: https://github.com/sqlcipher/sqlcipher/tree/v4.3.0 +[4.3.0 changes]: https://github.com/sqlcipher/sqlcipher/compare/v4.2.0...v4.3.0 [4.2.0]: https://github.com/sqlcipher/sqlcipher/tree/v4.2.0 [4.2.0 changes]: https://github.com/sqlcipher/sqlcipher/compare/v4.1.0...v4.2.0 [4.1.0]: https://github.com/sqlcipher/sqlcipher/tree/v4.1.0 diff --git a/SQLCipher.podspec.json b/SQLCipher.podspec.json index 73845d0..fbabe4b 100644 --- a/SQLCipher.podspec.json +++ b/SQLCipher.podspec.json @@ -15,10 +15,10 @@ "requires_arc": false, "source": { "git": "https://github.com/sqlcipher/sqlcipher.git", - "tag": "v4.2.0" + "tag": "v4.3.0" }, "summary": "Full Database Encryption for SQLite.", - "version": "4.2.0", + "version": "4.3.0", "subspecs": [ { "compiler_flags": [ diff --git a/src/crypto.h b/src/crypto.h index 22c91c8..c416f16 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -59,7 +59,7 @@ void sqlite3pager_reset(Pager *pPager); #define CIPHER_STR(s) #s #ifndef CIPHER_VERSION_NUMBER -#define CIPHER_VERSION_NUMBER 4.2.0 +#define CIPHER_VERSION_NUMBER 4.3.0 #endif #ifndef CIPHER_VERSION_BUILD diff --git a/test/sqlcipher-pragmas.test b/test/sqlcipher-pragmas.test index 8d13b21..e56cdd8 100644 --- a/test/sqlcipher-pragmas.test +++ b/test/sqlcipher-pragmas.test @@ -46,7 +46,7 @@ do_test verify-pragma-cipher-version { execsql { PRAGMA cipher_version; } -} {{4.2.0 community}} +} {{4.3.0 community}} db close file delete -force test.db From 4663c5ad5c959d2dce20b69b08b3ff2f1f00c6c2 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 5 Nov 2019 17:10:36 -0500 Subject: [PATCH 20/24] replace use of static master mutex in crypto providers --- src/crypto_nss.c | 43 ++++++++++++++++++++++++++++++------------- src/crypto_openssl.c | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/crypto_nss.c b/src/crypto_nss.c index 5df1a67..5d81fca 100644 --- a/src/crypto_nss.c +++ b/src/crypto_nss.c @@ -39,38 +39,55 @@ static NSSInitContext* nss_init_context = NULL; static unsigned int nss_init_count = 0; -static sqlite3_mutex* nss_rand_mutex = NULL; +static sqlite3_mutex* nss_mutex = NULL; int sqlcipher_nss_setup(sqlcipher_provider *p); static int sqlcipher_nss_activate(void *ctx) { - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering static master mutex\n"); - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered static master mutex\n"); + if(nss_mutex == NULL){ + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: allocating nss_mutex"); + nss_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: allocated nss_mutex %p", nss_mutex); + } + + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering nss_mutex %p\n", nss_mutex); + sqlite3_mutex_enter(nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered nss_mutex %p\n", nss_mutex); if (nss_init_context == NULL) { nss_init_context = NSS_InitContext("", "", "", "", NULL, NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_OPTIMIZESPACE | NSS_INIT_NOROOTINIT); } nss_init_count++; - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving static master mutex\n"); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left static master mutex\n"); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); + sqlite3_mutex_leave(nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); return SQLITE_OK; } static int sqlcipher_nss_deactivate(void *ctx) { - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: entering static master mutex\n"); - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: entered static master mutex\n"); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering nss_mutex %p\n", nss_mutex); + sqlite3_mutex_enter(nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered nss_mutex %p\n", nss_mutex); + nss_init_count--; if (nss_init_count == 0 && nss_init_context != NULL) { + sqlite3_mutex *temp_mutex; NSS_ShutdownContext(nss_init_context); nss_init_context = NULL; + temp_mutex = nss_mutex; + nss_mutex = NULL; + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); + sqlite3_mutex_leave(temp_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: freeing nss_mutex %p", nss_mutex); + sqlite3_mutex_free(temp_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: freed nss_mutex %p", nss_mutex); + } else { + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); + sqlite3_mutex_leave(nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); } - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: leaving static master mutex\n"); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: left static master mutex\n"); return SQLITE_OK; } diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 4f7ff3c..ff62228 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -47,6 +47,7 @@ typedef struct { static unsigned int openssl_external_init = 0; static unsigned int openssl_init_count = 0; static sqlite3_mutex* openssl_rand_mutex = NULL; +static sqlite3_mutex* openssl_activate_mutex = NULL; #if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) static HMAC_CTX *HMAC_CTX_new(void) @@ -99,9 +100,16 @@ static int sqlcipher_openssl_activate(void *ctx) { /* initialize openssl and increment the internal init counter but only if it hasn't been initalized outside of SQLCipher by this program e.g. on startup */ - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering static master mutex"); - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered static master mutex"); + + if(openssl_activate_mutex == NULL){ + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocating openssl_activate_mutex"); + openssl_activate_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocated openssl_activate_mutex %p", openssl_activate_mutex); + } + + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering openssl_activate_mutex %p\n", openssl_activate_mutex); + sqlite3_mutex_enter(openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered openssl_activate_mutex %p\n", openssl_activate_mutex); if(openssl_init_count == 0 && EVP_get_cipherbyname(OPENSSL_CIPHER) != NULL) { /* if openssl has not yet been initialized by this library, but @@ -136,9 +144,9 @@ static int sqlcipher_openssl_activate(void *ctx) { #endif openssl_init_count++; - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving static master mutex"); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left static master mutex"); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); + sqlite3_mutex_leave(openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); return SQLITE_OK; } @@ -146,12 +154,13 @@ static int sqlcipher_openssl_activate(void *ctx) { freeing the EVP structures on the final deactivation to ensure that OpenSSL memory is cleaned up */ static int sqlcipher_openssl_deactivate(void *ctx) { - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering static master mutex"); - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered static master mutex"); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering openssl_activate_mutex %p\n", openssl_activate_mutex); + sqlite3_mutex_enter(openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered openssl_activate_mutex %p\n", openssl_activate_mutex); openssl_init_count--; if(openssl_init_count == 0) { + sqlite3_mutex *temp_mutex; if(openssl_external_init == 0) { /* if OpenSSL hasn't be initialized externally, and the counter reaches zero after it's decremented, release EVP memory @@ -170,10 +179,19 @@ static int sqlcipher_openssl_deactivate(void *ctx) { CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_rand_mutex %p", openssl_rand_mutex); openssl_rand_mutex = NULL; #endif + temp_mutex = openssl_activate_mutex; + openssl_activate_mutex = NULL; + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); + sqlite3_mutex_leave(temp_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_activate_mutex %p", openssl_activate_mutex); + sqlite3_mutex_free(temp_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_activate_mutex %p", openssl_activate_mutex); + } else { + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); + sqlite3_mutex_leave(openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); } - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving static master mutex"); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left static master mutex"); return SQLITE_OK; } From 872fb0078fbb132c1c4abb53cc17b18f7ceb0482 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 6 Nov 2019 13:56:00 -0500 Subject: [PATCH 21/24] major rework of mutex allocation and management --- src/crypto_impl.c | 73 ++++++++++++++++-------------- src/crypto_libtomcrypt.c | 96 +++++++++++++++++++++------------------- src/crypto_nss.c | 43 ++++++------------ src/crypto_openssl.c | 83 +++++++++++----------------------- src/sqlcipher.h | 10 +++++ 5 files changed, 142 insertions(+), 163 deletions(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 48899fb..a2c8c75 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -56,9 +56,15 @@ static volatile int mem_security_initialized = 0; static volatile int mem_security_activated = 0; static volatile unsigned int sqlcipher_activate_count = 0; static volatile sqlite3_mem_methods default_mem_methods; -static sqlite3_mutex* sqlcipher_provider_mutex = NULL; static sqlcipher_provider *default_provider = NULL; +static sqlite3_mutex* sqlcipher_static_mutex[SQLCIPHER_MUTEX_COUNT]; + +sqlite3_mutex* sqlcipher_mutex(int mutex) { + if(mutex < 0 || mutex >= SQLCIPHER_MUTEX_COUNT) return NULL; + return sqlcipher_static_mutex[mutex]; +} + static int sqlcipher_mem_init(void *pAppData) { return default_mem_methods.xInit(pAppData); } @@ -116,9 +122,9 @@ void sqlcipher_init_memmethods() { } int sqlcipher_register_provider(sqlcipher_provider *p) { - CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_enter(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered SQLCIPHER_MUTEX_PROVIDER"\n); if(default_provider != NULL && default_provider != p) { /* only free the current registerd provider if it has been initialized @@ -127,9 +133,9 @@ int sqlcipher_register_provider(sqlcipher_provider *p) { sqlcipher_free(default_provider, sizeof(sqlcipher_provider)); } default_provider = p; - CODEC_TRACE_MUTEX("sqlcipher_register_provider: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_leave(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_register_provider: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: leaving SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: left SQLCIPHER_MUTEX_PROVIDER\n"); return SQLITE_OK; } @@ -146,11 +152,12 @@ void sqlcipher_activate() { sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); CODEC_TRACE_MUTEX("sqlcipher_activate: entered static master mutex\n"); - if(sqlcipher_provider_mutex == NULL) { - /* allocate a new mutex to guard access to the provider */ - CODEC_TRACE_MUTEX("sqlcipher_activate: allocating sqlcipher provider mutex\n"); - sqlcipher_provider_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - CODEC_TRACE_MUTEX("sqlcipher_activate: allocated sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + /* allocate new mutexes */ + if(sqlcipher_activate_count == 0) { + int i; + for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) { + sqlcipher_static_mutex[i] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + } } /* check to see if there is a provider registered at this point @@ -196,30 +203,32 @@ void sqlcipher_deactivate() { sqlcipher_activate_count--; /* if no connections are using sqlcipher, cleanup globals */ if(sqlcipher_activate_count < 1) { - CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_enter(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered SQLCIPHER_MUTEX_PROVIDER\n"); if(default_provider != NULL) { sqlcipher_free(default_provider, sizeof(sqlcipher_provider)); default_provider = NULL; } - CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_leave(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_deactivate: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - - /* last connection closed, free provider mutex*/ - CODEC_TRACE_MUTEX("sqlcipher_deactivate: freeing sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_free(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_deactivate: freed sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: left SQLCIPHER_MUTEX_PROVIDER\n"); - sqlcipher_provider_mutex = NULL; - - sqlcipher_activate_count = 0; /* reset activation count */ #ifdef SQLCIPHER_EXT sqlcipher_ext_provider_destroy(); #endif + + /* last connection closed, free mutexes */ + if(sqlcipher_activate_count == 0) { + int i; + for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) { + sqlite3_mutex_free(sqlcipher_static_mutex[i]); + } + } + sqlcipher_activate_count = 0; /* reset activation count */ } CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving static master mutex\n"); @@ -845,15 +854,15 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, const voi if(ctx->provider == NULL) return SQLITE_NOMEM; /* make a copy of the provider to be used for the duration of the context */ - CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_enter(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entering SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entered SQLCIPHER_MUTEX_PROVIDER\n"); memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider)); - CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); - sqlite3_mutex_leave(sqlcipher_provider_mutex); - CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: leaving SQLCIPHER_MUTEX_PROVIDER\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); + CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: left SQLCIPHER_MUTEX_PROVIDER\n"); CODEC_TRACE("sqlcipher_codec_ctx_init: calling provider ctx_init\n"); if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc; diff --git a/src/crypto_libtomcrypt.c b/src/crypto_libtomcrypt.c index 9b5e581..f49339c 100644 --- a/src/crypto_libtomcrypt.c +++ b/src/crypto_libtomcrypt.c @@ -39,7 +39,6 @@ static prng_state prng; static volatile unsigned int ltc_init = 0; static volatile unsigned int ltc_ref_count = 0; -static sqlite3_mutex* ltc_rand_mutex = NULL; #define LTC_CIPHER "rijndael" @@ -48,34 +47,37 @@ static int sqlcipher_ltc_add_random(void *ctx, void *buffer, int length) { int data_to_read = length; int block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ; const unsigned char * data = (const unsigned char *)buffer; -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_enter(ltc_rand_mutex); -#endif - while(data_to_read > 0){ - rc = fortuna_add_entropy(data, block_sz, &prng); - rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK; - if(rc != SQLITE_OK){ - break; - } - data_to_read -= block_sz; - data += block_sz; - block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ; + + CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + + while(data_to_read > 0){ + rc = fortuna_add_entropy(data, block_sz, &prng); + rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK; + if(rc != SQLITE_OK){ + break; } - fortuna_ready(&prng); -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_leave(ltc_rand_mutex); -#endif + data_to_read -= block_sz; + data += block_sz; + block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ; + } + fortuna_ready(&prng); + + CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + return rc; } static int sqlcipher_ltc_activate(void *ctx) { unsigned char random_buffer[FORTUNA_MAX_SZ]; -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - if(ltc_rand_mutex == NULL){ - ltc_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - } - sqlite3_mutex_enter(ltc_rand_mutex); -#endif + + CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ); if(ltc_init == 0) { if(register_prng(&fortuna_desc) < 0) return SQLITE_ERROR; @@ -86,41 +88,42 @@ static int sqlcipher_ltc_activate(void *ctx) { if(fortuna_start(&prng) != CRYPT_OK) { return SQLITE_ERROR; } + ltc_init = 1; } ltc_ref_count++; + #ifndef SQLCIPHER_TEST sqlite3_randomness(FORTUNA_MAX_SZ, random_buffer); #endif -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_leave(ltc_rand_mutex); -#endif + if(sqlcipher_ltc_add_random(ctx, random_buffer, FORTUNA_MAX_SZ) != SQLITE_OK) { return SQLITE_ERROR; } sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ); + + CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + return SQLITE_OK; } static int sqlcipher_ltc_deactivate(void *ctx) { -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_enter(ltc_rand_mutex); -#endif + CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + ltc_ref_count--; if(ltc_ref_count == 0){ fortuna_done(&prng); sqlcipher_memset((void *)&prng, 0, sizeof(prng)); -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_leave(ltc_rand_mutex); - sqlite3_mutex_free(ltc_rand_mutex); - ltc_rand_mutex = NULL; -#endif } -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - else { - sqlite3_mutex_leave(ltc_rand_mutex); - } -#endif + + CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + return SQLITE_OK; } @@ -133,13 +136,16 @@ static const char* sqlcipher_ltc_get_provider_version(void *ctx) { } static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) { -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_enter(ltc_rand_mutex); -#endif + CODEC_TRACE_MUTEX("sqlcipher_ltc_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + fortuna_read(buffer, length, &prng); -#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND - sqlite3_mutex_leave(ltc_rand_mutex); -#endif + + CODEC_TRACE_MUTEX("sqlcipher_ltc_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_ltc_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + return SQLITE_OK; } diff --git a/src/crypto_nss.c b/src/crypto_nss.c index 5d81fca..54d2370 100644 --- a/src/crypto_nss.c +++ b/src/crypto_nss.c @@ -39,55 +39,40 @@ static NSSInitContext* nss_init_context = NULL; static unsigned int nss_init_count = 0; -static sqlite3_mutex* nss_mutex = NULL; int sqlcipher_nss_setup(sqlcipher_provider *p); static int sqlcipher_nss_activate(void *ctx) { - if(nss_mutex == NULL){ - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: allocating nss_mutex"); - nss_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: allocated nss_mutex %p", nss_mutex); - } - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering nss_mutex %p\n", nss_mutex); - sqlite3_mutex_enter(nss_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered nss_mutex %p\n", nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); if (nss_init_context == NULL) { nss_init_context = NSS_InitContext("", "", "", "", NULL, NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_OPTIMIZESPACE | NSS_INIT_NOROOTINIT); } nss_init_count++; - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); - sqlite3_mutex_leave(nss_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); return SQLITE_OK; } static int sqlcipher_nss_deactivate(void *ctx) { - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering nss_mutex %p\n", nss_mutex); - sqlite3_mutex_enter(nss_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered nss_mutex %p\n", nss_mutex); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); nss_init_count--; if (nss_init_count == 0 && nss_init_context != NULL) { - sqlite3_mutex *temp_mutex; NSS_ShutdownContext(nss_init_context); nss_init_context = NULL; - temp_mutex = nss_mutex; - nss_mutex = NULL; - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); - sqlite3_mutex_leave(temp_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: freeing nss_mutex %p", nss_mutex); - sqlite3_mutex_free(temp_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_deactivate: freed nss_mutex %p", nss_mutex); - } else { - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving nss_mutex %p\n", nss_mutex); - sqlite3_mutex_leave(nss_mutex); - CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left nss_mutex %p\n", nss_mutex); - } + } + + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); return SQLITE_OK; } diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index ff62228..298255f 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -46,8 +46,6 @@ typedef struct { static unsigned int openssl_external_init = 0; static unsigned int openssl_init_count = 0; -static sqlite3_mutex* openssl_rand_mutex = NULL; -static sqlite3_mutex* openssl_activate_mutex = NULL; #if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) static HMAC_CTX *HMAC_CTX_new(void) @@ -74,15 +72,15 @@ static void HMAC_CTX_free(HMAC_CTX *ctx) static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) { #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering openssl_rand_mutex %p\n", openssl_rand_mutex); - sqlite3_mutex_enter(openssl_rand_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered openssl_rand_mutex %p\n", openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n"); #endif RAND_add(buffer, length, 0); #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving openssl_rand_mutex %p\n", openssl_rand_mutex); - sqlite3_mutex_leave(openssl_rand_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left openssl_rand_mutex %p\n", openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n"); #endif return SQLITE_OK; } @@ -101,15 +99,9 @@ static int sqlcipher_openssl_activate(void *ctx) { but only if it hasn't been initalized outside of SQLCipher by this program e.g. on startup */ - if(openssl_activate_mutex == NULL){ - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocating openssl_activate_mutex"); - openssl_activate_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocated openssl_activate_mutex %p", openssl_activate_mutex); - } - - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering openssl_activate_mutex %p\n", openssl_activate_mutex); - sqlite3_mutex_enter(openssl_activate_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered openssl_activate_mutex %p\n", openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); if(openssl_init_count == 0 && EVP_get_cipherbyname(OPENSSL_CIPHER) != NULL) { /* if openssl has not yet been initialized by this library, but @@ -134,19 +126,10 @@ static int sqlcipher_openssl_activate(void *ctx) { #endif } -#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - if(openssl_rand_mutex == NULL) { - /* allocate a mutex to guard against concurrent calls to RAND_bytes() */ - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocating openssl_rand_mutex"); - openssl_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocated openssl_rand_mutex %p", openssl_rand_mutex); - } -#endif - openssl_init_count++; - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); - sqlite3_mutex_leave(openssl_activate_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); return SQLITE_OK; } @@ -154,9 +137,9 @@ static int sqlcipher_openssl_activate(void *ctx) { freeing the EVP structures on the final deactivation to ensure that OpenSSL memory is cleaned up */ static int sqlcipher_openssl_deactivate(void *ctx) { - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering openssl_activate_mutex %p\n", openssl_activate_mutex); - sqlite3_mutex_enter(openssl_activate_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered openssl_activate_mutex %p\n", openssl_activate_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); openssl_init_count--; if(openssl_init_count == 0) { @@ -173,25 +156,11 @@ static int sqlcipher_openssl_deactivate(void *ctx) { } else { openssl_external_init = 0; } -#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_rand_mutex %p", openssl_rand_mutex); - sqlite3_mutex_free(openssl_rand_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_rand_mutex %p", openssl_rand_mutex); - openssl_rand_mutex = NULL; -#endif - temp_mutex = openssl_activate_mutex; - openssl_activate_mutex = NULL; - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); - sqlite3_mutex_leave(temp_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_activate_mutex %p", openssl_activate_mutex); - sqlite3_mutex_free(temp_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_activate_mutex %p", openssl_activate_mutex); - } else { - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving openssl_activate_mutex %p\n", openssl_activate_mutex); - sqlite3_mutex_leave(openssl_activate_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left openssl_activate_mutex %p\n", openssl_activate_mutex); - } + } + + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n"); return SQLITE_OK; } @@ -213,15 +182,15 @@ static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) { but a more proper solution is that applications setup platform-appropriate thread saftey in openssl externally */ #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entering openssl_rand_mutex %p", openssl_rand_mutex); - sqlite3_mutex_enter(openssl_rand_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entered openssl_rand_mutex %p", openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n"); #endif rc = RAND_bytes((unsigned char *)buffer, length); #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND - CODEC_TRACE_MUTEX("sqlcipher_openssl_random: leaving openssl_rand_mutex %p", openssl_rand_mutex); - sqlite3_mutex_leave(openssl_rand_mutex); - CODEC_TRACE_MUTEX("sqlcipher_openssl_random: left openssl_rand_mutex %p", openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n"); + sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n"); #endif return (rc == 1) ? SQLITE_OK : SQLITE_ERROR; } diff --git a/src/sqlcipher.h b/src/sqlcipher.h index bf680e8..f1f868d 100644 --- a/src/sqlcipher.h +++ b/src/sqlcipher.h @@ -87,6 +87,16 @@ void sqlcipher_free(void *, int); int sqlcipher_register_provider(sqlcipher_provider *); sqlcipher_provider* sqlcipher_get_provider(void); +#define SQLCIPHER_MUTEX_PROVIDER 0 +#define SQLCIPHER_MUTEX_PROVIDER_ACTIVATE 1 +#define SQLCIPHER_MUTEX_PROVIDER_RAND 2 +#define SQLCIPHER_MUTEX_RESERVED1 3 +#define SQLCIPHER_MUTEX_RESERVED2 4 +#define SQLCIPHER_MUTEX_RESERVED3 5 +#define SQLCIPHER_MUTEX_COUNT 6 + +sqlite3_mutex* sqlcipher_mutex(int); + #endif #endif /* END SQLCIPHER */ From 05ed3bfe86bb614b7c2916c15a2431dbedd62fec Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 6 Nov 2019 16:21:25 -0500 Subject: [PATCH 22/24] correct mutex trace log call --- src/crypto_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index a2c8c75..ed0e979 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -124,7 +124,7 @@ void sqlcipher_init_memmethods() { int sqlcipher_register_provider(sqlcipher_provider *p) { CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering SQLCIPHER_MUTEX_PROVIDER\n"); sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER)); - CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered SQLCIPHER_MUTEX_PROVIDER"\n); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered SQLCIPHER_MUTEX_PROVIDER\n"); if(default_provider != NULL && default_provider != p) { /* only free the current registerd provider if it has been initialized From 16835799b48a4d86d2b8eb9177ade680ac12bd27 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Mon, 18 Nov 2019 11:19:04 -0500 Subject: [PATCH 23/24] log error for android through log API --- src/crypto_openssl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 298255f..efc096c 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -113,8 +113,15 @@ static int sqlcipher_openssl_activate(void *ctx) { #ifdef SQLCIPHER_FIPS if(!FIPS_mode()){ if(!FIPS_mode_set(1)){ + unsigned long err = 0; ERR_load_crypto_strings(); +#ifdef __ANDROID__ + while((err = ERR_get_error()) != 0) { + __android_log_print(ANDROID_LOG_ERROR, "sqlcipher","error: %lx. %s.", err, ERR_error_string(err, NULL)); + } +#else ERR_print_errors_fp(stderr); +#endif } } #endif From 14dd199f683ededc5c0686fd52233addc3cfc989 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Mon, 18 Nov 2019 11:20:42 -0500 Subject: [PATCH 24/24] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a74a2..21ab158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. - Separates memory related traces to reduce verbosity of logging - Fixes output of PRAGMA cipher_integrity_check on big endian platforms - Cryptograpic provider interface cleanup +- Rework of mutex allocation and management - Resolves miscellaneous build warnings ## [4.2.0] - (May 2019 - [4.2.0 changes])