From 6df8c0cd3b971ab51431ac0ec124be77f5b1ccec Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 28 Nov 2021 19:54:38 +0000 Subject: [PATCH 001/148] Following a prior error, an ALWAYS() in sqlite3ExprCanBeNull() might be false. dbsqlfuzz 5dbec6678a20e7595a34dfdd869a3b9722b3ca43. FossilOrigin-Name: 4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/expr.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index dfb723ab2a..262f1306c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.37.0 -D 2021-11-27T14:13:22.430 +C Following\sa\sprior\serror,\san\sALWAYS()\sin\ssqlite3ExprCanBeNull()\smight\sbe\sfalse.\ndbsqlfuzz\s5dbec6678a20e7595a34dfdd869a3b9722b3ca43. +D 2021-11-28T19:54:38.307 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -502,7 +502,7 @@ F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7 -F src/expr.c 4b6dfb224b6234ff4f529023993b503048e1b045ff49cbb911e7d28a28cca795 +F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5 F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b @@ -1933,10 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7c567338ae4dd31097e9ae5c693b84369c35c5a52534797e8186b4be7297ba78 -R 1bdaa083fa0abfc53c61429627c688f2 -T +sym-major-release * -T +sym-release * -T +sym-version-3.37.0 * +P bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a +R ee6ac26534b5f5e3f1e9b2504f0fbd97 U drh -Z 6f6dbee10adfe1c5275055f73bc6984f +Z 9896c4e7bad9bcf4c4f3ad7c3deddb22 diff --git a/manifest.uuid b/manifest.uuid index 44318ef9d2..5374c9a521 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a \ No newline at end of file +4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 2a00748846..a51d37a7b7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2457,7 +2457,7 @@ int sqlite3ExprCanBeNull(const Expr *p){ return ExprHasProperty(p, EP_CanBeNull) || p->y.pTab==0 || /* Reference to column of index on expression */ (p->iColumn>=0 - && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */ + && p->y.pTab->aCol!=0 /* Possible due to prior error */ && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; From 1312a9c908eb72da0fee79bdd29457555e1b7b33 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 29 Nov 2021 17:23:27 +0000 Subject: [PATCH 002/148] Add the unixepoch() function and the 'auto' and 'julianday' modifiers. FossilOrigin-Name: 559fdc0aa76f4c207f99f7b0cee42043b402dc388165817529d9963b115a798c --- manifest | 15 +++++++------ manifest.uuid | 2 +- src/date.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 262f1306c1..cd9aab656c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Following\sa\sprior\serror,\san\sALWAYS()\sin\ssqlite3ExprCanBeNull()\smight\sbe\sfalse.\ndbsqlfuzz\s5dbec6678a20e7595a34dfdd869a3b9722b3ca43. -D 2021-11-28T19:54:38.307 +C Add\sthe\sunixepoch()\sfunction\sand\sthe\s'auto'\sand\s'julianday'\smodifiers. +D 2021-11-29T17:23:27.456 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -498,7 +498,7 @@ F src/build.c c46bd4f5a69f398410c4472f7c1c4291fb8078d2c9758a2dad5916edd1d30ecc F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 -F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e +F src/date.c d0f09f7924a27e0d8a41b41a781ccc680b102c35b5e9a94d129d58ba9d849ff2 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7 @@ -1933,7 +1933,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a -R ee6ac26534b5f5e3f1e9b2504f0fbd97 +P 4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 +R b11e280e59fe4b6e2248a7ea61ef7371 +T *branch * unixepoch +T *sym-unixepoch * +T -sym-trunk * U drh -Z 9896c4e7bad9bcf4c4f3ad7c3deddb22 +Z 331f65dd5ca8ead7ee1403436d508d31 diff --git a/manifest.uuid b/manifest.uuid index 5374c9a521..7cf507461c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 \ No newline at end of file +559fdc0aa76f4c207f99f7b0cee42043b402dc388165817529d9963b115a798c \ No newline at end of file diff --git a/src/date.c b/src/date.c index 20a0a5d175..dcec9c7cc1 100644 --- a/src/date.c +++ b/src/date.c @@ -662,6 +662,45 @@ static int parseModifier( int rc = 1; double r; switch(sqlite3UpperToLower[(u8)z[0]] ){ + case 'a': { + /* + ** auto + ** + ** If rawS is available, then interpret as a julian day number, or + ** a unix timestamp, depending on its magnitude. + */ + if( sqlite3_stricmp(z, "auto")==0 ){ + if( !p->rawS || p->validJD ){ + rc = 0; + p->rawS = 0; + }else if( p->s>=-210866760000 && p->s<=253402300799 ){ + r = p->s*1000.0 + 210866760000000.0; + clearYMD_HMS_TZ(p); + p->iJD = (sqlite3_int64)(r + 0.5); + p->validJD = 1; + p->rawS = 0; + rc = 0; + } + } + break; + } + case 'j': { + /* + ** julianday + ** + ** Always interpret the prior number as a julian-day value. If this + ** is not the first modifier, or if the prior argument is not a numeric + ** value in the allowed range of julian day numbers understood by + ** SQLite (0..5373484.5) then the result will be NULL. + */ + if( sqlite3_stricmp(z, "julianday")==0 ){ + if( p->validJD && p->rawS ){ + rc = 0; + p->rawS = 0; + } + } + break; + } #ifndef SQLITE_OMIT_LOCALTIME case 'l': { /* localtime @@ -926,6 +965,24 @@ static void juliandayFunc( } } +/* +** unixepoch( TIMESTRING, MOD, MOD, ...) +** +** Return the number of seconds (including fractional seconds) since +** the unix epoch of 1970-01-01 00:00:00 GMT. +*/ +static void unixepochFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + computeJD(&x); + sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); + } +} + /* ** datetime( TIMESTRING, MOD, MOD, ...) ** @@ -1202,6 +1259,7 @@ void sqlite3RegisterDateTimeFunctions(void){ static FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS PURE_DATE(julianday, -1, 0, 0, juliandayFunc ), + PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ), PURE_DATE(date, -1, 0, 0, dateFunc ), PURE_DATE(time, -1, 0, 0, timeFunc ), PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), From 4a0a98d3fdd51cf91b581a2ea2bb12b91ba73b7e Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 29 Nov 2021 17:55:12 +0000 Subject: [PATCH 003/148] Bump the version number up to 3.38.0 in order to begin the next development cycle. FossilOrigin-Name: 8ad1fcaa1b734e32d8d67c4cca7a23d2b9717ae5c7c2c5ad5a3411a503ee23ae --- VERSION | 2 +- configure | 80 ++++++++++++++++++++++----------------------------- configure.ac | 11 +++++++ manifest | 16 +++++------ manifest.uuid | 2 +- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/VERSION b/VERSION index c03c47aa89..4f7d6a223d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.37.0 +3.38.0 diff --git a/configure b/configure index 8da48f587a..74dddfe76e 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.37.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.38.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.37.0' -PACKAGE_STRING='sqlite 3.37.0' +PACKAGE_VERSION='3.38.0' +PACKAGE_STRING='sqlite 3.38.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -770,11 +770,11 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS BUILD_CFLAGS +AMALGAMATION_LINE_MACROS USE_GCOV OPT_FEATURE_FLAGS HAVE_ZLIB USE_AMALGAMATION -AMALGAMATION_LINE_MACROS TARGET_DEBUG TARGET_HAVE_EDITLINE TARGET_HAVE_READLINE @@ -903,7 +903,6 @@ with_readline_lib with_readline_inc enable_debug enable_amalgamation -amalgamation_line_macros enable_load_extension enable_math enable_all @@ -1469,7 +1468,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.37.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.38.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1534,7 +1533,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.37.0:";; + short | recursive ) echo "Configuration of sqlite 3.38.0:";; esac cat <<\_ACEOF @@ -1662,7 +1661,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.37.0 +sqlite configure 3.38.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2081,7 +2080,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.37.0, which was +It was created by sqlite $as_me 3.38.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3939,13 +3938,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:3940: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3941: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:3943: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3944: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:3946: output\"" >&5) + (eval echo "\"\$as_me:3947: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5151,7 +5150,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5152 "configure"' > conftest.$ac_ext + echo '#line 5153 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6676,11 +6675,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:6677: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6678: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6681: \$? = $ac_status" >&5 + echo "$as_me:6682: \$? = $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. @@ -7015,11 +7014,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:7016: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7017: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7020: \$? = $ac_status" >&5 + echo "$as_me:7021: \$? = $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. @@ -7120,11 +7119,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:7121: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7122: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7125: \$? = $ac_status" >&5 + echo "$as_me:7126: \$? = $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 @@ -7175,11 +7174,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:7176: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7177: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7180: \$? = $ac_status" >&5 + echo "$as_me:7181: \$? = $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 @@ -9555,7 +9554,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9556 "configure" +#line 9557 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -9651,7 +9650,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9652 "configure" +#line 9653 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10307,13 +10306,6 @@ done # USE_AMALGAMATION=1 -######### -# By default, amalgamation sqlite3.c will have #line directives. -# This is a build option not shown by ./configure --help -# To control it, use configure option: amalgamation_line_macros=? -# where ? is no to suppress #line directives or yes to create them. -AMALGAMATION_LINE_MACROS=--linemacros=0 - ######### # See whether we can run specific tclsh versions known to work well; # if not, then we fall back to plain tclsh. @@ -11284,19 +11276,6 @@ if test "${enable_amalgamation}" = "no" ; then USE_AMALGAMATION=0 fi -######## -# See whether --disable -if test "${amalgamation_line_macros+set}" = set; then : - enableval=$amalgamation_line_macros; -fi - -if test "${amalgamation_line_macros}" = "yes" ; then - AMALGAMATION_LINE_MACROS=--linemacros=1 -fi -if test "${amalgamation_line_macros}" = "no" ; then - AMALGAMATION_LINE_MACROS=--linemacros=0 -fi - ######### # Look for zlib. Only needed by extensions and by the sqlite3.exe shell @@ -11882,6 +11861,17 @@ else fi +######### +# Enable/disabled amalagamation line macros +######## +AMALGAMATION_LINE_MACROS=--linemacros=0 +if test "${amalgamation_line_macros}" = "yes" ; then + AMALGAMATION_LINE_MACROS=--linemacros=1 +fi +if test "${amalgamation_line_macros}" = "no" ; then + AMALGAMATION_LINE_MACROS=--linemacros=0 +fi + ######### # Output the config header @@ -12400,7 +12390,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.37.0, which was +This file was extended by sqlite $as_me 3.38.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12466,7 +12456,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.37.0 +sqlite config.status 3.38.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 70664dd411..32fe0d229a 100644 --- a/configure.ac +++ b/configure.ac @@ -791,6 +791,17 @@ else fi AC_SUBST(USE_GCOV) +######### +# Enable/disabled amalagamation line macros +######## +AMALGAMATION_LINE_MACROS=--linemacros=0 +if test "${amalgamation_line_macros}" = "yes" ; then + AMALGAMATION_LINE_MACROS=--linemacros=1 +fi +if test "${amalgamation_line_macros}" = "no" ; then + AMALGAMATION_LINE_MACROS=--linemacros=0 +fi +AC_SUBST(AMALGAMATION_LINE_MACROS) ######### # Output the config header diff --git a/manifest b/manifest index 262f1306c1..a2d8a55243 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Following\sa\sprior\serror,\san\sALWAYS()\sin\ssqlite3ExprCanBeNull()\smight\sbe\sfalse.\ndbsqlfuzz\s5dbec6678a20e7595a34dfdd869a3b9722b3ca43. -D 2021-11-28T19:54:38.307 +C Bump\sthe\sversion\snumber\sup\sto\s3.38.0\sin\sorder\sto\sbegin\sthe\snext\sdevelopment\ncycle. +D 2021-11-29T17:55:12.431 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -7,7 +7,7 @@ F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110 -F VERSION c6595fef606851f2bc3ebed6a7386c73751835fc909feab7c093739fa4b3c1d1 +F VERSION 392c2f83569705069415a5d98b1c138ec8fe8a56a663a0d94cea019e806537b2 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -34,8 +34,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559 -F configure e8003577b8c433cf61371d27d4beeca3a3ed37611a504ff5f4d4286923b87d03 x -F configure.ac 4e4b58b32f88c8da9914a2f2c3158f80e69907eccc019fcc7e3ba14ffd91c640 +F configure 56f2a6637cdba53788673ccc229c4f95ab3ab6fe67036e0b1291dc615e531a58 x +F configure.ac c8ba54bac7e73e000acdfef5e394fe21a3876aa09d0f5c07131bf5ac5a525299 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a -R ee6ac26534b5f5e3f1e9b2504f0fbd97 +P 4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 +R eb4491ad1178d62465400ed80ca522fe U drh -Z 9896c4e7bad9bcf4c4f3ad7c3deddb22 +Z 5bc34b2c0243a296f12576ce491eb989 diff --git a/manifest.uuid b/manifest.uuid index 5374c9a521..08c6297d97 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e207401acce1bdc17025f2d55bd94234b435e286cd43e1eda03b6949a2a91d3 \ No newline at end of file +8ad1fcaa1b734e32d8d67c4cca7a23d2b9717ae5c7c2c5ad5a3411a503ee23ae \ No newline at end of file From c1085ea412b5c78d58cad59273d71f44d39843c5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 30 Nov 2021 14:07:58 +0000 Subject: [PATCH 004/148] In the automatic index generator logic, be more precise about when a partial automatic index is allowed in order to capture more cases where it is legal to use a partial automatic index. FossilOrigin-Name: 664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 --- manifest | 15 ++++--- manifest.uuid | 2 +- src/where.c | 14 +++---- test/autoindex4.test | 93 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 3577caddb5..1799086100 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\sproposed\sdate/time\sfunction\senhancements:\s\s(1)\sAdd\sthe\nunixepoch()\sfunction,\s(2)\sthe\s'auto'\smodifier\sand\s(3)\sthe\s'julianday'\smodifier. -D 2021-11-29T18:09:54.447 +C In\sthe\sautomatic\sindex\sgenerator\slogic,\sbe\smore\sprecise\sabout\swhen\sa\npartial\sautomatic\sindex\sis\sallowed\sin\sorder\sto\scapture\smore\scases\swhere\sit\nis\slegal\sto\suse\sa\spartial\sautomatic\sindex. +D 2021-11-30T14:07:58.372 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c de0d4ff409c7b62a8803f9f267cc2c7fedddbc00de9ab7b5382c507383c18665 +F src/where.c 4b276017881185d0e1dc984df66c835cde6faf03834ef9ff34f48653f9144dec F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 @@ -705,7 +705,7 @@ F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728 F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5 -F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf +F test/autoindex4.test 75cb1191a552b8201351f5a50d160fcb9387a0fbbfb820c77798bfee7da3f8cf F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3 F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df F test/autovacuum2.test 76f7eb4fe6a6bf6d33a196a7141dba98886d2fb53a268d7feca285d5da4759d7 @@ -1933,8 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8ad1fcaa1b734e32d8d67c4cca7a23d2b9717ae5c7c2c5ad5a3411a503ee23ae 559fdc0aa76f4c207f99f7b0cee42043b402dc388165817529d9963b115a798c -R ff09119d5c0ee6b5a0429abffd206856 -T +closed 559fdc0aa76f4c207f99f7b0cee42043b402dc388165817529d9963b115a798c +P 19c51b46e4095ee28badb10f4e08bbd330bda320c9a8806e93b8fc60ba211a2e +R 0fbfb4a13255ae0bad405a99d2bdf9ec U drh -Z 24b943d8efa351054aa299f0bcbeffcd +Z 511f59b4656ae7d0825d672340080bad diff --git a/manifest.uuid b/manifest.uuid index d0851eaaea..8a15f64b8a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -19c51b46e4095ee28badb10f4e08bbd330bda320c9a8806e93b8fc60ba211a2e \ No newline at end of file +664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 7a8342675d..54e4ea8196 100644 --- a/src/where.c +++ b/src/where.c @@ -791,13 +791,13 @@ static void constructAutomaticIndex( idxCols = 0; for(pTerm=pWC->a; pTermpExpr; - assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ - || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ - || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ - if( pLoop->prereq==0 - && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && !ExprHasProperty(pExpr, EP_FromJoin) - && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ + /* Make the automatic index a partial index if there are terms in the + ** WHERE clause (or the ON clause of a LEFT join) that constrain which + ** rows of the target table (pSrc) that can be used. */ + if( (pTerm->wtFlags & TERM_VIRTUAL)==0 + && ((pSrc->fg.jointype&JT_LEFT)==0 || ExprHasProperty(pExpr,EP_FromJoin)) + && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) + ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); } diff --git a/test/autoindex4.test b/test/autoindex4.test index 0e7a80df21..24604af588 100644 --- a/test/autoindex4.test +++ b/test/autoindex4.test @@ -79,5 +79,98 @@ do_execsql_test autoindex4-3.1 { ORDER BY Items.ItemName; } {Item1 Item2} +# 2021-11-30 - Enhancement to help the automatic index mechanism to +# create a partial index more often. +# +unset -nocomplain id data1 data2 jointype onclause whereclause answer +foreach {id data1 data2 jointype onclause whereclause answer} { + 1 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4) + {LEFT JOIN} + a=x + {y=4 OR y IS NULL} + {3 4 3 4} + + 2 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4) + {LEFT JOIN} + {a=x AND y=4} + {coalesce(y,4)==4} + {1 2 {} {} 3 4 3 4} + + 3 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4) + {JOIN} + {a=x} + {y=4 OR y IS NULL} + {3 4 3 4} + + 4 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4) + {JOIN} + {a=x AND y=4} + {coalesce(y,4)==4} + {3 4 3 4} + + 5 + VALUES(1,2),(3,4),(NULL,4) + VALUES(1,2),(3,4) + {LEFT JOIN} + a=x + {y=4 OR y IS NULL} + {3 4 3 4 {} 4 {} {}} + + 6 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4),(NULL,4) + {LEFT JOIN} + {a=x AND y=4} + {coalesce(y,4)==4} + {1 2 {} {} 3 4 3 4} + + 7 + VALUES(1,2),(3,4),(NULL,4) + VALUES(1,2),(3,4),(NULL,4) + {JOIN} + {a=x} + {y=4 OR y IS NULL} + {3 4 3 4} + + 8 + VALUES(1,2),(3,4) + VALUES(1,2),(3,4) + {JOIN} + {a=x AND y=4} + {coalesce(y,4)==4} + {3 4 3 4} +} { + do_test autoindex4-4.$id.0 { + db eval { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INT, b INT); + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(x INT, y INT); + } + db eval "INSERT INTO t1(a,b) $data1;" + db eval "INSERT INTO t2(x,y) $data2;" + } {} + set sql "SELECT * FROM t1 $jointype t2 ON $onclause WHERE $whereclause" + # puts "sql = $sql" + do_test autoindex4-4.$id.1 { + db eval {PRAGMA automatic_index=ON;} + db eval $sql + } $answer + do_test autoindex4-4.$id.2 { + db eval {PRAGMA automatic_index=OFF;} + db eval $sql + } $answer +} + + + finish_test From 4baf43ff647ab8c6752e7fdd12efd1a979afd476 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 1 Dec 2021 11:03:50 +0000 Subject: [PATCH 005/148] Add the "static" qualifier to some internal functions in code for various SQLite extensions. FossilOrigin-Name: 8c986782547211098eb0e4e722eda0097421223af279381373d0055211b5e9d2 --- ext/expert/sqlite3expert.c | 2 +- ext/misc/sha1.c | 2 +- ext/misc/zipfile.c | 4 ++-- ext/rbu/sqlite3rbu.c | 2 +- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ext/expert/sqlite3expert.c b/ext/expert/sqlite3expert.c index a5eb109b46..f7a17e6ddc 100644 --- a/ext/expert/sqlite3expert.c +++ b/ext/expert/sqlite3expert.c @@ -1168,7 +1168,7 @@ static void idxWriteFree(IdxWrite *pTab){ ** runs all the queries to see which indexes they prefer, and populates ** IdxStatement.zIdx and IdxStatement.zEQP with the results. */ -int idxFindIndexes( +static int idxFindIndexes( sqlite3expert *p, char **pzErr /* OUT: Error message (sqlite3_malloc) */ ){ diff --git a/ext/misc/sha1.c b/ext/misc/sha1.c index 9fe6cae740..9790a1d877 100644 --- a/ext/misc/sha1.c +++ b/ext/misc/sha1.c @@ -71,7 +71,7 @@ struct SHA1Context { /* * Hash a single 512-bit block. This is the core of the algorithm. */ -void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){ +static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){ unsigned int qq[5]; /* a, b, c, d, e; */ static int one = 1; unsigned int block[16]; diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c index b7ceb9396d..db2aa78cc7 100644 --- a/ext/misc/zipfile.c +++ b/ext/misc/zipfile.c @@ -1938,7 +1938,7 @@ static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ ** SELECT zipfile(name,mode,mtime,data) ... ** SELECT zipfile(name,mode,mtime,data,method) ... */ -void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ +static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ ZipfileCtx *p; /* Aggregate function context */ ZipfileEntry e; /* New entry to add to zip archive */ @@ -2113,7 +2113,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ /* ** xFinalize() callback for zipfile aggregate function. */ -void zipfileFinal(sqlite3_context *pCtx){ +static void zipfileFinal(sqlite3_context *pCtx){ ZipfileCtx *p; ZipfileEOCD eocd; sqlite3_int64 nZip; diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 202712cca2..27a3720daa 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -1563,7 +1563,7 @@ static char *rbuVacuumTableStart( ** 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( +static char *rbuVacuumIndexStart( sqlite3rbu *p, /* RBU handle */ RbuObjIter *pIter /* RBU iterator object */ ){ diff --git a/manifest b/manifest index 1799086100..8ce5d39d14 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sautomatic\sindex\sgenerator\slogic,\sbe\smore\sprecise\sabout\swhen\sa\npartial\sautomatic\sindex\sis\sallowed\sin\sorder\sto\scapture\smore\scases\swhere\sit\nis\slegal\sto\suse\sa\spartial\sautomatic\sindex. -D 2021-11-30T14:07:58.372 +C Add\sthe\s"static"\squalifier\sto\ssome\sinternal\sfunctions\sin\scode\sfor\svarious\sSQLite\sextensions. +D 2021-12-01T11:03:50.030 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -51,7 +51,7 @@ F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a4980828 F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 F ext/expert/expert1.test 3c642a4e7bbb14f21ddab595436fb465a4733f47a0fe5b2855e1d5ff900ef08e -F ext/expert/sqlite3expert.c 921a00823a826150cbb9a3341285a8edec7533480b71281e77737f19559b4b14 +F ext/expert/sqlite3expert.c f09943e849d603a0c001471e229b2522bae7a70a77a5e28b16429ca2bb4240dc F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e @@ -321,7 +321,7 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6 F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946 F ext/misc/series.c f9896e76b029e3c6553c520552555e803e26e7dfe1890d5866243cf072d938d0 -F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac +F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f @@ -338,7 +338,7 @@ F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546 -F ext/misc/zipfile.c 5dcbbdae13ba45db5d3843b6f32a8f99df7ab0349a704857a3000618f9ea9ecb +F ext/misc/zipfile.c 238ccb990ed45a74e24d0fbb449d7752a568c2b7c1d5b255d451f11703ced592 F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2 @@ -381,7 +381,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697 F ext/rbu/rbuvacuum2.test 886add83fd74bcb02e6dd016ae5b585367bd58c5d0694c9d9ca7bdb1d1f578c2 F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10 -F ext/rbu/sqlite3rbu.c 3658f1c6603955c7426952b74a6896337b1f672d326cd565e5af20e18d5744f0 +F ext/rbu/sqlite3rbu.c 8737cabdfbee84bb25a7851ecef8b1312be332761238da9be6ddb10c62ad4291 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 19c51b46e4095ee28badb10f4e08bbd330bda320c9a8806e93b8fc60ba211a2e -R 0fbfb4a13255ae0bad405a99d2bdf9ec -U drh -Z 511f59b4656ae7d0825d672340080bad +P 664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 +R d309262586a9f358c551d21c41a37e90 +U dan +Z 906fededd9ee4cd9607f33e04b9150f2 diff --git a/manifest.uuid b/manifest.uuid index 8a15f64b8a..306d239d05 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 \ No newline at end of file +8c986782547211098eb0e4e722eda0097421223af279381373d0055211b5e9d2 \ No newline at end of file From 2db144c33b39985b159ec9210cc13bdb53c00e1c Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 1 Dec 2021 16:31:02 +0000 Subject: [PATCH 006/148] Add a Bloom filter to the automatic-index mechanism. FossilOrigin-Name: 50ac4de1d7cbb586ea7969e1ae80ea8b021e194edc2fa7db19374b4ee9369bee --- manifest | 27 ++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 1 + src/vdbe.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vdbeInt.h | 2 +- src/vdbemem.c | 4 +- src/where.c | 8 ++++ src/whereInt.h | 1 + src/wherecode.c | 8 ++++ 9 files changed, 143 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 1799086100..8fae6a4e21 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sautomatic\sindex\sgenerator\slogic,\sbe\smore\sprecise\sabout\swhen\sa\npartial\sautomatic\sindex\sis\sallowed\sin\sorder\sto\scapture\smore\scases\swhere\sit\nis\slegal\sto\suse\sa\spartial\sautomatic\sindex. -D 2021-11-30T14:07:58.372 +C Add\sa\sBloom\sfilter\sto\sthe\sautomatic-index\smechanism. +D 2021-12-01T16:31:02.486 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -555,7 +555,7 @@ F src/shell.c.in 975f268ef261773fcbed1e519dfa10c4f33e8b1cffc12120563e61857fff07c F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 193e716a67c877a6054a8c261c932bdc64f8c8be9b66388c74f21d94a259b7ce +F src/sqliteInt.h a44a3474b2247a82decc17644c68e00db5ba1bc239a6c005f6c08f6599083c01 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -622,13 +622,13 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c e98f1baf54a00db2c4669dbd04f8bbc89b5909a5b43e76fbbbf1a97007adba2b +F src/vdbe.c a77525ddf690771b13db4114dce5305657efe6b7393920f2cbaa2447e8b83129 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe -F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab +F src/vdbeInt.h fd1103c7ecec8c84164038c8eacaa4a633cb3c10a2f725aae7bd865d4a4fcceb F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a F src/vdbeaux.c 21db442d159fd745a7693d157b5f998260b6af4ca60de559fa3b7b68c7405af2 F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652 -F src/vdbemem.c a3d91dc9bb9ef725db77e4e9de7e1acef43192c9f8406c307665d503e3c2837c +F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c @@ -637,9 +637,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 4b276017881185d0e1dc984df66c835cde6faf03834ef9ff34f48653f9144dec -F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d -F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 +F src/where.c 1b8a6c53c34c59c765190484d245c457bedc211325de4c75a2070432fd67e314 +F src/whereInt.h 23f990791dc428f0bbb31f8ef5026b78b6290272de86185f4822c85f4c774803 +F src/wherecode.c 620e81077588a727876a86f87aab310c02fc4e4960691e48153d8a87ca1fa453 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 19c51b46e4095ee28badb10f4e08bbd330bda320c9a8806e93b8fc60ba211a2e -R 0fbfb4a13255ae0bad405a99d2bdf9ec +P 664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 +R 157be6898a36d49d7a017b78b4cdbad6 +T *branch * bloom-filter +T *sym-bloom-filter * +T -sym-trunk * U drh -Z 511f59b4656ae7d0825d672340080bad +Z 5c7d4c8ea12d463e648cb44a868717dc diff --git a/manifest.uuid b/manifest.uuid index 8a15f64b8a..2cbf640244 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 \ No newline at end of file +50ac4de1d7cbb586ea7969e1ae80ea8b021e194edc2fa7db19374b4ee9369bee \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b45151104a..d404b7b4fc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1761,6 +1761,7 @@ struct sqlite3 { #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ +#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* diff --git a/src/vdbe.c b/src/vdbe.c index 3476c02daa..e38527356c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -671,6 +671,35 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ } } +/* +** Default size of a bloom filter, in bytes +*/ +#define SQLITE_BLOOM_SZ 10000 + +/* +** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning +** with pOp->p3. Return the hash. +*/ +static unsigned int filterHash(const Mem *aMem, const Op *pOp){ + int i, mx; + u32 h = 0; + + i = pOp->p3; + assert( pOp->p4type==P4_INT32 ); + mx = i + pOp->p4.i; + for(i=pOp->p3, mx=i+pOp->p4.i; iflags & (MEM_Int|MEM_IntReal) ){ + h += (u32)(p->u.i&0xffffffff); + }else if( p->flags & MEM_Real ){ + h += (u32)(sqlite3VdbeIntValue(p)&0xffffffff); + }else if( p->flags & (MEM_Str|MEM_Blob) ){ + h += p->n; + } + } + return h % (SQLITE_BLOOM_SZ*8); +} + /* ** Return the symbolic name for the data type of a pMem */ @@ -8129,6 +8158,83 @@ case OP_Function: { /* group */ break; } +/* Opcode: FilterInit P1 * * * * +** Synopsis: filter(P1) = empty +** +** Initialize register P1 so that is an empty bloom filter. +*/ +case OP_FilterInit: { + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + sqlite3VdbeMemSetZeroBlob(pIn1, SQLITE_BLOOM_SZ); + if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; + break; +} + +/* Opcode: FilterAdd P1 * P3 P4 * +** Synopsis: filter(P1) += key(P3@P4) +** +** Compute a hash on the P4 registers starting with r[P3] and +** add that hash to the bloom filter contained in r[P1]. +*/ +case OP_FilterAdd: { + u32 h; + + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags & MEM_Blob ); + assert( pIn1->n==SQLITE_BLOOM_SZ ); + h = filterHash(aMem, pOp); +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + int ii; + for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ + registerTrace(ii, &aMem[ii]); + } + printf("hash = %u\n", h); + } +#endif + assert( h>=0 && hz[h/8] |= 1<<(h&7); + break; +} + +/* Opcode: Filter P1 P2 P3 P4 * +** Synopsis: if key(P3@P4) not in filter(P1) goto P2 +** +** Compute a hash on the key contained in the P4 registers starting +** with r[P3]. Check to see if that hash is found in the +** bloom filter hosted by register P1. If it is not present then +** maybe jump to P2. Otherwise fall through. +** +** False negatives are harmless. It is always safe to fall through, +** even if the value is in the bloom filter. A false negative causes +** more CPU cycles to be used, but it should still yield the correct +** answer. However, an incorrect answer may well arise from a +** false positive - if the jump is taken when it should fall through. +*/ +case OP_Filter: { /* jump */ + u32 h; + + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags & MEM_Blob ); + assert( pIn1->n==SQLITE_BLOOM_SZ ); + h = filterHash(aMem, pOp); +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + int ii; + for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ + registerTrace(ii, &aMem[ii]); + } + printf("hash = %u\n", h); + } +#endif + assert( h>=0 && hz[h/8] & (1<<(h&7)))==0 ) goto jump_to_p2; + break; +} + /* Opcode: Trace P1 P2 * P4 * ** ** Write P4 on the statement trace output if statement tracing is diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 599d064165..c76cdbfdbc 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -538,7 +538,7 @@ int sqlite3VdbeMemSetRowSet(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); int sqlite3VdbeMemStringify(Mem*, u8, u8); int sqlite3IntFloatCompare(i64,double); -i64 sqlite3VdbeIntValue(Mem*); +i64 sqlite3VdbeIntValue(const Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); int sqlite3VdbeBooleanValue(Mem*, int ifNull); diff --git a/src/vdbemem.c b/src/vdbemem.c index 570a2eb38c..5a9d15f465 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -596,12 +596,12 @@ static SQLITE_NOINLINE i64 doubleToInt64(double r){ ** ** If pMem represents a string value, its encoding might be changed. */ -static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){ +static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){ i64 value = 0; sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; } -i64 sqlite3VdbeIntValue(Mem *pMem){ +i64 sqlite3VdbeIntValue(const Mem *pMem){ int flags; assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); diff --git a/src/where.c b/src/where.c index 54e4ea8196..eaa45b0198 100644 --- a/src/where.c +++ b/src/where.c @@ -904,6 +904,10 @@ static void constructAutomaticIndex( sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); + if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ + pLevel->regFilter = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); + } /* Fill the automatic index with content */ pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; @@ -926,6 +930,10 @@ static void constructAutomaticIndex( regBase = sqlite3GenerateIndexKey( pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 ); + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, + regBase, pLoop->u.btree.nEq); + } sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); diff --git a/src/whereInt.h b/src/whereInt.h index f651e790cc..5b076e40e2 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -64,6 +64,7 @@ struct WhereLevel { u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif + int regFilter; /* Bloom filter */ 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 end the loop */ diff --git a/src/wherecode.c b/src/wherecode.c index 460ac4fe30..637db432ea 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1511,6 +1511,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, + iRowidReg, 1); + } sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); pLevel->op = OP_Noop; @@ -1836,6 +1840,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); VdbeComment((v, "NULL-scan pass ctr")); } + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, + regBase, nConstraint); + } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); From 3b26b2b56bea391120660b01836fa03bbde089f6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 1 Dec 2021 19:17:14 +0000 Subject: [PATCH 007/148] Check for foreign key constraint errors prior to returning the results from a RETURNING clause. See [forum:/forumpost/793beaf322|forum post 793beaf322]. FossilOrigin-Name: a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 --- manifest | 26 +++++++++++++------------- manifest.uuid | 2 +- src/build.c | 1 + src/delete.c | 14 +++++++++++--- src/insert.c | 4 +--- src/sqliteInt.h | 1 + src/update.c | 4 +--- src/vdbe.c | 22 ++++++++++------------ test/returning1.test | 13 +++++++++++++ 9 files changed, 52 insertions(+), 35 deletions(-) diff --git a/manifest b/manifest index 8ce5d39d14..879da8796e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"static"\squalifier\sto\ssome\sinternal\sfunctions\sin\scode\sfor\svarious\sSQLite\sextensions. -D 2021-12-01T11:03:50.030 +C Check\sfor\sforeign\skey\sconstraint\serrors\sprior\sto\sreturning\sthe\sresults\sfrom\na\sRETURNING\sclause.\s\sSee\s[forum:/forumpost/793beaf322|forum\spost\s793beaf322]. +D 2021-12-01T19:17:14.951 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -494,14 +494,14 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 13b965a0f3cd57221e3b4e61e24452ec264a5b163de347b03b5039ddcd95cd54 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c c46bd4f5a69f398410c4472f7c1c4291fb8078d2c9758a2dad5916edd1d30ecc +F src/build.c 179b11b07484497052096d88b953b9a6c22cbb0c23ba75c4347e9a99dae4a6c0 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 F src/date.c d0f09f7924a27e0d8a41b41a781ccc680b102c35b5e9a94d129d58ba9d849ff2 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d -F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7 +F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5 @@ -511,7 +511,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 7fcbbe9114ac402ea3c0c6a3810f13fc89cae8131ea1659ec472be7caac10192 +F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c F src/main.c 7bd4fdc41ef53535271a1816ff043ba153cda03842b444b6e2f57b27b2cb9090 @@ -555,7 +555,7 @@ F src/shell.c.in 975f268ef261773fcbed1e519dfa10c4f33e8b1cffc12120563e61857fff07c F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 193e716a67c877a6054a8c261c932bdc64f8c8be9b66388c74f21d94a259b7ce +F src/sqliteInt.h 375bb03b5c2de4c3e2f746e6205f01b8a51abd5835a1a72ab9a1c027f5c9849e F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -617,12 +617,12 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 865911afa00fed589cd03b25c140ca88544842aaef7b81f7d41ed769a7a54120 F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254 -F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d +F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c e98f1baf54a00db2c4669dbd04f8bbc89b5909a5b43e76fbbbf1a97007adba2b +F src/vdbe.c f25438ea079ff2a363c2cc0b70f3178fcf48d3c82ebe72534736a702a4d0eb54 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -1308,7 +1308,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2 F test/releasetest_data.tcl 7cea6c852ae6bb3a9ff1a2b910e4dd13c16a05f74443984dfd52159b0b01ea55 F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb -F test/returning1.test f96c7245f6ac16038e802760cd90b93479369939a8a7a44e2329ee5aed28239c +F test/returning1.test 76e4e8016e92a6abeaf15503fbf36deabbdc8b988d11edc2f7f82e18a56e35bd F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 664b461bb5063d98047fc2e51a3827235cd9f55ca2e23cb66e719eac53fb5437 -R d309262586a9f358c551d21c41a37e90 -U dan -Z 906fededd9ee4cd9607f33e04b9150f2 +P 8c986782547211098eb0e4e722eda0097421223af279381373d0055211b5e9d2 +R 21e311cc3a849b363a459e68e73e4039 +U drh +Z aa1759274fb4dd09e62bccb20e559386 diff --git a/manifest.uuid b/manifest.uuid index 306d239d05..22dfac2e19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8c986782547211098eb0e4e722eda0097421223af279381373d0055211b5e9d2 \ No newline at end of file +a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 \ No newline at end of file diff --git a/src/build.c b/src/build.c index d53ff3b670..d225227de8 100644 --- a/src/build.c +++ b/src/build.c @@ -173,6 +173,7 @@ void sqlite3FinishCoding(Parse *pParse){ if( pReturning->nRetCol==0 ){ assert( CORRUPT_DB ); }else{ + sqlite3VdbeAddOp0(v, OP_FkCheck); addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); VdbeCoverage(v); diff --git a/src/delete.c b/src/delete.c index e2b283ea47..9c56858e79 100644 --- a/src/delete.c +++ b/src/delete.c @@ -44,6 +44,16 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ return pTab; } +/* Generate byte-code that will report the number of rows modified +** by a DELETE, INSERT, or UPDATE statement. +*/ +void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){ + sqlite3VdbeAddOp0(v, OP_FkCheck); + sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC); +} + /* Return true if table pTab is read-only. ** ** A table is read-only if any of the following are true: @@ -619,9 +629,7 @@ void sqlite3DeleteFrom( ** invoke the callback function. */ if( memCnt ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); + sqlite3CodeChangeCount(v, memCnt, "rows deleted"); } delete_from_cleanup: diff --git a/src/insert.c b/src/insert.c index 97205cb2ae..96e86c9fb2 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1382,9 +1382,7 @@ insert_end: ** invoke the callback function. */ if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); + sqlite3CodeChangeCount(v, regRowCount, "rows inserted"); } insert_cleanup: diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b45151104a..c1a0d9853e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4563,6 +4563,7 @@ void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif +void sqlite3CodeChangeCount(Vdbe*,int,const char*); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, Upsert*); diff --git a/src/update.c b/src/update.c index 484bee47cd..ed96dc8b2d 100644 --- a/src/update.c +++ b/src/update.c @@ -1121,9 +1121,7 @@ void sqlite3Update( ** that information. */ if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); + sqlite3CodeChangeCount(v, regRowCount, "rows updated"); } update_cleanup: diff --git a/src/vdbe.c b/src/vdbe.c index 3476c02daa..7dfe379175 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1479,24 +1479,22 @@ case OP_IntCopy: { /* out2 */ break; } -/* Opcode: ChngCntRow P1 P2 * * * -** Synopsis: output=r[P1] +/* Opcode: FkCheck * * * * * ** -** Output value in register P1 as the chance count for a DML statement, -** due to the "PRAGMA count_changes=ON" setting. Or, if there was a -** foreign key error in the statement, trigger the error now. +** Halt with an SQLITE_CONSTRAINT error if there are any unresolved +** foreign key constraint violations. If there are no foreign key +** constraint violations, this is a no-op. ** -** This opcode is a variant of OP_ResultRow that checks the foreign key -** immediate constraint count and throws an error if the count is -** non-zero. The P2 opcode must be 1. +** FK constraint violations are also checked when the prepared statement +** exits. This opcode is used to raise foreign key constraint errors prior +** to returning results such as a row change count or the result of a +** RETURNING clause. */ -case OP_ChngCntRow: { - assert( pOp->p2==1 ); +case OP_FkCheck: { if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){ goto abort_due_to_error; } - /* Fall through to the next case, OP_ResultRow */ - /* no break */ deliberate_fall_through + break; } /* Opcode: ResultRow P1 P2 * * * diff --git a/test/returning1.test b/test/returning1.test index c64e72f723..b471544fd4 100644 --- a/test/returning1.test +++ b/test/returning1.test @@ -333,4 +333,17 @@ do_execsql_test 13.1 { } {{}} } ;# end ifcapable rtree +# 2021-12-01 Forum post https://sqlite.org/forum/forumpost/793beaf322 +# Need to report foreign key constraint errors prior to RETURNING +# +reset_db +do_execsql_test 14.0 { + PRAGMA foreign_keys(1); + CREATE TABLE Parent(id INTEGER PRIMARY KEY); + CREATE TABLE Child(id INTEGER PRIMARY KEY, parent_id INTEGER REFERENCES Parent(id)); +} {} +do_catchsql_test 14.1 { + INSERT INTO child(parent_id) VALUES(123) RETURNING id; +} {1 {FOREIGN KEY constraint failed}} + finish_test From 9b3bfa00cd232c102e826dd9b177ad66b962f359 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 01:30:16 +0000 Subject: [PATCH 008/148] Performance improvement in query planning. FossilOrigin-Name: ca59533bbb7f21d7b39dee7999d3f36ac516f8c75b2203039beeb2852ada42d4 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 17 +++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 879da8796e..aebe38655c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Check\sfor\sforeign\skey\sconstraint\serrors\sprior\sto\sreturning\sthe\sresults\sfrom\na\sRETURNING\sclause.\s\sSee\s[forum:/forumpost/793beaf322|forum\spost\s793beaf322]. -D 2021-12-01T19:17:14.951 +C Performance\simprovement\sin\squery\splanning. +D 2021-12-02T01:30:16.970 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 4b276017881185d0e1dc984df66c835cde6faf03834ef9ff34f48653f9144dec +F src/where.c db68967fe15efdddbc067835401a0c02e2d8460daee2fdda85ca491451865170 F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8c986782547211098eb0e4e722eda0097421223af279381373d0055211b5e9d2 -R 21e311cc3a849b363a459e68e73e4039 +P a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 +R b96a809fd19be7cd4fca1d2cbe967f1c U drh -Z aa1759274fb4dd09e62bccb20e559386 +Z 9b172105eb69d7dd67f53ef8928dc7e1 diff --git a/manifest.uuid b/manifest.uuid index 22dfac2e19..b993f82b37 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 \ No newline at end of file +ca59533bbb7f21d7b39dee7999d3f36ac516f8c75b2203039beeb2852ada42d4 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 54e4ea8196..fd67ac5f17 100644 --- a/src/where.c +++ b/src/where.c @@ -4868,12 +4868,6 @@ WhereInfo *sqlite3WhereBegin( if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; sWLB.pOrderBy = pOrderBy; - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ - wctrlFlags &= ~WHERE_WANT_DISTINCT; - } - /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ @@ -4940,7 +4934,9 @@ WhereInfo *sqlite3WhereBegin( */ if( nTabList==0 ){ if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; - if( wctrlFlags & WHERE_WANT_DISTINCT ){ + if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 + && OptimizationEnabled(db, SQLITE_DistinctOpt) + ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); @@ -5001,7 +4997,12 @@ WhereInfo *sqlite3WhereBegin( } if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ + if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ + /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via + ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ + wctrlFlags &= ~WHERE_WANT_DISTINCT; + pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT; + }else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ From 79ab38412186a2e19d0350d836ee95a84826cc94 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 02:22:35 +0000 Subject: [PATCH 009/148] Small performance enhancement for whereScanInit(). FossilOrigin-Name: ed84e124c6097b756ca687ac64df7ee801d14b16c835f1a9e8b336f785157d85 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index aebe38655c..f2027f792a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovement\sin\squery\splanning. -D 2021-12-02T01:30:16.970 +C Small\sperformance\senhancement\sfor\swhereScanInit(). +D 2021-12-02T02:22:35.475 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c db68967fe15efdddbc067835401a0c02e2d8460daee2fdda85ca491451865170 +F src/where.c 36e6ce4c1dd564885f2596e2c2aab61c7a56c7f9aeae63d6bb258d1464883ad6 F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a818ba2ed635b91e279dde44236fc7446a33db2b46c9409b67021248c01bf4e5 -R b96a809fd19be7cd4fca1d2cbe967f1c +P ca59533bbb7f21d7b39dee7999d3f36ac516f8c75b2203039beeb2852ada42d4 +R af3fe3cb608001edf986e30906f5d5ad U drh -Z 9b172105eb69d7dd67f53ef8928dc7e1 +Z e7cfc5073afcf7170a57b786bbc9a825 diff --git a/manifest.uuid b/manifest.uuid index b993f82b37..7e8fe9d6a3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca59533bbb7f21d7b39dee7999d3f36ac516f8c75b2203039beeb2852ada42d4 \ No newline at end of file +ed84e124c6097b756ca687ac64df7ee801d14b16c835f1a9e8b336f785157d85 \ No newline at end of file diff --git a/src/where.c b/src/where.c index fd67ac5f17..53fa001dee 100644 --- a/src/where.c +++ b/src/where.c @@ -419,16 +419,16 @@ static WhereTerm *whereScanInit( if( pIdx ){ int j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ){ - pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - pScan->zCollName = pIdx->azColl[j]; - pScan->aiColumn[0] = XN_EXPR; - return whereScanInitIndexExpr(pScan); - }else if( iColumn==pIdx->pTable->iPKey ){ + if( iColumn==pIdx->pTable->iPKey ){ iColumn = XN_ROWID; }else if( iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; + }else if( iColumn==XN_EXPR ){ + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + pScan->zCollName = pIdx->azColl[j]; + pScan->aiColumn[0] = XN_EXPR; + return whereScanInitIndexExpr(pScan); } }else if( iColumn==XN_EXPR ){ return 0; From dae2a109341fc22c2ebb1f03a8d8df61c3c1b03a Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 04:00:45 +0000 Subject: [PATCH 010/148] Small performance optimization in sqlite3WhereGetMask(). FossilOrigin-Name: 7edec54ab045c0493fc5d27d47d7bf0e08d3b0b298f428646fd3f0ee24dfcade --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 11 +++++++---- src/whereInt.h | 13 ++++--------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index f2027f792a..650ae769af 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\senhancement\sfor\swhereScanInit(). -D 2021-12-02T02:22:35.475 +C Small\sperformance\soptimization\sin\ssqlite3WhereGetMask(). +D 2021-12-02T04:00:45.798 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,8 +637,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 36e6ce4c1dd564885f2596e2c2aab61c7a56c7f9aeae63d6bb258d1464883ad6 -F src/whereInt.h 83877a75a1bce056ea44aff02f1dfa958ad1d6038c213ddadb8652003b45151d +F src/where.c 90903cab02f03aded5019e45cd1dec6adf307291a6af0e55fce5111e84cc9115 +F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ca59533bbb7f21d7b39dee7999d3f36ac516f8c75b2203039beeb2852ada42d4 -R af3fe3cb608001edf986e30906f5d5ad +P ed84e124c6097b756ca687ac64df7ee801d14b16c835f1a9e8b336f785157d85 +R 4968f927e754c905a194070e8df46560 U drh -Z e7cfc5073afcf7170a57b786bbc9a825 +Z 0a6600fef45926158d5c9c07197fe75a diff --git a/manifest.uuid b/manifest.uuid index 7e8fe9d6a3..3e8bb6ca63 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed84e124c6097b756ca687ac64df7ee801d14b16c835f1a9e8b336f785157d85 \ No newline at end of file +7edec54ab045c0493fc5d27d47d7bf0e08d3b0b298f428646fd3f0ee24dfcade \ No newline at end of file diff --git a/src/where.c b/src/where.c index 53fa001dee..a661940b39 100644 --- a/src/where.c +++ b/src/where.c @@ -232,13 +232,15 @@ whereOrInsert_done: ** iCursor is not in the set. */ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ - int i; + int i = 0; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - for(i=0; in; i++){ + assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 ); + assert( iCursor>=-1 ); + do{ if( pMaskSet->ix[i]==iCursor ){ return MASKBIT(i); } - } + }while( (++i)n ); return 0; } @@ -4926,7 +4928,8 @@ WhereInfo *sqlite3WhereBegin( /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ - initMaskSet(pMaskSet); + pMaskSet->n = 0; + pMaskSet->ix[0] = -99; sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); diff --git a/src/whereInt.h b/src/whereInt.h index f651e790cc..217dd0ba2a 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -292,11 +292,11 @@ struct WhereScan { WhereClause *pWC; /* WhereClause currently being scanned */ const char *zCollName; /* Required collating sequence, if not NULL */ Expr *pIdxExpr; /* Search for this index expression */ - char idxaff; /* Must match this affinity, if zCollName!=NULL */ - unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */ - unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */ - u32 opMask; /* Acceptable operators */ int k; /* Resume scanning at this->pWC->a[this->k] */ + u32 opMask; /* Acceptable operators */ + char idxaff; /* Must match this affinity, if zCollName!=NULL */ + unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */ + unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */ int aiCur[11]; /* Cursors in the equivalence class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */ }; @@ -377,11 +377,6 @@ struct WhereMaskSet { int ix[BMS]; /* Cursor assigned to each bit */ }; -/* -** Initialize a WhereMaskSet object -*/ -#define initMaskSet(P) (P)->n=0 - /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. From 844a89b518c47864e2c0e6d41ea85947c48519ed Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 12:34:05 +0000 Subject: [PATCH 011/148] More small performance optimizations for sqlite3WhereGetMask(). FossilOrigin-Name: 3de2c557d915d1b4a9b0e540d5e80ffb243e7123d0ec65c5052f4d6f1cce56b2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 15 ++++++++++----- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 650ae769af..1d0d293e6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\soptimization\sin\ssqlite3WhereGetMask(). -D 2021-12-02T04:00:45.798 +C More\ssmall\sperformance\soptimizations\sfor\ssqlite3WhereGetMask(). +D 2021-12-02T12:34:05.331 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 90903cab02f03aded5019e45cd1dec6adf307291a6af0e55fce5111e84cc9115 +F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed84e124c6097b756ca687ac64df7ee801d14b16c835f1a9e8b336f785157d85 -R 4968f927e754c905a194070e8df46560 +P 7edec54ab045c0493fc5d27d47d7bf0e08d3b0b298f428646fd3f0ee24dfcade +R 1c3ef5334121101d82935d790fc38231 U drh -Z 0a6600fef45926158d5c9c07197fe75a +Z 3bbf6be35a1404f46b703105b00b0544 diff --git a/manifest.uuid b/manifest.uuid index 3e8bb6ca63..d5b9582fdc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7edec54ab045c0493fc5d27d47d7bf0e08d3b0b298f428646fd3f0ee24dfcade \ No newline at end of file +3de2c557d915d1b4a9b0e540d5e80ffb243e7123d0ec65c5052f4d6f1cce56b2 \ No newline at end of file diff --git a/src/where.c b/src/where.c index a661940b39..925f98af16 100644 --- a/src/where.c +++ b/src/where.c @@ -232,15 +232,18 @@ whereOrInsert_done: ** iCursor is not in the set. */ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ - int i = 0; + int i; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 ); assert( iCursor>=-1 ); - do{ + if( pMaskSet->ix[0]==iCursor ){ + return 1; + } + for(i=1; in; i++){ if( pMaskSet->ix[i]==iCursor ){ return MASKBIT(i); } - }while( (++i)n ); + } return 0; } @@ -4916,6 +4919,10 @@ WhereInfo *sqlite3WhereBegin( memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; + pMaskSet->n = 0; + pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be + ** a valid cursor number, to avoid an initial + ** test for pMaskSet->n==0 in sqlite3WhereGetMask() */ sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); @@ -4928,8 +4935,6 @@ WhereInfo *sqlite3WhereBegin( /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ - pMaskSet->n = 0; - pMaskSet->ix[0] = -99; sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); From cdd905039666ba8c16f635621540cbd9b859bf93 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 12:55:05 +0000 Subject: [PATCH 012/148] Small performance optimization in sqlite3WhereClauseClear(). FossilOrigin-Name: 080b35e62e5c6bb4ea162bc75232b81e54da5e3e01e762127e228400e8afef1d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/whereexpr.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 1d0d293e6a..46ffc13fd4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\ssmall\sperformance\soptimizations\sfor\ssqlite3WhereGetMask(). -D 2021-12-02T12:34:05.331 +C Small\sperformance\soptimization\sin\ssqlite3WhereClauseClear(). +D 2021-12-02T12:55:05.367 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -640,7 +640,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c 17bdbf4f5b490e70a18635498f0b910a558f953a9bf80af7f19cbde6e60e6825 +F src/whereexpr.c 5780201555e62250ae176d40a1b840f63a3ab4fc015f286ac7e3dbea53c0b486 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7edec54ab045c0493fc5d27d47d7bf0e08d3b0b298f428646fd3f0ee24dfcade -R 1c3ef5334121101d82935d790fc38231 +P 3de2c557d915d1b4a9b0e540d5e80ffb243e7123d0ec65c5052f4d6f1cce56b2 +R 8a54b72f0460bed9e312d2981e2b1a82 U drh -Z 3bbf6be35a1404f46b703105b00b0544 +Z f5838c1c1adaaaafa1d74530a9dc2af4 diff --git a/manifest.uuid b/manifest.uuid index d5b9582fdc..b709254f66 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3de2c557d915d1b4a9b0e540d5e80ffb243e7123d0ec65c5052f4d6f1cce56b2 \ No newline at end of file +080b35e62e5c6bb4ea162bc75232b81e54da5e3e01e762127e228400e8afef1d \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index 53dd14031c..93992f4107 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1525,17 +1525,25 @@ void sqlite3WhereClauseInit( ** sqlite3WhereClauseInit(). */ void sqlite3WhereClauseClear(WhereClause *pWC){ - int i; - WhereTerm *a; sqlite3 *db = pWC->pWInfo->pParse->db; - for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ - if( a->wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, a->pExpr); - } - if( a->wtFlags & TERM_ORINFO ){ - whereOrInfoDelete(db, a->u.pOrInfo); - }else if( a->wtFlags & TERM_ANDINFO ){ - whereAndInfoDelete(db, a->u.pAndInfo); + if( pWC->nTerm>0 ){ + WhereTerm *a = pWC->a; + WhereTerm *aLast = &pWC->a[pWC->nTerm-1]; + while(1){ + if( a->wtFlags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, a->pExpr); + } + if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){ + if( a->wtFlags & TERM_ORINFO ){ + assert( (a->wtFlags & TERM_ANDINFO)==0 ); + whereOrInfoDelete(db, a->u.pOrInfo); + }else{ + assert( (a->wtFlags & TERM_ANDINFO)!=0 ); + whereAndInfoDelete(db, a->u.pAndInfo); + } + } + if( a==aLast ) break; + a++; } } if( pWC->a!=pWC->aStatic ){ From cbb7746caab4a6d258d55e7a76b7f81bea33993b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 13:45:10 +0000 Subject: [PATCH 013/148] Remove an unnecessary branch from exprAnalyze(), resulting in a small performance gain. FossilOrigin-Name: 3312be1db3519074393573265459f6a1eeabce541a9ef4d93689529ea2b8f739 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/whereexpr.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 46ffc13fd4..c51c6ca79e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\soptimization\sin\ssqlite3WhereClauseClear(). -D 2021-12-02T12:55:05.367 +C Remove\san\sunnecessary\sbranch\sfrom\sexprAnalyze(),\sresulting\sin\sa\ssmall\nperformance\sgain. +D 2021-12-02T13:45:10.819 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -640,7 +640,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c 5780201555e62250ae176d40a1b840f63a3ab4fc015f286ac7e3dbea53c0b486 +F src/whereexpr.c da93d2227cc5246fe4a79d130f2a1a215017e12d76a035434145c443abd6f64b F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3de2c557d915d1b4a9b0e540d5e80ffb243e7123d0ec65c5052f4d6f1cce56b2 -R 8a54b72f0460bed9e312d2981e2b1a82 +P 080b35e62e5c6bb4ea162bc75232b81e54da5e3e01e762127e228400e8afef1d +R a7ab895f8cfffd485e37af57ff425c88 U drh -Z f5838c1c1adaaaafa1d74530a9dc2af4 +Z 5fe3f769c9fffb4907c1638f83e89ed7 diff --git a/manifest.uuid b/manifest.uuid index b709254f66..7d6260d69b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -080b35e62e5c6bb4ea162bc75232b81e54da5e3e01e762127e228400e8afef1d \ No newline at end of file +3312be1db3519074393573265459f6a1eeabce541a9ef4d93689529ea2b8f739 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index 93992f4107..bb013f1c6f 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1070,9 +1070,11 @@ static void exprAnalyze( if( db->mallocFailed ){ return; } + assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; + assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; @@ -1084,8 +1086,6 @@ static void exprAnalyze( }else{ pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); } - }else if( op==TK_ISNULL ){ - pTerm->prereqRight = 0; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); } From 1872c5bd43f52a1aa4d14883ad9ece5ff7a7f0ec Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 2 Dec 2021 14:16:30 +0000 Subject: [PATCH 014/148] In the shell tool, avoid modifying internal data structures until after the arguments to ".open" have been parsed. FossilOrigin-Name: fcc509d325dabe06275e7804183bb8b4ba6470a45b443bc8292eecd0974e6367 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 34 +++++++++++++++++++--------------- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index c51c6ca79e..2a28256dc6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunnecessary\sbranch\sfrom\sexprAnalyze(),\sresulting\sin\sa\ssmall\nperformance\sgain. -D 2021-12-02T13:45:10.819 +C In\sthe\sshell\stool,\savoid\smodifying\sinternal\sdata\sstructures\suntil\safter\sthe\sarguments\sto\s".open"\shave\sbeen\sparsed. +D 2021-12-02T14:16:30.751 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 975f268ef261773fcbed1e519dfa10c4f33e8b1cffc12120563e61857fff07c6 +F src/shell.c.in e7ee6517544d075d9f06ee2571567026b89cf9fbeef16a74918019b1cb425764 F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 080b35e62e5c6bb4ea162bc75232b81e54da5e3e01e762127e228400e8afef1d -R a7ab895f8cfffd485e37af57ff425c88 -U drh -Z 5fe3f769c9fffb4907c1638f83e89ed7 +P 3312be1db3519074393573265459f6a1eeabce541a9ef4d93689529ea2b8f739 +R 7b39f65268d7d5d5ddeb7e728b46cc8a +U dan +Z 6583dbaeea3c12c619555be53ea08d30 diff --git a/manifest.uuid b/manifest.uuid index 7d6260d69b..c442c9baae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3312be1db3519074393573265459f6a1eeabce541a9ef4d93689529ea2b8f739 \ No newline at end of file +fcc509d325dabe06275e7804183bb8b4ba6470a45b443bc8292eecd0974e6367 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index b4b4e2fcce..72fe26339e 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8941,16 +8941,8 @@ static int do_meta_command(char *zLine, ShellState *p){ char *zNewFilename = 0; /* Name of the database file to open */ int iName = 1; /* Index in azArg[] of the filename */ int newFlag = 0; /* True to delete file before opening */ - /* Close the existing database */ - session_close_all(p, -1); - close_db(p->db); - p->db = 0; - p->pAuxDb->zDbFilename = 0; - sqlite3_free(p->pAuxDb->zFreeOnClose); - p->pAuxDb->zFreeOnClose = 0; - p->openMode = SHELL_OPEN_UNSPEC; - p->openFlags = 0; - p->szMax = 0; + int openMode = SHELL_OPEN_UNSPEC; + /* Check for command-line arguments */ for(iName=1; iNameopenMode = SHELL_OPEN_ZIPFILE; + openMode = SHELL_OPEN_ZIPFILE; #endif }else if( optionMatch(z, "append") ){ - p->openMode = SHELL_OPEN_APPENDVFS; + openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ - p->openMode = SHELL_OPEN_READONLY; + openMode = SHELL_OPEN_READONLY; }else if( optionMatch(z, "nofollow") ){ p->openFlags |= SQLITE_OPEN_NOFOLLOW; #ifndef SQLITE_OMIT_DESERIALIZE }else if( optionMatch(z, "deserialize") ){ - p->openMode = SHELL_OPEN_DESERIALIZE; + openMode = SHELL_OPEN_DESERIALIZE; }else if( optionMatch(z, "hexdb") ){ - p->openMode = SHELL_OPEN_HEXDB; + openMode = SHELL_OPEN_HEXDB; }else if( optionMatch(z, "maxsize") && iName+1szMax = integerValue(azArg[++iName]); #endif /* SQLITE_OMIT_DESERIALIZE */ @@ -8986,6 +8978,18 @@ static int do_meta_command(char *zLine, ShellState *p){ zNewFilename = sqlite3_mprintf("%s", z); } } + + /* Close the existing database */ + session_close_all(p, -1); + close_db(p->db); + p->db = 0; + p->pAuxDb->zDbFilename = 0; + sqlite3_free(p->pAuxDb->zFreeOnClose); + p->pAuxDb->zFreeOnClose = 0; + p->openMode = openMode; + p->openFlags = 0; + p->szMax = 0; + /* If a filename is specified, try to open it first */ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); From daebb0f9a0a8a72646a055347c97baf71311cd05 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 14:28:36 +0000 Subject: [PATCH 015/148] Move the TK_IS token so that it is adjacent to the TK_IN token, as this allows the C compiler to optimize better, resulting in a slightly smaller and faster executable. FossilOrigin-Name: 8832fa9088414a8d285a457a4effad0b7d610a87ca73cfb5c5812e784649761e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/parse.y | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2a28256dc6..fd242e54e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sshell\stool,\savoid\smodifying\sinternal\sdata\sstructures\suntil\safter\sthe\sarguments\sto\s".open"\shave\sbeen\sparsed. -D 2021-12-02T14:16:30.751 +C Move\sthe\sTK_IS\stoken\sso\sthat\sit\sis\sadjacent\sto\sthe\sTK_IN\stoken,\sas\sthis\nallows\sthe\sC\scompiler\sto\soptimize\sbetter,\sresulting\sin\sa\sslightly\ssmaller\nand\sfaster\sexecutable. +D 2021-12-02T14:28:36.785 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -539,7 +539,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c bc10c191d18bffd3d76eda5f162799e43a9f875ecfe7c4869f752e2ddef87ea2 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f -F src/parse.y 0bd7971a7489bbf6c3726f1b50da6e508bdff8fa493e9cc3f5a96b12cbb2361e +F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3312be1db3519074393573265459f6a1eeabce541a9ef4d93689529ea2b8f739 -R 7b39f65268d7d5d5ddeb7e728b46cc8a -U dan -Z 6583dbaeea3c12c619555be53ea08d30 +P fcc509d325dabe06275e7804183bb8b4ba6470a45b443bc8292eecd0974e6367 +R 888c8c19b41c8406ec3840142d61350f +U drh +Z 0b6dacbe87596435aee017d0aa63fe31 diff --git a/manifest.uuid b/manifest.uuid index c442c9baae..1a7fe9bc70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fcc509d325dabe06275e7804183bb8b4ba6470a45b443bc8292eecd0974e6367 \ No newline at end of file +8832fa9088414a8d285a457a4effad0b7d610a87ca73cfb5c5812e784649761e \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 97a26c28e8..559057f9ae 100644 --- a/src/parse.y +++ b/src/parse.y @@ -236,7 +236,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);} // %token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST. %token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL. -%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. +%token OR AND NOT MATCH LIKE_KW BETWEEN IS IN ISNULL NOTNULL NE EQ. %token GT LE LT GE ESCAPE. // The following directive causes tokens ABORT, AFTER, ASC, etc. to From 65a3c8508d3ebd32a1df2d1d72cdf23bf5f7892f Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 2 Dec 2021 18:15:16 +0000 Subject: [PATCH 016/148] Optimizations to exprAnalyze() and sqlite3WhereExprUsage() save about 1.5 million CPU cycles for speedtest1, and result in a smaller binary. FossilOrigin-Name: 1f2252e65dc5847c82246fab87dcad035bf594ba7c45362de87a009b7ebcf2d6 --- manifest | 12 +++++----- manifest.uuid | 2 +- src/whereexpr.c | 64 ++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index fd242e54e1..65ea3a6c49 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sthe\sTK_IS\stoken\sso\sthat\sit\sis\sadjacent\sto\sthe\sTK_IN\stoken,\sas\sthis\nallows\sthe\sC\scompiler\sto\soptimize\sbetter,\sresulting\sin\sa\sslightly\ssmaller\nand\sfaster\sexecutable. -D 2021-12-02T14:28:36.785 +C Optimizations\sto\sexprAnalyze()\sand\ssqlite3WhereExprUsage()\ssave\sabout\s1.5\nmillion\sCPU\scycles\sfor\sspeedtest1,\sand\sresult\sin\sa\ssmaller\sbinary. +D 2021-12-02T18:15:16.866 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -640,7 +640,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c da93d2227cc5246fe4a79d130f2a1a215017e12d76a035434145c443abd6f64b +F src/whereexpr.c ac082ec617802e7fc9c190aa0819696a7144a8aa0cad91948323b83720e5105c F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fcc509d325dabe06275e7804183bb8b4ba6470a45b443bc8292eecd0974e6367 -R 888c8c19b41c8406ec3840142d61350f +P 8832fa9088414a8d285a457a4effad0b7d610a87ca73cfb5c5812e784649761e +R 7228b3364cf2efa906def2eee014e4fe U drh -Z 0b6dacbe87596435aee017d0aa63fe31 +Z 0ddb7e6cff00de145e1d39d556b5aab6 diff --git a/manifest.uuid b/manifest.uuid index 1a7fe9bc70..a9c01fe47e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8832fa9088414a8d285a457a4effad0b7d610a87ca73cfb5c5812e784649761e \ No newline at end of file +1f2252e65dc5847c82246fab87dcad035bf594ba7c45362de87a009b7ebcf2d6 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index bb013f1c6f..542114e91d 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1076,6 +1076,7 @@ static void exprAnalyze( pExpr = pTerm->pExpr; assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); + pMaskSet->bVarSelect = 0; prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ @@ -1086,12 +1087,25 @@ static void exprAnalyze( }else{ pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); } + prereqAll = prereqLeft | pTerm->prereqRight; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); + if( pExpr->pLeft==0 || ExprUseXSelect(pExpr) || pExpr->x.pList!=0 ){ + prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); + }else{ + prereqAll = prereqLeft | pTerm->prereqRight; + } } - pMaskSet->bVarSelect = 0; - prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; + +#ifdef SQLITE_DEBUG + if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){ + printf("\n*** Incorrect prereqAll computed for:\n"); + sqlite3TreeViewExpr(0,pExpr,0); + abort(); + } +#endif + if( ExprHasProperty(pExpr, EP_FromJoin) ){ Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); prereqAll |= x; @@ -1556,15 +1570,38 @@ void sqlite3WhereClauseClear(WhereClause *pWC){ ** These routines walk (recursively) an expression tree and generate ** a bitmask indicating which tables are used in that expression ** tree. +** +** sqlite3WhereExprUsage(MaskSet, Expr) -> +** +** Return a Bitmask of all tables referenced by Expr. Expr can be +** be NULL, in which case 0 is returned. +** +** sqlite3WhereExprUsageNN(MaskSet, Expr) -> +** +** Same as sqlite3WhereExprUsage() except that Expr must not be +** NULL. The "NN" suffix on the name stands for "Not Null". +** +** sqlite3WhereExprListUsage(MaskSet, ExprList) -> +** +** Return a Bitmask of all tables referenced by every expression +** in the expression list ExprList. ExprList can be NULL, in which +** case 0 is returned. +** +** sqlite3WhereExprUsageFull(MaskSet, ExprList) -> +** +** Internal use only. Called only by sqlite3WhereExprUsageNN() for +** complex expressions that require pushing register values onto +** the stack. Many calls to sqlite3WhereExprUsageNN() do not need +** the more complex analysis done by this routine. Hence, the +** computations done by this routine are broken out into a separate +** "no-inline" function to avoid the stack push overhead in the +** common case where it is not needed. */ -Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ +static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull( + WhereMaskSet *pMaskSet, + Expr *p +){ Bitmask mask; - if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return sqlite3WhereGetMask(pMaskSet, p->iTable); - }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - assert( p->op!=TK_IF_NULL_ROW ); - return 0; - } mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); if( p->pRight ){ @@ -1586,6 +1623,15 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ #endif return mask; } +Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ + if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ + return sqlite3WhereGetMask(pMaskSet, p->iTable); + }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ + assert( p->op!=TK_IF_NULL_ROW ); + return 0; + } + return sqlite3WhereExprUsageFull(pMaskSet, p); +} Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; } From 2f0bc1d41b0956c75822332dc1af1c680291071a Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 3 Dec 2021 13:42:41 +0000 Subject: [PATCH 017/148] Performance optimization in the B-Tree cursor allocator btreeCursor(), making it about 800K CPU cycles faster in speedtest1, and reducing the executable size by about 100 bytes. FossilOrigin-Name: 9df939716ace8cfe60340bbe83fc52d452ea40c29c856c588f9a1b8973282391 --- manifest | 12 ++++----- manifest.uuid | 2 +- src/btree.c | 74 ++++++++++++++++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index 65ea3a6c49..18e751c5d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimizations\sto\sexprAnalyze()\sand\ssqlite3WhereExprUsage()\ssave\sabout\s1.5\nmillion\sCPU\scycles\sfor\sspeedtest1,\sand\sresult\sin\sa\ssmaller\sbinary. -D 2021-12-02T18:15:16.866 +C Performance\soptimization\sin\sthe\sB-Tree\scursor\sallocator\sbtreeCursor(),\smaking\nit\sabout\s800K\sCPU\scycles\sfaster\sin\sspeedtest1,\sand\sreducing\sthe\sexecutable\nsize\sby\sabout\s100\sbytes. +D 2021-12-03T13:42:41.900 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 13b965a0f3cd57221e3b4e61e24452ec264a5b163de347b03b5039ddcd95cd54 +F src/btree.c be33f2b299c2d1dcdd6c033368731b81c13c2dbc72fe15af64a43871f6cdb437 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 179b11b07484497052096d88b953b9a6c22cbb0c23ba75c4347e9a99dae4a6c0 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8832fa9088414a8d285a457a4effad0b7d610a87ca73cfb5c5812e784649761e -R 7228b3364cf2efa906def2eee014e4fe +P 1f2252e65dc5847c82246fab87dcad035bf594ba7c45362de87a009b7ebcf2d6 +R 8e0c1c78e15dfcc0933f0a89f97b367f U drh -Z 0ddb7e6cff00de145e1d39d556b5aab6 +Z 5947065c8f3472b5a2f6d47907db0ceb diff --git a/manifest.uuid b/manifest.uuid index a9c01fe47e..380663b6d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f2252e65dc5847c82246fab87dcad035bf594ba7c45362de87a009b7ebcf2d6 \ No newline at end of file +9df939716ace8cfe60340bbe83fc52d452ea40c29c856c588f9a1b8973282391 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index ba35af03f0..7dfce901ab 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2693,30 +2693,40 @@ static int removeFromSharingList(BtShared *pBt){ ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child ** pointer. */ -static void allocateTempSpace(BtShared *pBt){ - if( !pBt->pTmpSpace ){ - pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); - - /* One of the uses of pBt->pTmpSpace is to format cells before - ** inserting them into a leaf page (function fillInCell()). If - ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes - ** by the various routines that manipulate binary cells. Which - ** can mean that fillInCell() only initializes the first 2 or 3 - ** bytes of pTmpSpace, but that the first 4 bytes are copied from - ** it into a database page. This is not actually a problem, but it - ** does cause a valgrind error when the 1 or 2 bytes of unitialized - ** data is passed to system call write(). So to avoid this error, - ** zero the first 4 bytes of temp space here. - ** - ** Also: Provide four bytes of initialized space before the - ** beginning of pTmpSpace as an area available to prepend the - ** left-child pointer to the beginning of a cell. - */ - if( pBt->pTmpSpace ){ - memset(pBt->pTmpSpace, 0, 8); - pBt->pTmpSpace += 4; - } +static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ + assert( pBt!=0 ); + assert( pBt->pTmpSpace==0 ); + /* This routine is called only by btreeCursor() when allocating the + ** first write cursor for the BtShared object */ + assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 ); + pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); + if( pBt->pTmpSpace==0 ){ + BtCursor *pCur = pBt->pCursor; + pBt->pCursor = pCur->pNext; /* Unlink the cursor */ + memset(pCur, 0, sizeof(*pCur)); + return SQLITE_NOMEM_BKPT; } + + /* One of the uses of pBt->pTmpSpace is to format cells before + ** inserting them into a leaf page (function fillInCell()). If + ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes + ** by the various routines that manipulate binary cells. Which + ** can mean that fillInCell() only initializes the first 2 or 3 + ** bytes of pTmpSpace, but that the first 4 bytes are copied from + ** it into a database page. This is not actually a problem, but it + ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** data is passed to system call write(). So to avoid this error, + ** zero the first 4 bytes of temp space here. + ** + ** Also: Provide four bytes of initialized space before the + ** beginning of pTmpSpace as an area available to prepend the + ** left-child pointer to the beginning of a cell. + */ + if( pBt->pTmpSpace ){ + memset(pBt->pTmpSpace, 0, 8); + pBt->pTmpSpace += 4; + } + return SQLITE_OK; } /* @@ -4457,10 +4467,6 @@ static int btreeCursor( assert( pBt->pPage1 && pBt->pPage1->aData ); assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); - if( wrFlag ){ - allocateTempSpace(pBt); - if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT; - } if( iTable<=1 ){ if( iTable<1 ){ return SQLITE_CORRUPT_BKPT; @@ -4477,19 +4483,25 @@ static int btreeCursor( pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; - pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; + pCur->curFlags = 0; /* If there are two or more cursors on the same btree, then all such ** cursors *must* have the BTCF_Multiple flag set. */ for(pX=pBt->pCursor; pX; pX=pX->pNext){ if( pX->pgnoRoot==iTable ){ pX->curFlags |= BTCF_Multiple; - pCur->curFlags |= BTCF_Multiple; + pCur->curFlags = BTCF_Multiple; } } + pCur->eState = CURSOR_INVALID; pCur->pNext = pBt->pCursor; pBt->pCursor = pCur; - pCur->eState = CURSOR_INVALID; + if( wrFlag ){ + pCur->curFlags |= BTCF_WriteFlag; + pCur->curPagerFlags = 0; + if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt); + }else{ + pCur->curPagerFlags = PAGER_GET_READONLY; + } return SQLITE_OK; } static int btreeCursorWithLock( From fd4bf7746b2ce6a5b44ba3b237a5671327abcb4c Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 3 Dec 2021 14:43:49 +0000 Subject: [PATCH 018/148] Fix an over-length source code line in build.c. No logic changes. FossilOrigin-Name: b9db5c5fc618a36d70ea2aced9c96094d665935b5c15a987013334f1bd79eb00 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 18e751c5d3..1a4e57e525 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\sin\sthe\sB-Tree\scursor\sallocator\sbtreeCursor(),\smaking\nit\sabout\s800K\sCPU\scycles\sfaster\sin\sspeedtest1,\sand\sreducing\sthe\sexecutable\nsize\sby\sabout\s100\sbytes. -D 2021-12-03T13:42:41.900 +C Fix\san\sover-length\ssource\scode\sline\sin\sbuild.c.\s\sNo\slogic\schanges. +D 2021-12-03T14:43:49.562 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -494,7 +494,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c be33f2b299c2d1dcdd6c033368731b81c13c2dbc72fe15af64a43871f6cdb437 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c 179b11b07484497052096d88b953b9a6c22cbb0c23ba75c4347e9a99dae4a6c0 +F src/build.c 70759481a346322934332485381805c9ba9442bbe7959bf40bdc14140c832517 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1f2252e65dc5847c82246fab87dcad035bf594ba7c45362de87a009b7ebcf2d6 -R 8e0c1c78e15dfcc0933f0a89f97b367f +P 9df939716ace8cfe60340bbe83fc52d452ea40c29c856c588f9a1b8973282391 +R 9393106c7ba9e646319a5d3ddfef6c69 U drh -Z 5947065c8f3472b5a2f6d47907db0ceb +Z 97067e9e4125723429bb82f48b4944e2 diff --git a/manifest.uuid b/manifest.uuid index 380663b6d6..e4938138ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9df939716ace8cfe60340bbe83fc52d452ea40c29c856c588f9a1b8973282391 \ No newline at end of file +b9db5c5fc618a36d70ea2aced9c96094d665935b5c15a987013334f1bd79eb00 \ No newline at end of file diff --git a/src/build.c b/src/build.c index d225227de8..538a1e4d7f 100644 --- a/src/build.c +++ b/src/build.c @@ -4406,13 +4406,13 @@ void sqlite3CreateIndex( /* Add an entry in sqlite_schema for this index */ sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zDbSName, - pIndex->zName, - pTab->zName, - iMem, - zStmt - ); + "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", + db->aDb[iDb].zDbSName, + pIndex->zName, + pTab->zName, + iMem, + zStmt + ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire From 11e4fdb94861a92e9e14476a8a7cea58d559bb1b Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 3 Dec 2021 14:57:05 +0000 Subject: [PATCH 019/148] Fix unreachable branches resulting from prior optimizations. FossilOrigin-Name: f3d6853ee80be2dc6d7236d98b850beb0e1931a624d4f5b194c8db742cde7ec5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 6 ++---- src/whereexpr.c | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 1a4e57e525..dc6fa42308 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sover-length\ssource\scode\sline\sin\sbuild.c.\s\sNo\slogic\schanges. -D 2021-12-03T14:43:49.562 +C Fix\sunreachable\sbranches\sresulting\sfrom\sprior\soptimizations. +D 2021-12-03T14:57:05.912 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c be33f2b299c2d1dcdd6c033368731b81c13c2dbc72fe15af64a43871f6cdb437 +F src/btree.c 81feddbcc60d524518a7afc713b6dab0ad7caadb7370433f117c8c557dcdc889 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 70759481a346322934332485381805c9ba9442bbe7959bf40bdc14140c832517 @@ -640,7 +640,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c ac082ec617802e7fc9c190aa0819696a7144a8aa0cad91948323b83720e5105c +F src/whereexpr.c 779b3230a76510de63f5d45e47df931be05320a8f290c287130a30344c73ea1f F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9df939716ace8cfe60340bbe83fc52d452ea40c29c856c588f9a1b8973282391 -R 9393106c7ba9e646319a5d3ddfef6c69 +P b9db5c5fc618a36d70ea2aced9c96094d665935b5c15a987013334f1bd79eb00 +R 62fc2562c9bdca584bc5f7af404e360c U drh -Z 97067e9e4125723429bb82f48b4944e2 +Z a47d8ad1f6786c210062821f95b3efde diff --git a/manifest.uuid b/manifest.uuid index e4938138ce..a6d9596b1b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b9db5c5fc618a36d70ea2aced9c96094d665935b5c15a987013334f1bd79eb00 \ No newline at end of file +f3d6853ee80be2dc6d7236d98b850beb0e1931a624d4f5b194c8db742cde7ec5 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7dfce901ab..5060140731 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2722,10 +2722,8 @@ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ ** beginning of pTmpSpace as an area available to prepend the ** left-child pointer to the beginning of a cell. */ - if( pBt->pTmpSpace ){ - memset(pBt->pTmpSpace, 0, 8); - pBt->pTmpSpace += 4; - } + memset(pBt->pTmpSpace, 0, 8); + pBt->pTmpSpace += 4; return SQLITE_OK; } diff --git a/src/whereexpr.c b/src/whereexpr.c index 542114e91d..852c56f385 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1090,7 +1090,7 @@ static void exprAnalyze( prereqAll = prereqLeft | pTerm->prereqRight; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); - if( pExpr->pLeft==0 || ExprUseXSelect(pExpr) || pExpr->x.pList!=0 ){ + if( pExpr->pLeft==0 || NEVER(ExprUseXSelect(pExpr)) || pExpr->x.pList!=0 ){ prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); }else{ prereqAll = prereqLeft | pTerm->prereqRight; From 60a8e1b43c982e9317e255cafa40702b27ab98f0 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 3 Dec 2021 15:48:42 +0000 Subject: [PATCH 020/148] Fix exprAnalyze() after recent performance enhancements so that it is able to handle IF_NULL_ROW opcode correctly, again. FossilOrigin-Name: 8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/whereexpr.c | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index dc6fa42308..e2d4a70289 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sunreachable\sbranches\sresulting\sfrom\sprior\soptimizations. -D 2021-12-03T14:57:05.912 +C Fix\sexprAnalyze()\safter\srecent\sperformance\senhancements\sso\sthat\sit\sis\sable\nto\shandle\sIF_NULL_ROW\sopcode\scorrectly,\sagain. +D 2021-12-03T15:48:42.503 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -640,7 +640,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c 779b3230a76510de63f5d45e47df931be05320a8f290c287130a30344c73ea1f +F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b9db5c5fc618a36d70ea2aced9c96094d665935b5c15a987013334f1bd79eb00 -R 62fc2562c9bdca584bc5f7af404e360c +P f3d6853ee80be2dc6d7236d98b850beb0e1931a624d4f5b194c8db742cde7ec5 +R f7c21b32b86d486ed00c79fd5643ce8f U drh -Z a47d8ad1f6786c210062821f95b3efde +Z 7b145c2e945c01598a45c251b2a2a878 diff --git a/manifest.uuid b/manifest.uuid index a6d9596b1b..2be18ad032 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f3d6853ee80be2dc6d7236d98b850beb0e1931a624d4f5b194c8db742cde7ec5 \ No newline at end of file +8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index 852c56f385..eff7f4ab22 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1090,7 +1090,10 @@ static void exprAnalyze( prereqAll = prereqLeft | pTerm->prereqRight; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); - if( pExpr->pLeft==0 || NEVER(ExprUseXSelect(pExpr)) || pExpr->x.pList!=0 ){ + if( pExpr->pLeft==0 + || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow) + || pExpr->x.pList!=0 + ){ prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); }else{ prereqAll = prereqLeft | pTerm->prereqRight; From 70b403b667a3ec829e5435271c905cb7ba544e17 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 3 Dec 2021 18:53:53 +0000 Subject: [PATCH 021/148] Factor the noop-join-elimination optimization out of the sqlite3WhereBegin() routine and into a separate "no-inline" subroutine, in order to reduce the complexity of sqlite3WhereBegin() and thereby encourage C compilers to inline sqlite3WhereCodeOneLoopStart(). FossilOrigin-Name: 6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d --- manifest | 12 ++-- manifest.uuid | 2 +- src/where.c | 171 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 109 insertions(+), 76 deletions(-) diff --git a/manifest b/manifest index e2d4a70289..1fc8dc6703 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sexprAnalyze()\safter\srecent\sperformance\senhancements\sso\sthat\sit\sis\sable\nto\shandle\sIF_NULL_ROW\sopcode\scorrectly,\sagain. -D 2021-12-03T15:48:42.503 +C Factor\sthe\snoop-join-elimination\soptimization\sout\sof\sthe\ssqlite3WhereBegin()\nroutine\sand\sinto\sa\sseparate\s"no-inline"\ssubroutine,\sin\sorder\sto\sreduce\sthe\ncomplexity\sof\ssqlite3WhereBegin()\sand\sthereby\sencourage\sC\scompilers\sto\ninline\ssqlite3WhereCodeOneLoopStart(). +D 2021-12-03T18:53:53.434 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c b50391df607937593596fbb8ea39f673d9a3715a65750567b442d22dd20720ca +F src/where.c 5bd26902ddf3e385c0df9429b10e7358bbd0430c470ec1d2a53065723c4a55d2 F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f3d6853ee80be2dc6d7236d98b850beb0e1931a624d4f5b194c8db742cde7ec5 -R f7c21b32b86d486ed00c79fd5643ce8f +P 8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788 +R 963c220f26757d3ffbc2edfb4f7e86f0 U drh -Z 7b145c2e945c01598a45c251b2a2a878 +Z 180dbfc838231c2ae95c395bdf32b1d2 diff --git a/manifest.uuid b/manifest.uuid index 2be18ad032..9b8ce11932 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788 \ No newline at end of file +6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d \ No newline at end of file diff --git a/src/where.c b/src/where.c index 925f98af16..f1abd5483c 100644 --- a/src/where.c +++ b/src/where.c @@ -4743,6 +4743,96 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){ # define WHERETRACE_ALL_LOOPS(W,C) #endif +/* Attempt to omit tables from a join that do not affect the result. +** For a table to not affect the result, the following must be true: +** +** 1) The query must not be an aggregate. +** 2) The table must be the RHS of a LEFT JOIN. +** 3) Either the query must be DISTINCT, or else the ON or USING clause +** must contain a constraint that limits the scan of the table to +** at most a single row. +** 4) The table must not be referenced by any part of the query apart +** from its own USING or ON clause. +** +** For example, given: +** +** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); +** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); +** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); +** +** then table t2 can be omitted from the following: +** +** SELECT v1, v3 FROM t1 +** LEFT JOIN t2 ON (t1.ipk=t2.ipk) +** LEFT JOIN t3 ON (t1.ipk=t3.ipk) +** +** or from: +** +** SELECT DISTINCT v1, v3 FROM t1 +** LEFT JOIN t2 +** LEFT JOIN t3 ON (t1.ipk=t3.ipk) +*/ +static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( + WhereInfo *pWInfo, + Bitmask notReady +){ + int i; + Bitmask tabUsed; + + /* Preconditions checked by the caller */ + assert( pWInfo->nLevel>=2 ); + assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) ); + + /* These two preconditions checked by the caller combine to guarantee + ** condition (1) of the header comment */ + assert( pWInfo->pResultSet!=0 ); + assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) ); + + tabUsed = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet); + if( pWInfo->pOrderBy ){ + tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy); + } + for(i=pWInfo->nLevel-1; i>=1; i--){ + WhereTerm *pTerm, *pEnd; + SrcItem *pItem; + WhereLoop *pLoop; + pLoop = pWInfo->a[i].pWLoop; + pItem = &pWInfo->pTabList->a[pLoop->iTab]; + if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; + if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0 + && (pLoop->wsFlags & WHERE_ONEROW)==0 + ){ + continue; + } + if( (tabUsed & pLoop->maskSelf)!=0 ) continue; + pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm; + for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ + if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + || pTerm->pExpr->iRightJoinTable!=pItem->iCursor + ){ + break; + } + } + } + if( pTerm drop loop %c not used\n", pLoop->cId)); + notReady &= ~pLoop->maskSelf; + for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ + pTerm->wtFlags |= TERM_CODED; + } + } + if( i!=pWInfo->nLevel-1 ){ + int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); + memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); + } + pWInfo->nLevel--; + assert( pWInfo->nLevel>0 ); + } + return notReady; +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -5111,34 +5201,15 @@ WhereInfo *sqlite3WhereBegin( } #endif - /* Attempt to omit tables from the join that do not affect the result. - ** For a table to not affect the result, the following must be true: + /* Attempt to omit tables from a join that do not affect the result. + ** See the comment on whereOmitNoopJoin() for further information. ** - ** 1) The query must not be an aggregate. - ** 2) The table must be the RHS of a LEFT JOIN. - ** 3) Either the query must be DISTINCT, or else the ON or USING clause - ** must contain a constraint that limits the scan of the table to - ** at most a single row. - ** 4) The table must not be referenced by any part of the query apart - ** from its own USING or ON clause. - ** - ** For example, given: - ** - ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); - ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); - ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); - ** - ** then table t2 can be omitted from the following: - ** - ** SELECT v1, v3 FROM t1 - ** LEFT JOIN t2 ON (t1.ipk=t2.ipk) - ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) - ** - ** or from: - ** - ** SELECT DISTINCT v1, v3 FROM t1 - ** LEFT JOIN t2 - ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) + ** This query optimization is factored out into a separate "no-inline" + ** procedure to keep the sqlite3WhereBegin() procedure from becoming + ** too large. If sqlite3WhereBegin() becomes too large, that prevents + ** some C-compiler optimizers from in-lining the + ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to + ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. */ notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 @@ -5146,49 +5217,11 @@ WhereInfo *sqlite3WhereBegin( && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */ && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - int i; - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); - if( sWLB.pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); - } - for(i=pWInfo->nLevel-1; i>=1; i--){ - WhereTerm *pTerm, *pEnd; - SrcItem *pItem; - pLoop = pWInfo->a[i].pWLoop; - pItem = &pWInfo->pTabList->a[pLoop->iTab]; - if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; - if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 - && (pLoop->wsFlags & WHERE_ONEROW)==0 - ){ - continue; - } - if( (tabUsed & pLoop->maskSelf)!=0 ) continue; - pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - || pTerm->pExpr->iRightJoinTable!=pItem->iCursor - ){ - break; - } - } - } - if( pTerm drop loop %c not used\n", pLoop->cId)); - notReady &= ~pLoop->maskSelf; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } - if( i!=pWInfo->nLevel-1 ){ - int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); - memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); - } - pWInfo->nLevel--; - nTabList--; - } + notReady = whereOmitNoopJoin(pWInfo, notReady); + nTabList = pWInfo->nLevel; + assert( nTabList>0 ); } + #if defined(WHERETRACE_ENABLED) if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n"); From fa35f5c5a7868902019c6a18eeec52f4a577fc8b Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 4 Dec 2021 13:43:57 +0000 Subject: [PATCH 022/148] First attempt to use Bloom filters to optimize star-schema queries. FossilOrigin-Name: 28161fba9bcde5ae4b36b22d766c881b795af111a3a323c90f6149d0fea9297d --- manifest | 14 +++--- manifest.uuid | 2 +- src/where.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++-- src/whereInt.h | 1 + 4 files changed, 126 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 1e420b2cce..1e7e0a1ce4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\ssqlite3WhereBegin()\ssimplification\sfrom\strunk. -D 2021-12-03T19:10:17.141 +C First\sattempt\sto\suse\sBloom\sfilters\sto\soptimize\sstar-schema\squeries. +D 2021-12-04T13:43:57.343 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,8 +637,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c a0787ad0a3447685e553725dab50e52c9763b5f10e2506255713dbd736c89998 -F src/whereInt.h 83ae6f7d0fce8b5164d97698790e0005a909b3d06d73df86a4a6bb0d9411861e +F src/where.c e9cfeae040b60c21244f40fed1a3473f048ee20cb2fb987d5028350e4bead886 +F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 F src/wherecode.c 620e81077588a727876a86f87aab310c02fc4e4960691e48153d8a87ca1fa453 F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 11d97fb8be6b5155f38df130d7e828edd0f381e32f651458939b1cb9cb973fff 6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d -R 91b705f2730ed0122ffcaf8efbe0af73 +P 41ba2dfdd3a18671fc78d60935a16fa50f36af3d6481eff2ca9fba88e7093997 +R a2ed82c3d908c8671ab026e425f8c4f5 U drh -Z dab48a2f628412943ed7bfde21b0a086 +Z 92e3ffa168d28fa3c757a00a1d8afcc3 diff --git a/manifest.uuid b/manifest.uuid index 6adb3fed23..383563aee3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -41ba2dfdd3a18671fc78d60935a16fa50f36af3d6481eff2ca9fba88e7093997 \ No newline at end of file +28161fba9bcde5ae4b36b22d766c881b795af111a3a323c90f6149d0fea9297d \ No newline at end of file diff --git a/src/where.c b/src/where.c index 371bf52305..22ed0c9b5b 100644 --- a/src/where.c +++ b/src/where.c @@ -750,7 +750,7 @@ static int termCanDriveIndex( ** and to set up the WhereLevel object pLevel so that the code generator ** makes use of the automatic index. */ -static void constructAutomaticIndex( +static SQLITE_NOINLINE void constructAutomaticIndex( Parse *pParse, /* The parsing context */ WhereClause *pWC, /* The WHERE clause */ SrcItem *pSrc, /* The FROM clause term to get the next index */ @@ -965,6 +965,62 @@ end_auto_index_create: } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ +/* +** Create a Bloom filter for the WhereLevel in the parameter. +*/ +static SQLITE_NOINLINE void constructBloomFilter( + WhereInfo *pWInfo, /* The WHERE clause */ + WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ +){ + int addrTop; + int addrCont; + WhereTerm *pTerm; + WhereTerm *pWCEnd; + Parse *pParse = pWInfo->pParse; + Vdbe *v = pParse->pVdbe; + WhereLoop *pLoop = pLevel->pWLoop; + int iCur; + + + assert( pLoop!=0 ); + assert( v!=0 ); + iCur = pLevel->iTabCur; + addrCont = sqlite3VdbeMakeLabel(pParse); + addrTop = sqlite3VdbeAddOp0(v, OP_Once); + pLevel->regFilter = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); + sqlite3VdbeAddOp1(v, OP_Rewind, iCur); + pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; + for(pTerm=pWInfo->sWC.a; pTermpExpr; + if( (pTerm->wtFlags & TERM_VIRTUAL)==0 + && sqlite3ExprIsTableConstant(pExpr, iCur) + ){ + sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); + } + } + if( pLoop->wsFlags & WHERE_IPK ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); + }else{ + Index *pIdx = pLoop->u.btree.pIndex; + int r1 = sqlite3GetTempRange(pParse, pIdx->nKeyCol); + int n = pIdx->nKeyCol; + int jj; + for(jj=0; jjaiColumn[jj]; + sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); + } + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); + } + sqlite3VdbeResolveLabel(v, addrCont); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); + sqlite3VdbeJumpHere(v, addrTop); + sqlite3VdbeJumpHere(v, addrTop+2); +} + + #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the @@ -4841,6 +4897,49 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( return notReady; } +/* +** Check to see if there are any SEARCH loops that might benefit from +** using a Bloom filter. Consider a Bloom filter if: +** +** (1) The SEARCH happens more than N times where N is the number +** of rows in the table that is being considered for the Bloom +** filter. (TO DO: Make this condition more precise.) +** (2) Most searches are expected to find zero rows +** (3) The table being searched is not the right table of a LEFT JOIN +** (4) Bloom-filter processing is not disabled +** +** This block of code merely checks to see if a Bloom filter would be +** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the +** WhereLoop. The implementation of the Bloom filter comes further +** down where the code for each WhereLoop is generated. +*/ +static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( + WhereInfo *pWInfo, + sqlite3 *db +){ + int i; + LogEst nSearch; + SrcItem *pItem; + + assert( pWInfo->nLevel>=2 ); + assert( OptimizationEnabled(db, SQLITE_BloomFilter) ); + nSearch = pWInfo->a[0].pWLoop->nOut; + for(i=1; inLevel; i++){ + WhereLoop *pLoop = pWInfo->a[i].pWLoop; + if( (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 + && (pLoop->wsFlags & WHERE_COLUMN_EQ)!=0 + && pLoop->nOut<0 + && nSearch > (pItem = &pWInfo->pTabList->a[pLoop->iTab])->pTab->nRowLogEst + && (pItem->fg.jointype & JT_LEFT)==0 + ){ + pLoop->wsFlags |= WHERE_BLOOMFILTER; + pLoop->wsFlags &= ~WHERE_IDX_ONLY; + WHERETRACE(0xffff, ("-> use Bloom-filter on loop %c\n", pLoop->cId)); + } + nSearch += pLoop->nOut; + } +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -5230,6 +5329,15 @@ WhereInfo *sqlite3WhereBegin( assert( nTabList>0 ); } + /* Check to see if there are any SEARCH loops that might benefit from + ** using a Bloom filter. + */ + if( pWInfo->nLevel>=2 + && OptimizationEnabled(db, SQLITE_BloomFilter) + ){ + whereCheckIfBloomFilterIsUseful(pWInfo, db); + } + #if defined(WHERETRACE_ENABLED) if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n"); @@ -5418,13 +5526,17 @@ WhereInfo *sqlite3WhereBegin( if( pParse->nErr ) goto whereBeginError; pLevel = &pWInfo->a[ii]; wsFlags = pLevel->pWLoop->wsFlags; + if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){ + if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){ #ifndef SQLITE_OMIT_AUTOMATIC_INDEX - if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - constructAutomaticIndex(pParse, &pWInfo->sWC, - &pTabList->a[pLevel->iFrom], notReady, pLevel); + constructAutomaticIndex(pParse, &pWInfo->sWC, + &pTabList->a[pLevel->iFrom], notReady, pLevel); +#endif + }else{ + constructBloomFilter(pWInfo, pLevel); + } if( db->mallocFailed ) goto whereBeginError; } -#endif addrExplain = sqlite3WhereExplainOneScan( pParse, pTabList, pLevel, wctrlFlags ); diff --git a/src/whereInt.h b/src/whereInt.h index ff6ac4c397..fbe84787f9 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -600,5 +600,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ +#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ #endif /* !defined(SQLITE_WHEREINT_H) */ From 19ce9aafdb200670d5ee9c3f1b139801a988f2ba Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 4 Dec 2021 13:52:08 +0000 Subject: [PATCH 023/148] Add the "WITH BLOOM FILTER" clause to the EXPLAIN QUERY PLAN output for cases were a Bloom filter is used. FossilOrigin-Name: 8e078c0e404fe4b3661dd4a11a992a8914c99e2a144cecc417421cbd68fa08cc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wherecode.c | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 1e7e0a1ce4..dfe53bde8f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C First\sattempt\sto\suse\sBloom\sfilters\sto\soptimize\sstar-schema\squeries. -D 2021-12-04T13:43:57.343 +C Add\sthe\s"WITH\sBLOOM\sFILTER"\sclause\sto\sthe\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\ncases\swere\sa\sBloom\sfilter\sis\sused. +D 2021-12-04T13:52:08.699 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -639,7 +639,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c e9cfeae040b60c21244f40fed1a3473f048ee20cb2fb987d5028350e4bead886 F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 -F src/wherecode.c 620e81077588a727876a86f87aab310c02fc4e4960691e48153d8a87ca1fa453 +F src/wherecode.c 26b0cbc985deafe702037ed00bcf40857d129be0d80d198ac87644777b59984d F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 41ba2dfdd3a18671fc78d60935a16fa50f36af3d6481eff2ca9fba88e7093997 -R a2ed82c3d908c8671ab026e425f8c4f5 +P 28161fba9bcde5ae4b36b22d766c881b795af111a3a323c90f6149d0fea9297d +R 6eeaa3a323a583fb23be16ffd26ce73a U drh -Z 92e3ffa168d28fa3c757a00a1d8afcc3 +Z a160cdc5e20e6c677a6900e142dccac2 diff --git a/manifest.uuid b/manifest.uuid index 383563aee3..030f03de8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28161fba9bcde5ae4b36b22d766c881b795af111a3a323c90f6149d0fea9297d \ No newline at end of file +8e078c0e404fe4b3661dd4a11a992a8914c99e2a144cecc417421cbd68fa08cc \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index 637db432ea..2e616ad592 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -196,6 +196,9 @@ int sqlite3WhereExplainOneScan( pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif + if( flags & WHERE_BLOOMFILTER ){ + sqlite3_str_appendf(&str, " WITH BLOOM FILTER"); + } #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS if( pLoop->nOut>=10 ){ sqlite3_str_appendf(&str, " (~%llu rows)", From 770dade262f88ec531d7708ac2d0f2e7882dcb16 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 4 Dec 2021 14:24:30 +0000 Subject: [PATCH 024/148] Apply the Bloom filter only on those terms of an index that have equality constraints. FossilOrigin-Name: a70429596a3c6a413b03118b0d800521b3526d99dcf88a48acc3189b51518d82 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 2 +- src/wherecode.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index dfe53bde8f..f576dec37b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"WITH\sBLOOM\sFILTER"\sclause\sto\sthe\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\ncases\swere\sa\sBloom\sfilter\sis\sused. -D 2021-12-04T13:52:08.699 +C Apply\sthe\sBloom\sfilter\sonly\son\sthose\sterms\sof\san\sindex\sthat\shave\sequality\nconstraints. +D 2021-12-04T14:24:30.524 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,9 +637,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c e9cfeae040b60c21244f40fed1a3473f048ee20cb2fb987d5028350e4bead886 +F src/where.c d203a7acda584940eee49d80e38067ba354410ca08782792bdf4d6f56ca20aa3 F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 -F src/wherecode.c 26b0cbc985deafe702037ed00bcf40857d129be0d80d198ac87644777b59984d +F src/wherecode.c ab83c1f7c593ab5e9268c51dde80f478e48468e8c1e25866a4f445e7b4282b78 F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 28161fba9bcde5ae4b36b22d766c881b795af111a3a323c90f6149d0fea9297d -R 6eeaa3a323a583fb23be16ffd26ce73a +P 8e078c0e404fe4b3661dd4a11a992a8914c99e2a144cecc417421cbd68fa08cc +R a78591e6ea873c8de7a64c271c45d204 U drh -Z a160cdc5e20e6c677a6900e142dccac2 +Z 73637cbd9e62c30bcdc98bccabee0c03 diff --git a/manifest.uuid b/manifest.uuid index 030f03de8f..23eed8d9fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e078c0e404fe4b3661dd4a11a992a8914c99e2a144cecc417421cbd68fa08cc \ No newline at end of file +a70429596a3c6a413b03118b0d800521b3526d99dcf88a48acc3189b51518d82 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 22ed0c9b5b..87a00ef200 100644 --- a/src/where.c +++ b/src/where.c @@ -1006,7 +1006,7 @@ static SQLITE_NOINLINE void constructBloomFilter( }else{ Index *pIdx = pLoop->u.btree.pIndex; int r1 = sqlite3GetTempRange(pParse, pIdx->nKeyCol); - int n = pIdx->nKeyCol; + int n = pLoop->u.btree.nEq; int jj; for(jj=0; jjaiColumn[jj]; diff --git a/src/wherecode.c b/src/wherecode.c index 2e616ad592..fbb40ad4e3 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1845,7 +1845,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( } if( pLevel->regFilter ){ sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, - regBase, nConstraint); + regBase, nEq); } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; From 067c60cfc9aa3ec493f3bdd8f62d225846743a2a Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 4 Dec 2021 18:45:08 +0000 Subject: [PATCH 025/148] Add VdbeCoverage() macros. Adjust the Bloom-filter hash function so that it correctly deals with zero-blobs. FossilOrigin-Name: 629ee2e3e3125bfd2af435c6713d49e46691213ad15db0a5e93a63a77f1130c2 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 8 +++++++- src/where.c | 5 +++-- src/wherecode.c | 2 ++ 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index f576dec37b..2c58aedeeb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Apply\sthe\sBloom\sfilter\sonly\son\sthose\sterms\sof\san\sindex\sthat\shave\sequality\nconstraints. -D 2021-12-04T14:24:30.524 +C Add\sVdbeCoverage()\smacros.\s\sAdjust\sthe\sBloom-filter\shash\sfunction\sso\sthat\sit\ncorrectly\sdeals\swith\szero-blobs. +D 2021-12-04T18:45:08.377 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -622,7 +622,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c d4435e88e8abb076c955ee8262f548afcba77daa28b75f937ed914404bb29be7 +F src/vdbe.c 94af4eba93ad9ca7dd929cd19792ce2a5feb4797a7a64ec3cb3b2277e1467a8b F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h fd1103c7ecec8c84164038c8eacaa4a633cb3c10a2f725aae7bd865d4a4fcceb F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -637,9 +637,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c d203a7acda584940eee49d80e38067ba354410ca08782792bdf4d6f56ca20aa3 +F src/where.c 2607f8008b27f03003d62ed3b90e1818fda1dd5727daf020c8b3e526aff57269 F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 -F src/wherecode.c ab83c1f7c593ab5e9268c51dde80f478e48468e8c1e25866a4f445e7b4282b78 +F src/wherecode.c 2253f91bcded8932a4211238fa7dcf6ab40ff68dbd4c2d88eb4411f12b19552c F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8e078c0e404fe4b3661dd4a11a992a8914c99e2a144cecc417421cbd68fa08cc -R a78591e6ea873c8de7a64c271c45d204 +P a70429596a3c6a413b03118b0d800521b3526d99dcf88a48acc3189b51518d82 +R f0b7f8e349624b23e895cc40d5e34cdd U drh -Z 73637cbd9e62c30bcdc98bccabee0c03 +Z 186d2bb7a1014e61ff9f3f3c0fb31234 diff --git a/manifest.uuid b/manifest.uuid index 23eed8d9fa..55275e45b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a70429596a3c6a413b03118b0d800521b3526d99dcf88a48acc3189b51518d82 \ No newline at end of file +629ee2e3e3125bfd2af435c6713d49e46691213ad15db0a5e93a63a77f1130c2 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 9b6a4106d3..acbbee892f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -695,6 +695,7 @@ static unsigned int filterHash(const Mem *aMem, const Op *pOp){ h += (u32)(sqlite3VdbeIntValue(p)&0xffffffff); }else if( p->flags & (MEM_Str|MEM_Blob) ){ h += p->n; + if( p->flags & MEM_Zero ) h += p->u.nZero; } } return h % (SQLITE_BLOOM_SZ*8); @@ -8229,7 +8230,12 @@ case OP_Filter: { /* jump */ } #endif assert( h>=0 && hz[h/8] & (1<<(h&7)))==0 ) goto jump_to_p2; + if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ + VdbeBranchTaken(1, 2); + goto jump_to_p2; + }else{ + VdbeBranchTaken(0, 2); + } break; } diff --git a/src/where.c b/src/where.c index 87a00ef200..0d205125c8 100644 --- a/src/where.c +++ b/src/where.c @@ -986,10 +986,10 @@ static SQLITE_NOINLINE void constructBloomFilter( assert( v!=0 ); iCur = pLevel->iTabCur; addrCont = sqlite3VdbeMakeLabel(pParse); - addrTop = sqlite3VdbeAddOp0(v, OP_Once); + addrTop = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); pLevel->regFilter = ++pParse->nMem; sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); - sqlite3VdbeAddOp1(v, OP_Rewind, iCur); + sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; for(pTerm=pWInfo->sWC.a; pTermpExpr; @@ -1016,6 +1016,7 @@ static SQLITE_NOINLINE void constructBloomFilter( } sqlite3VdbeResolveLabel(v, addrCont); sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); + VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrTop); sqlite3VdbeJumpHere(v, addrTop+2); } diff --git a/src/wherecode.c b/src/wherecode.c index fbb40ad4e3..e02a736428 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1517,6 +1517,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pLevel->regFilter ){ sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, iRowidReg, 1); + VdbeCoverage(v); } sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); @@ -1846,6 +1847,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pLevel->regFilter ){ sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, regBase, nEq); + VdbeCoverage(v); } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; From fecbf0a179ae9c2aae0fbca17c80ce776ef78704 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 4 Dec 2021 21:11:18 +0000 Subject: [PATCH 026/148] Miscellaneous cleanup of the new Bloom-filter code. FossilOrigin-Name: 201b6dd875b0ae2bbc9969b098e88abfc09e37b59e857decd41f2dcbeeb13e01 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 31 +++++++++++++++---------------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 2c58aedeeb..e1808eea5b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sVdbeCoverage()\smacros.\s\sAdjust\sthe\sBloom-filter\shash\sfunction\sso\sthat\sit\ncorrectly\sdeals\swith\szero-blobs. -D 2021-12-04T18:45:08.377 +C Miscellaneous\scleanup\sof\sthe\snew\sBloom-filter\scode. +D 2021-12-04T21:11:18.037 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 2607f8008b27f03003d62ed3b90e1818fda1dd5727daf020c8b3e526aff57269 +F src/where.c 957543456a7d1683d21ed8c890bcdaa6414716082dfb076bb43decdc0f87909e F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 F src/wherecode.c 2253f91bcded8932a4211238fa7dcf6ab40ff68dbd4c2d88eb4411f12b19552c F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a70429596a3c6a413b03118b0d800521b3526d99dcf88a48acc3189b51518d82 -R f0b7f8e349624b23e895cc40d5e34cdd +P 629ee2e3e3125bfd2af435c6713d49e46691213ad15db0a5e93a63a77f1130c2 +R 5366235cd370e2a6adf5aabc2d25d6ed U drh -Z 186d2bb7a1014e61ff9f3f3c0fb31234 +Z ab3ac181064c99ca5c8ac656f604bf60 diff --git a/manifest.uuid b/manifest.uuid index 55275e45b8..5fe0ded6ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -629ee2e3e3125bfd2af435c6713d49e46691213ad15db0a5e93a63a77f1130c2 \ No newline at end of file +201b6dd875b0ae2bbc9969b098e88abfc09e37b59e857decd41f2dcbeeb13e01 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 0d205125c8..c1a538dcc9 100644 --- a/src/where.c +++ b/src/where.c @@ -717,9 +717,9 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){ ** index existed. */ static int termCanDriveIndex( - WhereTerm *pTerm, /* WHERE clause term to check */ - SrcItem *pSrc, /* Table we are trying to access */ - Bitmask notReady /* Tables in outer loops of the join */ + const WhereTerm *pTerm, /* WHERE clause term to check */ + const SrcItem *pSrc, /* Table we are trying to access */ + const Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; @@ -752,9 +752,9 @@ static int termCanDriveIndex( */ static SQLITE_NOINLINE void constructAutomaticIndex( Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - SrcItem *pSrc, /* The FROM clause term to get the next index */ - Bitmask notReady, /* Mask of cursors that are not available */ + const WhereClause *pWC, /* The WHERE clause */ + const SrcItem *pSrc, /* The FROM clause term to get the next index */ + const Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ int nKeyCol; /* Number of columns in the constructed index */ @@ -969,16 +969,16 @@ end_auto_index_create: ** Create a Bloom filter for the WhereLevel in the parameter. */ static SQLITE_NOINLINE void constructBloomFilter( - WhereInfo *pWInfo, /* The WHERE clause */ + const WhereInfo *pWInfo, /* The WHERE clause */ WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ ){ int addrTop; int addrCont; - WhereTerm *pTerm; - WhereTerm *pWCEnd; + const WhereTerm *pTerm; + const WhereTerm *pWCEnd; Parse *pParse = pWInfo->pParse; Vdbe *v = pParse->pVdbe; - WhereLoop *pLoop = pLevel->pWLoop; + const WhereLoop *pLoop = pLevel->pWLoop; int iCur; @@ -4915,21 +4915,20 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( ** down where the code for each WhereLoop is generated. */ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( - WhereInfo *pWInfo, - sqlite3 *db + const WhereInfo *pWInfo ){ int i; LogEst nSearch; SrcItem *pItem; assert( pWInfo->nLevel>=2 ); - assert( OptimizationEnabled(db, SQLITE_BloomFilter) ); + assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) ); nSearch = pWInfo->a[0].pWLoop->nOut; for(i=1; inLevel; i++){ WhereLoop *pLoop = pWInfo->a[i].pWLoop; - if( (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 + if( pLoop->nOut<0 + && (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 && (pLoop->wsFlags & WHERE_COLUMN_EQ)!=0 - && pLoop->nOut<0 && nSearch > (pItem = &pWInfo->pTabList->a[pLoop->iTab])->pTab->nRowLogEst && (pItem->fg.jointype & JT_LEFT)==0 ){ @@ -5336,7 +5335,7 @@ WhereInfo *sqlite3WhereBegin( if( pWInfo->nLevel>=2 && OptimizationEnabled(db, SQLITE_BloomFilter) ){ - whereCheckIfBloomFilterIsUseful(pWInfo, db); + whereCheckIfBloomFilterIsUseful(pWInfo); } #if defined(WHERETRACE_ENABLED) From 35685d3e5e0e28a7631616809be450b090029482 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 5 Dec 2021 00:45:55 +0000 Subject: [PATCH 027/148] Try to run all Bloom filters before any Seeks. This gives a small performance gain on the Star-Schema Benchmark. FossilOrigin-Name: 5be2470f8755ef454f813c880e659bdbf82f2396be9320cf3079cd4ca8e81a19 --- manifest | 16 +++++++------- manifest.uuid | 2 +- src/where.c | 8 ++++--- src/whereInt.h | 1 + src/wherecode.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index e1808eea5b..1a9a4b84ff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Miscellaneous\scleanup\sof\sthe\snew\sBloom-filter\scode. -D 2021-12-04T21:11:18.037 +C Try\sto\srun\sall\sBloom\sfilters\sbefore\sany\sSeeks.\s\sThis\sgives\sa\ssmall\sperformance\ngain\son\sthe\sStar-Schema\sBenchmark. +D 2021-12-05T00:45:55.528 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,9 +637,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 957543456a7d1683d21ed8c890bcdaa6414716082dfb076bb43decdc0f87909e -F src/whereInt.h 2c9d149b1b41c59f977deb1882e95632800946fcf15c83eaffb227afece04e51 -F src/wherecode.c 2253f91bcded8932a4211238fa7dcf6ab40ff68dbd4c2d88eb4411f12b19552c +F src/where.c 3d29b27e345a28f76ecb20b0c789a224e9dc74534363c3ddbc44c283eb4cb708 +F src/whereInt.h 3c634e184de128d99c2b017f899f2309c77330de54193ff970597e9acdeaff3b +F src/wherecode.c 48b456c910d552e1edf098071546c523837356ba0e3703d7b8fd9fc819da1c9b F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 629ee2e3e3125bfd2af435c6713d49e46691213ad15db0a5e93a63a77f1130c2 -R 5366235cd370e2a6adf5aabc2d25d6ed +P 201b6dd875b0ae2bbc9969b098e88abfc09e37b59e857decd41f2dcbeeb13e01 +R 8ad2d75d69a2ffc06bdf1b52eb7537e1 U drh -Z ab3ac181064c99ca5c8ac656f604bf60 +Z 42400fd1219d022ab29b577e6d964b89 diff --git a/manifest.uuid b/manifest.uuid index 5fe0ded6ae..cca08a44eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -201b6dd875b0ae2bbc9969b098e88abfc09e37b59e857decd41f2dcbeeb13e01 \ No newline at end of file +5be2470f8755ef454f813c880e659bdbf82f2396be9320cf3079cd4ca8e81a19 \ No newline at end of file diff --git a/src/where.c b/src/where.c index c1a538dcc9..2f7eb06097 100644 --- a/src/where.c +++ b/src/where.c @@ -968,7 +968,7 @@ end_auto_index_create: /* ** Create a Bloom filter for the WhereLevel in the parameter. */ -static SQLITE_NOINLINE void constructBloomFilter( +SQLITE_NOINLINE void sqlite3ConstructBloomFilter( const WhereInfo *pWInfo, /* The WHERE clause */ WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ ){ @@ -1003,16 +1003,18 @@ static SQLITE_NOINLINE void constructBloomFilter( int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); + sqlite3ReleaseTempReg(pParse, r1); }else{ Index *pIdx = pLoop->u.btree.pIndex; - int r1 = sqlite3GetTempRange(pParse, pIdx->nKeyCol); int n = pLoop->u.btree.nEq; + int r1 = sqlite3GetTempRange(pParse, n); int jj; for(jj=0; jjaiColumn[jj]; sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); } sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); + sqlite3ReleaseTempRange(pParse, r1, n); } sqlite3VdbeResolveLabel(v, addrCont); sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); @@ -5533,7 +5535,7 @@ WhereInfo *sqlite3WhereBegin( &pTabList->a[pLevel->iFrom], notReady, pLevel); #endif }else{ - constructBloomFilter(pWInfo, pLevel); + sqlite3ConstructBloomFilter(pWInfo, pLevel); } if( db->mallocFailed ) goto whereBeginError; } diff --git a/src/whereInt.h b/src/whereInt.h index fbe84787f9..19261ca397 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -484,6 +484,7 @@ struct WhereInfo { ** where.c: */ Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); +void sqlite3ConstructBloomFilter(const WhereInfo*, WhereLevel*); #ifdef WHERETRACE_ENABLED void sqlite3WhereClausePrint(WhereClause *pWC); void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); diff --git a/src/wherecode.c b/src/wherecode.c index e02a736428..adc7d5b8e1 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1304,6 +1304,60 @@ static void whereApplyPartialIndexConstraints( } } +#if 1 +/* +** An OP_Filter has just been generated, but the corresponding +** index search has not yet been performed. This routine +** checks to see if there are additional WHERE_BLOOMFILTER in +** inner loops that can be evaluated right away, and if there are, +** it evaluates those filters as well, and removes the WHERE_BLOOMFILTER +** tag. +*/ +static SQLITE_NOINLINE void filterPullDown( + Parse *pParse, /* Parsing context */ + WhereInfo *pWInfo, /* Complete information about the WHERE clause */ + int iLevel, /* Which level of pWInfo->a[] should be coded */ + int addrNxt, /* Jump here to bypass inner loops */ + Bitmask notReady /* Loops that are not ready */ +){ + while( ++iLevel < pWInfo->nLevel ){ + WhereLevel *pLevel = &pWInfo->a[iLevel]; + WhereLoop *pLoop = pLevel->pWLoop; + if( (pLoop->wsFlags & WHERE_BLOOMFILTER)==0 ) continue; + if( pLoop->prereq & notReady ) continue; + sqlite3ConstructBloomFilter(pWInfo, &pWInfo->a[iLevel]); + if( pLoop->wsFlags & WHERE_IPK ){ + WhereTerm *pTerm = pLoop->aLTerm[0]; + int r1, regRowid; + assert( pTerm!=0 ); + assert( pTerm->pExpr!=0 ); + testcase( pTerm->wtFlags & TERM_VIRTUAL ); + r1 = sqlite3GetTempReg(pParse); + regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, r1); + if( regRowid!=r1 ) sqlite3ReleaseTempReg(pParse, r1); + sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, + addrNxt, regRowid, 1); + VdbeCoverage(pParse->pVdbe); + }else{ + u16 nEq = pLoop->u.btree.nEq; + int r1; + char *zStartAff; + + assert( pLoop->wsFlags & WHERE_INDEXED ); + r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff); + codeApplyAffinity(pParse, r1, nEq, zStartAff); + sqlite3DbFree(pParse->db, zStartAff); + sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, + addrNxt, r1, nEq); + VdbeCoverage(pParse->pVdbe); + } + pLoop->wsFlags &= ~WHERE_BLOOMFILTER; + } +} +#else +#define filterPullDown(A,B,C,D,E) +#endif + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -1518,6 +1572,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, iRowidReg, 1); VdbeCoverage(v); + filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); } sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); @@ -1848,6 +1903,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, regBase, nEq); VdbeCoverage(v); + filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; From 6ae49e67cc6e40538d1de2e0239dbdd59e487814 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 5 Dec 2021 20:19:47 +0000 Subject: [PATCH 028/148] Run as many Bloom filters as possible before index lookups. FossilOrigin-Name: 06f6fefd67086896bc49272c6319545ff6c6792f18babe23aced27b60b032119 --- manifest | 18 +++---- manifest.uuid | 2 +- src/sqliteInt.h | 1 + src/where.c | 129 ++++++++++++++++++++++++++++++------------------ src/whereInt.h | 7 ++- src/wherecode.c | 77 +++++++++++++++++++++++------ 6 files changed, 158 insertions(+), 76 deletions(-) diff --git a/manifest b/manifest index 1a9a4b84ff..47992d2a2e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Try\sto\srun\sall\sBloom\sfilters\sbefore\sany\sSeeks.\s\sThis\sgives\sa\ssmall\sperformance\ngain\son\sthe\sStar-Schema\sBenchmark. -D 2021-12-05T00:45:55.528 +C Run\sas\smany\sBloom\sfilters\sas\spossible\sbefore\sindex\slookups. +D 2021-12-05T20:19:47.744 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -555,7 +555,7 @@ F src/shell.c.in e7ee6517544d075d9f06ee2571567026b89cf9fbeef16a74918019b1cb42576 F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 4a19ff088cc3bb1467cca94011eaf7e8432476124bbb72c77053d9f1e6b0a6c7 +F src/sqliteInt.h 178eb899c1edc08dcddf37e79dfaa39404a1f5d44a1d512509cd5d41867aa836 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -637,9 +637,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 3d29b27e345a28f76ecb20b0c789a224e9dc74534363c3ddbc44c283eb4cb708 -F src/whereInt.h 3c634e184de128d99c2b017f899f2309c77330de54193ff970597e9acdeaff3b -F src/wherecode.c 48b456c910d552e1edf098071546c523837356ba0e3703d7b8fd9fc819da1c9b +F src/where.c b07c5eefecffa1b69b91c366a83c69d01a83f1c900b9d9b1ffb6eb5ab59902a1 +F src/whereInt.h 5c6601d6d0b7b8936482506d2d835981cc6efcd8e106a829893a27a14cfb10b8 +F src/wherecode.c fa667db48db1077b42731bfd97e9181b39409ffdc7051162ecae6895ca71ad2c F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 201b6dd875b0ae2bbc9969b098e88abfc09e37b59e857decd41f2dcbeeb13e01 -R 8ad2d75d69a2ffc06bdf1b52eb7537e1 +P 5be2470f8755ef454f813c880e659bdbf82f2396be9320cf3079cd4ca8e81a19 +R da3cb867f9ab99abba060de93457c8d9 U drh -Z 42400fd1219d022ab29b577e6d964b89 +Z d87a509afa829d1cf21b5a6dcadef441 diff --git a/manifest.uuid b/manifest.uuid index cca08a44eb..669a897f37 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5be2470f8755ef454f813c880e659bdbf82f2396be9320cf3079cd4ca8e81a19 \ No newline at end of file +06f6fefd67086896bc49272c6319545ff6c6792f18babe23aced27b60b032119 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e96947e81d..896b2aa422 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1762,6 +1762,7 @@ struct sqlite3 { #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ +#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* diff --git a/src/where.c b/src/where.c index 2f7eb06097..1d88c3ed30 100644 --- a/src/where.c +++ b/src/where.c @@ -966,61 +966,92 @@ end_auto_index_create: #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ /* -** Create a Bloom filter for the WhereLevel in the parameter. +** Generate bytecode that will initialize a Bloom filter that is appropriate +** for pLevel. +** +** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER +** flag set, initialize a Bloomfilter for them as well. Except don't do +** this recursive initialization if the SQLITE_BloomPulldown optimization has +** been turned off. +** +** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared +** from the loop, but the regFilter value is set to a register that implements +** the Bloom filter. When regFilter is positive, the +** sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter +** and skip the subsequence B-Tree seek if the Bloom filter indicates that +** no matching rows exist. +** +** This routine may only be called if it has previously been determined that +** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit +** is set. */ -SQLITE_NOINLINE void sqlite3ConstructBloomFilter( - const WhereInfo *pWInfo, /* The WHERE clause */ - WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ +static SQLITE_NOINLINE void constructBloomFilter( + WhereInfo *pWInfo, /* The WHERE clause */ + int iLevel, /* Index in pWInfo->a[] that is pLevel */ + WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ ){ - int addrTop; - int addrCont; - const WhereTerm *pTerm; - const WhereTerm *pWCEnd; - Parse *pParse = pWInfo->pParse; - Vdbe *v = pParse->pVdbe; - const WhereLoop *pLoop = pLevel->pWLoop; - int iCur; - + int addrOnce; /* Address of opening OP_Once */ + int addrTop; /* Address of OP_Rewind */ + int addrCont; /* Jump here to skip a row */ + const WhereTerm *pTerm; /* For looping over WHERE clause terms */ + const WhereTerm *pWCEnd; /* Last WHERE clause term */ + Parse *pParse = pWInfo->pParse; /* Parsing context */ + Vdbe *v = pParse->pVdbe; /* VDBE under construction */ + WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ + int iCur; /* Cursor for table getting the filter */ assert( pLoop!=0 ); assert( v!=0 ); - iCur = pLevel->iTabCur; - addrCont = sqlite3VdbeMakeLabel(pParse); - addrTop = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - pLevel->regFilter = ++pParse->nMem; - sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); - sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; - for(pTerm=pWInfo->sWC.a; pTermpExpr; - if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsTableConstant(pExpr, iCur) - ){ - sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); + assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); + + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + do{ + sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); + addrCont = sqlite3VdbeMakeLabel(pParse); + iCur = pLevel->iTabCur; + pLevel->regFilter = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); + pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; + for(pTerm=pWInfo->sWC.a; pTermpExpr; + if( (pTerm->wtFlags & TERM_VIRTUAL)==0 + && sqlite3ExprIsTableConstant(pExpr, iCur) + ){ + sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); + } } - } - if( pLoop->wsFlags & WHERE_IPK ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); - sqlite3ReleaseTempReg(pParse, r1); - }else{ - Index *pIdx = pLoop->u.btree.pIndex; - int n = pLoop->u.btree.nEq; - int r1 = sqlite3GetTempRange(pParse, n); - int jj; - for(jj=0; jjaiColumn[jj]; - sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); + if( pLoop->wsFlags & WHERE_IPK ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); + sqlite3ReleaseTempReg(pParse, r1); + }else{ + Index *pIdx = pLoop->u.btree.pIndex; + int n = pLoop->u.btree.nEq; + int r1 = sqlite3GetTempRange(pParse, n); + int jj; + for(jj=0; jjaiColumn[jj]; + sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); + } + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); + sqlite3ReleaseTempRange(pParse, r1, n); } - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); - sqlite3ReleaseTempRange(pParse, r1, n); - } - sqlite3VdbeResolveLabel(v, addrCont); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrTop); - sqlite3VdbeJumpHere(v, addrTop+2); + sqlite3VdbeResolveLabel(v, addrCont); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addrTop); + pLoop->wsFlags &= ~WHERE_BLOOMFILTER; + if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break; + while( iLevel < pWInfo->nLevel ){ + iLevel++; + pLevel = &pWInfo->a[iLevel]; + pLoop = pLevel->pWLoop; + if( pLoop && pLoop->wsFlags & WHERE_BLOOMFILTER ) break; + } + }while( iLevel < pWInfo->nLevel ); + sqlite3VdbeJumpHere(v, addrOnce); } @@ -5535,7 +5566,7 @@ WhereInfo *sqlite3WhereBegin( &pTabList->a[pLevel->iFrom], notReady, pLevel); #endif }else{ - sqlite3ConstructBloomFilter(pWInfo, pLevel); + constructBloomFilter(pWInfo, ii, pLevel); } if( db->mallocFailed ) goto whereBeginError; } diff --git a/src/whereInt.h b/src/whereInt.h index 19261ca397..4da6015f16 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -484,7 +484,6 @@ struct WhereInfo { ** where.c: */ Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); -void sqlite3ConstructBloomFilter(const WhereInfo*, WhereLevel*); #ifdef WHERETRACE_ENABLED void sqlite3WhereClausePrint(WhereClause *pWC); void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); @@ -507,8 +506,14 @@ int sqlite3WhereExplainOneScan( WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); +int sqlite3WhereExplainBloomFilter( + const Parse *pParse, /* Parse context */ + const WhereInfo *pWInfo, /* WHERE clause */ + const WhereLevel *pLevel /* Bloom filter on this level */ +); #else # define sqlite3WhereExplainOneScan(u,v,w,x) 0 +# define sqlite3WhereExplainBloomFilter(u,v,w) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3WhereAddScanStatus( diff --git a/src/wherecode.c b/src/wherecode.c index adc7d5b8e1..dfe697f244 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -196,9 +196,6 @@ int sqlite3WhereExplainOneScan( pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif - if( flags & WHERE_BLOOMFILTER ){ - sqlite3_str_appendf(&str, " WITH BLOOM FILTER"); - } #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS if( pLoop->nOut>=10 ){ sqlite3_str_appendf(&str, " (~%llu rows)", @@ -214,6 +211,52 @@ int sqlite3WhereExplainOneScan( } return ret; } + +/* +** Add a single OP_Explain opcode that describes a Bloom filter. +** +** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or +** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not +** required and this routine is a no-op. +** +** If an OP_Explain opcode is added to the VM, its address is returned. +** Otherwise, if no OP_Explain is coded, zero is returned. +*/ +int sqlite3WhereExplainBloomFilter( + const Parse *pParse, /* Parse context */ + const WhereInfo *pWInfo, /* WHERE clause */ + const WhereLevel *pLevel /* Bloom filter on this level */ +){ + int ret = 0; +#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) + if( sqlite3ParseToplevel(pParse)->explain==2 ) +#endif + { + SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zMsg; /* Text to add to EQP output */ + int i; /* Loop counter */ + WhereLoop *pLoop; /* The where loop */ + StrAccum str; /* EQP output string */ + char zBuf[100]; /* Initial space for EQP output string */ + + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); + str.printfFlags = SQLITE_PRINTF_INTERNAL; + sqlite3_str_appendf(&str, "BLOOM FILTER ON %S(", pItem); + pLoop = pLevel->pWLoop; + for(i=pLoop->nSkip; iu.btree.nEq; i++){ + const char *z = pItem->pTab->aCol[i].zCnName; + if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); + sqlite3_str_appendf(&str, "%s=?", z); + } + sqlite3_str_append(&str, ")", 1); + zMsg = sqlite3StrAccumFinish(&str); + ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), + pParse->addrExplain, 0, zMsg,P4_DYNAMIC); + } + return ret; +} #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS @@ -1304,14 +1347,20 @@ static void whereApplyPartialIndexConstraints( } } -#if 1 /* -** An OP_Filter has just been generated, but the corresponding -** index search has not yet been performed. This routine -** checks to see if there are additional WHERE_BLOOMFILTER in -** inner loops that can be evaluated right away, and if there are, -** it evaluates those filters as well, and removes the WHERE_BLOOMFILTER -** tag. +** This routine is called right after An OP_Filter has been generated and +** before the corresponding index search has been performed. This routine +** checks to see if there are additional Bloom filters in inner loops that +** can be checked prior to doing the index lookup. If there are available +** inner-loop Bloom filters, then evaluate those filters now, before the +** index lookup. The idea is that a Bloom filter check is way faster than +** an index lookup, and the Bloom filter might return false, meaning that +** the index lookup can be skipped. +** +** We know that an inner loop uses a Bloom filter because it has the +** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked, +** then clear the WhereLoeve.regFilter value to prevent the Bloom filter +** from being checked a second time when the inner loop is evaluated. */ static SQLITE_NOINLINE void filterPullDown( Parse *pParse, /* Parsing context */ @@ -1323,9 +1372,8 @@ static SQLITE_NOINLINE void filterPullDown( while( ++iLevel < pWInfo->nLevel ){ WhereLevel *pLevel = &pWInfo->a[iLevel]; WhereLoop *pLoop = pLevel->pWLoop; - if( (pLoop->wsFlags & WHERE_BLOOMFILTER)==0 ) continue; + if( pLevel->regFilter==0 ) continue; if( pLoop->prereq & notReady ) continue; - sqlite3ConstructBloomFilter(pWInfo, &pWInfo->a[iLevel]); if( pLoop->wsFlags & WHERE_IPK ){ WhereTerm *pTerm = pLoop->aLTerm[0]; int r1, regRowid; @@ -1351,12 +1399,9 @@ static SQLITE_NOINLINE void filterPullDown( addrNxt, r1, nEq); VdbeCoverage(pParse->pVdbe); } - pLoop->wsFlags &= ~WHERE_BLOOMFILTER; + pLevel->regFilter = 0; } } -#else -#define filterPullDown(A,B,C,D,E) -#endif /* ** Generate code for the start of the iLevel-th loop in the WHERE clause From 5baaf40af1898bdcfcdb5c30405b6da1342e2011 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 13:07:28 +0000 Subject: [PATCH 029/148] Attempt to vary the size of Bloom filters based on an estimate of how many keys the filter will hold. FossilOrigin-Name: a7adcf69088cba4b86cc5731a45c9a5263af4355bc0a38f5225cab421c915f7f --- manifest | 18 +++++------ manifest.uuid | 2 +- src/malloc.c | 19 ++++++++++++ src/sqliteInt.h | 1 + src/vdbe.c | 81 +++++++++++++++++++++++++++++++++++++------------ src/where.c | 5 +-- 6 files changed, 95 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 47992d2a2e..648c9a9161 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sas\smany\sBloom\sfilters\sas\spossible\sbefore\sindex\slookups. -D 2021-12-05T20:19:47.744 +C Attempt\sto\svary\sthe\ssize\sof\sBloom\sfilters\sbased\son\san\sestimate\sof\show\smany\nkeys\sthe\sfilter\swill\shold. +D 2021-12-06T13:07:28.112 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -515,7 +515,7 @@ F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c F src/main.c 7bd4fdc41ef53535271a1816ff043ba153cda03842b444b6e2f57b27b2cb9090 -F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b +F src/malloc.c 183c2bf45cee1589254e4047e220f1ffbcc0a3bc8e4fe46fe64ba5db447a79af F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75 @@ -555,7 +555,7 @@ F src/shell.c.in e7ee6517544d075d9f06ee2571567026b89cf9fbeef16a74918019b1cb42576 F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 178eb899c1edc08dcddf37e79dfaa39404a1f5d44a1d512509cd5d41867aa836 +F src/sqliteInt.h ab40ea9c294c656e0d6ab14e67d58f10b015a77e962dd075fdbe3ea3cc1a976b F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -622,7 +622,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 94af4eba93ad9ca7dd929cd19792ce2a5feb4797a7a64ec3cb3b2277e1467a8b +F src/vdbe.c 6176125ea038f593597b5897898328142b5253201d321369df74e187b2b1abaa F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h fd1103c7ecec8c84164038c8eacaa4a633cb3c10a2f725aae7bd865d4a4fcceb F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c b07c5eefecffa1b69b91c366a83c69d01a83f1c900b9d9b1ffb6eb5ab59902a1 +F src/where.c 04ead529a272341a4cae3ef0dcd2f7675d433627acc5fb87fed1407e7b3d8614 F src/whereInt.h 5c6601d6d0b7b8936482506d2d835981cc6efcd8e106a829893a27a14cfb10b8 F src/wherecode.c fa667db48db1077b42731bfd97e9181b39409ffdc7051162ecae6895ca71ad2c F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5be2470f8755ef454f813c880e659bdbf82f2396be9320cf3079cd4ca8e81a19 -R da3cb867f9ab99abba060de93457c8d9 +P 06f6fefd67086896bc49272c6319545ff6c6792f18babe23aced27b60b032119 +R 5f90145148ed31800619d7b25d77beb7 U drh -Z d87a509afa829d1cf21b5a6dcadef441 +Z 3013773c2d9a03770ac02d1fdd22abd3 diff --git a/manifest.uuid b/manifest.uuid index 669a897f37..7894b82c00 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -06f6fefd67086896bc49272c6319545ff6c6792f18babe23aced27b60b032119 \ No newline at end of file +a7adcf69088cba4b86cc5731a45c9a5263af4355bc0a38f5225cab421c915f7f \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 932cecc210..ab9b37ddad 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -211,6 +211,25 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ return mx; } +/* +** Return an estimate of the amount of unallocated memory. +** +** This the hard heap limit minus the current memory usage. It might +** not be possible to allocate this much memory all at once. This is +** only an estimate. +*/ +sqlite3_int64 sqlite3EstMemoryAvailable(void){ + sqlite3_int64 n; + sqlite3_mutex_enter(mem0.mutex); + n = mem0.alarmThreshold; + if( n<=0 ) n = mem0.hardLimit; + sqlite3_mutex_leave(mem0.mutex); + if( n<=0 ) n = LARGEST_INT64; + n -= sqlite3_memory_used(); + if( n<0 ) n = 0; + return n; +} + /* ** Trigger the alarm */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 896b2aa422..9091f02115 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4293,6 +4293,7 @@ void sqlite3MemSetDefault(void); void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); #endif int sqlite3HeapNearlyFull(void); +sqlite3_int64 sqlite3EstMemoryAvailable(void); /* ** On systems with ample stack space and that support alloca(), make diff --git a/src/vdbe.c b/src/vdbe.c index acbbee892f..487d731af3 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -672,17 +672,29 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ } /* -** Default size of a bloom filter, in bytes +** The minimum size (in bytes) for a Bloom filter. +** +** No Bloom filter will be smaller than this many bytes. But they +** may be larger. */ -#define SQLITE_BLOOM_SZ 10000 +#ifndef SQLITE_BLOOM_MIN +# define SQLITE_BLOOM_MIN 10000 +#endif + +/* +** The maximum size (in bytes) for a Bloom filter. +*/ +#ifndef SQLITE_BLOOM_MAX +# define SQLITE_BLOOM_MAX 1000000 +#endif /* ** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning ** with pOp->p3. Return the hash. */ -static unsigned int filterHash(const Mem *aMem, const Op *pOp){ +static u64 filterHash(const Mem *aMem, const Op *pOp){ int i, mx; - u32 h = 0; + u64 h = 0; i = pOp->p3; assert( pOp->p4type==P4_INT32 ); @@ -690,15 +702,15 @@ static unsigned int filterHash(const Mem *aMem, const Op *pOp){ for(i=pOp->p3, mx=i+pOp->p4.i; iflags & (MEM_Int|MEM_IntReal) ){ - h += (u32)(p->u.i&0xffffffff); + h += p->u.i; }else if( p->flags & MEM_Real ){ - h += (u32)(sqlite3VdbeIntValue(p)&0xffffffff); + h += sqlite3VdbeIntValue(p); }else if( p->flags & (MEM_Str|MEM_Blob) ){ h += p->n; if( p->flags & MEM_Zero ) h += p->u.nZero; } } - return h % (SQLITE_BLOOM_SZ*8); + return h; } /* @@ -8157,15 +8169,44 @@ case OP_Function: { /* group */ break; } -/* Opcode: FilterInit P1 * * * * -** Synopsis: filter(P1) = empty +/* Opcode: FilterInit P1 P2 * * * ** ** Initialize register P1 so that is an empty bloom filter. +** +** If P2 is positive, it is a register that holds an estimate on +** the number of entries to be added to the Bloom filter. The +** Bloom filter is sized accordingly. If P2 is zero or negative, +** then a default-size Bloom filter is created. +** +** It is ok for P1 and P2 to be the same register. In that case the +** integer value originally in that register will be overwritten +** with the new empty bloom filter. */ case OP_FilterInit: { + i64 n, mx; assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; - sqlite3VdbeMemSetZeroBlob(pIn1, SQLITE_BLOOM_SZ); + if( pOp->p2>0 ){ + assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); + n = sqlite3VdbeIntValue(&aMem[pOp->p2]); + if( nSQLITE_BLOOM_MAX ){ + n = SQLITE_BLOOM_MAX; + } + }else{ + n = SQLITE_BLOOM_MIN; + } + mx = sqlite3EstMemoryAvailable()/2; + if( n>mx && mx>SQLITE_BLOOM_MIN ){ + n = mx; + } +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + printf("Bloom-filter size: %llu bytes\n", n); + } +#endif + sqlite3VdbeMemSetZeroBlob(pIn1, n); if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; break; } @@ -8177,12 +8218,12 @@ case OP_FilterInit: { ** add that hash to the bloom filter contained in r[P1]. */ case OP_FilterAdd: { - u32 h; + u64 h; assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; assert( pIn1->flags & MEM_Blob ); - assert( pIn1->n==SQLITE_BLOOM_SZ ); + assert( pIn1->n>0 ); h = filterHash(aMem, pOp); #ifdef SQLITE_DEBUG if( db->flags&SQLITE_VdbeTrace ){ @@ -8190,10 +8231,10 @@ case OP_FilterAdd: { for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ registerTrace(ii, &aMem[ii]); } - printf("hash = %u\n", h); + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - assert( h>=0 && hn; pIn1->z[h/8] |= 1<<(h&7); break; } @@ -8213,12 +8254,14 @@ case OP_FilterAdd: { ** false positive - if the jump is taken when it should fall through. */ case OP_Filter: { /* jump */ - u32 h; + u64 h; assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags & MEM_Blob ); - assert( pIn1->n==SQLITE_BLOOM_SZ ); + if( (pIn1->flags & MEM_Blob)==0 || NEVER(pIn1->n<=0) ){ + VdbeBranchTaken(0, 2); + break; + } h = filterHash(aMem, pOp); #ifdef SQLITE_DEBUG if( db->flags&SQLITE_VdbeTrace ){ @@ -8226,10 +8269,10 @@ case OP_Filter: { /* jump */ for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ registerTrace(ii, &aMem[ii]); } - printf("hash = %u\n", h); + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - assert( h>=0 && hn; if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ VdbeBranchTaken(1, 2); goto jump_to_p2; diff --git a/src/where.c b/src/where.c index 1d88c3ed30..233e77b6a7 100644 --- a/src/where.c +++ b/src/where.c @@ -1010,8 +1010,9 @@ static SQLITE_NOINLINE void constructBloomFilter( addrCont = sqlite3VdbeMakeLabel(pParse); iCur = pLevel->iTabCur; pLevel->regFilter = ++pParse->nMem; - sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Count, iCur, pLevel->regFilter, 1); + sqlite3VdbeAddOp2(v, OP_FilterInit, pLevel->regFilter, pLevel->regFilter); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; for(pTerm=pWInfo->sWC.a; pTermpExpr; @@ -1039,7 +1040,7 @@ static SQLITE_NOINLINE void constructBloomFilter( sqlite3ReleaseTempRange(pParse, r1, n); } sqlite3VdbeResolveLabel(v, addrCont); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrTop); pLoop->wsFlags &= ~WHERE_BLOOMFILTER; From 39addd0a3f2283f0192cc472bc4464645f2ca560 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 15:08:30 +0000 Subject: [PATCH 030/148] Fix SQLITE_TESTCTRL_IMPOSTER so that it is a harmless no-op if the schema parameter is invalid. FossilOrigin-Name: 2d9a45ab10aaad681e11d639195430c0988b6ca1b96db6bf0b31b889e88a5430 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/main.c | 14 +++++++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 1fc8dc6703..5faa6fdf66 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Factor\sthe\snoop-join-elimination\soptimization\sout\sof\sthe\ssqlite3WhereBegin()\nroutine\sand\sinto\sa\sseparate\s"no-inline"\ssubroutine,\sin\sorder\sto\sreduce\sthe\ncomplexity\sof\ssqlite3WhereBegin()\sand\sthereby\sencourage\sC\scompilers\sto\ninline\ssqlite3WhereCodeOneLoopStart(). -D 2021-12-03T18:53:53.434 +C Fix\sSQLITE_TESTCTRL_IMPOSTER\sso\sthat\sit\sis\sa\sharmless\sno-op\sif\sthe\sschema\nparameter\sis\sinvalid. +D 2021-12-06T15:08:30.916 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -514,7 +514,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c -F src/main.c 7bd4fdc41ef53535271a1816ff043ba153cda03842b444b6e2f57b27b2cb9090 +F src/main.c e94230dba03f44b73c52abc8b814468a0cb6d4a66d71af33452edd78ed1b1228 F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8029e6bab508bf0b8ec1df00a829c5d4de2a84d66dc56b9ff03da879ceef7788 -R 963c220f26757d3ffbc2edfb4f7e86f0 +P 6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d +R 6fd46b2d7adccacab3c0abe27b9e56ae U drh -Z 180dbfc838231c2ae95c395bdf32b1d2 +Z 22c0cc9c8951bcb92c9322270d05ef33 diff --git a/manifest.uuid b/manifest.uuid index 9b8ce11932..0d58923b42 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d \ No newline at end of file +2d9a45ab10aaad681e11d639195430c0988b6ca1b96db6bf0b31b889e88a5430 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 4b2d0592c9..ce53496bc0 100644 --- a/src/main.c +++ b/src/main.c @@ -4260,12 +4260,16 @@ int sqlite3_test_control(int op, ...){ */ case SQLITE_TESTCTRL_IMPOSTER: { sqlite3 *db = va_arg(ap, sqlite3*); + int iDb; sqlite3_mutex_enter(db->mutex); - db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); - db->init.busy = db->init.imposterTable = va_arg(ap,int); - db->init.newTnum = va_arg(ap,int); - if( db->init.busy==0 && db->init.newTnum>0 ){ - sqlite3ResetAllSchemasOfConnection(db); + iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); + if( iDb>=0 ){ + db->init.iDb = iDb; + db->init.busy = db->init.imposterTable = va_arg(ap,int); + db->init.newTnum = va_arg(ap,int); + if( db->init.busy==0 && db->init.newTnum>0 ){ + sqlite3ResetAllSchemasOfConnection(db); + } } sqlite3_mutex_leave(db->mutex); break; From 38ed1ceb5a15cde81e2aa9c697382f7fd52cbdb2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 15:24:36 +0000 Subject: [PATCH 031/148] Do not allow certain dangerous ".testctrl" commands in safe mode. FossilOrigin-Name: 080e72d119b836c49916201bf135445aa7d53cefe40a47437a93448c4d0f41cd --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 46 ++++++++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 5faa6fdf66..1732a9cef1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sSQLITE_TESTCTRL_IMPOSTER\sso\sthat\sit\sis\sa\sharmless\sno-op\sif\sthe\sschema\nparameter\sis\sinvalid. -D 2021-12-06T15:08:30.916 +C Do\snot\sallow\scertain\sdangerous\s".testctrl"\scommands\sin\ssafe\smode. +D 2021-12-06T15:24:36.293 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in e7ee6517544d075d9f06ee2571567026b89cf9fbeef16a74918019b1cb425764 +F src/shell.c.in 1458b700144c8326fda2514aaddeda49d6f01f1d1ccf7b9b696c53a3535a119c F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6225e9abcb0261fefca4a26530524ffc449f937f8ae1ece718af2c3c3d73d78d -R 6fd46b2d7adccacab3c0abe27b9e56ae +P 2d9a45ab10aaad681e11d639195430c0988b6ca1b96db6bf0b31b889e88a5430 +R 169bd6ff0c0343d681f5647183dbf9fb U drh -Z 22c0cc9c8951bcb92c9322270d05ef33 +Z c109fbe5b7da812b5ec8b08a3717b168 diff --git a/manifest.uuid b/manifest.uuid index 0d58923b42..886d9a10a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2d9a45ab10aaad681e11d639195430c0988b6ca1b96db6bf0b31b889e88a5430 \ No newline at end of file +080e72d119b836c49916201bf135445aa7d53cefe40a47437a93448c4d0f41cd \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 72fe26339e..543141c9e4 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -10208,30 +10208,31 @@ static int do_meta_command(char *zLine, ShellState *p){ static const struct { const char *zCtrlName; /* Name of a test-control option */ int ctrlCode; /* Integer code for that option */ + int unSafe; /* Not valid for --safe mode */ 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, "" }, - { "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, "" }, - { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, - { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, - { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, + { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" }, + { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" }, + /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/ + /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/ + { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" }, + { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" }, + /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/ + { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" }, + { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" }, #ifdef YYCOVERAGE - { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, + { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" }, #endif - { "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?" }, - { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" }, - { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" }, - { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" }, + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, + { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, + { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, + { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, + { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, }; int testctrl = -1; int iCtrl = -1; @@ -10279,6 +10280,11 @@ static int do_meta_command(char *zLine, ShellState *p){ if( testctrl<0 ){ utf8_printf(stderr,"Error: unknown test-control: %s\n" "Use \".testctrl --help\" for help\n", zCmd); + }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){ + utf8_printf(stderr, + "line %d: \".testctrl %s\" may not be used in safe mode\n", + p->lineno, aCtrl[iCtrl].zCtrlName); + exit(1); }else{ switch(testctrl){ From f6a4ef144e0746bb2bde64e3a9914addb4ce7e5c Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 15:40:24 +0000 Subject: [PATCH 032/148] Do not allow SQLITE_LIMIT_LENGTH to be set lower than 1 as an SQLITE_LIMIT_LENGTH of 0 causes lots of unnecessary problems for users of the sqlite3_str object. FossilOrigin-Name: 8fd5b8ec4ab9b5554d27f25a4638d56e347eab78b60900f24b15a815d3731330 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/main.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 1732a9cef1..bb27ffe6b3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\scertain\sdangerous\s".testctrl"\scommands\sin\ssafe\smode. -D 2021-12-06T15:24:36.293 +C Do\snot\sallow\sSQLITE_LIMIT_LENGTH\sto\sbe\sset\slower\sthan\s1\sas\san\s\nSQLITE_LIMIT_LENGTH\sof\s0\scauses\slots\sof\sunnecessary\sproblems\sfor\nusers\sof\sthe\ssqlite3_str\sobject. +D 2021-12-06T15:40:24.187 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -514,7 +514,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c -F src/main.c e94230dba03f44b73c52abc8b814468a0cb6d4a66d71af33452edd78ed1b1228 +F src/main.c 1ea70751e6005ab6a9f784730fa0919efaa6639440a287deb73cb711e5aae57a F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -1933,7 +1933,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2d9a45ab10aaad681e11d639195430c0988b6ca1b96db6bf0b31b889e88a5430 -R 169bd6ff0c0343d681f5647183dbf9fb +P 080e72d119b836c49916201bf135445aa7d53cefe40a47437a93448c4d0f41cd +R c4a19d6efe230f8d42eba90fbf4c1b2a U drh -Z c109fbe5b7da812b5ec8b08a3717b168 +Z 860c42735bbc5c02ee56a87604c8521a diff --git a/manifest.uuid b/manifest.uuid index 886d9a10a1..23a65b5f9d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -080e72d119b836c49916201bf135445aa7d53cefe40a47437a93448c4d0f41cd \ No newline at end of file +8fd5b8ec4ab9b5554d27f25a4638d56e347eab78b60900f24b15a815d3731330 \ No newline at end of file diff --git a/src/main.c b/src/main.c index ce53496bc0..804719f176 100644 --- a/src/main.c +++ b/src/main.c @@ -2857,6 +2857,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ if( newLimit>=0 ){ /* IMP: R-52476-28732 */ if( newLimit>aHardLimit[limitId] ){ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ + }else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){ + newLimit = 1; } db->aLimit[limitId] = newLimit; } From c436b3056d8da290fbd5870cea45e7547394051a Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 6 Dec 2021 18:57:02 +0000 Subject: [PATCH 033/148] Fix an OOB read that could occur in fts5 when processing corrupt records. FossilOrigin-Name: bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 --- ext/fts5/fts5_index.c | 8 +++-- ext/fts5/test/fts5corrupt6.test | 54 +++++++++++++++++++++++++++++++++ manifest | 15 ++++----- manifest.uuid | 2 +- 4 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 ext/fts5/test/fts5corrupt6.test diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 54efb340c3..fe253984b3 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -1879,8 +1879,12 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ - pIter->pLeaf = pNew; - pIter->iLeafOffset = iRowidOff; + if( iRowidOff>=pNew->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + pIter->pLeaf = pNew; + pIter->iLeafOffset = iRowidOff; + } } } diff --git a/ext/fts5/test/fts5corrupt6.test b/ext/fts5/test/fts5corrupt6.test new file mode 100644 index 0000000000..6403d3a406 --- /dev/null +++ b/ext/fts5/test/fts5corrupt6.test @@ -0,0 +1,54 @@ +# 2015 Apr 24 +# +# 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 tests that FTS5 handles corrupt databases (i.e. internal +# inconsistencies in the backing tables) correctly. In this case +# "correctly" means without crashing. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5corrupt6 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} +sqlite3_fts5_may_be_corrupt 1 +database_may_be_corrupt + +proc editblock {block} { + binary format Sa* 20000 [string range $block 2 end] +} +db func editblock editblock + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ft USING fts5(abc, def); + WITH a(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM a WHERE i<1000 + ) + INSERT INTO ft SELECT + 'abc abc abc abc abc abc abc abc abc abc', + 'def def def def def def def def def def' + FROM a; + UPDATE ft_data SET block = editblock(block) WHERE id=( + SELECT id FROM ft_data ORDER BY id LIMIT 1 OFFSET 5 + ); +} + +do_catchsql_test 1.1 { + SELECT rowid FROM ft('def') ORDER BY rowid DESC LIMIT 1 OFFSET 9999; +} {1 {database disk image is malformed}} + + +sqlite3_fts5_may_be_corrupt 0 +finish_test + diff --git a/manifest b/manifest index bb27ffe6b3..bd016deb39 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sSQLITE_LIMIT_LENGTH\sto\sbe\sset\slower\sthan\s1\sas\san\s\nSQLITE_LIMIT_LENGTH\sof\s0\scauses\slots\sof\sunnecessary\sproblems\sfor\nusers\sof\sthe\ssqlite3_str\sobject. -D 2021-12-06T15:40:24.187 +C Fix\san\sOOB\sread\sthat\scould\soccur\sin\sfts5\swhen\sprocessing\scorrupt\srecords. +D 2021-12-06T18:57:02.055 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -119,7 +119,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292 F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422f6c2078aa F ext/fts5/fts5_expr.c fcd0770d53028c2b53a15d0f53bf6d0e01b1bf3dd97630b9fedf0801f03aa3ec F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982 -F ext/fts5/fts5_index.c a3ada4897c3b14b8a15a8695d2cb3a46b5761137aae0964fc44efe96a877ddd0 +F ext/fts5/fts5_index.c b1b2e5d4a9e3b54c740d8354cc47e3fa879f54c2176de55e0b882dab45ab7b07 F ext/fts5/fts5_main.c 7c6092a53e6802962fa07b0fad3e61cb077b6c98b74b727d8d44ac2cf63bd914 F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae @@ -163,6 +163,7 @@ F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec99 F ext/fts5/test/fts5corrupt3.test 0e473620582a53ac61f468f364db8a151c1e18d2a879b16439d172c12c4c9828 F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3 F ext/fts5/test/fts5corrupt5.test 550d0884c14424f9acad051a741f1dd99ec9342277d938e91ff3daf9123d1209 +F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4 F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7 F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4 F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11 @@ -1933,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 080e72d119b836c49916201bf135445aa7d53cefe40a47437a93448c4d0f41cd -R c4a19d6efe230f8d42eba90fbf4c1b2a -U drh -Z 860c42735bbc5c02ee56a87604c8521a +P 8fd5b8ec4ab9b5554d27f25a4638d56e347eab78b60900f24b15a815d3731330 +R c3401645c738abc52212977ced7d66bd +U dan +Z bbca536d76f68538aaa5d06c505e1b60 diff --git a/manifest.uuid b/manifest.uuid index 23a65b5f9d..85e543009e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8fd5b8ec4ab9b5554d27f25a4638d56e347eab78b60900f24b15a815d3731330 \ No newline at end of file +bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 \ No newline at end of file From 50fb7e09b4247ce34a0b0266614303d00f929def Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 20:16:53 +0000 Subject: [PATCH 034/148] Omit the OP_FilterInit opcode. Use OP_Blob to initialize each Bloom filter instead. Size the Bloom filter based on sqlite_stat1 size estimates rather than a run-time measurement for improved testability. FossilOrigin-Name: 8a9036ee617a6ad93bfe827b0789773c49d3d45b085cb76fa4b9b20a41b79b97 --- manifest | 20 +++++++++--------- manifest.uuid | 2 +- src/malloc.c | 2 ++ src/sqliteInt.h | 7 +++---- src/util.c | 14 ------------- src/vdbe.c | 54 +++++++++---------------------------------------- src/where.c | 35 ++++++++++++++++++++++++++++---- 7 files changed, 56 insertions(+), 78 deletions(-) diff --git a/manifest b/manifest index 754a38701e..b4f5f5334e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\sfixes\sinto\sthe\sbloom-filter\sbranch. -D 2021-12-06T19:11:31.036 +C Omit\sthe\sOP_FilterInit\sopcode.\s\sUse\sOP_Blob\sto\sinitialize\seach\sBloom\sfilter\ninstead.\s\sSize\sthe\sBloom\sfilter\sbased\son\ssqlite_stat1\ssize\sestimates\srather\nthan\sa\srun-time\smeasurement\sfor\simproved\stestability. +D 2021-12-06T20:16:53.814 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -516,7 +516,7 @@ F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c F src/main.c 1ea70751e6005ab6a9f784730fa0919efaa6639440a287deb73cb711e5aae57a -F src/malloc.c 183c2bf45cee1589254e4047e220f1ffbcc0a3bc8e4fe46fe64ba5db447a79af +F src/malloc.c d9172a3946f11384f2fd6a799554ee26c6bb407c4bd0874a456ed485a2e362e4 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75 @@ -556,7 +556,7 @@ F src/shell.c.in 1458b700144c8326fda2514aaddeda49d6f01f1d1ccf7b9b696c53a3535a119 F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h ab40ea9c294c656e0d6ab14e67d58f10b015a77e962dd075fdbe3ea3cc1a976b +F src/sqliteInt.h f4fbb14ea32d57b813aabf82f586d2ac042234dd89df1c03281f557907745b98 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -621,9 +621,9 @@ F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 +F src/util.c 6dfbd0bd1954e9531e1c511e5d20390d7dab9ffbf1e20a37c960d1aaf8582b46 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 6176125ea038f593597b5897898328142b5253201d321369df74e187b2b1abaa +F src/vdbe.c 9cc221ebae54417b0b47b4ce6aa6eba7e919153f8ae6307f8d18a6749d453f9c F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h fd1103c7ecec8c84164038c8eacaa4a633cb3c10a2f725aae7bd865d4a4fcceb F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 04ead529a272341a4cae3ef0dcd2f7675d433627acc5fb87fed1407e7b3d8614 +F src/where.c 21bd1078837afb127827243d7ad549a4b47022ffaa43c5baa74dcac7f89809a7 F src/whereInt.h 5c6601d6d0b7b8936482506d2d835981cc6efcd8e106a829893a27a14cfb10b8 F src/wherecode.c fa667db48db1077b42731bfd97e9181b39409ffdc7051162ecae6895ca71ad2c F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a7adcf69088cba4b86cc5731a45c9a5263af4355bc0a38f5225cab421c915f7f bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 -R 0f448dc1f18098ffcb6b2fdc27d44d39 +P edacf8034dc6bd892038c220c480ea512dbb4005db2a6b1f8e679e8a4929c6ed +R 933b551d7a60e6c29e7de8b534d33928 U drh -Z a01a7e207ad8c3ff4f1aefb648f1cc10 +Z ded7cd3093221f3f9f8f684eb1a7389d diff --git a/manifest.uuid b/manifest.uuid index 63d6d10d76..0b0fb52902 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -edacf8034dc6bd892038c220c480ea512dbb4005db2a6b1f8e679e8a4929c6ed \ No newline at end of file +8a9036ee617a6ad93bfe827b0789773c49d3d45b085cb76fa4b9b20a41b79b97 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index ab9b37ddad..9a2eaeec15 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -211,6 +211,7 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ return mx; } +#if 0 /* ** Return an estimate of the amount of unallocated memory. ** @@ -229,6 +230,7 @@ sqlite3_int64 sqlite3EstMemoryAvailable(void){ if( n<0 ) n = 0; return n; } +#endif /* ** Trigger the alarm diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9091f02115..90e60d30b0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3927,6 +3927,7 @@ struct Sqlite3Config { int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ + int iEstCountScale; /* Multiple RowCountEst() by this amount */ /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ @@ -4293,7 +4294,9 @@ void sqlite3MemSetDefault(void); void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); #endif int sqlite3HeapNearlyFull(void); +#if 0 sqlite3_int64 sqlite3EstMemoryAvailable(void); +#endif /* ** On systems with ample stack space and that support alloca(), make @@ -4780,11 +4783,7 @@ LogEst sqlite3LogEstAdd(LogEst,LogEst); #ifndef SQLITE_OMIT_VIRTUALTABLE LogEst sqlite3LogEstFromDouble(double); #endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT4) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) u64 sqlite3LogEstToInt(LogEst); -#endif VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); const char *sqlite3VListNumToName(VList*,int); int sqlite3VListNameToNum(VList*,const char*,int); diff --git a/src/util.c b/src/util.c index 8452aea665..d93c298116 100644 --- a/src/util.c +++ b/src/util.c @@ -1603,14 +1603,8 @@ LogEst sqlite3LogEstFromDouble(double x){ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT4) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* ** Convert a LogEst into an integer. -** -** Note that this routine is only used when one or more of various -** non-standard compile-time options is enabled. */ u64 sqlite3LogEstToInt(LogEst x){ u64 n; @@ -1618,17 +1612,9 @@ u64 sqlite3LogEstToInt(LogEst x){ x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) if( x>60 ) return (u64)LARGEST_INT64; -#else - /* 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 return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); } -#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ /* ** Add a new name/number pair to a VList. This might require that the diff --git a/src/vdbe.c b/src/vdbe.c index 487d731af3..c2281e70a1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1367,12 +1367,18 @@ case OP_SoftNull: { ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this -** blob in register P2. +** blob in register P2. If P4 is a NULL pointer, then construct +** a zero-filled blob that is P1 bytes long in P2. */ case OP_Blob: { /* out2 */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); pOut = out2Prerelease(p, pOp); - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + if( pOp->p4.z==0 ){ + sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1); + if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem; + }else{ + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + } pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; @@ -3383,7 +3389,7 @@ case OP_MakeRecord: { break; } -/* Opcode: Count P1 P2 p3 * * +/* Opcode: Count P1 P2 P3 * * ** Synopsis: r[P2]=count() ** ** Store the number of entries (an integer value) in the table or index @@ -8169,48 +8175,6 @@ case OP_Function: { /* group */ break; } -/* Opcode: FilterInit P1 P2 * * * -** -** Initialize register P1 so that is an empty bloom filter. -** -** If P2 is positive, it is a register that holds an estimate on -** the number of entries to be added to the Bloom filter. The -** Bloom filter is sized accordingly. If P2 is zero or negative, -** then a default-size Bloom filter is created. -** -** It is ok for P1 and P2 to be the same register. In that case the -** integer value originally in that register will be overwritten -** with the new empty bloom filter. -*/ -case OP_FilterInit: { - i64 n, mx; - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - pIn1 = &aMem[pOp->p1]; - if( pOp->p2>0 ){ - assert( pOp->p2<=(p->nMem+1 - p->nCursor) ); - n = sqlite3VdbeIntValue(&aMem[pOp->p2]); - if( nSQLITE_BLOOM_MAX ){ - n = SQLITE_BLOOM_MAX; - } - }else{ - n = SQLITE_BLOOM_MIN; - } - mx = sqlite3EstMemoryAvailable()/2; - if( n>mx && mx>SQLITE_BLOOM_MIN ){ - n = mx; - } -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("Bloom-filter size: %llu bytes\n", n); - } -#endif - sqlite3VdbeMemSetZeroBlob(pIn1, n); - if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; - break; -} - /* Opcode: FilterAdd P1 * P3 P4 * ** Synopsis: filter(P1) += key(P3@P4) ** diff --git a/src/where.c b/src/where.c index 233e77b6a7..e7246b1040 100644 --- a/src/where.c +++ b/src/where.c @@ -911,7 +911,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( VdbeComment((v, "for %s", pTable->zName)); if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ pLevel->regFilter = ++pParse->nMem; - sqlite3VdbeAddOp1(v, OP_FilterInit, pLevel->regFilter); + sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter); } /* Fill the automatic index with content */ @@ -1006,13 +1006,39 @@ static SQLITE_NOINLINE void constructBloomFilter( addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); do{ + const SrcItem *pItem; + const Table *pTab; + int sz; sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); addrCont = sqlite3VdbeMakeLabel(pParse); iCur = pLevel->iTabCur; pLevel->regFilter = ++pParse->nMem; + + /* The Bloom filter is a Blob held in a register. Initialize it + ** to zero-filled blob of at least 80K bits, but maybe more if the + ** estimated size of the table is larger. We could actually + ** measure the size of the table at run-time using OP_Count with + ** P3==1 and use that value to initialize the blob. But that makes + ** testing complicated. By basing the blob size on the value in the + ** sqlite_stat1 table, testing is much easier. + */ + pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + assert( pItem!=0 ); + pTab = pItem->pTab; + assert( pTab!=0 ); + if( pTab->tabFlags & TF_HasStat1 ){ + sz = sqlite3LogEstToInt(pItem->pTab->nRowLogEst); + if( sz<10000 ){ + sz = 10000; + }else if( sz>10000000 ){ + sz = 10000000; + } + }else{ + sz = 10000; + } + sqlite3VdbeAddOp2(v, OP_Blob, sz, pLevel->regFilter); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Count, iCur, pLevel->regFilter, 1); - sqlite3VdbeAddOp2(v, OP_FilterInit, pLevel->regFilter, pLevel->regFilter); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; for(pTerm=pWInfo->sWC.a; pTermpExpr; @@ -1034,13 +1060,14 @@ static SQLITE_NOINLINE void constructBloomFilter( int jj; for(jj=0; jjaiColumn[jj]; + assert( pIdx->pTable==pItem->pTab ); sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); } sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); sqlite3ReleaseTempRange(pParse, r1, n); } sqlite3VdbeResolveLabel(v, addrCont); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+3); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrTop); pLoop->wsFlags &= ~WHERE_BLOOMFILTER; From 23d41e63f2e4560728e13cefabb4fd411c687672 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 21:45:31 +0000 Subject: [PATCH 035/148] Add SQLITE_STMTSTATUS_FILTER_HIT and _MISS for tracking the effectiveness of Bloom filters. FossilOrigin-Name: 24ba535d200fc8a99dd8e66c6d100b5f6ae442098bafb152008429398eefe3e7 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/shell.c.in | 7 +++++++ src/sqlite.h.in | 9 +++++++++ src/vdbe.c | 2 ++ src/vdbeInt.h | 2 +- 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b4f5f5334e..956bcffef9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sthe\sOP_FilterInit\sopcode.\s\sUse\sOP_Blob\sto\sinitialize\seach\sBloom\sfilter\ninstead.\s\sSize\sthe\sBloom\sfilter\sbased\son\ssqlite_stat1\ssize\sestimates\srather\nthan\sa\srun-time\smeasurement\sfor\simproved\stestability. -D 2021-12-06T20:16:53.814 +C Add\sSQLITE_STMTSTATUS_FILTER_HIT\sand\s_MISS\sfor\stracking\sthe\seffectiveness\nof\sBloom\sfilters. +D 2021-12-06T21:45:31.659 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,8 +552,8 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 1458b700144c8326fda2514aaddeda49d6f01f1d1ccf7b9b696c53a3535a119c -F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 +F src/shell.c.in cda1eaf0292259b4b0721a5e03af9701fd482ebc37ce6a86ddc94cd9a38bb826 +F src/sqlite.h.in bb56040e3c498711c9f77727e477674395a50931ccba8095cfef5c8fb3c3e138 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 F src/sqliteInt.h f4fbb14ea32d57b813aabf82f586d2ac042234dd89df1c03281f557907745b98 @@ -623,9 +623,9 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 6dfbd0bd1954e9531e1c511e5d20390d7dab9ffbf1e20a37c960d1aaf8582b46 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 9cc221ebae54417b0b47b4ce6aa6eba7e919153f8ae6307f8d18a6749d453f9c +F src/vdbe.c fd8542b7131f299659871535a41ea732764fb25e4d2931965c97fa36658c50d7 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe -F src/vdbeInt.h fd1103c7ecec8c84164038c8eacaa4a633cb3c10a2f725aae7bd865d4a4fcceb +F src/vdbeInt.h 910985ac2783fe0938b314d811759d53fd25caf215810f62ca1ff068d6d60d7b F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a F src/vdbeaux.c 21db442d159fd745a7693d157b5f998260b6af4ca60de559fa3b7b68c7405af2 F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P edacf8034dc6bd892038c220c480ea512dbb4005db2a6b1f8e679e8a4929c6ed -R 933b551d7a60e6c29e7de8b534d33928 +P 8a9036ee617a6ad93bfe827b0789773c49d3d45b085cb76fa4b9b20a41b79b97 +R ec73578237c4366b7d0d282bfae04830 U drh -Z ded7cd3093221f3f9f8f684eb1a7389d +Z e55f2c8840b9a35831f295372358b466 diff --git a/manifest.uuid b/manifest.uuid index 0b0fb52902..71816720c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a9036ee617a6ad93bfe827b0789773c49d3d45b085cb76fa4b9b20a41b79b97 \ No newline at end of file +24ba535d200fc8a99dd8e66c6d100b5f6ae442098bafb152008429398eefe3e7 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 543141c9e4..c46eaffd62 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -2790,6 +2790,7 @@ static int display_stats( } if( pArg->pStmt ){ + int iHit, iMiss; iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); @@ -2797,6 +2798,12 @@ static int display_stats( raw_printf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); + iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset); + iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset); + if( iHit || iMiss ){ + raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n", + iHit, iHit+iMiss); + } 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); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 98a028b0b0..4125122e17 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8467,6 +8467,13 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** +** [[SQLITE_STMTSTATUS_FILTER HIT]]
SQLITE_STMTSTATUS_FILTER_HIT
+**
^This is the number of times that a join step was bypassed because +** a Bloom filtered returned non-found. The corresponding +** SQLITE_STMTSTATUS_FILTER_MISS value is the number of times that the +** Bloom filter returned a find, and thus the join step had to be processed +** as normal. +** ** [[SQLITE_STMTSTATUS_MEMUSED]]
SQLITE_STMTSTATUS_MEMUSED
**
^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually @@ -8481,6 +8488,8 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_FILTER_MISS 7 +#define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* diff --git a/src/vdbe.c b/src/vdbe.c index c2281e70a1..0abe64a71f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -8239,8 +8239,10 @@ case OP_Filter: { /* jump */ h %= pIn1->n; if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ VdbeBranchTaken(1, 2); + p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; goto jump_to_p2; }else{ + p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++; VdbeBranchTaken(0, 2); } break; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index c76cdbfdbc..38863f6d65 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -430,7 +430,7 @@ struct Vdbe { bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ + u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ #ifdef SQLITE_ENABLE_NORMALIZE char *zNormSql; /* Normalization of the associated SQL statement */ From 3bd7cd736d142ec3068f56cac510afdbc85c925d Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 6 Dec 2021 23:07:59 +0000 Subject: [PATCH 036/148] Improved EXPLAIN QUERY PLAN output for Bloom filters. FossilOrigin-Name: 00070e1fff6aec3d7c7b121f2b02bbca38a1664aca9afc3fb7e293f07fd1704f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wherecode.c | 41 +++++++++++++++++++++++++++++------------ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 956bcffef9..6a4298ce44 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sSQLITE_STMTSTATUS_FILTER_HIT\sand\s_MISS\sfor\stracking\sthe\seffectiveness\nof\sBloom\sfilters. -D 2021-12-06T21:45:31.659 +C Improved\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\sBloom\sfilters. +D 2021-12-06T23:07:59.482 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -640,7 +640,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c 21bd1078837afb127827243d7ad549a4b47022ffaa43c5baa74dcac7f89809a7 F src/whereInt.h 5c6601d6d0b7b8936482506d2d835981cc6efcd8e106a829893a27a14cfb10b8 -F src/wherecode.c fa667db48db1077b42731bfd97e9181b39409ffdc7051162ecae6895ca71ad2c +F src/wherecode.c f82a322a8849a0290587d968f5c1c71b0d5018e078f43ea732a4cdbf837ed42b F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8a9036ee617a6ad93bfe827b0789773c49d3d45b085cb76fa4b9b20a41b79b97 -R ec73578237c4366b7d0d282bfae04830 +P 24ba535d200fc8a99dd8e66c6d100b5f6ae442098bafb152008429398eefe3e7 +R 7eae2a1d2a9d2b173d70c0467bdac4ba U drh -Z e55f2c8840b9a35831f295372358b466 +Z 477e7fdac36f7f761dc02a6457a5f233 diff --git a/manifest.uuid b/manifest.uuid index 71816720c8..a54777d56d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -24ba535d200fc8a99dd8e66c6d100b5f6ae442098bafb152008429398eefe3e7 \ No newline at end of file +00070e1fff6aec3d7c7b121f2b02bbca38a1664aca9afc3fb7e293f07fd1704f \ No newline at end of file diff --git a/src/wherecode.c b/src/wherecode.c index dfe697f244..c04a73c2a8 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -176,19 +176,27 @@ int sqlite3WhereExplainOneScan( explainIndexRange(&str, pLoop); } }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ - const char *zRangeOp; + char cRangeOp; +#if 0 /* Better output, but breaks many tests */ + const Table *pTab = pItem->pTab; + const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName: + "rowid"; +#else + const char *zRowid = "rowid"; +#endif + sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid); if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ - zRangeOp = "="; + cRangeOp = '='; }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - zRangeOp = ">? AND rowid<"; + sqlite3_str_appendf(&str, ">? AND %s", zRowid); + cRangeOp = '<'; }else if( flags&WHERE_BTM_LIMIT ){ - zRangeOp = ">"; + cRangeOp = '>'; }else{ assert( flags&WHERE_TOP_LIMIT); - zRangeOp = "<"; + cRangeOp = '<'; } - sqlite3_str_appendf(&str, - " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + sqlite3_str_appendf(&str, "%c?)", cRangeOp); } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ @@ -243,12 +251,21 @@ int sqlite3WhereExplainBloomFilter( sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "BLOOM FILTER ON %S(", pItem); + sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); pLoop = pLevel->pWLoop; - for(i=pLoop->nSkip; iu.btree.nEq; i++){ - const char *z = pItem->pTab->aCol[i].zCnName; - if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); - sqlite3_str_appendf(&str, "%s=?", z); + if( pLoop->wsFlags & WHERE_IPK ){ + const Table *pTab = pItem->pTab; + if( pTab->iPKey>=0 ){ + sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); + }else{ + sqlite3_str_appendf(&str, "rowid=?"); + } + }else{ + for(i=pLoop->nSkip; iu.btree.nEq; i++){ + const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); + if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); + sqlite3_str_appendf(&str, "%s=?", z); + } } sqlite3_str_append(&str, ")", 1); zMsg = sqlite3StrAccumFinish(&str); From 761d64b73bc7ceb5ef60d956b6e1b78c1997082d Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 7 Dec 2021 22:37:50 +0000 Subject: [PATCH 037/148] Do not generate a Bloom filter if it cannot be used prior to the next seek, as that leads to a misleading EXPLAIN QUERY PLAN. FossilOrigin-Name: 2739ed5192058fbcc816ecbc252be687efc606e038bfcd6cf71194a3f4f5684e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 9 ++++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 6a4298ce44..78850cff06 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\sBloom\sfilters. -D 2021-12-06T23:07:59.482 +C Do\snot\sgenerate\sa\sBloom\sfilter\sif\sit\scannot\sbe\sused\sprior\sto\sthe\snext\sseek,\nas\sthat\sleads\sto\sa\smisleading\sEXPLAIN\sQUERY\sPLAN. +D 2021-12-07T22:37:50.686 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 21bd1078837afb127827243d7ad549a4b47022ffaa43c5baa74dcac7f89809a7 +F src/where.c 328e5c6f5a91f8c1e36417159cc93ea180700ae97726f934f69e68c8c60030b5 F src/whereInt.h 5c6601d6d0b7b8936482506d2d835981cc6efcd8e106a829893a27a14cfb10b8 F src/wherecode.c f82a322a8849a0290587d968f5c1c71b0d5018e078f43ea732a4cdbf837ed42b F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 24ba535d200fc8a99dd8e66c6d100b5f6ae442098bafb152008429398eefe3e7 -R 7eae2a1d2a9d2b173d70c0467bdac4ba +P 00070e1fff6aec3d7c7b121f2b02bbca38a1664aca9afc3fb7e293f07fd1704f +R 6ef1a6c68af918fb5dc855e869b3769c U drh -Z 477e7fdac36f7f761dc02a6457a5f233 +Z 7a26146d090468562610338a13462117 diff --git a/manifest.uuid b/manifest.uuid index a54777d56d..f1d3a5f29a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00070e1fff6aec3d7c7b121f2b02bbca38a1664aca9afc3fb7e293f07fd1704f \ No newline at end of file +2739ed5192058fbcc816ecbc252be687efc606e038bfcd6cf71194a3f4f5684e \ No newline at end of file diff --git a/src/where.c b/src/where.c index e7246b1040..1eb9f36017 100644 --- a/src/where.c +++ b/src/where.c @@ -988,7 +988,8 @@ end_auto_index_create: static SQLITE_NOINLINE void constructBloomFilter( WhereInfo *pWInfo, /* The WHERE clause */ int iLevel, /* Index in pWInfo->a[] that is pLevel */ - WhereLevel *pLevel /* Make a Bloom filter for this FROM term */ + WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */ + Bitmask notReady /* Loops that are not ready */ ){ int addrOnce; /* Address of opening OP_Once */ int addrTop; /* Address of OP_Rewind */ @@ -1076,7 +1077,9 @@ static SQLITE_NOINLINE void constructBloomFilter( iLevel++; pLevel = &pWInfo->a[iLevel]; pLoop = pLevel->pWLoop; - if( pLoop && pLoop->wsFlags & WHERE_BLOOMFILTER ) break; + if( pLoop==0 ) continue; + if( pLoop->prereq & notReady ) continue; + if( pLoop->wsFlags & WHERE_BLOOMFILTER ) break; } }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); @@ -5594,7 +5597,7 @@ WhereInfo *sqlite3WhereBegin( &pTabList->a[pLevel->iFrom], notReady, pLevel); #endif }else{ - constructBloomFilter(pWInfo, ii, pLevel); + constructBloomFilter(pWInfo, ii, pLevel, notReady); } if( db->mallocFailed ) goto whereBeginError; } From 132f96fc75496d93cc01be7dabb11eea55bddea2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 8 Dec 2021 16:07:22 +0000 Subject: [PATCH 038/148] In the WhereClause object, do not assume that all TERM_VIRTUAL terms appear at the end of the list, because that is no longer true. Instead, keep a separate nBase count that is the size of the list excluding the tail of virtual terms. Use nBase instead of nTerm when scanning terms that are not virtual. Add assert()s to validate correctness of WhereClause. FossilOrigin-Name: 6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/where.c | 9 +++++---- src/whereInt.h | 1 + src/wherecode.c | 6 +++--- src/whereexpr.c | 10 ++++++++++ 6 files changed, 30 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index bd016deb39..d59214aeb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sOOB\sread\sthat\scould\soccur\sin\sfts5\swhen\sprocessing\scorrupt\srecords. -D 2021-12-06T18:57:02.055 +C In\sthe\sWhereClause\sobject,\sdo\snot\sassume\sthat\sall\sTERM_VIRTUAL\sterms\sappear\nat\sthe\send\sof\sthe\slist,\sbecause\sthat\sis\sno\slonger\strue.\s\sInstead,\skeep\sa\nseparate\snBase\scount\sthat\sis\sthe\ssize\sof\sthe\slist\sexcluding\sthe\stail\sof\nvirtual\sterms.\s\sUse\snBase\sinstead\sof\snTerm\swhen\sscanning\sterms\sthat\sare\snot\nvirtual.\s\sAdd\sassert()s\sto\svalidate\scorrectness\sof\sWhereClause. +D 2021-12-08T16:07:22.778 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,10 +638,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 5bd26902ddf3e385c0df9429b10e7358bbd0430c470ec1d2a53065723c4a55d2 -F src/whereInt.h 1630d9418512b080598e9a72b8af6b8bd1b9ab13fee1458f151762b6df206791 -F src/wherecode.c 1f5b62f46d284c8886945eb7438415bc27e23e87bb60b9ee468fa6bd31268f33 -F src/whereexpr.c 19394cb463003e9cc9305730b1508b8817a22bb7247170d81234b691a7f05b89 +F src/where.c 6e07a2ebfccedec1926f9cd13f773741002a56c40dd90adc3ea25e41354db46f +F src/whereInt.h 14ebb040acac47091a4dd3075f4ab511cad7fc31010fc5e6a750e06b7950c021 +F src/wherecode.c 280f1f87311827f8921a815dbb9b8e84bb394556716fa6a2e111c855b299de20 +F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8fd5b8ec4ab9b5554d27f25a4638d56e347eab78b60900f24b15a815d3731330 -R c3401645c738abc52212977ced7d66bd -U dan -Z bbca536d76f68538aaa5d06c505e1b60 +P bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 +R 2e19e97323a5794a031526354d3fd247 +U drh +Z 8c650a14815db39748cc380bbb1958b3 diff --git a/manifest.uuid b/manifest.uuid index 85e543009e..4c34bfe654 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 \ No newline at end of file +6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 \ No newline at end of file diff --git a/src/where.c b/src/where.c index f1abd5483c..649b786520 100644 --- a/src/where.c +++ b/src/where.c @@ -2361,11 +2361,11 @@ static void whereLoopOutputAdjust( 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++){ + for(i=pWC->nBase, 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; + if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; + if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; for(j=pLoop->nLTerm-1; j>=0; j--){ pX = pLoop->aLTerm[j]; if( pX==0 ) continue; @@ -3636,6 +3636,7 @@ static int whereLoopAddOr( tempWC.pOuter = pWC; tempWC.op = TK_AND; tempWC.nTerm = 1; + tempWC.nBase = 1; tempWC.a = pOrTerm; sSubBuild.pWC = &tempWC; }else{ @@ -5085,7 +5086,7 @@ WhereInfo *sqlite3WhereBegin( ** FROM ... WHERE random()>0; -- eval random() once per row ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall */ - for(ii=0; iinTerm; ii++){ + for(ii=0; iinBase; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; if( pT->wtFlags & TERM_VIRTUAL ) continue; if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ diff --git a/src/whereInt.h b/src/whereInt.h index 217dd0ba2a..0df84ad6c0 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -320,6 +320,7 @@ struct WhereClause { u8 hasOr; /* True if any a[].eOperator is WO_OR */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ + int nBase; /* Number of terms through the last non-Virtual */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ diff --git a/src/wherecode.c b/src/wherecode.c index 460ac4fe30..a6633967a2 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -970,7 +970,7 @@ static void codeCursorHint( sWalker.pParse = pParse; sWalker.u.pCCurHint = &sHint; pWC = &pWInfo->sWC; - for(i=0; inTerm; i++){ + for(i=0; inBase; i++){ pTerm = &pWC->a[i]; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->prereqAll & pLevel->notReady ) continue; @@ -2467,7 +2467,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( ** then we cannot use the "t1.a=t2.b" constraint, but we can code ** the implied "t1.a=123" constraint. */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ + for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){ Expr *pE, sEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; @@ -2512,7 +2512,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); - for(pTerm=pWC->a, j=0; jnTerm; j++, pTerm++){ + for(pTerm=pWC->a, j=0; jnBase; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; diff --git a/src/whereexpr.c b/src/whereexpr.c index eff7f4ab22..5a3fbe2d7f 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -79,6 +79,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; + if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm; if( p && ExprHasProperty(p, EP_Unlikely) ){ pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; }else{ @@ -1532,6 +1533,7 @@ void sqlite3WhereClauseInit( pWC->hasOr = 0; pWC->pOuter = 0; pWC->nTerm = 0; + pWC->nBase = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; } @@ -1543,9 +1545,17 @@ void sqlite3WhereClauseInit( */ void sqlite3WhereClauseClear(WhereClause *pWC){ sqlite3 *db = pWC->pWInfo->pParse->db; + assert( pWC->nTerm>=pWC->nBase ); if( pWC->nTerm>0 ){ WhereTerm *a = pWC->a; WhereTerm *aLast = &pWC->a[pWC->nTerm-1]; +#ifdef SQLITE_DEBUG + int i; + /* Verify that every term past pWC->nBase is virtual */ + for(i=pWC->nBase; inTerm; i++){ + assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); + } +#endif while(1){ if( a->wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, a->pExpr); From 46658d7f9a19506c086d2cea9bbd695f4e9e6104 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 8 Dec 2021 18:50:30 +0000 Subject: [PATCH 039/148] Enhance the sqlite3SrcListAppendFromTerm() routine so that it sets the Parser error on an OOM, causing an earlier unwind of the stack. FossilOrigin-Name: fee469925231d074c17b948605143cfbb2e9595851a797995e7331f1ab2a61ca --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/build.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d59214aeb8..6ae530945c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sWhereClause\sobject,\sdo\snot\sassume\sthat\sall\sTERM_VIRTUAL\sterms\sappear\nat\sthe\send\sof\sthe\slist,\sbecause\sthat\sis\sno\slonger\strue.\s\sInstead,\skeep\sa\nseparate\snBase\scount\sthat\sis\sthe\ssize\sof\sthe\slist\sexcluding\sthe\stail\sof\nvirtual\sterms.\s\sUse\snBase\sinstead\sof\snTerm\swhen\sscanning\sterms\sthat\sare\snot\nvirtual.\s\sAdd\sassert()s\sto\svalidate\scorrectness\sof\sWhereClause. -D 2021-12-08T16:07:22.778 +C Enhance\sthe\ssqlite3SrcListAppendFromTerm()\sroutine\sso\sthat\sit\ssets\sthe\nParser\serror\son\san\sOOM,\scausing\san\searlier\sunwind\sof\sthe\sstack. +D 2021-12-08T18:50:30.727 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -495,7 +495,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 81feddbcc60d524518a7afc713b6dab0ad7caadb7370433f117c8c557dcdc889 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c 70759481a346322934332485381805c9ba9442bbe7959bf40bdc14140c832517 +F src/build.c 86a15afda3a8c01de8f9671b4e5a54e1102976052a055e73cc4832e2044091f5 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bb9b1a15f7e80483162049dfd981d059dc69d03348b521f7ac164a8cd3ae3cc4 -R 2e19e97323a5794a031526354d3fd247 +P 6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 +R 7bf3b67c1460c7978720979a3b51c559 U drh -Z 8c650a14815db39748cc380bbb1958b3 +Z b61f652f2f5aa07cb62f1c8531dfb3ea diff --git a/manifest.uuid b/manifest.uuid index 4c34bfe654..69fdf2af2c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 \ No newline at end of file +fee469925231d074c17b948605143cfbb2e9595851a797995e7331f1ab2a61ca \ No newline at end of file diff --git a/src/build.c b/src/build.c index 538a1e4d7f..b927056101 100644 --- a/src/build.c +++ b/src/build.c @@ -4960,8 +4960,9 @@ SrcList *sqlite3SrcListAppendFromTerm( pItem->pUsing = pUsing; return p; - append_from_error: +append_from_error: assert( p==0 ); + if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "out of memory"); sqlite3ExprDelete(db, pOn); sqlite3IdListDelete(db, pUsing); sqlite3SelectDelete(db, pSubquery); From fb82caf0bed2cd006cda440888939b87641b00c9 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 8 Dec 2021 19:50:45 +0000 Subject: [PATCH 040/148] Improvements on the decision of whether or not to use a Bloom filter. FossilOrigin-Name: 0fb2a4e08f518cb38ea3edc6a084d1e4874fd622ba3cf9101b49b3e7dc1a3f2b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 35 ++++++++++++++++++++++++----------- src/whereInt.h | 1 + 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index ed505a6910..4c4a9d684d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sWhereClause\sfix\sfrom\strunk -D 2021-12-08T16:15:41.698 +C Improvements\son\sthe\sdecision\sof\swhether\sor\snot\sto\suse\sa\sBloom\sfilter. +D 2021-12-08T19:50:45.145 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,8 +638,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 74382d720f2a9a06f738467929ecf0d79fcdd6b9779184bddbb97352895a1b23 -F src/whereInt.h d55d5ce5c9de361e16cf5cd23da054cdecc1ae7735682ee55c2f40e58e960d22 +F src/where.c 89958d4fc7c45e916882ebc97481d98597f516ce3d778ace3271aacf34e24e91 +F src/whereInt.h c2cb535e755b25a7e152bdb407cbb2f62bdb8747c44bf2d984139f5cbebb8704 F src/wherecode.c e2207f011b7e5bdef5722da5e8d95eb30ad01051b3526757901ecb19a9e98ff3 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2739ed5192058fbcc816ecbc252be687efc606e038bfcd6cf71194a3f4f5684e 6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 -R d3afb24f2c63fc5d59ade7856914b3ad +P d3250256772e3348abe887c0ca3550a6647cce3804c9456a9d0112aea7ee1c46 +R a7fca9e9fc2528f3e921fdfbeaa2e361 U drh -Z 246d691185204c115a5a684ad14acaf7 +Z 815ca39cf2b788796cb5ebc9be23c44d diff --git a/manifest.uuid b/manifest.uuid index 1416a80b0a..a9d9e689b3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d3250256772e3348abe887c0ca3550a6647cce3804c9456a9d0112aea7ee1c46 \ No newline at end of file +0fb2a4e08f518cb38ea3edc6a084d1e4874fd622ba3cf9101b49b3e7dc1a3f2b \ No newline at end of file diff --git a/src/where.c b/src/where.c index bf10262a76..065d14fd64 100644 --- a/src/where.c +++ b/src/where.c @@ -2028,9 +2028,9 @@ void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3_free(z); } if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); + sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); }else{ - sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); + sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm); } sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ @@ -2502,6 +2502,9 @@ static void whereLoopOutputAdjust( if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; } if( j<0 ){ + if( pLoop->maskSelf==pTerm->prereqAll ){ + pLoop->wsFlags |= WHERE_CULLED; + } if( pTerm->truthProb<=0 ){ /* If a truth probability is specified using the likelihood() hints, ** then use the probability provided by the application. */ @@ -2529,7 +2532,9 @@ static void whereLoopOutputAdjust( } } } - if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; + if( pLoop->nOut > nRow-iReduce ){ + pLoop->nOut = nRow - iReduce; + } } /* @@ -4984,22 +4989,30 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( ){ int i; LogEst nSearch; - SrcItem *pItem; assert( pWInfo->nLevel>=2 ); assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) ); nSearch = pWInfo->a[0].pWLoop->nOut; for(i=1; inLevel; i++){ WhereLoop *pLoop = pWInfo->a[i].pWLoop; - if( pLoop->nOut<0 + const int reqFlags = (WHERE_CULLED|WHERE_COLUMN_EQ); + if( (pLoop->wsFlags & reqFlags)==reqFlags && (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 - && (pLoop->wsFlags & WHERE_COLUMN_EQ)!=0 - && nSearch > (pItem = &pWInfo->pTabList->a[pLoop->iTab])->pTab->nRowLogEst - && (pItem->fg.jointype & JT_LEFT)==0 ){ - pLoop->wsFlags |= WHERE_BLOOMFILTER; - pLoop->wsFlags &= ~WHERE_IDX_ONLY; - WHERETRACE(0xffff, ("-> use Bloom-filter on loop %c\n", pLoop->cId)); + SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; + Table *pTab = pItem->pTab; + pTab->tabFlags |= TF_StatsUsed; + if( nSearch > pTab->nRowLogEst + && (pItem->fg.jointype & JT_LEFT)==0 + ){ + pLoop->wsFlags |= WHERE_BLOOMFILTER; + pLoop->wsFlags &= ~WHERE_IDX_ONLY; + WHERETRACE(0xffff, ( + "-> use Bloom-filter on loop %c because there are ~%.1e " + "lookups into %s which has only ~%.1e rows\n", + pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, + (double)sqlite3LogEstToInt(pTab->nRowLogEst))); + } } nSearch += pLoop->nOut; } diff --git a/src/whereInt.h b/src/whereInt.h index 558a1e3eb9..d790653a71 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -608,5 +608,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ +#define WHERE_CULLED 0x00800000 /* nOut reduced by extra WHERE terms */ #endif /* !defined(SQLITE_WHEREINT_H) */ From 969c46486c3d169ed7002931d6ed3e4074a1d05e Mon Sep 17 00:00:00 2001 From: larrybr Date: Wed, 8 Dec 2021 20:36:08 +0000 Subject: [PATCH 041/148] Clarity tweak for date.c FossilOrigin-Name: db58b2def014bdb146751110488a088767530ca2557baf73d6181a2558bbe6d3 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/date.c | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6ae530945c..d474662745 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite3SrcListAppendFromTerm()\sroutine\sso\sthat\sit\ssets\sthe\nParser\serror\son\san\sOOM,\scausing\san\searlier\sunwind\sof\sthe\sstack. -D 2021-12-08T18:50:30.727 +C Clarity\stweak\sfor\sdate.c +D 2021-12-08T20:36:08.193 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -499,7 +499,7 @@ F src/build.c 86a15afda3a8c01de8f9671b4e5a54e1102976052a055e73cc4832e2044091f5 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 -F src/date.c d0f09f7924a27e0d8a41b41a781ccc680b102c35b5e9a94d129d58ba9d849ff2 +F src/date.c b49c12c7564ddd7f1922f76e7a086a6db5b91aa0e729b180cd433e22bab37be0 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6024682ca467fa4fe49608772b0bbfa2f8a419b32cebfa715941073c8b29da49 -R 7bf3b67c1460c7978720979a3b51c559 -U drh -Z b61f652f2f5aa07cb62f1c8531dfb3ea +P fee469925231d074c17b948605143cfbb2e9595851a797995e7331f1ab2a61ca +R a155c96fa61b0490e6fe4dac239420d6 +U larrybr +Z 91a082ea2c3f2144aa72dff5c2fe9b69 diff --git a/manifest.uuid b/manifest.uuid index 69fdf2af2c..0179047adb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fee469925231d074c17b948605143cfbb2e9595851a797995e7331f1ab2a61ca \ No newline at end of file +db58b2def014bdb146751110488a088767530ca2557baf73d6181a2558bbe6d3 \ No newline at end of file diff --git a/src/date.c b/src/date.c index dcec9c7cc1..f5b22d7538 100644 --- a/src/date.c +++ b/src/date.c @@ -523,7 +523,9 @@ static int osLocaltime(time_t *t, struct tm *pTm){ if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; +#if SQLITE_THREADSAFE>0 sqlite3_mutex_leave(mutex); +#endif rc = pX==0; #else #ifndef SQLITE_UNTESTABLE From 7e910f6422553150a62332bdc2f3c21b16184abb Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 01:28:15 +0000 Subject: [PATCH 042/148] Add SQLITE_TESTCTRL_LOGEST and enhance the LogEst utility program. Improvements to testability of bloom filters. FossilOrigin-Name: 88b43d798cc5aa59855e92d3e658aee9f0a5def6ffbc5db77af048d75ecdf8cc --- manifest | 28 ++++++++++++++-------------- manifest.uuid | 2 +- src/main.c | 20 ++++++++++++++++++++ src/sqlite.h.in | 3 ++- src/sqliteInt.h | 2 -- src/util.c | 2 -- src/vdbe.c | 6 ++---- src/where.c | 34 +++++++++++++++++++--------------- src/whereInt.h | 2 +- src/wherecode.c | 7 +++---- tool/logest.c | 5 ++++- 11 files changed, 66 insertions(+), 45 deletions(-) diff --git a/manifest b/manifest index 4c4a9d684d..7cbde1e303 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\son\sthe\sdecision\sof\swhether\sor\snot\sto\suse\sa\sBloom\sfilter. -D 2021-12-08T19:50:45.145 +C Add\sSQLITE_TESTCTRL_LOGEST\sand\senhance\sthe\sLogEst\sutility\sprogram.\nImprovements\sto\stestability\sof\sbloom\sfilters. +D 2021-12-09T01:28:15.168 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -515,7 +515,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c -F src/main.c 1ea70751e6005ab6a9f784730fa0919efaa6639440a287deb73cb711e5aae57a +F src/main.c 674a0fdfc2808e1d5a78b2eefe2ec3f93428cf82f0f6c013d577df1a1caa5940 F src/malloc.c d9172a3946f11384f2fd6a799554ee26c6bb407c4bd0874a456ed485a2e362e4 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -553,10 +553,10 @@ F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/shell.c.in cda1eaf0292259b4b0721a5e03af9701fd482ebc37ce6a86ddc94cd9a38bb826 -F src/sqlite.h.in bb56040e3c498711c9f77727e477674395a50931ccba8095cfef5c8fb3c3e138 +F src/sqlite.h.in 50c8f27251b11f1c89b06abc6e4085fce15151bcbd355a44609ecb2ba5424841 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h f4fbb14ea32d57b813aabf82f586d2ac042234dd89df1c03281f557907745b98 +F src/sqliteInt.h 31b9673bc26b5b2a846bf26ce7124c869f64368f4eaac865d9350749ea314000 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -621,9 +621,9 @@ F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c 6dfbd0bd1954e9531e1c511e5d20390d7dab9ffbf1e20a37c960d1aaf8582b46 +F src/util.c 569349b0bddcbfbc661856f446adb92e1b0a47b3cbef548da9fc5aa639d7964c F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c fd8542b7131f299659871535a41ea732764fb25e4d2931965c97fa36658c50d7 +F src/vdbe.c 855ee903521fcc5a799f673f5b05fc599dc50a31e6cb6a15e1e8a6858087595b F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 910985ac2783fe0938b314d811759d53fd25caf215810f62ca1ff068d6d60d7b F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -638,9 +638,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 89958d4fc7c45e916882ebc97481d98597f516ce3d778ace3271aacf34e24e91 -F src/whereInt.h c2cb535e755b25a7e152bdb407cbb2f62bdb8747c44bf2d984139f5cbebb8704 -F src/wherecode.c e2207f011b7e5bdef5722da5e8d95eb30ad01051b3526757901ecb19a9e98ff3 +F src/where.c 4946af4e7d073fd35c97ffce4c4b4f3d84f6a0c9e5cb20342560cfaf072ef3a6 +F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 +F src/wherecode.c 560424f5845ec4ef1e36e8a6a066cc497aaf8163fef29fa18a0317e1e14ba9b7 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1856,7 +1856,7 @@ F tool/lemon.c 258881835bd5bccd0c74fb110fe54244ff18e8e7ef3d949cbdab7187f02132bb F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 -F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca +F tool/logest.c 83dbfda91615f1db5dce38215303d8bb456f437342d2c64262406dbdd1c931e2 F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d3250256772e3348abe887c0ca3550a6647cce3804c9456a9d0112aea7ee1c46 -R a7fca9e9fc2528f3e921fdfbeaa2e361 +P 0fb2a4e08f518cb38ea3edc6a084d1e4874fd622ba3cf9101b49b3e7dc1a3f2b +R 13197c53db0503b249bb051590a0a6df U drh -Z 815ca39cf2b788796cb5ebc9be23c44d +Z 80d7c2199cca2c3c9ca5b22286927a11 diff --git a/manifest.uuid b/manifest.uuid index a9d9e689b3..2d8c59a7eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0fb2a4e08f518cb38ea3edc6a084d1e4874fd622ba3cf9101b49b3e7dc1a3f2b \ No newline at end of file +88b43d798cc5aa59855e92d3e658aee9f0a5def6ffbc5db77af048d75ecdf8cc \ No newline at end of file diff --git a/src/main.c b/src/main.c index 804719f176..1b7853f609 100644 --- a/src/main.c +++ b/src/main.c @@ -4347,6 +4347,26 @@ int sqlite3_test_control(int op, ...){ break; } + /* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST, + ** double fIn, // Input value + ** int *pLogEst, // sqlite3LogEstFromDouble(fIn) + ** u64 *pInt, // sqlite3LogEstToInt(*pLogEst) + ** int *pLogEst2 // sqlite3LogEst(*pInt) + ** ); + ** + ** Test access for the LogEst conversion routines. + */ + case SQLITE_TESTCTRL_LOGEST: { + double rIn = va_arg(ap, double); + LogEst rLogEst = sqlite3LogEstFromDouble(rIn); + u64 iInt = sqlite3LogEstToInt(rLogEst); + va_arg(ap, int*)[0] = rLogEst; + va_arg(ap, u64*)[0] = iInt; + va_arg(ap, int*)[0] = sqlite3LogEst(iInt); + break; + } + + #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) ** diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4125122e17..f7cf4d2fe1 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7944,7 +7944,8 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_LOGEST 33 +#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 90e60d30b0..0104bace6d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4780,9 +4780,7 @@ int sqlite3Utf8CharLen(const char *pData, int nByte); u32 sqlite3Utf8Read(const u8**); LogEst sqlite3LogEst(u64); LogEst sqlite3LogEstAdd(LogEst,LogEst); -#ifndef SQLITE_OMIT_VIRTUALTABLE LogEst sqlite3LogEstFromDouble(double); -#endif u64 sqlite3LogEstToInt(LogEst); VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); const char *sqlite3VListNumToName(VList*,int); diff --git a/src/util.c b/src/util.c index d93c298116..8ea951fa16 100644 --- a/src/util.c +++ b/src/util.c @@ -1586,7 +1586,6 @@ LogEst sqlite3LogEst(u64 x){ return a[x&7] + y - 10; } -#ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Convert a double into a LogEst ** In other words, compute an approximation for 10*log2(x). @@ -1601,7 +1600,6 @@ LogEst sqlite3LogEstFromDouble(double x){ e = (a>>52) - 1022; return e*10; } -#endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Convert a LogEst into an integer. diff --git a/src/vdbe.c b/src/vdbe.c index 0abe64a71f..ef60ed0123 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -8222,10 +8222,8 @@ case OP_Filter: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Blob)==0 || NEVER(pIn1->n<=0) ){ - VdbeBranchTaken(0, 2); - break; - } + assert( (pIn1->flags & MEM_Blob)!=0 ); + assert( pIn1->n >= 1 ); h = filterHash(aMem, pOp); #ifdef SQLITE_DEBUG if( db->flags&SQLITE_VdbeTrace ){ diff --git a/src/where.c b/src/where.c index 065d14fd64..859dac7cbb 100644 --- a/src/where.c +++ b/src/where.c @@ -1009,7 +1009,7 @@ static SQLITE_NOINLINE void constructBloomFilter( do{ const SrcItem *pItem; const Table *pTab; - int sz; + u64 sz; sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); addrCont = sqlite3VdbeMakeLabel(pParse); iCur = pLevel->iTabCur; @@ -1027,17 +1027,13 @@ static SQLITE_NOINLINE void constructBloomFilter( assert( pItem!=0 ); pTab = pItem->pTab; assert( pTab!=0 ); - if( pTab->tabFlags & TF_HasStat1 ){ - sz = sqlite3LogEstToInt(pItem->pTab->nRowLogEst); - if( sz<10000 ){ - sz = 10000; - }else if( sz>10000000 ){ - sz = 10000000; - } - }else{ + sz = sqlite3LogEstToInt(pTab->nRowLogEst); + if( sz<10000 ){ sz = 10000; + }else if( sz>10000000 ){ + sz = 10000000; } - sqlite3VdbeAddOp2(v, OP_Blob, sz, pLevel->regFilter); + sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; @@ -2503,7 +2499,11 @@ static void whereLoopOutputAdjust( } if( j<0 ){ if( pLoop->maskSelf==pTerm->prereqAll ){ - pLoop->wsFlags |= WHERE_CULLED; + /* If there are extra terms in the WHERE clause not used by an index + ** that depend only on the table being scanned, and that will tend to + ** cause many rows to be omitted, then mark that table as + ** "self-culling". */ + pLoop->wsFlags |= WHERE_SELFCULL; } if( pTerm->truthProb<=0 ){ /* If a truth probability is specified using the likelihood() hints, @@ -4974,10 +4974,13 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( ** ** (1) The SEARCH happens more than N times where N is the number ** of rows in the table that is being considered for the Bloom -** filter. (TO DO: Make this condition more precise.) -** (2) Most searches are expected to find zero rows +** filter. +** (2) Some searches are expected to find zero rows. (This is determined +** by the WHERE_SELFCULL flag on the term.) ** (3) The table being searched is not the right table of a LEFT JOIN -** (4) Bloom-filter processing is not disabled +** (4) Bloom-filter processing is not disabled. (Checked by the +** caller.) +** (5) The size of the table being searched is known by ANALYZE. ** ** This block of code merely checks to see if a Bloom filter would be ** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the @@ -4995,7 +4998,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( nSearch = pWInfo->a[0].pWLoop->nOut; for(i=1; inLevel; i++){ WhereLoop *pLoop = pWInfo->a[i].pWLoop; - const int reqFlags = (WHERE_CULLED|WHERE_COLUMN_EQ); + const int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); if( (pLoop->wsFlags & reqFlags)==reqFlags && (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 ){ @@ -5004,6 +5007,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( pTab->tabFlags |= TF_StatsUsed; if( nSearch > pTab->nRowLogEst && (pItem->fg.jointype & JT_LEFT)==0 + && (pTab->tabFlags & TF_HasStat1)!=0 ){ pLoop->wsFlags |= WHERE_BLOOMFILTER; pLoop->wsFlags &= ~WHERE_IDX_ONLY; diff --git a/src/whereInt.h b/src/whereInt.h index d790653a71..8051b78a02 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -608,6 +608,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ -#define WHERE_CULLED 0x00800000 /* nOut reduced by extra WHERE terms */ +#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ #endif /* !defined(SQLITE_WHEREINT_H) */ diff --git a/src/wherecode.c b/src/wherecode.c index 42cfcc9eac..05d1f12ced 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1393,13 +1393,12 @@ static SQLITE_NOINLINE void filterPullDown( if( pLoop->prereq & notReady ) continue; if( pLoop->wsFlags & WHERE_IPK ){ WhereTerm *pTerm = pLoop->aLTerm[0]; - int r1, regRowid; + int regRowid; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); - r1 = sqlite3GetTempReg(pParse); - regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, r1); - if( regRowid!=r1 ) sqlite3ReleaseTempReg(pParse, r1); + regRowid = sqlite3GetTempReg(pParse); + regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid); sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, addrNxt, regRowid, 1); VdbeCoverage(pParse->pVdbe); diff --git a/tool/logest.c b/tool/logest.c index e936e02cbe..580a3a6f96 100644 --- a/tool/logest.c +++ b/tool/logest.c @@ -75,6 +75,7 @@ static sqlite3_uint64 logEstToInt(LogEst x){ x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; + if( x>60 ) return ((sqlite3_uint64)0xffffffff)<<32 + 0xffffffff; if( x>=3 ) return (n+8)<<(x-3); return (n+8)>>(3-x); } @@ -149,7 +150,7 @@ int main(int argc, char **argv){ }else if( z[0]=='^' ){ a[n++] = (LogEst)atoi(z+1); }else if( isInteger(z) ){ - a[n++] = logEstFromInteger(atoi(z)); + a[n++] = logEstFromInteger(atoll(z)); }else if( isFloat(z) && z[0]!='-' ){ a[n++] = logEstFromDouble(atof(z)); }else{ @@ -161,6 +162,8 @@ int main(int argc, char **argv){ printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i])); }else if( a[i]<10 ){ printf("%5d (%f)\n", a[i], logEstToInt(a[i]+100)/1024.0); + }else if( a[i]>100 ){ + printf("%5d (%lld)\n", a[i], logEstToInt(a[i])); }else{ sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024; printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100); From 15561b916d1bdc72b7e874f50687ce8c9155570b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 14:09:47 +0000 Subject: [PATCH 043/148] Do not attempt to reprepare a prepared statement that returns SQLITE_SCHEMA if there was an OOM. This enhancement supercedes check-in [fee469925231d074]. FossilOrigin-Name: 94fdbeffaf501daf30dc7fae7cef5c2bfdb3a9b055562adfc04374a9fc899c8d --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/build.c | 1 - src/prepare.c | 1 + 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index d474662745..dad1d28d7a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarity\stweak\sfor\sdate.c -D 2021-12-08T20:36:08.193 +C Do\snot\sattempt\sto\sreprepare\sa\sprepared\sstatement\sthat\sreturns\sSQLITE_SCHEMA\nif\sthere\swas\san\sOOM.\s\sThis\senhancement\ssupercedes\scheck-in\n[fee469925231d074]. +D 2021-12-09T14:09:47.530 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -495,7 +495,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 81feddbcc60d524518a7afc713b6dab0ad7caadb7370433f117c8c557dcdc889 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c 86a15afda3a8c01de8f9671b4e5a54e1102976052a055e73cc4832e2044091f5 +F src/build.c 107e1ecc98ca8965c2e08fc283a06067a1d829b1a82531a6f0a0e0fa60e7b0c1 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -546,7 +546,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad -F src/prepare.c 7520a371f1de8a53e3023eba75bc0d3473196833c6363d285cad8d002eabef0b +F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fee469925231d074c17b948605143cfbb2e9595851a797995e7331f1ab2a61ca -R a155c96fa61b0490e6fe4dac239420d6 -U larrybr -Z 91a082ea2c3f2144aa72dff5c2fe9b69 +P db58b2def014bdb146751110488a088767530ca2557baf73d6181a2558bbe6d3 +R 55b31a86584594f0db916a3c47bba8ab +U drh +Z 92ddcb516729f4a545eea1159efb8c91 diff --git a/manifest.uuid b/manifest.uuid index 0179047adb..dafe3b9453 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -db58b2def014bdb146751110488a088767530ca2557baf73d6181a2558bbe6d3 \ No newline at end of file +94fdbeffaf501daf30dc7fae7cef5c2bfdb3a9b055562adfc04374a9fc899c8d \ No newline at end of file diff --git a/src/build.c b/src/build.c index b927056101..c7ba85fe75 100644 --- a/src/build.c +++ b/src/build.c @@ -4962,7 +4962,6 @@ SrcList *sqlite3SrcListAppendFromTerm( append_from_error: assert( p==0 ); - if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "out of memory"); sqlite3ExprDelete(db, pOn); sqlite3IdListDelete(db, pUsing); sqlite3SelectDelete(db, pSubquery); diff --git a/src/prepare.c b/src/prepare.c index 14b5dbad6d..183a749a5f 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -808,6 +808,7 @@ static int sqlite3LockAndPrepare( ** reset is considered a permanent error. */ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); assert( rc==SQLITE_OK || *ppStmt==0 ); + if( rc==SQLITE_OK || db->mallocFailed ) break; }while( rc==SQLITE_ERROR_RETRY || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) ); sqlite3BtreeLeaveAll(db); From 92704681a1d3bbef8115c356ceb361a929dffeef Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 14:15:39 +0000 Subject: [PATCH 044/148] New test cases added to test/fuzzdata8.db FossilOrigin-Name: 7046877006259a0073cca4ddb4541321d373c462eac9924be26b5ae224075732 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/fuzzdata8.db | Bin 3019776 -> 3067904 bytes 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index dad1d28d7a..446b5336f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sattempt\sto\sreprepare\sa\sprepared\sstatement\sthat\sreturns\sSQLITE_SCHEMA\nif\sthere\swas\san\sOOM.\s\sThis\senhancement\ssupercedes\scheck-in\n[fee469925231d074]. -D 2021-12-09T14:09:47.530 +C New\stest\scases\sadded\sto\stest/fuzzdata8.db +D 2021-12-09T14:15:39.430 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1067,7 +1067,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2 -F test/fuzzdata8.db ef4d280ee69d6da0ebda7f81c0c66839fa577a97b29cc5790a564fde88be7183 +F test/fuzzdata8.db a0c7af954bcbb226ed7ae087b3b6d6e48eaac8fac5671150ffd23c35b55bffe6 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P db58b2def014bdb146751110488a088767530ca2557baf73d6181a2558bbe6d3 -R 55b31a86584594f0db916a3c47bba8ab +P 94fdbeffaf501daf30dc7fae7cef5c2bfdb3a9b055562adfc04374a9fc899c8d +R 038bdb896bed6cf3889d86d96df22335 U drh -Z 92ddcb516729f4a545eea1159efb8c91 +Z 9371649fa5af3eb0258d92eb2e10b334 diff --git a/manifest.uuid b/manifest.uuid index dafe3b9453..8b253b040a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -94fdbeffaf501daf30dc7fae7cef5c2bfdb3a9b055562adfc04374a9fc899c8d \ No newline at end of file +7046877006259a0073cca4ddb4541321d373c462eac9924be26b5ae224075732 \ No newline at end of file diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 966b73730c2c0c73069714e73127ecf2b056a306..960b15762510e89b40395c13f4ce6cc24be0678f 100644 GIT binary patch delta 55039 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 N8JpT->iK)@{~uhQey#uj delta 47468 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 From 5d88be8f488e2915563cd823bbf632d167b7ca51 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 16:17:43 +0000 Subject: [PATCH 045/148] Add ".mode off" and ".mode count" to the CLI. FossilOrigin-Name: b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 7cbde1e303..9862becc43 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sSQLITE_TESTCTRL_LOGEST\sand\senhance\sthe\sLogEst\sutility\sprogram.\nImprovements\sto\stestability\sof\sbloom\sfilters. -D 2021-12-09T01:28:15.168 +C Add\s".mode\soff"\sand\s".mode\scount"\sto\sthe\sCLI. +D 2021-12-09T16:17:43.145 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in cda1eaf0292259b4b0721a5e03af9701fd482ebc37ce6a86ddc94cd9a38bb826 +F src/shell.c.in 239bee1085d94964f02582b0714dc3fc85cfc16e27e95813e4dbc24bb215a7e0 F src/sqlite.h.in 50c8f27251b11f1c89b06abc6e4085fce15151bcbd355a44609ecb2ba5424841 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0fb2a4e08f518cb38ea3edc6a084d1e4874fd622ba3cf9101b49b3e7dc1a3f2b -R 13197c53db0503b249bb051590a0a6df +P 88b43d798cc5aa59855e92d3e658aee9f0a5def6ffbc5db77af048d75ecdf8cc +R 9caa791b08a3199a0c8bfc0ce172ce1a U drh -Z 80d7c2199cca2c3c9ca5b22286927a11 +Z 89026152bfb77d836155ab364d1ebd27 diff --git a/manifest.uuid b/manifest.uuid index 2d8c59a7eb..274a6197ab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88b43d798cc5aa59855e92d3e658aee9f0a5def6ffbc5db77af048d75ecdf8cc \ No newline at end of file +b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c46eaffd62..3262f98c12 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1253,6 +1253,8 @@ struct ShellState { #define MODE_Markdown 14 /* Markdown formatting */ #define MODE_Table 15 /* MySQL-style table formatting */ #define MODE_Box 16 /* Unicode box-drawing characters */ +#define MODE_Count 17 /* Output only a count of the rows of output */ +#define MODE_Off 18 /* No query output shown */ static const char *modeDescr[] = { "line", @@ -1271,7 +1273,9 @@ static const char *modeDescr[] = { "json", "markdown", "table", - "box" + "box", + "count", + "off" }; /* @@ -2093,6 +2097,10 @@ static int shell_callback( if( azArg==0 ) return 0; switch( p->cMode ){ + case MODE_Count: + case MODE_Off: { + break; + } case MODE_Line: { int w = 5; if( azArg==0 ) break; @@ -3310,6 +3318,7 @@ static void exec_prepared_stmt( sqlite3_stmt *pStmt /* Statment to run */ ){ int rc; + sqlite3_uint64 nRow = 0; if( pArg->cMode==MODE_Column || pArg->cMode==MODE_Table @@ -3342,6 +3351,7 @@ static void exec_prepared_stmt( azCols[i] = (char *)sqlite3_column_name(pStmt, i); } do{ + nRow++; /* extract the data and data types */ for(i=0; icMode==MODE_Json ){ fputs("]\n", pArg->out); + }else if( pArg->cMode==MODE_Count ){ + printf("%llu row%s\n", nRow, nRow!=1 ? "s" : ""); } } } @@ -8879,6 +8891,10 @@ static int do_meta_command(char *zLine, ShellState *p){ p->mode = MODE_Table; }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){ p->mode = MODE_Box; + }else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){ + p->mode = MODE_Count; + }else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){ + p->mode = MODE_Off; }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){ p->mode = MODE_Json; }else if( nArg==1 ){ From 59285ed788480505056cbdf3353525e442cfa536 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 16:26:45 +0000 Subject: [PATCH 046/148] Add ".mode off" and ".mode count" to the CLI. FossilOrigin-Name: 1eefd957ff35e961685db565f7ef116c566a04574c5bedad7298b3cc69dd72d2 --- manifest | 13 +++++++------ manifest.uuid | 2 +- src/shell.c.in | 18 +++++++++++++++++- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 446b5336f1..1e8f395183 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stest\scases\sadded\sto\stest/fuzzdata8.db -D 2021-12-09T14:15:39.430 +C Add\s".mode\soff"\sand\s".mode\scount"\sto\sthe\sCLI. +D 2021-12-09T16:26:45.642 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 1458b700144c8326fda2514aaddeda49d6f01f1d1ccf7b9b696c53a3535a119c +F src/shell.c.in 24e39ae0d6c2b8681740bc88e68ed3247a110c3a7aaaca63416477f3de79bcad F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 94fdbeffaf501daf30dc7fae7cef5c2bfdb3a9b055562adfc04374a9fc899c8d -R 038bdb896bed6cf3889d86d96df22335 +P 7046877006259a0073cca4ddb4541321d373c462eac9924be26b5ae224075732 +Q +b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c +R c56a6044af5ef1581ccf8dda1f9e99a9 U drh -Z 9371649fa5af3eb0258d92eb2e10b334 +Z 806d5f1c1ccd0354c71d5e148acabb04 diff --git a/manifest.uuid b/manifest.uuid index 8b253b040a..a61c9e96ac 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7046877006259a0073cca4ddb4541321d373c462eac9924be26b5ae224075732 \ No newline at end of file +1eefd957ff35e961685db565f7ef116c566a04574c5bedad7298b3cc69dd72d2 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 543141c9e4..216e0e46ff 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1253,6 +1253,8 @@ struct ShellState { #define MODE_Markdown 14 /* Markdown formatting */ #define MODE_Table 15 /* MySQL-style table formatting */ #define MODE_Box 16 /* Unicode box-drawing characters */ +#define MODE_Count 17 /* Output only a count of the rows of output */ +#define MODE_Off 18 /* No query output shown */ static const char *modeDescr[] = { "line", @@ -1271,7 +1273,9 @@ static const char *modeDescr[] = { "json", "markdown", "table", - "box" + "box", + "count", + "off" }; /* @@ -2093,6 +2097,10 @@ static int shell_callback( if( azArg==0 ) return 0; switch( p->cMode ){ + case MODE_Count: + case MODE_Off: { + break; + } case MODE_Line: { int w = 5; if( azArg==0 ) break; @@ -3303,6 +3311,7 @@ static void exec_prepared_stmt( sqlite3_stmt *pStmt /* Statment to run */ ){ int rc; + sqlite3_uint64 nRow = 0; if( pArg->cMode==MODE_Column || pArg->cMode==MODE_Table @@ -3335,6 +3344,7 @@ static void exec_prepared_stmt( azCols[i] = (char *)sqlite3_column_name(pStmt, i); } do{ + nRow++; /* extract the data and data types */ for(i=0; icMode==MODE_Json ){ fputs("]\n", pArg->out); + }else if( pArg->cMode==MODE_Count ){ + printf("%llu row%s\n", nRow, nRow!=1 ? "s" : ""); } } } @@ -8872,6 +8884,10 @@ static int do_meta_command(char *zLine, ShellState *p){ p->mode = MODE_Table; }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){ p->mode = MODE_Box; + }else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){ + p->mode = MODE_Count; + }else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){ + p->mode = MODE_Off; }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){ p->mode = MODE_Json; }else if( nArg==1 ){ From a11c5e22b5eb32cdf2061a6c19fd7bf4d2a36e05 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 18:44:03 +0000 Subject: [PATCH 047/148] Enable bloom filters for the right table of a LEFT JOIN. Fix unreachable branches. FossilOrigin-Name: d342ab722de1fc3f34219c9755253db9d88eb50a6fa5cc257207008b00e7fc03 --- manifest | 16 ++++++------- manifest.uuid | 2 +- src/where.c | 4 ++-- src/wherecode.c | 63 +++++++++++++++++++++++-------------------------- test/join5.test | 1 + 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/manifest b/manifest index 9862becc43..a498dda5fc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s".mode\soff"\sand\s".mode\scount"\sto\sthe\sCLI. -D 2021-12-09T16:17:43.145 +C Enable\sbloom\sfilters\sfor\sthe\sright\stable\sof\sa\sLEFT\sJOIN.\s\sFix\sunreachable\nbranches. +D 2021-12-09T18:44:03.070 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,9 +638,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 4946af4e7d073fd35c97ffce4c4b4f3d84f6a0c9e5cb20342560cfaf072ef3a6 +F src/where.c abd620b4823c0c72322ad5307805d0a350e808bd2424e3e00a1c3ecae32b8a09 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 -F src/wherecode.c 560424f5845ec4ef1e36e8a6a066cc497aaf8163fef29fa18a0317e1e14ba9b7 +F src/wherecode.c c2324c3204b7f51648cc71aa0c98bff3c72c96c2e0c2169809a921febef7e5e1 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1138,7 +1138,7 @@ F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e23 F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 -F test/join5.test f418fccdfefa41f1659663463aa517431ddcf3e30ccbb80e64173b7d615a03f4 +F test/join5.test d22395f7d4020a58cabbc8316f300a5cfef84aee9e8ba7ce79b33cc43a3e1e2e F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 88b43d798cc5aa59855e92d3e658aee9f0a5def6ffbc5db77af048d75ecdf8cc -R 9caa791b08a3199a0c8bfc0ce172ce1a +P b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c +R e684e836076af2e815def08dd3898cfa U drh -Z 89026152bfb77d836155ab364d1ebd27 +Z 309930b0d62304a131a19ba2d8419e5a diff --git a/manifest.uuid b/manifest.uuid index 274a6197ab..c9a3436415 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c \ No newline at end of file +d342ab722de1fc3f34219c9755253db9d88eb50a6fa5cc257207008b00e7fc03 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 859dac7cbb..44423f4bda 100644 --- a/src/where.c +++ b/src/where.c @@ -5000,15 +5000,15 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( WhereLoop *pLoop = pWInfo->a[i].pWLoop; const int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); if( (pLoop->wsFlags & reqFlags)==reqFlags - && (pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0 + && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) ){ SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; Table *pTab = pItem->pTab; pTab->tabFlags |= TF_StatsUsed; if( nSearch > pTab->nRowLogEst - && (pItem->fg.jointype & JT_LEFT)==0 && (pTab->tabFlags & TF_HasStat1)!=0 ){ + testcase( pItem->fg.jointype & JT_LEFT ); pLoop->wsFlags |= WHERE_BLOOMFILTER; pLoop->wsFlags &= ~WHERE_IDX_ONLY; WHERETRACE(0xffff, ( diff --git a/src/wherecode.c b/src/wherecode.c index 05d1f12ced..8cc76b1fdf 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -236,42 +236,37 @@ int sqlite3WhereExplainBloomFilter( const WhereLevel *pLevel /* Bloom filter on this level */ ){ int ret = 0; -#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( sqlite3ParseToplevel(pParse)->explain==2 ) -#endif - { - SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom]; - Vdbe *v = pParse->pVdbe; /* VM being constructed */ - sqlite3 *db = pParse->db; /* Database handle */ - char *zMsg; /* Text to add to EQP output */ - int i; /* Loop counter */ - WhereLoop *pLoop; /* The where loop */ - StrAccum str; /* EQP output string */ - char zBuf[100]; /* Initial space for EQP output string */ + SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zMsg; /* Text to add to EQP output */ + int i; /* Loop counter */ + WhereLoop *pLoop; /* The where loop */ + StrAccum str; /* EQP output string */ + char zBuf[100]; /* Initial space for EQP output string */ - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); - pLoop = pLevel->pWLoop; - if( pLoop->wsFlags & WHERE_IPK ){ - const Table *pTab = pItem->pTab; - if( pTab->iPKey>=0 ){ - sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); - }else{ - sqlite3_str_appendf(&str, "rowid=?"); - } + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); + str.printfFlags = SQLITE_PRINTF_INTERNAL; + sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); + pLoop = pLevel->pWLoop; + if( pLoop->wsFlags & WHERE_IPK ){ + const Table *pTab = pItem->pTab; + if( pTab->iPKey>=0 ){ + sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); }else{ - for(i=pLoop->nSkip; iu.btree.nEq; i++){ - const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); - if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); - sqlite3_str_appendf(&str, "%s=?", z); - } + sqlite3_str_appendf(&str, "rowid=?"); + } + }else{ + for(i=pLoop->nSkip; iu.btree.nEq; i++){ + const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); + if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); + sqlite3_str_appendf(&str, "%s=?", z); } - sqlite3_str_append(&str, ")", 1); - zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), - pParse->addrExplain, 0, zMsg,P4_DYNAMIC); } + sqlite3_str_append(&str, ")", 1); + zMsg = sqlite3StrAccumFinish(&str); + ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), + pParse->addrExplain, 0, zMsg,P4_DYNAMIC); return ret; } #endif /* SQLITE_OMIT_EXPLAIN */ @@ -1390,7 +1385,9 @@ static SQLITE_NOINLINE void filterPullDown( WhereLevel *pLevel = &pWInfo->a[iLevel]; WhereLoop *pLoop = pLevel->pWLoop; if( pLevel->regFilter==0 ) continue; - if( pLoop->prereq & notReady ) continue; + /* ,--- Because constructBloomFilter() has will not have set + ** vvvvv--' pLevel->regFilter if this were true. */ + if( NEVER(pLoop->prereq & notReady) ) continue; if( pLoop->wsFlags & WHERE_IPK ){ WhereTerm *pTerm = pLoop->aLTerm[0]; int regRowid; diff --git a/test/join5.test b/test/join5.test index e2ff2f6c27..0ae4ca1127 100644 --- a/test/join5.test +++ b/test/join5.test @@ -303,6 +303,7 @@ do_eqp_test 7.4 { } { QUERY PLAN |--SCAN t3 + |--BLOOM FILTER ON t4 (x=?) `--SEARCH t4 USING INDEX t4xz (x=?) } From 5a4ac1cc302388e8717f9873fc90e5b648a74eac Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 9 Dec 2021 19:42:52 +0000 Subject: [PATCH 048/148] Remove unused code and fix comments. Final cleanup before merging. FossilOrigin-Name: ce42039f5647b1f276acf5d9911528ecb47df1544a587def72c8cd6b2f664289 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/malloc.c | 21 --------------------- src/sqlite.h.in | 15 +++++++++------ src/sqliteInt.h | 4 ---- src/vdbe.c | 17 ----------------- src/where.c | 6 +++--- src/wherecode.c | 2 +- 8 files changed, 25 insertions(+), 64 deletions(-) diff --git a/manifest b/manifest index a498dda5fc..d3b9720825 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sbloom\sfilters\sfor\sthe\sright\stable\sof\sa\sLEFT\sJOIN.\s\sFix\sunreachable\nbranches. -D 2021-12-09T18:44:03.070 +C Remove\sunused\scode\sand\sfix\scomments.\s\sFinal\scleanup\sbefore\smerging. +D 2021-12-09T19:42:52.951 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -516,7 +516,7 @@ F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c F src/main.c 674a0fdfc2808e1d5a78b2eefe2ec3f93428cf82f0f6c013d577df1a1caa5940 -F src/malloc.c d9172a3946f11384f2fd6a799554ee26c6bb407c4bd0874a456ed485a2e362e4 +F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75 @@ -553,10 +553,10 @@ F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/shell.c.in 239bee1085d94964f02582b0714dc3fc85cfc16e27e95813e4dbc24bb215a7e0 -F src/sqlite.h.in 50c8f27251b11f1c89b06abc6e4085fce15151bcbd355a44609ecb2ba5424841 +F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 31b9673bc26b5b2a846bf26ce7124c869f64368f4eaac865d9350749ea314000 +F src/sqliteInt.h b4391c3c2ae0a8020ce0f543fc2b529f9bcdf72ab7ba3c31d170e3228169162f F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -623,7 +623,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 569349b0bddcbfbc661856f446adb92e1b0a47b3cbef548da9fc5aa639d7964c F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 855ee903521fcc5a799f673f5b05fc599dc50a31e6cb6a15e1e8a6858087595b +F src/vdbe.c 5c05b1149a930851f36b29172002dfa56ce703e13f82d5bb4242a29dc144e350 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 910985ac2783fe0938b314d811759d53fd25caf215810f62ca1ff068d6d60d7b F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -638,9 +638,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c abd620b4823c0c72322ad5307805d0a350e808bd2424e3e00a1c3ecae32b8a09 +F src/where.c 71bbbac8748ddd470dd3c4213342dce2e39c2c0aa84f9b03d80bbc075fb7c502 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 -F src/wherecode.c c2324c3204b7f51648cc71aa0c98bff3c72c96c2e0c2169809a921febef7e5e1 +F src/wherecode.c 98ec56212ea7c0993f5eb808c515076d42c814f833c1641022927903cef0e811 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b11f4d080aa9e6f694e2ec401e871f42bf25997e8e8bf77fa9b6014a50466e3c -R e684e836076af2e815def08dd3898cfa +P d342ab722de1fc3f34219c9755253db9d88eb50a6fa5cc257207008b00e7fc03 +R 5df525a734b3c13f01d7f10e288ab697 U drh -Z 309930b0d62304a131a19ba2d8419e5a +Z ccda542cb10f0dae6599ca15d7e6a94e diff --git a/manifest.uuid b/manifest.uuid index c9a3436415..96b8bdf103 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d342ab722de1fc3f34219c9755253db9d88eb50a6fa5cc257207008b00e7fc03 \ No newline at end of file +ce42039f5647b1f276acf5d9911528ecb47df1544a587def72c8cd6b2f664289 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 9a2eaeec15..932cecc210 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -211,27 +211,6 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ return mx; } -#if 0 -/* -** Return an estimate of the amount of unallocated memory. -** -** This the hard heap limit minus the current memory usage. It might -** not be possible to allocate this much memory all at once. This is -** only an estimate. -*/ -sqlite3_int64 sqlite3EstMemoryAvailable(void){ - sqlite3_int64 n; - sqlite3_mutex_enter(mem0.mutex); - n = mem0.alarmThreshold; - if( n<=0 ) n = mem0.hardLimit; - sqlite3_mutex_leave(mem0.mutex); - if( n<=0 ) n = LARGEST_INT64; - n -= sqlite3_memory_used(); - if( n<0 ) n = 0; - return n; -} -#endif - /* ** Trigger the alarm */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f7cf4d2fe1..63a6f37e9a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8468,12 +8468,15 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** -** [[SQLITE_STMTSTATUS_FILTER HIT]]

SQLITE_STMTSTATUS_FILTER_HIT
-**
^This is the number of times that a join step was bypassed because -** a Bloom filtered returned non-found. The corresponding -** SQLITE_STMTSTATUS_FILTER_MISS value is the number of times that the -** Bloom filter returned a find, and thus the join step had to be processed -** as normal. +** [[SQLITE_STMTSTATUS_FILTER_MISS]] +** [[SQLITE_STMTSTATUS_FILTER HIT]] +**
SQLITE_STMTSTATUS_FILTER_HIT
+** SQLITE_STMTSTATUS_FILTER_MISS
+**
^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join +** step was bypassed because a Bloom filter returned not-found. The +** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of +** times that the Bloom filter returned a find, and thus the join step +** had to be processed as normal. ** ** [[SQLITE_STMTSTATUS_MEMUSED]]
SQLITE_STMTSTATUS_MEMUSED
**
^This is the approximate number of bytes of heap memory diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0104bace6d..bd02e2626f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3927,7 +3927,6 @@ struct Sqlite3Config { int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ - int iEstCountScale; /* Multiple RowCountEst() by this amount */ /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ @@ -4294,9 +4293,6 @@ void sqlite3MemSetDefault(void); void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); #endif int sqlite3HeapNearlyFull(void); -#if 0 -sqlite3_int64 sqlite3EstMemoryAvailable(void); -#endif /* ** On systems with ample stack space and that support alloca(), make diff --git a/src/vdbe.c b/src/vdbe.c index ef60ed0123..27e030ec19 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -671,23 +671,6 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ } } -/* -** The minimum size (in bytes) for a Bloom filter. -** -** No Bloom filter will be smaller than this many bytes. But they -** may be larger. -*/ -#ifndef SQLITE_BLOOM_MIN -# define SQLITE_BLOOM_MIN 10000 -#endif - -/* -** The maximum size (in bytes) for a Bloom filter. -*/ -#ifndef SQLITE_BLOOM_MAX -# define SQLITE_BLOOM_MAX 1000000 -#endif - /* ** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning ** with pOp->p3. Return the hash. diff --git a/src/where.c b/src/where.c index 44423f4bda..be75101b26 100644 --- a/src/where.c +++ b/src/where.c @@ -4977,10 +4977,9 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( ** filter. ** (2) Some searches are expected to find zero rows. (This is determined ** by the WHERE_SELFCULL flag on the term.) -** (3) The table being searched is not the right table of a LEFT JOIN -** (4) Bloom-filter processing is not disabled. (Checked by the +** (3) Bloom-filter processing is not disabled. (Checked by the ** caller.) -** (5) The size of the table being searched is known by ANALYZE. +** (4) The size of the table being searched is known by ANALYZE. ** ** This block of code merely checks to see if a Bloom filter would be ** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the @@ -5000,6 +4999,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( WhereLoop *pLoop = pWInfo->a[i].pWLoop; const int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); if( (pLoop->wsFlags & reqFlags)==reqFlags + /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) ){ SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; diff --git a/src/wherecode.c b/src/wherecode.c index 8cc76b1fdf..dd73bc4e83 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1371,7 +1371,7 @@ static void whereApplyPartialIndexConstraints( ** ** We know that an inner loop uses a Bloom filter because it has the ** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked, -** then clear the WhereLoeve.regFilter value to prevent the Bloom filter +** then clear the WhereLevel.regFilter value to prevent the Bloom filter ** from being checked a second time when the inner loop is evaluated. */ static SQLITE_NOINLINE void filterPullDown( From 27a9e1f6152822a69f11a7e83308fbf898314eda Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Dec 2021 17:36:16 +0000 Subject: [PATCH 049/148] Rename the internal routine constructBloomFilter() to sqlite3ConstructBloomFilter(). OSSFuzz is reporting a crash with a garbled stack that we cannot reproduce. Perhaps the original "constructBloomFilter()" name is colliding with some internal name used by OSSFuzz. We'll see if this rename clears the problem. FossilOrigin-Name: 403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/where.c | 4 ++-- src/wherecode.c | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 765acd7045..2c5dc8afef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssupport\sfor\sBloom-filters\sas\sa\sperformance\soptimization\sfor\sjoins. -D 2021-12-09T20:06:18.928 +C Rename\sthe\sinternal\sroutine\sconstructBloomFilter()\sto\nsqlite3ConstructBloomFilter().\sOSSFuzz\sis\sreporting\sa\scrash\swith\sa\sgarbled\nstack\sthat\swe\scannot\sreproduce.\sPerhaps\sthe\soriginal\s"constructBloomFilter()"\nname\sis\scolliding\swith\ssome\sinternal\sname\sused\sby\sOSSFuzz.\sWe'll\ssee\sif\sthis\nrename\sclears\sthe\sproblem. +D 2021-12-10T17:36:16.695 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,9 +638,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 71bbbac8748ddd470dd3c4213342dce2e39c2c0aa84f9b03d80bbc075fb7c502 +F src/where.c 179e0376b8fa1a9ac9671cd7382d88aef547a4c6a7cc2833f57011990e826956 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 -F src/wherecode.c 98ec56212ea7c0993f5eb808c515076d42c814f833c1641022927903cef0e811 +F src/wherecode.c 47311c0a64e9038c8f52f889558bdbe93f8b105a5517f05bef4260bd8c35e66d F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1934,8 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1eefd957ff35e961685db565f7ef116c566a04574c5bedad7298b3cc69dd72d2 ce42039f5647b1f276acf5d9911528ecb47df1544a587def72c8cd6b2f664289 -R c6e1a17bdb20d0994b97369ef3d14311 -T +closed ce42039f5647b1f276acf5d9911528ecb47df1544a587def72c8cd6b2f664289 +P 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882 +R 2727e42f3726d0bce34928653c056def U drh -Z 2960f76524291316688b632931fc780c +Z 81c6addbec75f6f350e0d3032a7fdc73 diff --git a/manifest.uuid b/manifest.uuid index bbb228f8b8..5b54a326b3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882 \ No newline at end of file +403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3 \ No newline at end of file diff --git a/src/where.c b/src/where.c index be75101b26..123c0c062b 100644 --- a/src/where.c +++ b/src/where.c @@ -985,7 +985,7 @@ end_auto_index_create: ** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit ** is set. */ -static SQLITE_NOINLINE void constructBloomFilter( +static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( WhereInfo *pWInfo, /* The WHERE clause */ int iLevel, /* Index in pWInfo->a[] that is pLevel */ WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */ @@ -5615,7 +5615,7 @@ WhereInfo *sqlite3WhereBegin( &pTabList->a[pLevel->iFrom], notReady, pLevel); #endif }else{ - constructBloomFilter(pWInfo, ii, pLevel, notReady); + sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady); } if( db->mallocFailed ) goto whereBeginError; } diff --git a/src/wherecode.c b/src/wherecode.c index dd73bc4e83..f9eb7724a9 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1385,7 +1385,7 @@ static SQLITE_NOINLINE void filterPullDown( WhereLevel *pLevel = &pWInfo->a[iLevel]; WhereLoop *pLoop = pLevel->pWLoop; if( pLevel->regFilter==0 ) continue; - /* ,--- Because constructBloomFilter() has will not have set + /* ,--- Because sqlite3ConstructBloomFilter() has will not have set ** vvvvv--' pLevel->regFilter if this were true. */ if( NEVER(pLoop->prereq & notReady) ) continue; if( pLoop->wsFlags & WHERE_IPK ){ From ef95d5583b2638c22b8b2d4c8e3cb1129b041484 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 10 Dec 2021 21:01:24 +0000 Subject: [PATCH 050/148] Factor out the logic that does quoting for the SQL quote() function, so that it might be reused for other purposes. FossilOrigin-Name: 8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f --- manifest | 16 ++++---- manifest.uuid | 2 +- src/func.c | 102 ++++++++++++++++++++++++++---------------------- src/printf.c | 2 +- src/sqliteInt.h | 2 + 5 files changed, 67 insertions(+), 57 deletions(-) diff --git a/manifest b/manifest index 2c5dc8afef..fdf5374107 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sthe\sinternal\sroutine\sconstructBloomFilter()\sto\nsqlite3ConstructBloomFilter().\sOSSFuzz\sis\sreporting\sa\scrash\swith\sa\sgarbled\nstack\sthat\swe\scannot\sreproduce.\sPerhaps\sthe\soriginal\s"constructBloomFilter()"\nname\sis\scolliding\swith\ssome\sinternal\sname\sused\sby\sOSSFuzz.\sWe'll\ssee\sif\sthis\nrename\sclears\sthe\sproblem. -D 2021-12-10T17:36:16.695 +C Factor\sout\sthe\slogic\sthat\sdoes\squoting\sfor\sthe\sSQL\squote()\sfunction,\sso\sthat\nit\smight\sbe\sreused\sfor\sother\spurposes. +D 2021-12-10T21:01:24.675 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -506,7 +506,7 @@ F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5 -F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b +F src/func.c 0f576a0c102485676266e63a796223e63c3cdb04baf3678ccc8bfeedba4a6fd4 F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 @@ -547,7 +547,7 @@ F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 -F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d +F src/printf.c 9565aeb5af5376fd23c993b8da1ac37008fad65435a703316eef9f41229f702d F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 @@ -556,7 +556,7 @@ F src/shell.c.in 239bee1085d94964f02582b0714dc3fc85cfc16e27e95813e4dbc24bb215a7e F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h b4391c3c2ae0a8020ce0f543fc2b529f9bcdf72ab7ba3c31d170e3228169162f +F src/sqliteInt.h e7dd69a85c53461c937d50c97f8efd9761b14f9bcfb63450809e85c100c08538 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882 -R 2727e42f3726d0bce34928653c056def +P 403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3 +R 4fa3f8129d17f257f0557369c327b148 U drh -Z 81c6addbec75f6f350e0d3032a7fdc73 +Z 1eec60e7fbec94682a3271bf749ce5cf diff --git a/manifest.uuid b/manifest.uuid index 5b54a326b3..579ae8fcd8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3 \ No newline at end of file +8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f \ No newline at end of file diff --git a/src/func.c b/src/func.c index 6a2903d328..eeab1d2647 100644 --- a/src/func.c +++ b/src/func.c @@ -1027,39 +1027,42 @@ static const char hexdigits[] = { }; /* -** Implementation of the QUOTE() function. This function takes a single -** argument. If the argument is numeric, the return value is the same as -** the argument. If the argument is NULL, the return value is the string -** "NULL". Otherwise, the argument is enclosed in single quotes with -** single-quote escapes. +** Append to pStr text that is the SQL literal representation of the +** value contained in pValue. */ -static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ +void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ + /* As currently implemented, the string must be initially empty. + ** we might relax this requirement in the future, but that will + ** require enhancements to the implementation. */ + assert( pStr!=0 && pStr->nChar==0 ); + + switch( sqlite3_value_type(pValue) ){ case SQLITE_FLOAT: { double r1, r2; - char zBuf[50]; - r1 = sqlite3_value_double(argv[0]); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); - sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); - if( r1!=r2 ){ - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); + const char *zVal; + r1 = sqlite3_value_double(pValue); + sqlite3_str_appendf(pStr, "%!.15g", r1); + zVal = sqlite3_str_value(pStr); + if( zVal ){ + sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); + if( r1!=r2 ){ + sqlite3_str_reset(pStr); + sqlite3_str_appendf(pStr, "%!.20e", r1); + } } - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); break; } case SQLITE_INTEGER: { - sqlite3_result_value(context, argv[0]); + sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue)); break; } case SQLITE_BLOB: { - char *zText = 0; - char const *zBlob = sqlite3_value_blob(argv[0]); - int nBlob = sqlite3_value_bytes(argv[0]); - assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); - if( zText ){ + char const *zBlob = sqlite3_value_blob(pValue); + int nBlob = sqlite3_value_bytes(pValue); + assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */ + sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4); + if( pStr->accError==0 ){ + char *zText = pStr->zText; int i; for(i=0; i>4)&0x0F]; @@ -1069,42 +1072,47 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ zText[(nBlob*2)+3] = '\0'; zText[0] = 'X'; zText[1] = '\''; - sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); - sqlite3_free(zText); + pStr->nChar = nBlob*2 + 3; } break; } case SQLITE_TEXT: { - int i,j; - u64 n; - const unsigned char *zArg = sqlite3_value_text(argv[0]); - char *z; - - if( zArg==0 ) return; - for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } - z = contextMalloc(context, ((i64)i)+((i64)n)+3); - if( z ){ - z[0] = '\''; - for(i=0, j=1; zArg[i]; i++){ - z[j++] = zArg[i]; - if( zArg[i]=='\'' ){ - z[j++] = '\''; - } - } - z[j++] = '\''; - z[j] = 0; - sqlite3_result_text(context, z, j, sqlite3_free); - } + const unsigned char *zArg = sqlite3_value_text(pValue); + sqlite3_str_appendf(pStr, "%Q", zArg); break; } default: { - assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); - sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); + assert( sqlite3_value_type(pValue)==SQLITE_NULL ); + sqlite3_str_append(pStr, "NULL", 4); break; } } } +/* +** Implementation of the QUOTE() function. +** +** The quote(X) function returns the text of an SQL literal which is the +** value of its argument suitable for inclusion into an SQL statement. +** Strings are surrounded by single-quotes with escapes on interior quotes +** as needed. BLOBs are encoded as hexadecimal literals. Strings with +** embedded NUL characters cannot be represented as string literals in SQL +** and hence the returned string literal is truncated prior to the first NUL. +*/ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + sqlite3_str str; + sqlite3 *db = sqlite3_context_db_handle(context); + assert( argc==1 ); + UNUSED_PARAMETER(argc); + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3QuoteValue(&str,argv[0]); + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, + SQLITE_DYNAMIC); + if( str.accError==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + } +} + /* ** The unicode() function. Return the integer unicode code-point value ** for the first character of the input string. diff --git a/src/printf.c b/src/printf.c index e63518450c..6128e5cb4c 100644 --- a/src/printf.c +++ b/src/printf.c @@ -916,7 +916,7 @@ void sqlite3_str_vappendf( ** Return the number of bytes of text that StrAccum is able to accept ** after the attempted enlargement. The value returned might be zero. */ -static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ +int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bd02e2626f..48a94a7b33 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4684,6 +4684,7 @@ Select *sqlite3SelectDup(sqlite3*,const Select*,int); FuncDef *sqlite3FunctionSearch(int,const char*); void sqlite3InsertBuiltinFuncs(FuncDef*,int); FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); +void sqlite3QuoteValue(StrAccum*,sqlite3_value*); void sqlite3RegisterBuiltinFunctions(void); void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); @@ -4970,6 +4971,7 @@ int sqlite3ApiExit(sqlite3 *db, int); int sqlite3OpenTempDatabase(Parse *); void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +int sqlite3StrAccumEnlarge(StrAccum*, int); char *sqlite3StrAccumFinish(StrAccum*); void sqlite3StrAccumSetError(StrAccum*, u8); void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); From dc56dc93a545188f8842053ff33b5e8e2b5983d1 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 11 Dec 2021 17:10:58 +0000 Subject: [PATCH 051/148] Do not allow early evaluation of Bloom filters that use the IN operator as the machinery to deal with the IN operator is not available. dbsqlfuzz 5b51c247518278f79a45cea978702e86e86cd4f9. FossilOrigin-Name: 799db7cb2e0d73031182d26a0e5919368f9f9823df81cb2863bfe79eca344f5c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 7 ++++++- src/wherecode.c | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fdf5374107..a1357c0e59 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Factor\sout\sthe\slogic\sthat\sdoes\squoting\sfor\sthe\sSQL\squote()\sfunction,\sso\sthat\nit\smight\sbe\sreused\sfor\sother\spurposes. -D 2021-12-10T21:01:24.675 +C Do\snot\sallow\searly\sevaluation\sof\sBloom\sfilters\sthat\suse\sthe\sIN\soperator\sas\nthe\smachinery\sto\sdeal\swith\sthe\sIN\soperator\sis\snot\savailable.\ndbsqlfuzz\s5b51c247518278f79a45cea978702e86e86cd4f9. +D 2021-12-11T17:10:58.929 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,9 +638,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 179e0376b8fa1a9ac9671cd7382d88aef547a4c6a7cc2833f57011990e826956 +F src/where.c f92862c2d7b9dd6524b10c4ad1f1b30d9cd6724b93077550ad8ebe4a74810458 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 -F src/wherecode.c 47311c0a64e9038c8f52f889558bdbe93f8b105a5517f05bef4260bd8c35e66d +F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3 -R 4fa3f8129d17f257f0557369c327b148 +P 8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f +R 593507c8b07b9c8531bd64e8d5ab1fc4 U drh -Z 1eec60e7fbec94682a3271bf749ce5cf +Z a179a37fd038e80569064057605d6e4f diff --git a/manifest.uuid b/manifest.uuid index 579ae8fcd8..9d7a80fbfb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f \ No newline at end of file +799db7cb2e0d73031182d26a0e5919368f9f9823df81cb2863bfe79eca344f5c \ No newline at end of file diff --git a/src/where.c b/src/where.c index 123c0c062b..221ab8f0e7 100644 --- a/src/where.c +++ b/src/where.c @@ -1075,7 +1075,12 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( pLoop = pLevel->pWLoop; if( pLoop==0 ) continue; if( pLoop->prereq & notReady ) continue; - if( pLoop->wsFlags & WHERE_BLOOMFILTER ) break; + if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN))==WHERE_BLOOMFILTER ){ + /* This is a candidate for bloom-filter pull-down (early evaluation). + ** The test that WHERE_COLUMN_IN is omitted is important, as we are not able + ** to do early evaluation of bloom filters that make use of the IN operator */ + break; + } } }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); diff --git a/src/wherecode.c b/src/wherecode.c index f9eb7724a9..a08ff84d28 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1405,6 +1405,7 @@ static SQLITE_NOINLINE void filterPullDown( char *zStartAff; assert( pLoop->wsFlags & WHERE_INDEXED ); + assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 ); r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff); codeApplyAffinity(pParse, r1, nEq, zStartAff); sqlite3DbFree(pParse->db, zStartAff); From 089a9ff48aa612fd5343e1f107587f9c659bb869 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 13 Dec 2021 00:02:59 +0000 Subject: [PATCH 052/148] Remove unused code. FossilOrigin-Name: b98b24f26518fb362e776bbaef80910bed66b654239e7c76d4b234033ef4174b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index a1357c0e59..301a4cf91b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\searly\sevaluation\sof\sBloom\sfilters\sthat\suse\sthe\sIN\soperator\sas\nthe\smachinery\sto\sdeal\swith\sthe\sIN\soperator\sis\snot\savailable.\ndbsqlfuzz\s5b51c247518278f79a45cea978702e86e86cd4f9. -D 2021-12-11T17:10:58.929 +C Remove\sunused\scode. +D 2021-12-13T00:02:59.146 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -623,7 +623,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 569349b0bddcbfbc661856f446adb92e1b0a47b3cbef548da9fc5aa639d7964c F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 5c05b1149a930851f36b29172002dfa56ce703e13f82d5bb4242a29dc144e350 +F src/vdbe.c b63594839cbf770a29e2b3b81570971a3d2c1c995c0586aade09bb548142113a F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 910985ac2783fe0938b314d811759d53fd25caf215810f62ca1ff068d6d60d7b F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f -R 593507c8b07b9c8531bd64e8d5ab1fc4 +P 799db7cb2e0d73031182d26a0e5919368f9f9823df81cb2863bfe79eca344f5c +R 443c4836c6ff4faa05c5e5c0f674c8e4 U drh -Z a179a37fd038e80569064057605d6e4f +Z fcc54c34db6e9396cb50523f7150424b diff --git a/manifest.uuid b/manifest.uuid index 9d7a80fbfb..f6fc789672 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -799db7cb2e0d73031182d26a0e5919368f9f9823df81cb2863bfe79eca344f5c \ No newline at end of file +b98b24f26518fb362e776bbaef80910bed66b654239e7c76d4b234033ef4174b \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 27e030ec19..66ce3438f7 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -681,7 +681,6 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){ i = pOp->p3; assert( pOp->p4type==P4_INT32 ); - mx = i + pOp->p4.i; for(i=pOp->p3, mx=i+pOp->p4.i; iflags & (MEM_Int|MEM_IntReal) ){ From c5860af006bba5c80bca1c7523c38eddd4580c42 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 13 Dec 2021 18:43:46 +0000 Subject: [PATCH 053/148] Fix an off-by-one error in the Bloom filter pulldown logic, found by OSSFuzz. Also fix over-length source code lines in the immediate vicinity. FossilOrigin-Name: 027626521c02be06ef61e8229bde49d20cb3f1cb600c4cb127c5f139b9de8858 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 12 +++++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 301a4cf91b..9fb8ae3cb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunused\scode. -D 2021-12-13T00:02:59.146 +C Fix\san\soff-by-one\serror\sin\sthe\sBloom\sfilter\spulldown\slogic,\sfound\sby\sOSSFuzz.\nAlso\sfix\sover-length\ssource\scode\slines\sin\sthe\simmediate\svicinity. +D 2021-12-13T18:43:46.407 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c f92862c2d7b9dd6524b10c4ad1f1b30d9cd6724b93077550ad8ebe4a74810458 +F src/where.c 78a878f3264b4710b805bc11d18651435fbc80051d00e3e42692fc86c1cd31bb F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 799db7cb2e0d73031182d26a0e5919368f9f9823df81cb2863bfe79eca344f5c -R 443c4836c6ff4faa05c5e5c0f674c8e4 +P b98b24f26518fb362e776bbaef80910bed66b654239e7c76d4b234033ef4174b +R 3a4dce129857177521e360c2e6772ed6 U drh -Z fcc54c34db6e9396cb50523f7150424b +Z e1c941de49bea239b2265178ce7baef0 diff --git a/manifest.uuid b/manifest.uuid index f6fc789672..2e6de68e21 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b98b24f26518fb362e776bbaef80910bed66b654239e7c76d4b234033ef4174b \ No newline at end of file +027626521c02be06ef61e8229bde49d20cb3f1cb600c4cb127c5f139b9de8858 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 221ab8f0e7..852f1c17ff 100644 --- a/src/where.c +++ b/src/where.c @@ -1069,16 +1069,18 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( sqlite3VdbeJumpHere(v, addrTop); pLoop->wsFlags &= ~WHERE_BLOOMFILTER; if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break; - while( iLevel < pWInfo->nLevel ){ - iLevel++; + while( ++iLevel < pWInfo->nLevel ){ pLevel = &pWInfo->a[iLevel]; pLoop = pLevel->pWLoop; if( pLoop==0 ) continue; if( pLoop->prereq & notReady ) continue; - if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN))==WHERE_BLOOMFILTER ){ + if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN)) + ==WHERE_BLOOMFILTER + ){ /* This is a candidate for bloom-filter pull-down (early evaluation). - ** The test that WHERE_COLUMN_IN is omitted is important, as we are not able - ** to do early evaluation of bloom filters that make use of the IN operator */ + ** The test that WHERE_COLUMN_IN is omitted is important, as we are + ** not able to do early evaluation of bloom filters that make use of + ** the IN operator */ break; } } From 4f2006ddec1f119026d87207d799feafe1d29f3a Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 13 Dec 2021 18:53:10 +0000 Subject: [PATCH 054/148] Add NEVER() on an unreachable branch in the Bloom filter pull-down logic. FossilOrigin-Name: 471070462593faba865d8d05ee89161b340145351e2fa0bfbaa766d974e932d6 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9fb8ae3cb8..539740affc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\soff-by-one\serror\sin\sthe\sBloom\sfilter\spulldown\slogic,\sfound\sby\sOSSFuzz.\nAlso\sfix\sover-length\ssource\scode\slines\sin\sthe\simmediate\svicinity. -D 2021-12-13T18:43:46.407 +C Add\sNEVER()\son\san\sunreachable\sbranch\sin\sthe\sBloom\sfilter\spull-down\slogic. +D 2021-12-13T18:53:10.371 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 78a878f3264b4710b805bc11d18651435fbc80051d00e3e42692fc86c1cd31bb +F src/where.c c3299a18bb95a0189629aaad1207e2214251181e4c71763c2c0a2575a5e4a4c2 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b98b24f26518fb362e776bbaef80910bed66b654239e7c76d4b234033ef4174b -R 3a4dce129857177521e360c2e6772ed6 +P 027626521c02be06ef61e8229bde49d20cb3f1cb600c4cb127c5f139b9de8858 +R 057e2625c45c96442011c44c84a35821 U drh -Z e1c941de49bea239b2265178ce7baef0 +Z 1a75a7377d82483ef4328f4adf9ae9ae diff --git a/manifest.uuid b/manifest.uuid index 2e6de68e21..801ce1024e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -027626521c02be06ef61e8229bde49d20cb3f1cb600c4cb127c5f139b9de8858 \ No newline at end of file +471070462593faba865d8d05ee89161b340145351e2fa0bfbaa766d974e932d6 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 852f1c17ff..982685738a 100644 --- a/src/where.c +++ b/src/where.c @@ -1072,7 +1072,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( while( ++iLevel < pWInfo->nLevel ){ pLevel = &pWInfo->a[iLevel]; pLoop = pLevel->pWLoop; - if( pLoop==0 ) continue; + if( NEVER(pLoop==0) ) continue; if( pLoop->prereq & notReady ) continue; if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN)) ==WHERE_BLOOMFILTER From 7f8f659260aec0051ff9a7d7ca661df9402db12f Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 13 Dec 2021 19:59:55 +0000 Subject: [PATCH 055/148] Small performance optimization and code size reduction in moveToRoot(). FossilOrigin-Name: cdcde00b2d68eeb35c472fdfd4c4508551f6722054394b43cc97eaf01ad7181d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 539740affc..e0d8823816 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sNEVER()\son\san\sunreachable\sbranch\sin\sthe\sBloom\sfilter\spull-down\slogic. -D 2021-12-13T18:53:10.371 +C Small\sperformance\soptimization\sand\scode\ssize\sreduction\sin\smoveToRoot(). +D 2021-12-13T19:59:55.504 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -492,7 +492,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 81feddbcc60d524518a7afc713b6dab0ad7caadb7370433f117c8c557dcdc889 +F src/btree.c 06abea6fbd9e28f86c8fcb2edfd3fb3afde388750a4f7f5fa425935a789c1f5c F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 107e1ecc98ca8965c2e08fc283a06067a1d829b1a82531a6f0a0e0fa60e7b0c1 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 027626521c02be06ef61e8229bde49d20cb3f1cb600c4cb127c5f139b9de8858 -R 057e2625c45c96442011c44c84a35821 +P 471070462593faba865d8d05ee89161b340145351e2fa0bfbaa766d974e932d6 +R 31496f1551d29819dc300c6e9471d345 U drh -Z 1a75a7377d82483ef4328f4adf9ae9ae +Z 3da685334c6fbdb2df60cd96248cd338 diff --git a/manifest.uuid b/manifest.uuid index 801ce1024e..259c297ce1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -471070462593faba865d8d05ee89161b340145351e2fa0bfbaa766d974e932d6 \ No newline at end of file +cdcde00b2d68eeb35c472fdfd4c4508551f6722054394b43cc97eaf01ad7181d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 5060140731..6ffc6b6a1a 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5274,7 +5274,7 @@ static int moveToRoot(BtCursor *pCur){ while( --pCur->iPage ){ releasePageNotNull(pCur->apPage[pCur->iPage]); } - pCur->pPage = pCur->apPage[0]; + pRoot = pCur->pPage = pCur->apPage[0]; goto skip_init; } }else if( pCur->pgnoRoot==0 ){ @@ -5321,7 +5321,6 @@ skip_init: pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); - pRoot = pCur->pPage; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ From 06164b23402388575704d29489f7244e982f507b Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 14 Dec 2021 00:36:09 +0000 Subject: [PATCH 056/148] Omit the return value from sqlite3VdbeSerialGet() for a size reduction and performance improvement. FossilOrigin-Name: 788e79f881d443fc1b3a213a7ba4f19bfd245e96c15bb21fcb6bffd92c4320b8 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/test_func.c | 6 ++++-- src/vdbeInt.h | 2 +- src/vdbeaux.c | 36 +++++++++++++++++++----------------- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index e0d8823816..bb83da2331 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\soptimization\sand\scode\ssize\sreduction\sin\smoveToRoot(). -D 2021-12-13T19:59:55.504 +C Omit\sthe\sreturn\svalue\sfrom\ssqlite3VdbeSerialGet()\sfor\sa\ssize\sreduction\nand\sperformance\simprovement. +D 2021-12-14T00:36:09.965 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -581,7 +581,7 @@ F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91 F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593 F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480 -F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276 +F src/test_func.c 24df3a346c012b1fc9e1001d346db6054deb426db0a7437e92490630e71c9b0a F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664 F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71 @@ -625,9 +625,9 @@ F src/util.c 569349b0bddcbfbc661856f446adb92e1b0a47b3cbef548da9fc5aa639d7964c F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 F src/vdbe.c b63594839cbf770a29e2b3b81570971a3d2c1c995c0586aade09bb548142113a F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe -F src/vdbeInt.h 910985ac2783fe0938b314d811759d53fd25caf215810f62ca1ff068d6d60d7b +F src/vdbeInt.h a7f01b0cd0dcb496343eacd37b0839250f9a718199ab6096e3995db42dec3ec8 F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a -F src/vdbeaux.c 21db442d159fd745a7693d157b5f998260b6af4ca60de559fa3b7b68c7405af2 +F src/vdbeaux.c 175f2dad949150abdf0d91d19b2b6db30ff3776af5a84008db4bfe5e12a60180 F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652 F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 471070462593faba865d8d05ee89161b340145351e2fa0bfbaa766d974e932d6 -R 31496f1551d29819dc300c6e9471d345 +P cdcde00b2d68eeb35c472fdfd4c4508551f6722054394b43cc97eaf01ad7181d +R 74fcb3641325f5444e7c25132e4edd61 U drh -Z 3da685334c6fbdb2df60cd96248cd338 +Z 1db5e6a6595e0e17160e9f47eedbec36 diff --git a/manifest.uuid b/manifest.uuid index 259c297ce1..e757759542 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cdcde00b2d68eeb35c472fdfd4c4508551f6722054394b43cc97eaf01ad7181d \ No newline at end of file +788e79f881d443fc1b3a213a7ba4f19bfd245e96c15bb21fcb6bffd92c4320b8 \ No newline at end of file diff --git a/src/test_func.c b/src/test_func.c index b7c9e08ceb..fa52438261 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -499,7 +499,8 @@ static void test_extract( mem.db = db; mem.enc = ENC(db); pHdr += sqlite3GetVarint(pHdr, &iSerialType); - pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); + sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); + pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType); if( iCurrent==iIdx ){ sqlite3_result_value(context, &mem); @@ -547,7 +548,8 @@ static void test_decode( mem.db = db; mem.enc = ENC(db); pHdr += sqlite3GetVarint(pHdr, &iSerialType); - pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); + sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); + pBody += sqlite3VdbeSerialTypeLen((u32)iSerialType); switch( sqlite3_value_type(&mem) ){ case SQLITE_TEXT: diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 38863f6d65..481c93ddb0 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -492,7 +492,7 @@ int sqlite3VdbeCursorRestore(VdbeCursor*); u32 sqlite3VdbeSerialTypeLen(u32); u8 sqlite3VdbeOneByteSerialTypeLen(u8); u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); -u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index f03196bffe..6fe81e95fa 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3851,14 +3851,14 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ /* ** Deserialize the data blob pointed to by buf as serial type serial_type -** and store the result in pMem. Return the number of bytes read. +** and store the result in pMem. ** ** This function is implemented as two separate routines for performance. ** The few cases that require local variables are broken out into a separate ** routine so that in most cases the overhead of moving the stack pointer ** is avoided. */ -static u32 serialGet( +static void serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ @@ -3892,9 +3892,8 @@ static u32 serialGet( memcpy(&pMem->u.r, &x, sizeof(x)); pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; } - return 8; } -u32 sqlite3VdbeSerialGet( +void sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ @@ -3905,13 +3904,13 @@ u32 sqlite3VdbeSerialGet( pMem->flags = MEM_Null|MEM_Zero; pMem->n = 0; pMem->u.nZero = 0; - break; + return; } case 11: /* Reserved for future use */ case 0: { /* Null */ /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ pMem->flags = MEM_Null; - break; + return; } case 1: { /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement @@ -3919,7 +3918,7 @@ u32 sqlite3VdbeSerialGet( pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 1; + return; } case 2: { /* 2-byte signed integer */ /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit @@ -3927,7 +3926,7 @@ u32 sqlite3VdbeSerialGet( pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 2; + return; } case 3: { /* 3-byte signed integer */ /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit @@ -3935,7 +3934,7 @@ u32 sqlite3VdbeSerialGet( pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 3; + return; } case 4: { /* 4-byte signed integer */ /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit @@ -3947,7 +3946,7 @@ u32 sqlite3VdbeSerialGet( #endif pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 4; + return; } case 5: { /* 6-byte signed integer */ /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit @@ -3955,13 +3954,14 @@ u32 sqlite3VdbeSerialGet( pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 6; + return; } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ /* These use local variables, so do them in a separate routine ** to avoid having to move the frame pointer in the common case */ - return serialGet(buf,serial_type,pMem); + serialGet(buf,serial_type,pMem); + return; } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ @@ -3969,7 +3969,7 @@ u32 sqlite3VdbeSerialGet( /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; - return 0; + return; } default: { /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in @@ -3980,10 +3980,10 @@ u32 sqlite3VdbeSerialGet( pMem->z = (char *)buf; pMem->n = (serial_type-12)/2; pMem->flags = aFlag[serial_type&1]; - return pMem->n; + return; } } - return 0; + return; } /* ** This routine is used to allocate sufficient space for an UnpackedRecord @@ -4046,7 +4046,8 @@ void sqlite3VdbeRecordUnpack( /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ pMem->szMalloc = 0; pMem->z = 0; - d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + d += sqlite3VdbeSerialTypeLen(serial_type); pMem++; if( (++u)>=p->nField ) break; } @@ -4130,7 +4131,8 @@ static int vdbeRecordCompareDebug( /* Extract the values to be compared. */ - d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + d1 += sqlite3VdbeSerialTypeLen(serial_type1); /* Do the comparison */ From 22f018c9389cfd7fb0e8fc06d0988f2deae1cc0e Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 14 Dec 2021 18:11:46 +0000 Subject: [PATCH 057/148] Minor fix to the ORDER BY elimination logic in generate_series(). FossilOrigin-Name: a2e50712fca9dff1b8d19631f792270c82da3c8696a5d9890cf0d1e13e950d60 --- ext/misc/series.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- test/tabfunc01.test | 28 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/ext/misc/series.c b/ext/misc/series.c index e8d8c10aec..3941d96c47 100644 --- a/ext/misc/series.c +++ b/ext/misc/series.c @@ -386,7 +386,7 @@ static int seriesBestIndex( ** the preferred case */ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; - if( pIdxInfo->nOrderBy==1 ){ + if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){ if( pIdxInfo->aOrderBy[0].desc ){ idxNum |= 8; }else{ diff --git a/manifest b/manifest index bb83da2331..edd28753b3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Omit\sthe\sreturn\svalue\sfrom\ssqlite3VdbeSerialGet()\sfor\sa\ssize\sreduction\nand\sperformance\simprovement. -D 2021-12-14T00:36:09.965 +C Minor\sfix\sto\sthe\sORDER\sBY\selimination\slogic\sin\sgenerate_series(). +D 2021-12-14T18:11:46.057 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -321,7 +321,7 @@ F ext/misc/regexp.c 8cd0d2d904bf7014ba28beab8c1d502b5154e04a8c738b079d88e4ecca1b F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946 -F ext/misc/series.c f9896e76b029e3c6553c520552555e803e26e7dfe1890d5866243cf072d938d0 +F ext/misc/series.c 8d79354f2c3d46b95ee21272a07cf0bcabb58d1f2b06d9e7b8a31dca1dacb3e5 F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 @@ -1453,7 +1453,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309 F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039 F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 -F test/tabfunc01.test d6821e7042e5653104dac0c63d75eff24a2415ab1889fc68b5db7fde59464c59 +F test/tabfunc01.test 2708073a405ee3989cfc87a9ee47b2f231b8996529b48ba111ed15fa9106d22c F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132 F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cdcde00b2d68eeb35c472fdfd4c4508551f6722054394b43cc97eaf01ad7181d -R 74fcb3641325f5444e7c25132e4edd61 +P 788e79f881d443fc1b3a213a7ba4f19bfd245e96c15bb21fcb6bffd92c4320b8 +R 842bfdb0c978a51950e5dd7fb39c0333 U drh -Z 1db5e6a6595e0e17160e9f47eedbec36 +Z d877d022570b657f3f70fd02d0845d09 diff --git a/manifest.uuid b/manifest.uuid index e757759542..fd6e39c5d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -788e79f881d443fc1b3a213a7ba4f19bfd245e96c15bb21fcb6bffd92c4320b8 \ No newline at end of file +a2e50712fca9dff1b8d19631f792270c82da3c8696a5d9890cf0d1e13e950d60 \ No newline at end of file diff --git a/test/tabfunc01.test b/test/tabfunc01.test index d3d93792da..1d990efc4a 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -117,6 +117,34 @@ do_execsql_test tabfunc01-3.1 { SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1; } {1 2 3} +do_eqp_test tabfunc01-3.10 { + SELECT value FROM generate_series(1,10) ORDER BY value; +} { + QUERY PLAN + `--SCAN generate_series VIRTUAL TABLE INDEX 19: +} +do_eqp_test tabfunc01-3.11 { + SELECT value FROM generate_series(1,10) ORDER BY +value; +} { + QUERY PLAN + |--SCAN generate_series VIRTUAL TABLE INDEX 3: + `--USE TEMP B-TREE FOR ORDER BY +} +do_eqp_test tabfunc01-3.12 { + SELECT value FROM generate_series(1,10) ORDER BY value, stop; +} { + QUERY PLAN + `--SCAN generate_series VIRTUAL TABLE INDEX 19: +} +do_eqp_test tabfunc01-3.13 { + SELECT value FROM generate_series(1,10) ORDER BY stop, value; +} { + QUERY PLAN + |--SCAN generate_series VIRTUAL TABLE INDEX 3: + `--USE TEMP B-TREE FOR ORDER BY +} + + # Eponymous virtual table exists in all schemas. # do_execsql_test tabfunc01-4.1 { From 52576b78f6bb0cf9e88a861c14225480abc835fb Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 14 Dec 2021 20:13:28 +0000 Subject: [PATCH 058/148] Enhance the virtual table query planner so that it is able to deal with ORDER BY terms that contain COLLATE clauses as long as the specified collation matches the virtual table. This is especially important for UNION ALL since a "COLLATE binary" is added to ORDER BY clauses if no COLLATE clause exists in the original SQL. FossilOrigin-Name: 5c3d398d20b86a1558720e995eddf11403aec2d160590571fa9525fe8f6efff9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 37 ++++++++++++++++++++++++++++++++++++- test/tabfunc01.test | 17 +++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index edd28753b3..19da831492 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sfix\sto\sthe\sORDER\sBY\selimination\slogic\sin\sgenerate_series(). -D 2021-12-14T18:11:46.057 +C Enhance\sthe\svirtual\stable\squery\splanner\sso\sthat\sit\sis\sable\sto\sdeal\swith\nORDER\sBY\sterms\sthat\scontain\sCOLLATE\sclauses\sas\slong\sas\sthe\sspecified\ncollation\smatches\sthe\svirtual\stable.\s\sThis\sis\sespecially\simportant\sfor\nUNION\sALL\ssince\sa\s"COLLATE\sbinary"\sis\sadded\sto\sORDER\sBY\sclauses\sif\sno\nCOLLATE\sclause\sexists\sin\sthe\soriginal\sSQL. +D 2021-12-14T20:13:28.303 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c c3299a18bb95a0189629aaad1207e2214251181e4c71763c2c0a2575a5e4a4c2 +F src/where.c c69fed81e5dfd38e261e9af8c3faba133434b233757b0b2814db71eba86a0a62 F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 @@ -1453,7 +1453,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309 F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039 F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 -F test/tabfunc01.test 2708073a405ee3989cfc87a9ee47b2f231b8996529b48ba111ed15fa9106d22c +F test/tabfunc01.test 241425ce3998687ab24adba09cb95e8012e17499b84a0ed47e128ab45e588bef F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132 F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 788e79f881d443fc1b3a213a7ba4f19bfd245e96c15bb21fcb6bffd92c4320b8 -R 842bfdb0c978a51950e5dd7fb39c0333 +P a2e50712fca9dff1b8d19631f792270c82da3c8696a5d9890cf0d1e13e950d60 +R 1e0532988fdf8f21a62bc70005049044 U drh -Z d877d022570b657f3f70fd02d0845d09 +Z 0d6fc2fca37175245191cba6d8527f4e diff --git a/manifest.uuid b/manifest.uuid index fd6e39c5d8..17670695af 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a2e50712fca9dff1b8d19631f792270c82da3c8696a5d9890cf0d1e13e950d60 \ No newline at end of file +5c3d398d20b86a1558720e995eddf11403aec2d160590571fa9525fe8f6efff9 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 982685738a..33e0e43a4c 100644 --- a/src/where.c +++ b/src/where.c @@ -1114,6 +1114,10 @@ static sqlite3_index_info *allocateIndexInfo( sqlite3_index_info *pIdxInfo; u16 mNoOmit = 0; + assert( pSrc!=0 ); + assert( pSrc->pTab!=0 ); + assert( IsVirtual(pSrc->pTab) ); + /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ @@ -1140,8 +1144,36 @@ static sqlite3_index_info *allocateIndexInfo( int n = pOrderBy->nExpr; for(i=0; ia[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + Expr *pE2; + + /* Virtual tables are unable to deal with NULLS FIRST */ if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break; + + /* First case - a direct column references without a COLLATE operator */ + if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){ + assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumnpTab->nCol ); + continue; + } + + /* 2nd case - a column reference with a COLLATE operator. Only match + ** of the COLLATE operator matches the collation of the column. */ + if( pExpr->op==TK_COLLATE + && (pE2 = pExpr->pLeft)->op==TK_COLUMN + && pE2->iTable==pSrc->iCursor + ){ + const char *zColl; /* The collating sequence name */ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pE2->iColumn>=XN_ROWID && pE2->iColumnpTab->nCol ); + pExpr->iColumn = pE2->iColumn; + if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */ + zColl = sqlite3ColumnColl(&pSrc->pTab->aCol[pE2->iColumn]); + if( zColl==0 ) zColl = sqlite3StrBINARY; + if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; + } + + /* No matches cause a break out of the loop */ + break; } if( i==n){ nOrderBy = n; @@ -1228,6 +1260,9 @@ static sqlite3_index_info *allocateIndexInfo( pIdxInfo->nConstraint = j; for(i=0; ia[i].pExpr; + assert( pExpr->op==TK_COLUMN + || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN + && pExpr->iColumn==pExpr->pLeft->iColumn) ); pIdxOrderBy[i].iColumn = pExpr->iColumn; pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; } diff --git a/test/tabfunc01.test b/test/tabfunc01.test index 1d990efc4a..0a7e3bc245 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -145,6 +145,23 @@ do_eqp_test tabfunc01-3.13 { } +do_eqp_test tabfunc01-3.20 { + WITH t1(a) AS ( + SELECT value FROM generate_series(0,10,2) + UNION ALL + SELECT value FROM generate_series(9,18,3) + ) + SELECT * FROM t1 ORDER BY a; +} { + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + `--RIGHT + `--SCAN generate_series VIRTUAL TABLE INDEX 23: +} + + # Eponymous virtual table exists in all schemas. # do_execsql_test tabfunc01-4.1 { From 8a95d3d433ccc466899c2da9b880918dd70151b6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 15 Dec 2021 20:48:15 +0000 Subject: [PATCH 059/148] Simplify the generation of the sqlite3_index_info object during query planning for virtual tables. FossilOrigin-Name: 241dc0428a6e0238c57e2449e98ea60047e777e29c83a4ebe6da16f7cba40e19 --- manifest | 16 +++++++-------- manifest.uuid | 2 +- src/where.c | 54 ++++++++++++++++++++++++------------------------- src/whereInt.h | 2 +- src/whereexpr.c | 8 ++++---- 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index 19da831492..9ffb0be7d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\svirtual\stable\squery\splanner\sso\sthat\sit\sis\sable\sto\sdeal\swith\nORDER\sBY\sterms\sthat\scontain\sCOLLATE\sclauses\sas\slong\sas\sthe\sspecified\ncollation\smatches\sthe\svirtual\stable.\s\sThis\sis\sespecially\simportant\sfor\nUNION\sALL\ssince\sa\s"COLLATE\sbinary"\sis\sadded\sto\sORDER\sBY\sclauses\sif\sno\nCOLLATE\sclause\sexists\sin\sthe\soriginal\sSQL. -D 2021-12-14T20:13:28.303 +C Simplify\sthe\sgeneration\sof\sthe\ssqlite3_index_info\sobject\sduring\squery\splanning\nfor\svirtual\stables. +D 2021-12-15T20:48:15.594 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,10 +638,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c c69fed81e5dfd38e261e9af8c3faba133434b233757b0b2814db71eba86a0a62 -F src/whereInt.h e83f7ba73db5b1b2685118fad67d178fbe04751a25419f0f6ff73e58b4807325 +F src/where.c 8696f664dceaa7bab9c18212633b1d7d61063ee8c5066b49514b148946a4c467 +F src/whereInt.h 91865afa4a3540bb3bd643619acc56fbceff7defeb8f249b8e157fd5325d88be F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 -F src/whereexpr.c 791544603b254cf11f8e84e3b50b0863c57322e9f213b828680f658e232ebc57 +F src/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3 F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a2e50712fca9dff1b8d19631f792270c82da3c8696a5d9890cf0d1e13e950d60 -R 1e0532988fdf8f21a62bc70005049044 +P 5c3d398d20b86a1558720e995eddf11403aec2d160590571fa9525fe8f6efff9 +R 508a1ec856c9c59ad14d9d50f3ec0f6a U drh -Z 0d6fc2fca37175245191cba6d8527f4e +Z 7cfa744adc9adca884cde06b49136ec0 diff --git a/manifest.uuid b/manifest.uuid index 17670695af..b41eacb4bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c3d398d20b86a1558720e995eddf11403aec2d160590571fa9525fe8f6efff9 \ No newline at end of file +241dc0428a6e0238c57e2449e98ea60047e777e29c83a4ebe6da16f7cba40e19 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 33e0e43a4c..c7a9b856aa 100644 --- a/src/where.c +++ b/src/where.c @@ -1113,14 +1113,19 @@ static sqlite3_index_info *allocateIndexInfo( int nOrderBy; sqlite3_index_info *pIdxInfo; u16 mNoOmit = 0; + const Table *pTab; assert( pSrc!=0 ); - assert( pSrc->pTab!=0 ); - assert( IsVirtual(pSrc->pTab) ); + pTab = pSrc->pTab; + assert( pTab!=0 ); + assert( IsVirtual(pTab) ); - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ + /* Find all WHERE clause constraints referring to this virtual table. + ** Mark each term with the TERM_OK flag. Set nTerm to the number of + ** terms found. + */ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + pTerm->wtFlags &= ~TERM_OK; if( pTerm->leftCursor != pSrc->iCursor ) continue; if( pTerm->prereqRight & mUnusable ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); @@ -1131,8 +1136,19 @@ static sqlite3_index_info *allocateIndexInfo( if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=(-1) ); + assert( pTerm->u.x.leftColumn>=XN_ROWID ); + assert( pTerm->u.x.leftColumnnCol ); + + /* tag-20191211-002: WHERE-clause constraints are not useful to the + ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the + ** equivalent restriction for ordinary tables. */ + if( (pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + ){ + continue; + } nTerm++; + pTerm->wtFlags |= TERM_OK; } /* If the ORDER BY clause contains only columns in the current @@ -1151,7 +1167,7 @@ static sqlite3_index_info *allocateIndexInfo( /* First case - a direct column references without a COLLATE operator */ if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){ - assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumnpTab->nCol ); + assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumnnCol ); continue; } @@ -1164,10 +1180,10 @@ static sqlite3_index_info *allocateIndexInfo( const char *zColl; /* The collating sequence name */ assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); - assert( pE2->iColumn>=XN_ROWID && pE2->iColumnpTab->nCol ); + assert( pE2->iColumn>=XN_ROWID && pE2->iColumnnCol ); pExpr->iColumn = pE2->iColumn; if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */ - zColl = sqlite3ColumnColl(&pSrc->pTab->aCol[pE2->iColumn]); + zColl = sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]); if( zColl==0 ) zColl = sqlite3StrBINARY; if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; } @@ -1201,26 +1217,7 @@ static sqlite3_index_info *allocateIndexInfo( pHidden->pParse = pParse; for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ u16 op; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - - /* tag-20191211-002: WHERE-clause constraints are not useful to the - ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the - ** equivalent restriction for ordinary tables. */ - if( (pSrc->fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - continue; - } - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=(-1) ); + if( (pTerm->wtFlags & TERM_OK)==0 ) continue; pIdxCons[j].iColumn = pTerm->u.x.leftColumn; pIdxCons[j].iTermOffset = i; op = pTerm->eOperator & WO_ALL; @@ -1257,6 +1254,7 @@ static sqlite3_index_info *allocateIndexInfo( j++; } + assert( j==nTerm ); pIdxInfo->nConstraint = j; for(i=0; ia[i].pExpr; diff --git a/src/whereInt.h b/src/whereInt.h index 8051b78a02..a97b4afc69 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -270,7 +270,7 @@ struct WhereTerm { #define TERM_COPIED 0x0008 /* Has a child */ #define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */ #define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */ -#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */ +#define TERM_OK 0x0040 /* Used during OR-clause processing */ #define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */ #define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */ #define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */ diff --git a/src/whereexpr.c b/src/whereexpr.c index 5a3fbe2d7f..f0660a990e 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -796,7 +796,7 @@ static void exprAnalyzeOrTerm( pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); - pOrTerm->wtFlags &= ~TERM_OR_OK; + pOrTerm->wtFlags &= ~TERM_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ @@ -837,7 +837,7 @@ static void exprAnalyzeOrTerm( assert( pOrTerm->eOperator & WO_EQ ); assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); if( pOrTerm->leftCursor!=iCursor ){ - pOrTerm->wtFlags &= ~TERM_OR_OK; + pOrTerm->wtFlags &= ~TERM_OK; }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1) )){ @@ -853,7 +853,7 @@ static void exprAnalyzeOrTerm( if( affRight!=0 && affRight!=affLeft ){ okToChngToIN = 0; }else{ - pOrTerm->wtFlags |= TERM_OR_OK; + pOrTerm->wtFlags |= TERM_OK; } } } @@ -870,7 +870,7 @@ static void exprAnalyzeOrTerm( Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; + if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); assert( pOrTerm->leftCursor==iCursor ); From e3e2565daa2d7f6c325b91304919b5b5b3effce4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 13:29:28 +0000 Subject: [PATCH 060/148] Add more tests for OOM conditions in the CLI. FossilOrigin-Name: b6fa402d159b2475a7b99ef6a5180d7bf800f90afe28cea726d346d071405045 --- manifest | 12 +++--- manifest.uuid | 2 +- src/shell.c.in | 112 +++++++++++++++++++++++++++++++------------------ 3 files changed, 78 insertions(+), 48 deletions(-) diff --git a/manifest b/manifest index 9ffb0be7d0..e2a8249a6d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\sgeneration\sof\sthe\ssqlite3_index_info\sobject\sduring\squery\splanning\nfor\svirtual\stables. -D 2021-12-15T20:48:15.594 +C Add\smore\stests\sfor\sOOM\sconditions\sin\sthe\sCLI. +D 2021-12-16T13:29:28.610 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 239bee1085d94964f02582b0714dc3fc85cfc16e27e95813e4dbc24bb215a7e0 +F src/shell.c.in 487402a1242eda123a7765415765c2ba5fd80b251af968ac5cd753a21361dca7 F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5c3d398d20b86a1558720e995eddf11403aec2d160590571fa9525fe8f6efff9 -R 508a1ec856c9c59ad14d9d50f3ec0f6a +P 241dc0428a6e0238c57e2449e98ea60047e777e29c83a4ebe6da16f7cba40e19 +R c242be18b9914b844987d57ba93b7d7b U drh -Z 7cfa744adc9adca884cde06b49136ec0 +Z 275dad0e920745aee275fd4bee05334a diff --git a/manifest.uuid b/manifest.uuid index b41eacb4bb..47e19b4667 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -241dc0428a6e0238c57e2449e98ea60047e777e29c83a4ebe6da16f7cba40e19 \ No newline at end of file +b6fa402d159b2475a7b99ef6a5180d7bf800f90afe28cea726d346d071405045 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 3262f98c12..7cabf94ec2 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -487,6 +487,13 @@ static void shell_out_of_memory(void){ exit(1); } +/* Check a pointer to see if it is NULL. If it is NULL, exit with an +** out-of-memory error. +*/ +static void shell_check_oom(void *p){ + if( p==0 ) shell_out_of_memory(); +} + #ifdef SQLITE_DEBUG /* This routine is called when a simulated OOM occurs. It is broken ** out as a separate routine to make it easy to set a breakpoint on @@ -685,7 +692,7 @@ static char *local_getline(char *zLine, FILE *in){ if( n+100>nLine ){ nLine = nLine*2 + 100; zLine = realloc(zLine, nLine); - if( zLine==0 ) shell_out_of_memory(); + shell_check_oom(zLine); } if( fgets(&zLine[n], nLine - n, in)==0 ){ if( n==0 ){ @@ -712,7 +719,7 @@ static char *local_getline(char *zLine, FILE *in){ int nTrans = strlen30(zTrans)+1; if( nTrans>nLine ){ zLine = realloc(zLine, nTrans); - if( zLine==0 ) shell_out_of_memory(); + shell_check_oom(zLine); } memcpy(zLine, zTrans, nTrans); sqlite3_free(zTrans); @@ -859,7 +866,7 @@ static void appendText(ShellText *p, char const *zAppend, char quote){ if( p->z==0 || p->n+len>=p->nAlloc ){ p->nAlloc = p->nAlloc*2 + len + 20; p->z = realloc(p->z, p->nAlloc); - if( p->z==0 ) shell_out_of_memory(); + shell_check_oom(p->z); } if( quote ){ @@ -914,6 +921,7 @@ static char *shellFakeSchema( zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", zSchema ? zSchema : "main", zName); + shell_check_oom(zSql); sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); initText(&s); @@ -1775,6 +1783,7 @@ static void output_csv(ShellState *p, const char *z, int bSep){ } if( i==0 || strstr(z, p->colSeparator)!=0 ){ char *zQuoted = sqlite3_mprintf("\"%w\"", z); + shell_check_oom(zQuoted); utf8_printf(out, "%s", zQuoted); sqlite3_free(zQuoted); }else{ @@ -1949,7 +1958,7 @@ static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); } pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); - if( pNew==0 ) shell_out_of_memory(); + shell_check_oom(pNew); pNew->iEqpId = iEqpId; pNew->iParentId = p2; memcpy(pNew->zText, zText, nText+1); @@ -2170,6 +2179,7 @@ static int shell_callback( break; } z = sqlite3_mprintf("%s", azArg[0]); + shell_check_oom(z); j = 0; for(i=0; IsSpace(z[i]); i++){} for(; (c = z[i])!=0; i++){ @@ -2301,6 +2311,7 @@ static int shell_callback( if( i>0 ) raw_printf(p->out, ","); if( quoteChar(azCol[i]) ){ char *z = sqlite3_mprintf("\"%w\"", azCol[i]); + shell_check_oom(z); utf8_printf(p->out, "%s", z); sqlite3_free(z); }else{ @@ -2546,7 +2557,7 @@ static void set_table_name(ShellState *p, const char *zName){ n = strlen30(zName); if( cQuote ) n += n+2; z = p->zDestTable = malloc( n+1 ); - if( z==0 ) shell_out_of_memory(); + shell_check_oom(z); n = 0; if( cQuote ) z[n++] = cQuote; for(i=0; zName[i]; i++){ @@ -2618,9 +2629,11 @@ static char *save_err_msg( const char *zWhen, /* Qualifier (format) wrapper */ int rc /* Error code returned from API */ ){ - if( zWhen==0 ) - zWhen = "%s (%d)"; - return sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc); + char *zErr; + if( zWhen==0 ) zWhen = "%s (%d)"; + zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc); + shell_check_oom(zErr); + return zErr; } #ifdef __linux__ @@ -2968,9 +2981,9 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ } nAlloc += 100; p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); - if( p->aiIndent==0 ) shell_out_of_memory(); + shell_check_oom(p->aiIndent); abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); - if( abYield==0 ) shell_out_of_memory(); + shell_check_oom(abYield); } abYield[iOp] = str_in_array(zOp, azYield); p->aiIndent[iOp] = 0; @@ -3179,7 +3192,7 @@ static void exec_prepared_stmt_columnar( nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); - if( azData==0 ) shell_out_of_memory(); + shell_check_oom(azData); for(i=0; i= nAlloc ){ nAlloc *= 2; azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); - if( azData==0 ) shell_out_of_memory(); + shell_check_oom(azData); } nRow++; for(i=0; ip->nWidth ){ p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int)); - if( p->colWidth==0 ) shell_out_of_memory(); + shell_check_oom(p->colWidth); for(i=p->nWidth; icolWidth[i] = 0; p->nWidth = nColumn; p->actualWidth = &p->colWidth[nColumn]; @@ -3588,6 +3601,7 @@ static int shell_exec( sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); } zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); + shell_check_oom(zEQP); rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); if( rc==SQLITE_OK ){ while( sqlite3_step(pExplain)==SQLITE_ROW ){ @@ -3605,6 +3619,7 @@ static int shell_exec( if( pArg->autoEQP>=AUTOEQP_full ){ /* Also do an EXPLAIN for ".eqp full" mode */ zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); + shell_check_oom(zEQP); rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); if( rc==SQLITE_OK ){ pArg->cMode = MODE_Explain; @@ -3717,6 +3732,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){ int rc; zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); + shell_check_oom(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ) return 0; @@ -3724,9 +3740,10 @@ static char **tableColumnList(ShellState *p, const char *zTab){ if( nCol>=nAlloc-2 ){ nAlloc = nAlloc*2 + nCol + 10; azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); - if( azCol==0 ) shell_out_of_memory(); + shell_check_oom(azCol); } azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + shell_check_oom(azCol[nCol]); if( sqlite3_column_int(pStmt, 5) ){ nPK++; if( nPK==1 @@ -3760,6 +3777,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){ */ zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" " WHERE origin='pk'", zTab); + shell_check_oom(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ @@ -3851,6 +3869,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){ "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)" "VALUES('table','%q','%q',0,'%q');", zTable, zTable, zSql); + shell_check_oom(zIns); utf8_printf(p->out, "%s\n", zIns); sqlite3_free(zIns); return 0; @@ -4252,6 +4271,7 @@ static int showHelp(FILE *out, const char *zPattern){ }else{ /* Look for commands that for which zPattern is an exact prefix */ zPat = sqlite3_mprintf(".%s*", zPattern); + shell_check_oom(zPat); for(i=0; i65536 || (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"); - goto readHexDb_error; - } + shell_check_oom(a); memset(a, 0, n); if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){ utf8_printf(stderr, "invalid pagesize\n"); @@ -4773,6 +4791,7 @@ static void open_db(ShellState *p, int openFlags){ if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename); + shell_check_oom(zSql); sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } @@ -4830,6 +4849,7 @@ static char *readline_completion_generator(const char *text, int state){ sqlite3_finalize(pStmt); zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" " FROM completion(%Q) ORDER BY 1", text); + shell_check_oom(zSql); sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } @@ -4867,6 +4887,7 @@ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" " FROM completion(%Q,%Q) ORDER BY 1", &zLine[iStart], zLine); + shell_check_oom(zSql); sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); sqlite3_free(zSql); sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ @@ -5108,7 +5129,7 @@ static void import_append_char(ImportCtx *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; p->z = sqlite3_realloc64(p->z, p->nAlloc); - if( p->z==0 ) shell_out_of_memory(); + shell_check_oom(p->z); } p->z[p->n++] = (char)c; } @@ -5260,6 +5281,7 @@ static void tryToCloneData( const int spinRate = 10000; zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ utf8_printf(stderr, "Error %d: %s on [%s]\n", @@ -5269,7 +5291,7 @@ static void tryToCloneData( } n = sqlite3_column_count(pQuery); zInsert = sqlite3_malloc64(200 + nTable + n*3); - if( zInsert==0 ) shell_out_of_memory(); + shell_check_oom(zInsert); sqlite3_snprintf(200+nTable,zInsert, "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); i = strlen30(zInsert); @@ -5332,6 +5354,7 @@ static void tryToCloneData( sqlite3_free(zQuery); zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;", zTable); + shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable); @@ -5368,6 +5391,7 @@ static void tryToCloneSchema( zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" " WHERE %s", zWhere); + shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ utf8_printf(stderr, "Error: (%d) %s on [%s]\n", @@ -5395,6 +5419,7 @@ static void tryToCloneSchema( sqlite3_free(zQuery); zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" " WHERE %s ORDER BY rowid DESC", zWhere); + shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ utf8_printf(stderr, "Error: (%d) %s on [%s]\n", @@ -5789,9 +5814,7 @@ static void newTempFile(ShellState *p, const char *zSuffix){ }else{ p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); } - if( p->zTempFile==0 ){ - shell_out_of_memory(); - } + shell_check_oom(p->zTempFile); } @@ -7864,7 +7887,7 @@ static int do_meta_command(char *zLine, ShellState *p){ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1); const char *zFile = (const char*)sqlite3_column_text(pStmt,2); azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*)); - if( azName==0 ){ shell_out_of_memory(); /* Does not return */ } + shell_check_oom(azName); azName[nName*2] = strdup(zSchema); azName[nName*2+1] = strdup(zFile); nName++; @@ -9076,7 +9099,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else if( zFile==0 && eMode!='e' && eMode!='x' ){ zFile = sqlite3_mprintf("%s", z); - if( zFile[0]=='|' ){ + if( zFile && zFile[0]=='|' ){ while( i+1outCount = 2; }else{ @@ -9116,6 +9141,7 @@ static int do_meta_command(char *zLine, ShellState *p){ zFile = sqlite3_mprintf("%s", p->zTempFile); } #endif /* SQLITE_NOHAVE_SYSTEM */ + shell_check_oom(zFile); if( zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN raw_printf(stderr, "Error: pipes are not supported in this OS\n"); @@ -9212,7 +9238,7 @@ static int do_meta_command(char *zLine, ShellState *p){ zSql = sqlite3_mprintf( "REPLACE INTO temp.sqlite_parameters(key,value)" "VALUES(%Q,%s);", zKey, zValue); - if( zSql==0 ) shell_out_of_memory(); + shell_check_oom(zSql); pStmt = 0; rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); @@ -9222,7 +9248,7 @@ static int do_meta_command(char *zLine, ShellState *p){ zSql = sqlite3_mprintf( "REPLACE INTO temp.sqlite_parameters(key,value)" "VALUES(%Q,%Q);", zKey, zValue); - if( zSql==0 ) shell_out_of_memory(); + shell_check_oom(zSql); rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rx!=SQLITE_OK ){ @@ -9243,7 +9269,7 @@ static int do_meta_command(char *zLine, ShellState *p){ if( nArg==3 && strcmp(azArg[1],"unset")==0 ){ char *zSql = sqlite3_mprintf( "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]); - if( zSql==0 ) shell_out_of_memory(); + shell_check_oom(zSql); sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); }else @@ -9469,6 +9495,7 @@ static int do_meta_command(char *zLine, ShellState *p){ " rootpage integer,\n" " sql text\n" ")", zName); + shell_check_oom(new_argv[0]); new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; @@ -9520,6 +9547,7 @@ static int do_meta_command(char *zLine, ShellState *p){ appendText(&sSelect, ") WHERE ", 0); if( zName ){ char *zQarg = sqlite3_mprintf("%Q", zName); + shell_check_oom(zQarg); int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || strchr(zName, '[') != 0; if( strchr(zName, '.') ){ @@ -9684,7 +9712,8 @@ static int do_meta_command(char *zLine, ShellState *p){ exit(1); } for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); + char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); + shell_check_oom(x); } pSession->nFilter = ii-1; } @@ -9756,6 +9785,7 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3session_table_filter(pSession->p, session_filter, pSession); pAuxDb->nSession++; pSession->zName = sqlite3_mprintf("%s", zName); + shell_check_oom(pSession->zName); }else /* If no command name matches, show a syntax error */ session_syntax_error: @@ -9851,9 +9881,7 @@ static int do_meta_command(char *zLine, ShellState *p){ k = 0; if( bVerbose>0 ){ - char *zQuote = sqlite3_mprintf("%q", zSql); printf("%d: %s %s\n", tno, zOp, zSql); - sqlite3_free(zQuote); } if( strcmp(zOp,"memo")==0 ){ utf8_printf(p->out, "%s\n", zSql); @@ -10011,6 +10039,7 @@ static int do_meta_command(char *zLine, ShellState *p){ " FROM [sha3sum$query]", sSql.z, iSize); } + shell_check_oom(zSql); freeText(&sQuery); freeText(&sSql); if( bDebug ){ @@ -10034,11 +10063,11 @@ static int do_meta_command(char *zLine, ShellState *p){ goto meta_command_exit; } zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); - for(i=2; i>1)+nLine+100; zSql = realloc(zSql, nAlloc); - if( zSql==0 ) shell_out_of_memory(); + shell_check_oom(zSql); } if( nSql==0 ){ int i; @@ -11080,6 +11109,7 @@ static void process_sqliterc( return; } zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + shell_check_oom(zBuf); sqliterc = zBuf; } p->in = fopen(sqliterc,"rb"); @@ -11321,16 +11351,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ #if !SQLITE_SHELL_IS_UTF8 sqlite3_initialize(); argvToFree = malloc(sizeof(argv[0])*argc*2); + shell_check_oom(argvToFree); argcToFree = argc; argv = argvToFree + argc; - if( argv==0 ) shell_out_of_memory(); for(i=0; i Date: Thu, 16 Dec 2021 13:56:04 +0000 Subject: [PATCH 061/148] Fix a potential NULL pointer dereference in the CLI logic for printing the schema of virtual tables. FossilOrigin-Name: fe44ebf6be47e1c7f2458297669dbd2b882a31595ea8759f7e8bb024ffc44d11 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e2a8249a6d..5af23d213c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smore\stests\sfor\sOOM\sconditions\sin\sthe\sCLI. -D 2021-12-16T13:29:28.610 +C Fix\sa\spotential\sNULL\spointer\sdereference\sin\sthe\sCLI\slogic\sfor\sprinting\sthe\nschema\sof\svirtual\stables. +D 2021-12-16T13:56:04.308 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 487402a1242eda123a7765415765c2ba5fd80b251af968ac5cd753a21361dca7 +F src/shell.c.in ee436c66e767f9ade478d6026dc96ed010ce9984d6bb0a05ee7295d4a6a5d8aa F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 241dc0428a6e0238c57e2449e98ea60047e777e29c83a4ebe6da16f7cba40e19 -R c242be18b9914b844987d57ba93b7d7b +P b6fa402d159b2475a7b99ef6a5180d7bf800f90afe28cea726d346d071405045 +R deeacfaf4293a19f1f0da5da107a5410 U drh -Z 275dad0e920745aee275fd4bee05334a +Z c97827e8de3c5a52ec9e189c6ecc8d7b diff --git a/manifest.uuid b/manifest.uuid index 47e19b4667..ac4f40b380 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6fa402d159b2475a7b99ef6a5180d7bf800f90afe28cea726d346d071405045 \ No newline at end of file +fe44ebf6be47e1c7f2458297669dbd2b882a31595ea8759f7e8bb024ffc44d11 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 7cabf94ec2..d78a3583f0 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -961,9 +961,11 @@ static void shellModuleSchema( int nVal, sqlite3_value **apVal ){ - const char *zName = (const char*)sqlite3_value_text(apVal[0]); - char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); + const char *zName; + char *zFake; UNUSED_PARAMETER(nVal); + zName = (const char*)sqlite3_value_text(apVal[0]); + zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0; if( zFake ){ sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), -1, sqlite3_free); From e0adf60241ea26b309915400c029922e5a5ae9e1 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 14:26:16 +0000 Subject: [PATCH 062/148] Improved robustness against OOM in the expert extension. FossilOrigin-Name: e732c429bafeffaf7e0f458213089c073c262a39eabb41b291e5006078ca7f98 --- ext/expert/sqlite3expert.c | 33 +++++++++++++++++++++++++-------- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 3 ++- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/ext/expert/sqlite3expert.c b/ext/expert/sqlite3expert.c index f7a17e6ddc..f29b8a9e0b 100644 --- a/ext/expert/sqlite3expert.c +++ b/ext/expert/sqlite3expert.c @@ -697,17 +697,25 @@ static int idxGetTableInfo( ){ sqlite3_stmt *p1 = 0; int nCol = 0; - int nTab = STRLEN(zTab); - int nByte = sizeof(IdxTable) + nTab + 1; + int nTab; + int nByte; IdxTable *pNew = 0; int rc, rc2; char *pCsr = 0; int nPk = 0; + *ppOut = 0; + if( zTab==0 ) return SQLITE_ERROR; + nTab = STRLEN(zTab); + nByte = sizeof(IdxTable) + nTab + 1; rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ const char *zCol = (const char*)sqlite3_column_text(p1, 1); const char *zColSeq = 0; + if( zCol==0 ){ + rc = SQLITE_ERROR; + break; + } nByte += 1 + STRLEN(zCol); rc = sqlite3_table_column_metadata( db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 @@ -734,7 +742,9 @@ static int idxGetTableInfo( while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ const char *zCol = (const char*)sqlite3_column_text(p1, 1); const char *zColSeq = 0; - int nCopy = STRLEN(zCol) + 1; + int nCopy; + if( zCol==0 ) continue; + nCopy = STRLEN(zCol) + 1; pNew->aCol[nCol].zName = pCsr; pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1); memcpy(pCsr, zCol, nCopy); @@ -886,6 +896,7 @@ static int idxFindCompatible( IdxConstraint *pT = pTail; sqlite3_stmt *pInfo = 0; const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1); + if( zIdx==0 ) continue; /* Zero the IdxConstraint.bFlag values in the pEq list */ for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0; @@ -1297,6 +1308,7 @@ static int idxProcessOneTrigger( rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){ const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0); + if( zCreate==0 ) continue; rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr); } idxFinalize(&rc, pSelect); @@ -1399,8 +1411,9 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){ const char *zName = (const char*)sqlite3_column_text(pSchema, 1); const char *zSql = (const char*)sqlite3_column_text(pSchema, 2); + if( zType==0 || zName==0 ) continue; if( zType[0]=='v' || zType[1]=='r' ){ - rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); + if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); }else{ IdxTable *pTab; rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg); @@ -1537,6 +1550,7 @@ static void idxRemFunc( case SQLITE_BLOB: case SQLITE_TEXT: { int nByte = sqlite3_value_bytes(argv[1]); + const void *pData = 0; if( nByte>pSlot->nByte ){ char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); if( zNew==0 ){ @@ -1548,9 +1562,11 @@ static void idxRemFunc( } pSlot->n = nByte; if( pSlot->eType==SQLITE_BLOB ){ - memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte); + pData = sqlite3_value_blob(argv[1]); + if( pData ) memcpy(pSlot->z, pData, nByte); }else{ - memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte); + pData = sqlite3_value_text(argv[1]); + memcpy(pSlot->z, pData, nByte); } break; } @@ -1761,6 +1777,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){ i64 iRowid = sqlite3_column_int64(pAllIndex, 0); const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1); const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2); + if( zTab==0 || zIdx==0 ) continue; if( p->iSample<100 && iPrev!=iRowid ){ samplectx.target = (double)p->iSample / 100.0; samplectx.iTarget = p->iSample; @@ -1827,14 +1844,14 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){ /* Copy the entire schema of database [db] into [dbm]. */ if( rc==SQLITE_OK ){ - sqlite3_stmt *pSql; + sqlite3_stmt *pSql = 0; rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" " AND sql NOT LIKE 'CREATE VIRTUAL %%'" ); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ const char *zSql = (const char*)sqlite3_column_text(pSql, 0); - rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); + if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); } idxFinalize(&rc, pSql); } diff --git a/manifest b/manifest index 5af23d213c..77d78d2601 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\spotential\sNULL\spointer\sdereference\sin\sthe\sCLI\slogic\sfor\sprinting\sthe\nschema\sof\svirtual\stables. -D 2021-12-16T13:56:04.308 +C Improved\srobustness\sagainst\sOOM\sin\sthe\sexpert\sextension. +D 2021-12-16T14:26:16.891 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -51,7 +51,7 @@ F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a4980828 F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 F ext/expert/expert1.test 3c642a4e7bbb14f21ddab595436fb465a4733f47a0fe5b2855e1d5ff900ef08e -F ext/expert/sqlite3expert.c f09943e849d603a0c001471e229b2522bae7a70a77a5e28b16429ca2bb4240dc +F ext/expert/sqlite3expert.c 6ca30d73b9ed75bd56d6e0d7f2c962d2affaa72c505458619d0ff5d9cdfac204 F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in ee436c66e767f9ade478d6026dc96ed010ce9984d6bb0a05ee7295d4a6a5d8aa +F src/shell.c.in e1c8a1ce01c8d70e530919978b28419ab68c9d643a3de39049fa2ed0a8a655e5 F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b6fa402d159b2475a7b99ef6a5180d7bf800f90afe28cea726d346d071405045 -R deeacfaf4293a19f1f0da5da107a5410 +P fe44ebf6be47e1c7f2458297669dbd2b882a31595ea8759f7e8bb024ffc44d11 +R 9238339fb3e82f00e85db14fa52ea256 U drh -Z c97827e8de3c5a52ec9e189c6ecc8d7b +Z 238125be5e0c8f6d8b18a0df5a618e44 diff --git a/manifest.uuid b/manifest.uuid index ac4f40b380..29e1991c94 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe44ebf6be47e1c7f2458297669dbd2b882a31595ea8759f7e8bb024ffc44d11 \ No newline at end of file +e732c429bafeffaf7e0f458213089c073c262a39eabb41b291e5006078ca7f98 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index d78a3583f0..f87c15db05 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3519,7 +3519,7 @@ static int expertDotCommand( if( rc==SQLITE_OK ){ pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); if( pState->expert.pExpert==0 ){ - raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); + raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory"); rc = SQLITE_ERROR; }else{ sqlite3_expert_config( @@ -3527,6 +3527,7 @@ static int expertDotCommand( ); } } + sqlite3_free(zErr); return rc; } From b71a485386e339dc3a5079daedb4caaeacbbb85e Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 14:36:36 +0000 Subject: [PATCH 063/148] Fix harmless compiler warning in the new Bloom filter logic. FossilOrigin-Name: 9406d95d3fbaf0d8e65623adb790845f78a7456fb32aafd7fa4f74eda2f2dacc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 77d78d2601..e435a30bbf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\srobustness\sagainst\sOOM\sin\sthe\sexpert\sextension. -D 2021-12-16T14:26:16.891 +C Fix\sharmless\scompiler\swarning\sin\sthe\snew\sBloom\sfilter\slogic. +D 2021-12-16T14:36:36.423 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 8696f664dceaa7bab9c18212633b1d7d61063ee8c5066b49514b148946a4c467 +F src/where.c d47e14778162f00b732a74fc0b45a92be1b4d5cda3d11876901a3d54a367f5ec F src/whereInt.h 91865afa4a3540bb3bd643619acc56fbceff7defeb8f249b8e157fd5325d88be F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fe44ebf6be47e1c7f2458297669dbd2b882a31595ea8759f7e8bb024ffc44d11 -R 9238339fb3e82f00e85db14fa52ea256 +P e732c429bafeffaf7e0f458213089c073c262a39eabb41b291e5006078ca7f98 +R 720cf5f28e762396fb457a8dae05b590 U drh -Z 238125be5e0c8f6d8b18a0df5a618e44 +Z a0a1b2f028aa9dcc9dce157f74e8589a diff --git a/manifest.uuid b/manifest.uuid index 29e1991c94..bd1766c52f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e732c429bafeffaf7e0f458213089c073c262a39eabb41b291e5006078ca7f98 \ No newline at end of file +9406d95d3fbaf0d8e65623adb790845f78a7456fb32aafd7fa4f74eda2f2dacc \ No newline at end of file diff --git a/src/where.c b/src/where.c index c7a9b856aa..5210299e7c 100644 --- a/src/where.c +++ b/src/where.c @@ -5037,7 +5037,7 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( nSearch = pWInfo->a[0].pWLoop->nOut; for(i=1; inLevel; i++){ WhereLoop *pLoop = pWInfo->a[i].pWLoop; - const int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); + const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); if( (pLoop->wsFlags & reqFlags)==reqFlags /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) From 61fd4b9c3da59d28fc1ecc4f34856e333b3eb07b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 14:59:25 +0000 Subject: [PATCH 064/148] Fix a memory leak in the CLI that occurs after an error in the ".open" command. FossilOrigin-Name: d156123885abe6bf23c3530de99be257f82ef85b89fbe019568ac60fa1ed5bb7 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 13 ++++++++++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e435a30bbf..c5d96cdc93 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning\sin\sthe\snew\sBloom\sfilter\slogic. -D 2021-12-16T14:36:36.423 +C Fix\sa\smemory\sleak\sin\sthe\sCLI\sthat\soccurs\safter\san\serror\sin\sthe\s".open"\scommand. +D 2021-12-16T14:59:25.008 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in e1c8a1ce01c8d70e530919978b28419ab68c9d643a3de39049fa2ed0a8a655e5 +F src/shell.c.in 0c68cd37963afef2086fddc61a282df448d911fdf7d960817eaebe4e0fa4b38a F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e732c429bafeffaf7e0f458213089c073c262a39eabb41b291e5006078ca7f98 -R 720cf5f28e762396fb457a8dae05b590 +P 9406d95d3fbaf0d8e65623adb790845f78a7456fb32aafd7fa4f74eda2f2dacc +R e0df8ce6fe4f8339b59c88c348589e55 U drh -Z a0a1b2f028aa9dcc9dce157f74e8589a +Z 6900fb872cf581b1501f7decf3624ec2 diff --git a/manifest.uuid b/manifest.uuid index bd1766c52f..74e74828c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9406d95d3fbaf0d8e65623adb790845f78a7456fb32aafd7fa4f74eda2f2dacc \ No newline at end of file +d156123885abe6bf23c3530de99be257f82ef85b89fbe019568ac60fa1ed5bb7 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index f87c15db05..f67d79e327 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8987,6 +8987,7 @@ static int do_meta_command(char *zLine, ShellState *p){ #endif /* SQLITE_DEBUG */ if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ + const char *zFN = 0; /* Pointer to constant filename */ char *zNewFilename = 0; /* Name of the database file to open */ int iName = 1; /* Index in azArg[] of the filename */ int newFlag = 0; /* True to delete file before opening */ @@ -9019,12 +9020,12 @@ static int do_meta_command(char *zLine, ShellState *p){ utf8_printf(stderr, "unknown option: %s\n", z); rc = 1; goto meta_command_exit; - }else if( zNewFilename ){ + }else if( zFN ){ utf8_printf(stderr, "extra argument: \"%s\"\n", z); rc = 1; goto meta_command_exit; }else{ - zNewFilename = sqlite3_mprintf("%s", z); + zFN = z; } } @@ -9040,7 +9041,7 @@ static int do_meta_command(char *zLine, ShellState *p){ p->szMax = 0; /* If a filename is specified, try to open it first */ - if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ + if( zFN || p->openMode==SHELL_OPEN_HEXDB ){ if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); if( p->bSafeMode && p->openMode!=SHELL_OPEN_HEXDB @@ -9049,6 +9050,12 @@ static int do_meta_command(char *zLine, ShellState *p){ ){ failIfSafeMode(p, "cannot open disk-based database files in safe mode"); } + if( zFN ){ + zNewFilename = sqlite3_mprintf("%s", zFN); + shell_check_oom(zNewFilename); + }else{ + zNewFilename = 0; + } p->pAuxDb->zDbFilename = zNewFilename; open_db(p, OPEN_DB_KEEPALIVE); if( p->db==0 ){ From 2999068d2c468d3eca8885e33d5afc17f4d564b7 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 16 Dec 2021 15:29:49 +0000 Subject: [PATCH 065/148] Fix fts3 and fts4 so that they can still be used even if the other is dropped by a call to sqlite3_drop_modules(). FossilOrigin-Name: a0a8d6c9f0e91996003626e4f80dfac278e3c5bddd9ace5d442061e6c95e49dc --- ext/fts3/fts3.c | 45 ++++++++++++++++++++++------------- ext/fts3/fts3Int.h | 2 +- ext/fts3/fts3_tokenize_vtab.c | 6 +++-- manifest | 21 ++++++++-------- manifest.uuid | 2 +- src/test1.c | 2 +- test/fts3dropmod.test | 44 ++++++++++++++++++++++++++++++++++ 7 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 test/fts3dropmod.test diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index d729454634..9a341a89a0 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -308,6 +308,12 @@ SQLITE_EXTENSION_INIT1 #endif +typedef struct Fts3HashWrapper Fts3HashWrapper; +struct Fts3HashWrapper { + Fts3Hash hash; /* Hash table */ + int nRef; /* Number of pointers to this object */ +}; + static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( @@ -1172,7 +1178,7 @@ static int fts3InitVtab( sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ char **pzErr /* Write any error message here */ ){ - Fts3Hash *pHash = (Fts3Hash *)pAux; + Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash; Fts3Table *p = 0; /* Pointer to allocated vtab */ int rc = SQLITE_OK; /* Return code */ int i; /* Iterator variable */ @@ -4007,9 +4013,12 @@ static const sqlite3_module fts3Module = { ** allocated for the tokenizer hash table. */ static void hashDestroy(void *p){ - Fts3Hash *pHash = (Fts3Hash *)p; - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); + Fts3HashWrapper *pHash = (Fts3HashWrapper *)p; + pHash->nRef--; + if( pHash->nRef<=0 ){ + sqlite3Fts3HashClear(&pHash->hash); + sqlite3_free(pHash); + } } /* @@ -4039,7 +4048,7 @@ void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); */ int sqlite3Fts3Init(sqlite3 *db){ int rc = SQLITE_OK; - Fts3Hash *pHash = 0; + Fts3HashWrapper *pHash = 0; const sqlite3_tokenizer_module *pSimple = 0; const sqlite3_tokenizer_module *pPorter = 0; #ifndef SQLITE_DISABLE_FTS3_UNICODE @@ -4067,23 +4076,24 @@ int sqlite3Fts3Init(sqlite3 *db){ sqlite3Fts3PorterTokenizerModule(&pPorter); /* Allocate and initialize the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(Fts3Hash)); + pHash = sqlite3_malloc(sizeof(Fts3HashWrapper)); if( !pHash ){ rc = SQLITE_NOMEM; }else{ - sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); + sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1); + pHash->nRef = 0; } /* Load the built-in tokenizers into the hash table */ if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) + if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple) + || sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter) #ifndef SQLITE_DISABLE_FTS3_UNICODE - || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) + || sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode) #endif #ifdef SQLITE_ENABLE_ICU - || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) + || (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu)) #endif ){ rc = SQLITE_NOMEM; @@ -4092,7 +4102,7 @@ int sqlite3Fts3Init(sqlite3 *db){ #ifdef SQLITE_TEST if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db, pHash); + rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash); } #endif @@ -4101,23 +4111,26 @@ int sqlite3Fts3Init(sqlite3 *db){ ** module with sqlite. */ if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) + && SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer")) && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) ){ + pHash->nRef++; rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); if( rc==SQLITE_OK ){ + pHash->nRef++; rc = sqlite3_create_module_v2( - db, "fts4", &fts3Module, (void *)pHash, 0 + db, "fts4", &fts3Module, (void *)pHash, hashDestroy ); } if( rc==SQLITE_OK ){ - rc = sqlite3Fts3InitTok(db, (void *)pHash); + pHash->nRef++; + rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy); } return rc; } @@ -4126,7 +4139,7 @@ int sqlite3Fts3Init(sqlite3 *db){ /* An error has occurred. Delete the hash table and return the error code. */ assert( rc!=SQLITE_OK ); if( pHash ){ - sqlite3Fts3HashClear(pHash); + sqlite3Fts3HashClear(&pHash->hash); sqlite3_free(pHash); } return rc; diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 3a62ccc7a7..0626486edf 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -641,7 +641,7 @@ int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); /* fts3_tokenize_vtab.c */ -int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); +int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*)); /* fts3_unicode2.c (functions generated by parsing unicode text files) */ #ifndef SQLITE_DISABLE_FTS3_UNICODE diff --git a/ext/fts3/fts3_tokenize_vtab.c b/ext/fts3/fts3_tokenize_vtab.c index 8bd22230cc..65d7eef4c3 100644 --- a/ext/fts3/fts3_tokenize_vtab.c +++ b/ext/fts3/fts3_tokenize_vtab.c @@ -420,7 +420,7 @@ static int fts3tokRowidMethod( ** Register the fts3tok module with database connection db. Return SQLITE_OK ** if successful or an error code if sqlite3_create_module() fails. */ -int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ +int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){ static const sqlite3_module fts3tok_module = { 0, /* iVersion */ fts3tokConnectMethod, /* xCreate */ @@ -449,7 +449,9 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ }; int rc; /* Return code */ - rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); + rc = sqlite3_create_module_v2( + db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy + ); return rc; } diff --git a/manifest b/manifest index c5d96cdc93..5b9ccfd3e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\smemory\sleak\sin\sthe\sCLI\sthat\soccurs\safter\san\serror\sin\sthe\s".open"\scommand. -D 2021-12-16T14:59:25.008 +C Fix\sfts3\sand\sfts4\sso\sthat\sthey\scan\sstill\sbe\sused\seven\sif\sthe\sother\sis\sdropped\sby\sa\scall\sto\ssqlite3_drop_modules(). +D 2021-12-16T15:29:49.836 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -84,9 +84,9 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c da41de21622774b1cb8c3415e8d2a6961ad7c978ab534f2a54434f76a5c4dfbc +F ext/fts3/fts3.c f27e890395640be4938b9b554cad46fdf1e42e6bd7d64154bbac27d079d00f9e F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h cff59b8b13dafe9d59924a5d710f771ed8b121a55cccbc99b6e2a723fcde14dc +F ext/fts3/fts3Int.h dafdc371f9fbab175744b06cfe019d5f040cdfdbd11fea752f5dc28d45b04c05 F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f F ext/fts3/fts3_expr.c 903bfb9433109fffb10e910d7066c49cbf8eeae316adc93f0499c4da7dfc932a F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7 @@ -96,7 +96,7 @@ F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 F ext/fts3/fts3_snippet.c f9a8149173553113f3c495a503843e30028b5dc3723d0ca798c5ad6142e130e6 F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1 F ext/fts3/fts3_test.c d8d7b2734f894e8a489987447658e374cdd3a3bc8575c401decf1911cb7c6454 -F ext/fts3/fts3_tokenize_vtab.c 8d15b148e7d88a4280389a200b26e8d52abda4c4ec2e9a35e9d7a1fa50e5aa03 +F ext/fts3/fts3_tokenize_vtab.c a95feda3590f3c3e17672fe35b67ea6112471aeea4c07ef7744a6606b66549aa F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7 F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 @@ -561,7 +561,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6 -F src/test1.c d6c945a8bb211ed72ea515f0b9743caeaf38c66da6418a7b1dcf3764e1368bbb +F src/test1.c 37b323d74aef3156394478bd09dff855332077e537b37c9a7e455c03cb04da09 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -991,6 +991,7 @@ F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4 F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7 F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297 +F test/fts3dropmod.test 30e0e43011ccb5aa8920922b123480415d8504cc4192d7cf342a45dcabea54a7 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a @@ -1934,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9406d95d3fbaf0d8e65623adb790845f78a7456fb32aafd7fa4f74eda2f2dacc -R e0df8ce6fe4f8339b59c88c348589e55 -U drh -Z 6900fb872cf581b1501f7decf3624ec2 +P d156123885abe6bf23c3530de99be257f82ef85b89fbe019568ac60fa1ed5bb7 +R a5bbf409ca818885e606c4cbcf796195 +U dan +Z ded9a804bf5da97234a4d2625392c243 diff --git a/manifest.uuid b/manifest.uuid index 74e74828c8..be87a011d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d156123885abe6bf23c3530de99be257f82ef85b89fbe019568ac60fa1ed5bb7 \ No newline at end of file +a0a8d6c9f0e91996003626e4f80dfac278e3c5bddd9ace5d442061e6c95e49dc \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 6060290b98..8cdb7b285e 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1097,7 +1097,7 @@ static int SQLITE_TCLAPI test_drop_modules( ){ sqlite3 *db; - if( argc!=2 ){ + if( argc<2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); return TCL_ERROR; diff --git a/test/fts3dropmod.test b/test/fts3dropmod.test new file mode 100644 index 0000000000..3739c31a67 --- /dev/null +++ b/test/fts3dropmod.test @@ -0,0 +1,44 @@ +# 2021 December 16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# This file implements regression tests for SQLite library. The +# focus of this script is testing the FTS3 module. +# +# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $ +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix fts3dropmod + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +sqlite3_drop_modules db fts3 +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts3(x); +} +do_catchsql_test 1.1 { + CREATE VIRTUAL TABLE t2 USING fts4(x); +} {1 {no such module: fts4}} + +reset_db +sqlite3_drop_modules db fts4 +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts4(x); +} +do_catchsql_test 2.1 { + CREATE VIRTUAL TABLE t2 USING fts3(x); +} {1 {no such module: fts4}} + +finish_test From aca5e49caad9819cc09c26cd4a5ecf6e02a1e02e Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 17:21:34 +0000 Subject: [PATCH 066/148] Fix a typo in the result of one of the new test cases. FossilOrigin-Name: 4d02a129c4781c97981748f3c69564e1320d8085dfba4c207e54793390cd64ab --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fts3dropmod.test | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5b9ccfd3e6..07a5a4759c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfts3\sand\sfts4\sso\sthat\sthey\scan\sstill\sbe\sused\seven\sif\sthe\sother\sis\sdropped\sby\sa\scall\sto\ssqlite3_drop_modules(). -D 2021-12-16T15:29:49.836 +C Fix\sa\stypo\sin\sthe\sresult\sof\sone\sof\sthe\snew\stest\scases. +D 2021-12-16T17:21:34.554 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -991,7 +991,7 @@ F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4 F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7 F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297 -F test/fts3dropmod.test 30e0e43011ccb5aa8920922b123480415d8504cc4192d7cf342a45dcabea54a7 +F test/fts3dropmod.test 7de242ea1c8a713a8b143ea54468f4b1c4953fa068349e23ac178e2c90c59889 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a @@ -1935,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d156123885abe6bf23c3530de99be257f82ef85b89fbe019568ac60fa1ed5bb7 -R a5bbf409ca818885e606c4cbcf796195 -U dan -Z ded9a804bf5da97234a4d2625392c243 +P a0a8d6c9f0e91996003626e4f80dfac278e3c5bddd9ace5d442061e6c95e49dc +R cf0f5fd610bdee3d3f0b634a51bd7d90 +U drh +Z cd128a421a3db385221a4ff48ec0de2b diff --git a/manifest.uuid b/manifest.uuid index be87a011d5..ca4719aa2a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a0a8d6c9f0e91996003626e4f80dfac278e3c5bddd9ace5d442061e6c95e49dc \ No newline at end of file +4d02a129c4781c97981748f3c69564e1320d8085dfba4c207e54793390cd64ab \ No newline at end of file diff --git a/test/fts3dropmod.test b/test/fts3dropmod.test index 3739c31a67..d6b1677ac2 100644 --- a/test/fts3dropmod.test +++ b/test/fts3dropmod.test @@ -39,6 +39,6 @@ do_execsql_test 2.0 { } do_catchsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING fts3(x); -} {1 {no such module: fts4}} +} {1 {no such module: fts3}} finish_test From 621a5e0c478677b938a992ee88a847a9281306fd Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 17:35:27 +0000 Subject: [PATCH 067/148] New defenses against OOM and corrupt database problems in the CLI. FossilOrigin-Name: 5c9fd7fde16d8e335488b8bf5c691961d2636201b034d1f29d25de8708de291d --- ext/misc/fileio.c | 3 ++- ext/misc/shathree.c | 1 + manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c.in | 30 +++++++++++++++++++++--------- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c index c9988f6078..7cdbd5968f 100644 --- a/ext/misc/fileio.c +++ b/ext/misc/fileio.c @@ -368,10 +368,11 @@ static int writeFile( mode_t mode, /* MODE parameter passed to writefile() */ sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ ){ + if( zFile==0 ) return 1; #if !defined(_WIN32) && !defined(WIN32) if( S_ISLNK(mode) ){ const char *zTo = (const char*)sqlite3_value_text(pData); - if( symlink(zTo, zFile)<0 ) return 1; + if( zTo==0 || symlink(zTo, zFile)<0 ) return 1; }else #endif { diff --git a/ext/misc/shathree.c b/ext/misc/shathree.c index ef25cb56c6..1f100986ea 100644 --- a/ext/misc/shathree.c +++ b/ext/misc/shathree.c @@ -436,6 +436,7 @@ static void SHA3Update( unsigned int nData ){ unsigned int i = 0; + if( aData==0 ) return; #if SHA3_BYTEORDER==1234 if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ for(; i+7iPk = sqlite3_column_int(pPkFinder, 0); zPk = (const char*)sqlite3_column_text(pPkFinder, 1); + if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ } } } @@ -7194,8 +7199,10 @@ static RecoverTable *recoverFindTable( 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; + if( zName!=0 && zSql!=0 ){ + pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol); + break; + } } } @@ -7889,6 +7896,7 @@ static int do_meta_command(char *zLine, ShellState *p){ while( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1); const char *zFile = (const char*)sqlite3_column_text(pStmt,2); + if( zSchema==0 || zFile==0 ) continue; azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*)); shell_check_oom(azName); azName[nName*2] = strdup(zSchema); @@ -9889,6 +9897,9 @@ static int do_meta_command(char *zLine, ShellState *p){ const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); + if( zOp==0 ) continue; + if( zSql==0 ) continue; + if( zAns==0 ) continue; k = 0; if( bVerbose>0 ){ printf("%d: %s %s\n", tno, zOp, zSql); @@ -10009,6 +10020,7 @@ static int do_meta_command(char *zLine, ShellState *p){ zSep = "VALUES("; while( SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zTab = (const char*)sqlite3_column_text(pStmt,0); + if( zTab==0 ) continue; if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; if( strncmp(zTab, "sqlite_",7)!=0 ){ appendText(&sQuery,"SELECT * FROM ", 0); From fe46317e26024d00bbb49f37bc846282034e70aa Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 17:57:21 +0000 Subject: [PATCH 068/148] In the CLI, omit the ".oom" command (only available in debug builds) and disable the experimental ".expert" commmand in --safe mode. FossilOrigin-Name: 5cda1f7da885afdfda8683c59e78fec8da1a05c7a4fde573e89db5f872fcfb20 --- manifest | 12 +++--- manifest.uuid | 2 +- src/shell.c.in | 101 ++++++------------------------------------------- 3 files changed, 18 insertions(+), 97 deletions(-) diff --git a/manifest b/manifest index 7ee1aaca0d..61d4dbfef9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\sdefenses\sagainst\sOOM\sand\scorrupt\sdatabase\sproblems\sin\sthe\sCLI. -D 2021-12-16T17:35:27.612 +C In\sthe\sCLI,\somit\sthe\s".oom"\scommand\s(only\savailable\sin\sdebug\sbuilds)\sand\ndisable\sthe\sexperimental\s".expert"\scommmand\sin\s--safe\smode. +D 2021-12-16T17:57:21.780 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 3f53d10076f3d0a7f993a03edec15d0ddad236536f300578cadd536e1a5b2d8c +F src/shell.c.in 6d2c65052522d964dd09c937820e6b618ee6d6f12be524390dd82c2a57b9abfd F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1935,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4d02a129c4781c97981748f3c69564e1320d8085dfba4c207e54793390cd64ab -R d166a1375475e15d05923fef18bf064e +P 5c9fd7fde16d8e335488b8bf5c691961d2636201b034d1f29d25de8708de291d +R 7feb81258c8f4748886f602fc3eeba00 U drh -Z 5bfe5520d7a9e1ead42448469dfb8bb8 +Z 8a322aaf96dc4e6ca11de1635edd3a36 diff --git a/manifest.uuid b/manifest.uuid index 6b046b2652..5bd7354eb9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c9fd7fde16d8e335488b8bf5c691961d2636201b034d1f29d25de8708de291d \ No newline at end of file +5cda1f7da885afdfda8683c59e78fec8da1a05c7a4fde573e89db5f872fcfb20 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index dd5a80424a..f743453b9f 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -427,15 +427,6 @@ static sqlite3 *globalDb = 0; */ static volatile int seenInterrupt = 0; -#ifdef SQLITE_DEBUG -/* -** Out-of-memory simulator variables -*/ -static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */ -static unsigned int oomRepeat = 0; /* Number of OOMs in a row */ -static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */ -#endif /* SQLITE_DEBUG */ - /* ** This is the name of our program. It is set in main(), used ** in a number of other places, mostly for error messages. @@ -494,49 +485,6 @@ static void shell_check_oom(void *p){ if( p==0 ) shell_out_of_memory(); } -#ifdef SQLITE_DEBUG -/* This routine is called when a simulated OOM occurs. It is broken -** out as a separate routine to make it easy to set a breakpoint on -** the OOM -*/ -void shellOomFault(void){ - if( oomRepeat>0 ){ - oomRepeat--; - }else{ - oomCounter--; - } -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* This routine is a replacement malloc() that is used to simulate -** Out-Of-Memory (OOM) errors for testing purposes. -*/ -static void *oomMalloc(int nByte){ - if( oomCounter ){ - if( oomCounter==1 ){ - shellOomFault(); - return 0; - }else{ - oomCounter--; - } - } - return defaultMalloc(nByte); -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* Register the OOM simulator. This must occur before any memory -** allocations */ -static void registerOomSimulator(void){ - sqlite3_mem_methods mem; - sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem); - defaultMalloc = mem.xMalloc; - mem.xMalloc = oomMalloc; - sqlite3_config(SQLITE_CONFIG_MALLOC, &mem); -} -#endif - /* ** Write I/O traces to the following stream. */ @@ -4117,9 +4065,6 @@ static const char *(azHelp[]) = { " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", -#ifdef SQLITE_DEBUG - ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", -#endif ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", @@ -8154,8 +8099,15 @@ static int do_meta_command(char *zLine, ShellState *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ - open_db(p, 0); - expertDotCommand(p, azArg, nArg); + if( p->bSafeMode ){ + raw_printf(stderr, + "Cannot run experimental commands such as \"%s\" in safe mode\n", + azArg[0]); + rc = 1; + }else{ + open_db(p, 0); + expertDotCommand(p, azArg, nArg); + } }else #endif @@ -8947,7 +8899,8 @@ static int do_meta_command(char *zLine, ShellState *p){ raw_printf(stderr, "Usage: .nonce NONCE\n"); rc = 1; }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){ - raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]); + raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", + p->lineno, azArg[1]); exit(1); }else{ p->bSafeMode = 0; @@ -8966,34 +8919,6 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else -#ifdef SQLITE_DEBUG - if( c=='o' && strcmp(azArg[0],"oom")==0 ){ - int i; - for(i=1; iout, "missing argument on \"%s\"\n", azArg[i]); - rc = 1; - }else{ - oomRepeat = (int)integerValue(azArg[++i]); - } - }else if( IsDigit(z[0]) ){ - oomCounter = (int)integerValue(azArg[i]); - }else{ - raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]); - raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n"); - rc = 1; - } - } - if( rc==0 ){ - raw_printf(p->out, "oomCounter = %d\n", oomCounter); - raw_printf(p->out, "oomRepeat = %d\n", oomRepeat); - } - }else -#endif /* SQLITE_DEBUG */ - if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ const char *zFN = 0; /* Pointer to constant filename */ char *zNewFilename = 0; /* Name of the database file to open */ @@ -11330,10 +11255,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); -#ifdef SQLITE_DEBUG - registerOomSimulator(); -#endif - #if !defined(_WIN32_WCE) if( getenv("SQLITE_DEBUG_BREAK") ){ if( isatty(0) && isatty(2) ){ From a91734894ef18557f6b0b92aa196916af84ee0dc Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 19:43:16 +0000 Subject: [PATCH 069/148] Give the correct prefix to tests in the windowC.test module. FossilOrigin-Name: fb43456324c26879767b08febf1b5a2b46a289f25398a3872f81d845afd5d84e --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/windowC.test | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 61d4dbfef9..053d96a9cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sCLI,\somit\sthe\s".oom"\scommand\s(only\savailable\sin\sdebug\sbuilds)\sand\ndisable\sthe\sexperimental\s".expert"\scommmand\sin\s--safe\smode. -D 2021-12-16T17:57:21.780 +C Give\sthe\scorrect\sprefix\sto\stests\sin\sthe\swindowC.test\smodule. +D 2021-12-16T19:43:16.431 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1805,7 +1805,7 @@ F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45 F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836 F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be F test/windowB.test b67bda5645f3226790e1a360c4225241840b84adb5aa2e69bfb0b27eef3b84d9 -F test/windowC.test 8799158a2a3ea365980371400f08fd4dff70eadffa5a1e45d42430246da70706 +F test/windowC.test 7d3753c5fd780935a01c9ff30f3585da52e4c7f062a1eb8d442096cecab3041e F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0 F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c @@ -1935,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5c9fd7fde16d8e335488b8bf5c691961d2636201b034d1f29d25de8708de291d -R 7feb81258c8f4748886f602fc3eeba00 +P 5cda1f7da885afdfda8683c59e78fec8da1a05c7a4fde573e89db5f872fcfb20 +R 7915650a4719e50f82fc587e7854cb64 U drh -Z 8a322aaf96dc4e6ca11de1635edd3a36 +Z f56385933405d75be2428da5c2eab0e1 diff --git a/manifest.uuid b/manifest.uuid index 5bd7354eb9..1b87df6a6a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5cda1f7da885afdfda8683c59e78fec8da1a05c7a4fde573e89db5f872fcfb20 \ No newline at end of file +fb43456324c26879767b08febf1b5a2b46a289f25398a3872f81d845afd5d84e \ No newline at end of file diff --git a/test/windowC.test b/test/windowC.test index 499c2f50fd..4b1b3bad2a 100644 --- a/test/windowC.test +++ b/test/windowC.test @@ -13,7 +13,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -set testprefix windowB +set testprefix windowC ifcapable !windowfunc { finish_test From 6e627c44de539151992cad6282558b52b8f42fd6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 16 Dec 2021 19:50:02 +0000 Subject: [PATCH 070/148] Fix windowC tests to specify little-endian or big-endian UTF16, for cross-platform portability. [forum post 559b84a5c6|forum:/forumpost/559b84a5c6] FossilOrigin-Name: adf3a1e6f7575964e467f6813ff980e802cf5a37aaa9e1736af702c493f276b1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/windowC.test | 10 +++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 053d96a9cf..28c68b65fd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Give\sthe\scorrect\sprefix\sto\stests\sin\sthe\swindowC.test\smodule. -D 2021-12-16T19:43:16.431 +C Fix\swindowC\stests\sto\sspecify\slittle-endian\sor\sbig-endian\sUTF16,\sfor\ncross-platform\sportability.\n[forum\spost\s559b84a5c6|forum:/forumpost/559b84a5c6] +D 2021-12-16T19:50:02.315 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1805,7 +1805,7 @@ F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45 F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836 F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be F test/windowB.test b67bda5645f3226790e1a360c4225241840b84adb5aa2e69bfb0b27eef3b84d9 -F test/windowC.test 7d3753c5fd780935a01c9ff30f3585da52e4c7f062a1eb8d442096cecab3041e +F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2 F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0 F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c @@ -1935,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5cda1f7da885afdfda8683c59e78fec8da1a05c7a4fde573e89db5f872fcfb20 -R 7915650a4719e50f82fc587e7854cb64 +P fb43456324c26879767b08febf1b5a2b46a289f25398a3872f81d845afd5d84e +R 378abf936c7f697eae5ac7ce982ddcfc U drh -Z f56385933405d75be2428da5c2eab0e1 +Z 33f9b55eaded7b5ef1cb8f803d4888ec diff --git a/manifest.uuid b/manifest.uuid index 1b87df6a6a..432ebb993a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb43456324c26879767b08febf1b5a2b46a289f25398a3872f81d845afd5d84e \ No newline at end of file +adf3a1e6f7575964e467f6813ff980e802cf5a37aaa9e1736af702c493f276b1 \ No newline at end of file diff --git a/test/windowC.test b/test/windowC.test index 4b1b3bad2a..013876f9b3 100644 --- a/test/windowC.test +++ b/test/windowC.test @@ -67,11 +67,19 @@ foreach {tn bBlob seps} { # reset_db do_execsql_test 2.0 { - PRAGMA encoding=UTF16; + PRAGMA encoding=UTF16le; WITH separator(x) AS (VALUES(',a,'),(',bc,')), value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a')) SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) FROM separator, value; } {{} 1 蕕郐䔓硑ᇍ䫎 1} +reset_db +do_execsql_test 2.1 { + PRAGMA encoding=UTF16be; + WITH separator(x) AS (VALUES(',a,'),(',bc,')), + value(y) AS (VALUES(1),(x'5585d09013455178cd11ce4a')) + SELECT group_concat(y,x) OVER (ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) + FROM separator, value; +} {{} 1 喅킐ፅ典촑칊 1} finish_test From b6592f6563df7a3b049ea5f5b1856bcdde2132ef Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 17 Dec 2021 23:56:43 +0000 Subject: [PATCH 071/148] Improved documentation for the sqlite3_vtab_collation() interface. FossilOrigin-Name: 826f84a92d3b1f760560bff72c911a2c664737820af0c9114eb3494df7b8e878 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 33 ++++++++++++++++++++++++++------- src/where.c | 24 +++++++++++++++++------- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index 28c68b65fd..cc524d9e66 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\swindowC\stests\sto\sspecify\slittle-endian\sor\sbig-endian\sUTF16,\sfor\ncross-platform\sportability.\n[forum\spost\s559b84a5c6|forum:/forumpost/559b84a5c6] -D 2021-12-16T19:50:02.315 +C Improved\sdocumentation\sfor\sthe\ssqlite3_vtab_collation()\sinterface. +D 2021-12-17T23:56:43.941 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -553,7 +553,7 @@ F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/shell.c.in 6d2c65052522d964dd09c937820e6b618ee6d6f12be524390dd82c2a57b9abfd -F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209 +F src/sqlite.h.in 5124aa99d3eb9b6a4e5030cb035076ed060d2dac020cd8fc8fba3022725d54af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 F src/sqliteInt.h e7dd69a85c53461c937d50c97f8efd9761b14f9bcfb63450809e85c100c08538 @@ -638,7 +638,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c d47e14778162f00b732a74fc0b45a92be1b4d5cda3d11876901a3d54a367f5ec +F src/where.c 18d32aa675078a6e3b181138c59d70c07c0f8b8f439124991f95bb6a84fab1d8 F src/whereInt.h 91865afa4a3540bb3bd643619acc56fbceff7defeb8f249b8e157fd5325d88be F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3 @@ -1935,7 +1935,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fb43456324c26879767b08febf1b5a2b46a289f25398a3872f81d845afd5d84e -R 378abf936c7f697eae5ac7ce982ddcfc +P adf3a1e6f7575964e467f6813ff980e802cf5a37aaa9e1736af702c493f276b1 +R 14747f133cdcf1f7cf5355ca59ba5e4d U drh -Z 33f9b55eaded7b5ef1cb8f803d4888ec +Z ab5d47a9bb7bb00af7ed6678c976d522 diff --git a/manifest.uuid b/manifest.uuid index 432ebb993a..a9d57c4e9d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -adf3a1e6f7575964e467f6813ff980e802cf5a37aaa9e1736af702c493f276b1 \ No newline at end of file +826f84a92d3b1f760560bff72c911a2c664737820af0c9114eb3494df7b8e878 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 63a6f37e9a..3c92503a11 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -9464,14 +9464,33 @@ int sqlite3_vtab_nochange(sqlite3_context*); ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** ** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table]. +** method of a [virtual table]. This function returns a pointer to a string +** that is the name of the appropriate collation sequence to use for text +** comparisons on the constraint identified by its arguments. ** -** The first argument must be the sqlite3_index_info object that is the -** first parameter to the xBestIndex() method. The second argument must be -** an index into the aConstraint[] array belonging to the sqlite3_index_info -** structure passed to xBestIndex. This function returns a pointer to a buffer -** containing the name of the collation sequence for the corresponding -** constraint. +** The first argument must be the pointer to the sqlite3_index_info object +** that is the first parameter to the xBestIndex() method. The second argument +** must be an index into the aConstraint[] array belonging to the +** sqlite3_index_info structure passed to xBestIndex. +** +** Important: +** The first parameter must be the same pointer that is passed into the +** xBestMethod() method. The first parameter may not be a pointer to a +** different sqlite3_index_info object, even an exact copy. +** +** The return value is computed as follows: +** +**
    +**
  1. If the constraint comes from a WHERE clause expression that contains +** a [COLLATE operator], then the name of the collation specified by +** that COLLATE operator is returned. +**

  2. If there is no COLLATE operator, but the column that is the subject +** of the constraint specifies an alternative collating sequence via +** a [COLLATE clause] on the column definition within the CREATE TABLE +** statement that was passed into [sqlite3_declare_vtab()], then the +** name of that alternative collating sequence is returned. +**

  3. Otherwise, "BINARY" is returned. +**

*/ SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); diff --git a/src/where.c b/src/where.c index 5210299e7c..02964c92c7 100644 --- a/src/where.c +++ b/src/where.c @@ -676,12 +676,14 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){ int i; if( !sqlite3WhereTrace ) return; for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", + sqlite3DebugPrintf( + " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", i, p->aConstraint[i].iColumn, p->aConstraint[i].iTermOffset, p->aConstraint[i].op, - p->aConstraint[i].usable); + p->aConstraint[i].usable, + sqlite3_vtab_collation(p,i)); } for(i=0; inOrderBy; i++){ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", @@ -3595,11 +3597,19 @@ static int whereLoopAddVirtualOne( } /* -** If this function is invoked from within an xBestIndex() callback, it -** returns a pointer to a buffer containing the name of the collation -** sequence associated with element iCons of the sqlite3_index_info.aConstraint -** array. Or, if iCons is out of range or there is no active xBestIndex -** call, return NULL. +** Return the collating sequence for a constraint passed into xBestIndex. +** +** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex. +** This routine depends on there being a HiddenIndexInfo structure immediately +** following the sqlite3_index_info structure. +** +** Return a pointer to the collation name: +** +** 1. If there is an explicit COLLATE operator on the constaint, return it. +** +** 2. Else, if the column has an alternative collation, return that. +** +** 3. Otherwise, return "BINARY". */ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; From 62e9c352ebe0f6e59f7e53b79fadc3e8cd3bd42a Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 20 Dec 2021 17:00:42 +0000 Subject: [PATCH 072/148] Remove old script ext/fts3/mkfts3amal.tcl, as it doesn't work. FossilOrigin-Name: 9e33ee24b3793b3d7faf7421279d16217f8b09b1e92bfdc771f902f2f1e1b7d6 --- ext/fts3/mkfts3amal.tcl | 115 ---------------------------------------- main.mk | 9 ---- manifest | 15 +++--- manifest.uuid | 2 +- 4 files changed, 8 insertions(+), 133 deletions(-) delete mode 100644 ext/fts3/mkfts3amal.tcl diff --git a/ext/fts3/mkfts3amal.tcl b/ext/fts3/mkfts3amal.tcl deleted file mode 100644 index 059048717f..0000000000 --- a/ext/fts3/mkfts3amal.tcl +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/tclsh -# -# This script builds a single C code file holding all of FTS3 code. -# The name of the output file is fts3amal.c. To build this file, -# first do: -# -# make target_source -# -# The make target above moves all of the source code files into -# a subdirectory named "tsrc". (This script expects to find the files -# there and will not work if they are not found.) -# -# After the "tsrc" directory has been created and populated, run -# this script: -# -# tclsh mkfts3amal.tcl -# -# The amalgamated FTS3 code will be written into fts3amal.c -# - -# Open the output file and write a header comment at the beginning -# of the file. -# -set out [open fts3amal.c w] -set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] -puts $out [subst \ -{/****************************************************************************** -** This file is an amalgamation of separate C source files from the SQLite -** Full Text Search extension 2 (fts3). By combining all the individual C -** code files into this single large file, the entire code can be compiled -** as a one translation unit. This allows many compilers to do optimizations -** that would not be possible if the files were compiled separately. It also -** makes the code easier to import into other projects. -** -** This amalgamation was generated on $today. -*/}] - -# These are the header files used by FTS3. The first time any of these -# files are seen in a #include statement in the C code, include the complete -# text of the file in-line. The file only needs to be included once. -# -foreach hdr { - fts3.h - fts3_hash.h - fts3_tokenizer.h - sqlite3.h - sqlite3ext.h -} { - set available_hdr($hdr) 1 -} - -# 78 stars used for comment formatting. -set s78 \ -{*****************************************************************************} - -# Insert a comment into the code -# -proc section_comment {text} { - global out s78 - set n [string length $text] - set nstar [expr {60 - $n}] - set stars [string range $s78 0 $nstar] - puts $out "/************** $text $stars/" -} - -# Read the source file named $filename and write it into the -# sqlite3.c output file. If any #include statements are seen, -# process them approprately. -# -proc copy_file {filename} { - global seen_hdr available_hdr out - set tail [file tail $filename] - section_comment "Begin file $tail" - set in [open $filename r] - while {![eof $in]} { - set line [gets $in] - if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { - if {[info exists available_hdr($hdr)]} { - if {$available_hdr($hdr)} { - section_comment "Include $hdr in the middle of $tail" - copy_file tsrc/$hdr - section_comment "Continuing where we left off in $tail" - } - } elseif {![info exists seen_hdr($hdr)]} { - set seen_hdr($hdr) 1 - puts $out $line - } - } elseif {[regexp {^#ifdef __cplusplus} $line]} { - puts $out "#if 0" - } elseif {[regexp {^#line} $line]} { - # Skip #line directives. - } else { - puts $out $line - } - } - close $in - section_comment "End of $tail" -} - - -# Process the source files. Process files containing commonly -# used subroutines first in order to help the compiler find -# inlining opportunities. -# -foreach file { - fts3.c - fts3_hash.c - fts3_porter.c - fts3_tokenizer.c - fts3_tokenizer1.c -} { - copy_file tsrc/$file -} - -close $out diff --git a/main.mk b/main.mk index f1a4660a8d..a3a4f33bd3 100644 --- a/main.mk +++ b/main.mk @@ -678,9 +678,6 @@ sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl tclsh $(TOP)/ext/fts2/mkfts2amal.tcl -fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl - tclsh $(TOP)/ext/fts3/mkfts3amal.tcl - # Rules to build the LEMON compiler generator # lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c @@ -931,12 +928,6 @@ amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c \ $(TOP)/ext/session/test_session.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) -fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c - $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ - -DSQLITE_ENABLE_FTS3=1 \ - $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \ - -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) - coretestprogs: $(TESTPROGS) testprogs: coretestprogs srcck1$(EXE) fuzzcheck$(EXE) sessionfuzz$(EXE) diff --git a/manifest b/manifest index cc524d9e66..185a53f757 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sdocumentation\sfor\sthe\ssqlite3_vtab_collation()\sinterface. -D 2021-12-17T23:56:43.941 +C Remove\sold\sscript\sext/fts3/mkfts3amal.tcl,\sas\sit\sdoesn't\swork. +D 2021-12-20T17:00:42.392 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -104,7 +104,6 @@ F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0 F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f F ext/fts3/fts3_write.c 3109c1a232da86474e196cc7db754445a354409f141e08cb11c846cdb17bdf31 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 -F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73 F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674 F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c @@ -473,7 +472,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 002e77acdfeb08d1d8f4d360b01e130aa243fb5701728e81fac9085794f27155 +F main.mk 24547d9000c965553e6f5c875d91935eac250ca19ae6d9afa57fe093e3edd257 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -1935,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P adf3a1e6f7575964e467f6813ff980e802cf5a37aaa9e1736af702c493f276b1 -R 14747f133cdcf1f7cf5355ca59ba5e4d -U drh -Z ab5d47a9bb7bb00af7ed6678c976d522 +P 826f84a92d3b1f760560bff72c911a2c664737820af0c9114eb3494df7b8e878 +R 1a8968caa97e9985e6bb05a7e129d767 +U dan +Z d65382ca9147f68f2405c8ceb9d8b3f8 diff --git a/manifest.uuid b/manifest.uuid index a9d57c4e9d..8b7c1d4e61 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -826f84a92d3b1f760560bff72c911a2c664737820af0c9114eb3494df7b8e878 \ No newline at end of file +9e33ee24b3793b3d7faf7421279d16217f8b09b1e92bfdc771f902f2f1e1b7d6 \ No newline at end of file From f3c33c62351053b784cd9a49337fa75470cf3553 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 20 Dec 2021 23:46:44 +0000 Subject: [PATCH 073/148] In the json1 extension, which compiling it separately, ensure that either SQLITE_DEBUG macro or the NDEBUG macro is set prior to including assert.h. If neither macro is defined, then assert() statement do generate code but VVA() statements do not, and that is a deadly combination. [forum:/forumpost/858dee399e|forum post 858dee399e] FossilOrigin-Name: d9f814a6402ca7fd999bbb847dc354b52ab9b97cae0c932344584d26c9430f24 --- ext/misc/json1.c | 9 +++++++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 7fcd7342a6..787b46982e 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -26,6 +26,15 @@ #include "sqlite3ext.h" #endif SQLITE_EXTENSION_INIT1 + +/* If compiling this extension separately (why would anybody do that when +** it is built into the amalgamation?) we must set NDEBUG if SQLITE_DEBUG +** is not defined *before* including , in order to disable asserts(). +*/ +#if !defined(SQLITE_AMALGAMATION) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + #include #include #include diff --git a/manifest b/manifest index 185a53f757..b33ded8fae 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sold\sscript\sext/fts3/mkfts3amal.tcl,\sas\sit\sdoesn't\swork. -D 2021-12-20T17:00:42.392 +C In\sthe\sjson1\sextension,\swhich\scompiling\sit\sseparately,\sensure\sthat\seither\nSQLITE_DEBUG\smacro\sor\sthe\sNDEBUG\smacro\sis\sset\sprior\sto\sincluding\sassert.h.\nIf\sneither\smacro\sis\sdefined,\sthen\sassert()\sstatement\sdo\sgenerate\scode\sbut\nVVA()\sstatements\sdo\snot,\sand\sthat\sis\sa\sdeadly\scombination.\n[forum:/forumpost/858dee399e|forum\spost\s858dee399e] +D 2021-12-20T23:46:44.985 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c 89a988f06dcb3da0d0af9fdb2b09892452ad12dfd8f432600ee6437a6dcac310 +F ext/misc/json1.c a4ea54d9b228901695a7f51df338dddb29a2a574b870d0c0cb58539cc90e9a31 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 826f84a92d3b1f760560bff72c911a2c664737820af0c9114eb3494df7b8e878 -R 1a8968caa97e9985e6bb05a7e129d767 -U dan -Z d65382ca9147f68f2405c8ceb9d8b3f8 +P 9e33ee24b3793b3d7faf7421279d16217f8b09b1e92bfdc771f902f2f1e1b7d6 +R c2fe6fb3b4bbdde0430d16a68d16873f +U drh +Z f951da4ac66930095755e6f72f9aabea diff --git a/manifest.uuid b/manifest.uuid index 8b7c1d4e61..1a02279256 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e33ee24b3793b3d7faf7421279d16217f8b09b1e92bfdc771f902f2f1e1b7d6 \ No newline at end of file +d9f814a6402ca7fd999bbb847dc354b52ab9b97cae0c932344584d26c9430f24 \ No newline at end of file From 8b6dfc474b7ba9d46b0c017e08d229668d6544b5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 21 Dec 2021 16:59:45 +0000 Subject: [PATCH 074/148] Update the README.md to instruct the user to remove the final comment line from the "manifest" file before using it to compute the check-in hash. FossilOrigin-Name: 7b4f9d95a95f685ea4ee045e43c67b1a5c70e908e357b0b41d522699255663ce --- README.md | 8 +++++--- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b79fc67f15..9e8bb2610e 100644 --- a/README.md +++ b/README.md @@ -309,9 +309,11 @@ describes its purpose and role within the larger system. 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. -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 +The name of the version of the entire source tree is just the +SHA3-256 hash of the `manifest` file itself, possibly with the +last line of that file omitted if the last line begins with +"`# Remove this line`". +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. diff --git a/manifest b/manifest index b33ded8fae..8ac551ff37 100644 --- a/manifest +++ b/manifest @@ -1,12 +1,12 @@ -C In\sthe\sjson1\sextension,\swhich\scompiling\sit\sseparately,\sensure\sthat\seither\nSQLITE_DEBUG\smacro\sor\sthe\sNDEBUG\smacro\sis\sset\sprior\sto\sincluding\sassert.h.\nIf\sneither\smacro\sis\sdefined,\sthen\sassert()\sstatement\sdo\sgenerate\scode\sbut\nVVA()\sstatements\sdo\snot,\sand\sthat\sis\sa\sdeadly\scombination.\n[forum:/forumpost/858dee399e|forum\spost\s858dee399e] -D 2021-12-20T23:46:44.985 +C Update\sthe\sREADME.md\sto\sinstruct\sthe\suser\sto\sremove\sthe\sfinal\scomment\sline\nfrom\sthe\s"manifest"\sfile\sbefore\susing\sit\sto\scompute\sthe\scheck-in\shash. +D 2021-12-21T16:59:45.424 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f -F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110 +F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c F VERSION 392c2f83569705069415a5d98b1c138ec8fe8a56a663a0d94cea019e806537b2 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 @@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9e33ee24b3793b3d7faf7421279d16217f8b09b1e92bfdc771f902f2f1e1b7d6 -R c2fe6fb3b4bbdde0430d16a68d16873f +P d9f814a6402ca7fd999bbb847dc354b52ab9b97cae0c932344584d26c9430f24 +R db9606205e7c40e39afd2f95792c8925 U drh -Z f951da4ac66930095755e6f72f9aabea +Z c2c3d0387ea5fddc68383e50b25ca47d diff --git a/manifest.uuid b/manifest.uuid index 1a02279256..711c78ee68 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9f814a6402ca7fd999bbb847dc354b52ab9b97cae0c932344584d26c9430f24 \ No newline at end of file +7b4f9d95a95f685ea4ee045e43c67b1a5c70e908e357b0b41d522699255663ce \ No newline at end of file From b131bf7039b17ed51b85dc5895a4438a1c5652a2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 23 Dec 2021 00:16:06 +0000 Subject: [PATCH 075/148] Reduce the size of the compiled binary by a couple of hundred bytes by using a thigher packing of a transformation table in date.c. Suggested by [forum:/forumpost/4f6efbb2a9|forum post 4f6efbb2a9]. FossilOrigin-Name: c75ba4fa644d338d22813c17172b9975411fe6197e07fd584e3209e3beb78036 --- manifest | 13 +++++++------ manifest.uuid | 2 +- src/date.c | 31 ++++++++++++++++--------------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index 8ac551ff37..8f88f47470 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sREADME.md\sto\sinstruct\sthe\suser\sto\sremove\sthe\sfinal\scomment\sline\nfrom\sthe\s"manifest"\sfile\sbefore\susing\sit\sto\scompute\sthe\scheck-in\shash. -D 2021-12-21T16:59:45.424 +C Reduce\sthe\ssize\sof\sthe\scompiled\sbinary\sby\sa\scouple\sof\shundred\sbytes\sby\nusing\sa\sthigher\spacking\sof\sa\stransformation\stable\sin\sdate.c.\nSuggested\sby\s[forum:/forumpost/4f6efbb2a9|forum\spost\s4f6efbb2a9]. +D 2021-12-23T00:16:06.350 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -498,7 +498,7 @@ F src/build.c 107e1ecc98ca8965c2e08fc283a06067a1d829b1a82531a6f0a0e0fa60e7b0c1 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 -F src/date.c b49c12c7564ddd7f1922f76e7a086a6db5b91aa0e729b180cd433e22bab37be0 +F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c @@ -1934,7 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d9f814a6402ca7fd999bbb847dc354b52ab9b97cae0c932344584d26c9430f24 -R db9606205e7c40e39afd2f95792c8925 +P 7b4f9d95a95f685ea4ee045e43c67b1a5c70e908e357b0b41d522699255663ce +R 7b101808d3a49cd62c69eb0ecccc8da0 U drh -Z c2c3d0387ea5fddc68383e50b25ca47d +Z 7db45fce779218ebd5032a4f8090eaaf +# Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 711c78ee68..5abf37fc5b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7b4f9d95a95f685ea4ee045e43c67b1a5c70e908e357b0b41d522699255663ce \ No newline at end of file +c75ba4fa644d338d22813c17172b9975411fe6197e07fd584e3209e3beb78036 \ No newline at end of file diff --git a/src/date.c b/src/date.c index f5b22d7538..b018c39f68 100644 --- a/src/date.c +++ b/src/date.c @@ -617,18 +617,17 @@ static sqlite3_int64 localtimeOffset( ** of several units of time. */ static const struct { - u8 eType; /* Transformation type code */ - u8 nName; /* Length of th name */ - char *zName; /* Name of the transformation */ - double rLimit; /* Maximum NNN value for this transform */ - double rXform; /* Constant used for this transform */ + u8 nName; /* Length of the name */ + char zName[7]; /* Name of the transformation */ + float rLimit; /* Maximum NNN value for this transform */ + float rXform; /* Constant used for this transform */ } aXformType[] = { - { 0, 6, "second", 464269060800.0, 1000.0 }, - { 0, 6, "minute", 7737817680.0, 60000.0 }, - { 0, 4, "hour", 128963628.0, 3600000.0 }, - { 0, 3, "day", 5373485.0, 86400000.0 }, - { 1, 5, "month", 176546.0, 2592000000.0 }, - { 2, 4, "year", 14713.0, 31536000000.0 }, + { 6, "second", 4.6427e+14, 1.0 }, + { 6, "minute", 7.7379e+12, 60.0 }, + { 4, "hour", 1.2897e+11, 3600.0 }, + { 3, "day", 5373485.0, 86400.0 }, + { 5, "month", 176546.0, 2592000.0 }, + { 4, "year", 14713.0, 31536000.0 }, }; /* @@ -865,9 +864,10 @@ static int parseModifier( && sqlite3_strnicmp(aXformType[i].zName, z, n)==0 && r>-aXformType[i].rLimit && rM += (int)r; x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; @@ -877,8 +877,9 @@ static int parseModifier( r -= (int)r; break; } - case 2: { /* Special processing to add years */ + case 5: { /* Special processing to add years */ int y = (int)r; + assert( strcmp(aXformType[i].zName,"year")==0 ); computeYMD_HMS(p); p->Y += y; p->validJD = 0; @@ -887,7 +888,7 @@ static int parseModifier( } } computeJD(p); - p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder); + p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder); rc = 0; break; } From ceeb04bf907ebe6970071aa94d5ac0546f82de53 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 24 Dec 2021 13:30:22 +0000 Subject: [PATCH 076/148] Raise an error if a schema name is attached to the table-alias name of a subquery or view. See [forum:/forumpost/021a33600b|forum post 021a33600b] for the bug report. FossilOrigin-Name: 8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/resolve.c | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8f88f47470..8dfd7262f4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reduce\sthe\ssize\sof\sthe\scompiled\sbinary\sby\sa\scouple\sof\shundred\sbytes\sby\nusing\sa\sthigher\spacking\sof\sa\stransformation\stable\sin\sdate.c.\nSuggested\sby\s[forum:/forumpost/4f6efbb2a9|forum\spost\s4f6efbb2a9]. -D 2021-12-23T00:16:06.350 +C Raise\san\serror\sif\sa\sschema\sname\sis\sattached\sto\sthe\stable-alias\sname\sof\sa\nsubquery\sor\sview.\s\sSee\n[forum:/forumpost/021a33600b|forum\spost\s021a33600b]\sfor\sthe\sbug\sreport. +D 2021-12-24T13:30:22.324 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -548,7 +548,7 @@ F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 F src/printf.c 9565aeb5af5376fd23c993b8da1ac37008fad65435a703316eef9f41229f702d F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c -F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571 +F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/shell.c.in 6d2c65052522d964dd09c937820e6b618ee6d6f12be524390dd82c2a57b9abfd @@ -1934,8 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7b4f9d95a95f685ea4ee045e43c67b1a5c70e908e357b0b41d522699255663ce -R 7b101808d3a49cd62c69eb0ecccc8da0 +P c75ba4fa644d338d22813c17172b9975411fe6197e07fd584e3209e3beb78036 +R 42b010745a367038b1833ffaa7617d2a U drh -Z 7db45fce779218ebd5032a4f8090eaaf +Z bd32e76337e9222c745f2103282a5506 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5abf37fc5b..0bea1ce04e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c75ba4fa644d338d22813c17172b9975411fe6197e07fd584e3209e3beb78036 \ No newline at end of file +8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 27b260e059..bf6900f239 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -320,8 +320,9 @@ static int lookupName( } if( hit || zTab==0 ) continue; } - if( zDb && pTab->pSchema!=pSchema ){ - continue; + if( zDb ){ + if( pTab->pSchema!=pSchema ) continue; + if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue; } if( zTab ){ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; From c320e062a3eaa4be3c8e7b50c63c43054decb441 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 24 Dec 2021 19:44:11 +0000 Subject: [PATCH 077/148] Fix a minor problem in the CLI introduced by [d156123885abe6bf], apparently. FossilOrigin-Name: 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 8dfd7262f4..a6c925887d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Raise\san\serror\sif\sa\sschema\sname\sis\sattached\sto\sthe\stable-alias\sname\sof\sa\nsubquery\sor\sview.\s\sSee\n[forum:/forumpost/021a33600b|forum\spost\s021a33600b]\sfor\sthe\sbug\sreport. -D 2021-12-24T13:30:22.324 +C Fix\sa\sminor\sproblem\sin\sthe\sCLI\sintroduced\sby\s[d156123885abe6bf],\sapparently. +D 2021-12-24T19:44:11.241 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 6d2c65052522d964dd09c937820e6b618ee6d6f12be524390dd82c2a57b9abfd +F src/shell.c.in 1b567fc5463470fb22f3e45a5dbf05ee2ce9dd9066b2973c4a2bdd7daa74bb5f F src/sqlite.h.in 5124aa99d3eb9b6a4e5030cb035076ed060d2dac020cd8fc8fba3022725d54af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,8 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c75ba4fa644d338d22813c17172b9975411fe6197e07fd584e3209e3beb78036 -R 42b010745a367038b1833ffaa7617d2a +P 8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 +R b3820a24a997ecbc0d96c676f9253e0d U drh -Z bd32e76337e9222c745f2103282a5506 +Z 32815daf40ab0d51da0a9e14b1eae912 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 0bea1ce04e..b59febd5a3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 \ No newline at end of file +37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index f743453b9f..c6f623f5b7 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8975,11 +8975,11 @@ static int do_meta_command(char *zLine, ShellState *p){ /* If a filename is specified, try to open it first */ if( zFN || p->openMode==SHELL_OPEN_HEXDB ){ - if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); + if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN); if( p->bSafeMode && p->openMode!=SHELL_OPEN_HEXDB - && zNewFilename - && strcmp(zNewFilename,":memory:")!=0 + && zFN + && strcmp(zFN,":memory:")!=0 ){ failIfSafeMode(p, "cannot open disk-based database files in safe mode"); } From f62641e91cc0aee1a24ea4a3c81289e4e821c4e5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 24 Dec 2021 20:22:13 +0000 Subject: [PATCH 078/148] Add the sqlite3_error_offset() interface. Use it in the CLI to provide better context for error messages. FossilOrigin-Name: b518ce77439852759bc0901071f36d622b1314c9bf3d29c279dfcc405188b975 --- manifest | 31 +++++++++++++----------- manifest.uuid | 2 +- src/loadext.c | 2 ++ src/main.c | 13 +++++++++++ src/printf.c | 25 ++++++++++++++++++++ src/shell.c.in | 61 ++++++++++++++++++++++++++++++++++++++++++------ src/sqlite.h.in | 11 ++++++++- src/sqlite3ext.h | 4 ++++ src/sqliteInt.h | 2 ++ src/test1.c | 29 +++++++++++++++++++++++ src/util.c | 29 ++++++++--------------- 11 files changed, 167 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index a6c925887d..086b4676d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sminor\sproblem\sin\sthe\sCLI\sintroduced\sby\s[d156123885abe6bf],\sapparently. -D 2021-12-24T19:44:11.241 +C Add\sthe\ssqlite3_error_offset()\sinterface.\s\sUse\sit\sin\sthe\sCLI\sto\sprovide\nbetter\scontext\sfor\serror\smessages. +D 2021-12-24T20:22:13.535 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -513,8 +513,8 @@ F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa -F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c -F src/main.c 674a0fdfc2808e1d5a78b2eefe2ec3f93428cf82f0f6c013d577df1a1caa5940 +F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d +F src/main.c d7719ea81cc8ea81253cb2af0603d089407ea70dd5742f53a81ee3c168186344 F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -546,21 +546,21 @@ F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 -F src/printf.c 9565aeb5af5376fd23c993b8da1ac37008fad65435a703316eef9f41229f702d +F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 1b567fc5463470fb22f3e45a5dbf05ee2ce9dd9066b2973c4a2bdd7daa74bb5f -F src/sqlite.h.in 5124aa99d3eb9b6a4e5030cb035076ed060d2dac020cd8fc8fba3022725d54af +F src/shell.c.in c2f60a11f4a0720cd952d14ec20331543fb185a982e10a2385c5715e129369fd +F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 -F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h e7dd69a85c53461c937d50c97f8efd9761b14f9bcfb63450809e85c100c08538 +F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef +F src/sqliteInt.h 418dd1a178abcc40b86b39cee972083822b17e84888fe56ed7a3b00b473d8bb5 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6 -F src/test1.c 37b323d74aef3156394478bd09dff855332077e537b37c9a7e455c03cb04da09 +F src/test1.c c24fe3a13ff78f5cbc29ac7049123e03ee1f33c6601646a45766c5f8d5db7f92 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -620,7 +620,7 @@ F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c 569349b0bddcbfbc661856f446adb92e1b0a47b3cbef548da9fc5aa639d7964c +F src/util.c 89e51820bcb468ff3877a8d942f5cc807208087f021227e0927693e928a195bc F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 F src/vdbe.c b63594839cbf770a29e2b3b81570971a3d2c1c995c0586aade09bb548142113a F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe @@ -1934,8 +1934,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 8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 -R b3820a24a997ecbc0d96c676f9253e0d +P 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 +R dc8a0d1713a6a184c2032656b8115b23 +T *branch * improved-error-context +T *sym-improved-error-context * +T -sym-trunk * U drh -Z 32815daf40ab0d51da0a9e14b1eae912 +Z 3c3faf346f54edef0799304c35a23ad2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b59febd5a3..4479c72102 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 \ No newline at end of file +b518ce77439852759bc0901071f36d622b1314c9bf3d29c279dfcc405188b975 \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index 4edefec0c9..681e12c4e7 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -485,6 +485,8 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, + /* Version 3.38.0 and later */ + sqlite3_error_offset, }; /* True if x is the directory separator character diff --git a/src/main.c b/src/main.c index 1b7853f609..07c67d33d7 100644 --- a/src/main.c +++ b/src/main.c @@ -2597,6 +2597,19 @@ const char *sqlite3_errmsg(sqlite3 *db){ return z; } +/* +** Return the byte offset of the most recent error +*/ +int sqlite3_error_offset(sqlite3 *db){ + int iOffset = -1; + if( db && sqlite3SafetyCheckSickOrOk(db) ){ + sqlite3_mutex_enter(db->mutex); + iOffset = db->errByteOffset; + sqlite3_mutex_leave(db->mutex); + } + return iOffset; +} + #ifndef SQLITE_OMIT_UTF16 /* ** Return UTF-16 encoded English language explanation of the most recent diff --git a/src/printf.c b/src/printf.c index 6128e5cb4c..9fea2d6ef0 100644 --- a/src/printf.c +++ b/src/printf.c @@ -855,6 +855,7 @@ void sqlite3_str_vappendf( assert( bArgList==0 ); if( pToken && pToken->n ){ sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); } length = width = 0; break; @@ -909,6 +910,30 @@ void sqlite3_str_vappendf( }/* End for loop over the format string */ } /* End of function */ + +/* +** The z string points to the first character of a token that is +** associated with an error. If db does not already have an error +** byte offset recorded, try to compute the error byte offset for +** z and set the error byte offset in db. +*/ +void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){ + const Parse *pParse; + const char *zText; + const char *zEnd; + assert( z!=0 ); + if( NEVER(db==0) ) return; + if( db->errByteOffset!=(-2) ) return; + pParse = db->pParse; + if( NEVER(pParse==0) ) return; + zText =pParse->zTail; + if( NEVER(zText==0) ) return; + zEnd = &zText[strlen(zText)]; + if( SQLITE_WITHIN(z,zText,zEnd) ){ + db->errByteOffset = (int)(z-zText); + } +} + /* ** Enlarge the memory allocation on a StrAccum object so that it is ** able to accept at least N more bytes of text. diff --git a/src/shell.c.in b/src/shell.c.in index c6f623f5b7..c8d7692560 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -2519,6 +2519,47 @@ static void set_table_name(ShellState *p, const char *zName){ z[n] = 0; } +/* +** Maybe construct two lines of text that point out the position of a +** syntax error. Return a pointer to the text, in memory obtained from +** sqlite3_malloc(). Or, if the most recent error does not involve a +** specific token that we can point to, return an empty string. +** +** In all cases, the memory returned is obtained from sqlite3_malloc64() +** and should be released by the caller invoking sqlite3_free(). +*/ +static char *shell_error_context(const char *zSql, sqlite3 *db){ + int iOffset; + size_t len; + char *zCode; + char *zMsg; + int i; + if( db==0 + || zSql==0 + || (iOffset = sqlite3_error_offset(db))<0 + ){ + return sqlite3_mprintf(""); + } + while( iOffset>50 ){ + iOffset--; + zSql++; + while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; } + } + len = strlen(zSql); + if( len>78 ){ + len = 78; + while( (zSql[len]&0xc0)==0x80 ) len--; + } + zCode = sqlite3_mprintf("%.*s", len, zSql); + for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; } + if( iOffset<25 ){ + zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, ""); + }else{ + zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, ""); + } + return zMsg; +} + /* ** Execute a query statement that will generate SQL output. Print @@ -2541,8 +2582,10 @@ static int run_table_dump_query( const char *z; rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ - utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, - sqlite3_errmsg(p->db)); + char *zContext = shell_error_context(zSelect, p->db); + utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc, + sqlite3_errmsg(p->db), zContext); + sqlite3_free(zContext); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; return rc; } @@ -2578,12 +2621,16 @@ static int run_table_dump_query( static char *save_err_msg( sqlite3 *db, /* Database to query */ const char *zWhen, /* Qualifier (format) wrapper */ - int rc /* Error code returned from API */ + int rc, /* Error code returned from API */ + const char *zSql /* SQL string, or NULL */ ){ char *zErr; - if( zWhen==0 ) zWhen = "%s (%d)"; - zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc); + char *zContext; + if( zWhen==0 ) zWhen = "%s (%d)%s"; + zContext = shell_error_context(zSql, db); + zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc, zContext); shell_check_oom(zErr); + sqlite3_free(zContext); return zErr; } @@ -3518,7 +3565,7 @@ static int shell_exec( rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); if( SQLITE_OK != rc ){ if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)", rc); + *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)%s", rc, zSql); } }else{ if( !pStmt ){ @@ -3634,7 +3681,7 @@ static int shell_exec( zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; }else if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc); + *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc, 0); } /* clear saved stmt handle */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3c92503a11..3aad3690a2 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -3824,13 +3824,14 @@ void sqlite3_free_filename(char*); ** sqlite3_extended_errcode() might change with each API call. ** Except, there are some interfaces that are guaranteed to never ** change the value of the error code. The error-code preserving -** interfaces are: +** interfaces include the following: ** **
    **
  • sqlite3_errcode() **
  • sqlite3_extended_errcode() **
  • sqlite3_errmsg() **
  • sqlite3_errmsg16() +**
  • sqlite3_error_offset() **
** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -3845,6 +3846,13 @@ void sqlite3_free_filename(char*); ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** +** ^If the most recent error references a specific token in the input +** SQL, the sqlite3_error_offset() interface returns the byte offset +** of the start of that token. ^The byte offset returned by +** sqlite3_error_offset() assumes that the input SQL is UTF8. +** ^If the most error does not reference a specific token in the input +** SQL, then the sqlite3_error_offset() function returns -1. +** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. @@ -3864,6 +3872,7 @@ int sqlite3_extended_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); const void *sqlite3_errmsg16(sqlite3*); const char *sqlite3_errstr(int); +int sqlite3_error_offset(sqlite3 *db); /* ** CAPI3REF: Prepared Statement Object diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 9767daa01d..5b82346227 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -344,6 +344,8 @@ struct sqlite3_api_routines { int (*autovacuum_pages)(sqlite3*, unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), void*, void(*)(void*)); + /* Version 3.38.0 and later */ + int (*error_offset)(sqlite3*); }; /* @@ -655,6 +657,8 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages +/* Version 3.38.0 and later */ +#define sqlite3_error_offset sqlite3_api->error_offset #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 48a94a7b33..092bbccdc6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1527,6 +1527,7 @@ struct sqlite3 { u32 nSchemaLock; /* Do not reset the schema when non-zero */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ + int errByteOffset; /* Byte offset of error in SQL statement */ int errMask; /* & result codes with this before returning */ int iSysErrno; /* Errno value from last system error */ u32 dbOptFlags; /* Flags to enable/disable optimizations */ @@ -4977,6 +4978,7 @@ void sqlite3StrAccumSetError(StrAccum*, u8); void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); void sqlite3SelectDestInit(SelectDest*,int,int); Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); +void sqlite3RecordErrorByteOffset(sqlite3*,const char*); void sqlite3BackupRestart(sqlite3_backup *); void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); diff --git a/src/test1.c b/src/test1.c index 8cdb7b285e..84d888ff37 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4366,6 +4366,34 @@ static int SQLITE_TCLAPI test_errmsg( return TCL_OK; } + +/* +** Usage: sqlite3_error_offset DB +** +** Return the byte offset into the input UTF8 SQL for the most recent +** error, or -1 of the error does not refer to a specific token. +*/ +static int SQLITE_TCLAPI test_error_offset( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int iByteOffset; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + iByteOffset = sqlite3_error_offset(db); + Tcl_SetObjResult(interp, Tcl_NewIntObj(zErr, -1)); + return TCL_OK; +} + /* ** Usage: test_errmsg16 DB ** @@ -8422,6 +8450,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_errcode", test_errcode ,0 }, { "sqlite3_extended_errcode", test_ex_errcode ,0 }, { "sqlite3_errmsg", test_errmsg ,0 }, + { "sqlite3_error_offset", test_error_offset ,0 }, { "sqlite3_errmsg16", test_errmsg16 ,0 }, { "sqlite3_open", test_open ,0 }, { "sqlite3_open16", test_open16 ,0 }, diff --git a/src/util.c b/src/util.c index 8ea951fa16..dec205df43 100644 --- a/src/util.c +++ b/src/util.c @@ -117,7 +117,11 @@ static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){ void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; - if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code); + if( err_code || db->pErr ){ + sqlite3ErrorFinish(db, err_code); + }else{ + db->errByteOffset = -1; + } } /* @@ -127,6 +131,7 @@ void sqlite3Error(sqlite3 *db, int err_code){ void sqlite3ErrorClear(sqlite3 *db){ assert( db!=0 ); db->errCode = SQLITE_OK; + db->errByteOffset = -1; if( db->pErr ) sqlite3ValueSetNull(db->pErr); } @@ -147,17 +152,8 @@ void sqlite3SystemError(sqlite3 *db, int rc){ ** handle "db". The error code is set to "err_code". ** ** If it is not NULL, string zFormat specifies the format of the -** error string in the style of the printf functions: The following -** format characters are allowed: -** -** %s Insert a string -** %z A string that should be freed after use -** %d Insert an integer -** %T Insert a token -** %S Insert the first element of a SrcList -** -** zFormat and any string tokens that follow it are assumed to be -** encoded in UTF-8. +** error string. zFormat and any string tokens that follow it are +** assumed to be encoded in UTF-8. ** ** To clear the most recent error for sqlite handle "db", sqlite3Error ** should be called with err_code set to SQLITE_OK and zFormat set @@ -181,13 +177,6 @@ void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ /* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. -** The following formatting characters are allowed: -** -** %s Insert a string -** %z A string that should be freed after use -** %d Insert an integer -** %T Insert a token -** %S Insert the first element of a SrcList ** ** This function should be used to report any error that occurs while ** compiling an SQL statement (i.e. within sqlite3_prepare()). The @@ -200,9 +189,11 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; va_list ap; sqlite3 *db = pParse->db; + db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); + if( db->errByteOffset<-1 ) db->errByteOffset = -1; if( db->suppressErr ){ sqlite3DbFree(db, zMsg); }else{ From 5cec7e1a5fdde96c2386a6c40e488e58ebc2b78a Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 25 Dec 2021 00:19:46 +0000 Subject: [PATCH 079/148] One minor change for an exceptional case in sqlite3_error_offset(). FossilOrigin-Name: c93609a8b9dc2e656bb4360138606e269fd323469f7666dbc3bbc699e431313e --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/main.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 086b4676d3..6cd01d0137 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_error_offset()\sinterface.\s\sUse\sit\sin\sthe\sCLI\sto\sprovide\nbetter\scontext\sfor\serror\smessages. -D 2021-12-24T20:22:13.535 +C One\sminor\schange\sfor\san\sexceptional\scase\sin\ssqlite3_error_offset(). +D 2021-12-25T00:19:46.998 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -514,7 +514,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d -F src/main.c d7719ea81cc8ea81253cb2af0603d089407ea70dd5742f53a81ee3c168186344 +F src/main.c aa24539f6c26460543d51027ea14b79cad35e34bc9d4907bc349b52b71066644 F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -1934,11 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 -R dc8a0d1713a6a184c2032656b8115b23 -T *branch * improved-error-context -T *sym-improved-error-context * -T -sym-trunk * +P b518ce77439852759bc0901071f36d622b1314c9bf3d29c279dfcc405188b975 +R 8f03bf9f6f19504237d0970665f639d4 U drh -Z 3c3faf346f54edef0799304c35a23ad2 +Z 4eae18cf6b28cc5b2fc2672ed68ce869 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4479c72102..45b61f562d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b518ce77439852759bc0901071f36d622b1314c9bf3d29c279dfcc405188b975 \ No newline at end of file +c93609a8b9dc2e656bb4360138606e269fd323469f7666dbc3bbc699e431313e \ No newline at end of file diff --git a/src/main.c b/src/main.c index 07c67d33d7..be73f6df65 100644 --- a/src/main.c +++ b/src/main.c @@ -2602,7 +2602,7 @@ const char *sqlite3_errmsg(sqlite3 *db){ */ int sqlite3_error_offset(sqlite3 *db){ int iOffset = -1; - if( db && sqlite3SafetyCheckSickOrOk(db) ){ + if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){ sqlite3_mutex_enter(db->mutex); iOffset = db->errByteOffset; sqlite3_mutex_leave(db->mutex); From d66d5c2d353d031d4125ac80f840741a264d91c2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 25 Dec 2021 23:59:54 +0000 Subject: [PATCH 080/148] Change an assert() in FTS3 into assert_fts3_nc(), since it is a harmless condition that can occur when processing a corrupt database file. FossilOrigin-Name: c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 --- ext/fts3/fts3.c | 2 +- manifest | 13 ++++++------- manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 9a341a89a0..097338f547 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -4486,7 +4486,7 @@ void sqlite3Fts3DoclistPrev( assert( nDoclist>0 ); assert( *pbEof==0 ); - assert( p || *piDocid==0 ); + assert_fts3_nc( p || *piDocid==0 ); assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); if( p==0 ){ diff --git a/manifest b/manifest index 1e06248283..0a9e781a33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_error_offset()\sinterface.\s\sUse\sit\sto\senhance\serror\sreporting\nin\sthe\sCLI. -D 2021-12-25T00:26:51.340 +C Change\san\sassert()\sin\sFTS3\sinto\sassert_fts3_nc(),\ssince\sit\sis\sa\sharmless\ncondition\sthat\scan\soccur\swhen\sprocessing\sa\scorrupt\sdatabase\sfile. +D 2021-12-25T23:59:54.620 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -84,7 +84,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c f27e890395640be4938b9b554cad46fdf1e42e6bd7d64154bbac27d079d00f9e +F ext/fts3/fts3.c 6634a3854e70afa8710ee5e3a7253cd0f0c89d4cce207fcbfe2ead3bad1db7d5 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h dafdc371f9fbab175744b06cfe019d5f040cdfdbd11fea752f5dc28d45b04c05 F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f @@ -1934,9 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 c93609a8b9dc2e656bb4360138606e269fd323469f7666dbc3bbc699e431313e -R 8f03bf9f6f19504237d0970665f639d4 -T +closed c93609a8b9dc2e656bb4360138606e269fd323469f7666dbc3bbc699e431313e +P 7fa20ca4c09ab0249de0363691541fa836120ec277e72feb0e1516b9bfbdd97a +R 2b2719b5920685e35cd64747f22d50b0 U drh -Z 6c4e7daae6067f5d0876bbf1b0ae2412 +Z 595d1de7ae7f6fab7b1ff88e1ba1b7f2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f50d0ac9ba..8a9e02a19f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7fa20ca4c09ab0249de0363691541fa836120ec277e72feb0e1516b9bfbdd97a \ No newline at end of file +c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 \ No newline at end of file From a2ba25b508d0442e2b1fd7b9eb8f184e61957f83 Mon Sep 17 00:00:00 2001 From: larrybr Date: Tue, 28 Dec 2021 05:08:38 +0000 Subject: [PATCH 081/148] Make .read's help tell of piped input FossilOrigin-Name: e4ddcd8aa582c1130c34e9f05cd3e5f96ebf03c97a36c09ca442e3612fee4a20 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0a9e781a33..8e741d300c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\san\sassert()\sin\sFTS3\sinto\sassert_fts3_nc(),\ssince\sit\sis\sa\sharmless\ncondition\sthat\scan\soccur\swhen\sprocessing\sa\scorrupt\sdatabase\sfile. -D 2021-12-25T23:59:54.620 +C Make\s.read's\shelp\stell\sof\spiped\sinput +D 2021-12-28T05:08:38.128 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in c2f60a11f4a0720cd952d14ec20331543fb185a982e10a2385c5715e129369fd +F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a359 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef @@ -1934,8 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7fa20ca4c09ab0249de0363691541fa836120ec277e72feb0e1516b9bfbdd97a -R 2b2719b5920685e35cd64747f22d50b0 -U drh -Z 595d1de7ae7f6fab7b1ff88e1ba1b7f2 +P c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 +R 035fc7ecc447249d615762da61b11d6c +U larrybr +Z a3c99601a959abd1cb8e7bea62bdef11 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8a9e02a19f..7aef9d428e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 \ No newline at end of file +e4ddcd8aa582c1130c34e9f05cd3e5f96ebf03c97a36c09ca442e3612fee4a20 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c8d7692560..1bc57873da 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4147,7 +4147,8 @@ static const char *(azHelp[]) = { #endif ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", - ".read FILE Read input from FILE", + ".read FILE Read input from FILE or command output", + " If FILE begins with \"|\", it is a command that generates the input.", #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", From 9169d0cb0f8dcf3f5594f5520e5c9607fa90cbae Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 29 Dec 2021 04:08:11 +0000 Subject: [PATCH 082/148] Fix the build-breaker bug in test1.c introduced by check-in [7fa20ca4c09ab024]. FossilOrigin-Name: 5f804da1820c98e7ff5c377e57e30b5154844b92ce622ed2ff888fe2c887e1ca --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test1.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8e741d300c..7b690ae778 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\s.read's\shelp\stell\sof\spiped\sinput -D 2021-12-28T05:08:38.128 +C Fix\sthe\sbuild-breaker\sbug\sin\stest1.c\sintroduced\sby\scheck-in\s[7fa20ca4c09ab024]. +D 2021-12-29T04:08:11.285 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -560,7 +560,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6 -F src/test1.c c24fe3a13ff78f5cbc29ac7049123e03ee1f33c6601646a45766c5f8d5db7f92 +F src/test1.c a02b46f382baadfdfb1a541caf55a26aae44619ad0cff4f6d27eeca84594636a F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -1934,8 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 -R 035fc7ecc447249d615762da61b11d6c -U larrybr -Z a3c99601a959abd1cb8e7bea62bdef11 +P e4ddcd8aa582c1130c34e9f05cd3e5f96ebf03c97a36c09ca442e3612fee4a20 +R 258b3a6c81183d6fd1aebc821d3d480b +U drh +Z c81e1f18d29297bc5455db4d8770f644 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 7aef9d428e..9adea975c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e4ddcd8aa582c1130c34e9f05cd3e5f96ebf03c97a36c09ca442e3612fee4a20 \ No newline at end of file +5f804da1820c98e7ff5c377e57e30b5154844b92ce622ed2ff888fe2c887e1ca \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 84d888ff37..520f4145ef 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4390,7 +4390,7 @@ static int SQLITE_TCLAPI test_error_offset( if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; iByteOffset = sqlite3_error_offset(db); - Tcl_SetObjResult(interp, Tcl_NewIntObj(zErr, -1)); + Tcl_SetObjResult(interp, Tcl_NewIntObj(iByteOffset)); return TCL_OK; } From 412a59f56ef2ce2865b4e862828d79377bbaeb68 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 29 Dec 2021 04:10:03 +0000 Subject: [PATCH 083/148] Change an assert() in FTS3 into assert_fts3_nc(), since it is a harmless condition that can occur when processing a corrupt database file. FossilOrigin-Name: e773d6219bded9a5dfa9930882682dadaa7f1c6be344dbde904c9477a89f2d2c --- ext/fts3/fts3.c | 2 +- manifest | 13 +++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 9a341a89a0..097338f547 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -4486,7 +4486,7 @@ void sqlite3Fts3DoclistPrev( assert( nDoclist>0 ); assert( *pbEof==0 ); - assert( p || *piDocid==0 ); + assert_fts3_nc( p || *piDocid==0 ); assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); if( p==0 ){ diff --git a/manifest b/manifest index a6c925887d..7ab3b3981c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sminor\sproblem\sin\sthe\sCLI\sintroduced\sby\s[d156123885abe6bf],\sapparently. -D 2021-12-24T19:44:11.241 +C Change\san\sassert()\sin\sFTS3\sinto\sassert_fts3_nc(),\ssince\sit\sis\sa\sharmless\ncondition\sthat\scan\soccur\swhen\sprocessing\sa\scorrupt\sdatabase\sfile. +D 2021-12-29T04:10:03.195 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -84,7 +84,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c f27e890395640be4938b9b554cad46fdf1e42e6bd7d64154bbac27d079d00f9e +F ext/fts3/fts3.c 6634a3854e70afa8710ee5e3a7253cd0f0c89d4cce207fcbfe2ead3bad1db7d5 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h dafdc371f9fbab175744b06cfe019d5f040cdfdbd11fea752f5dc28d45b04c05 F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f @@ -1934,8 +1934,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8af8c153f8c3fe16db1c2280571e005838c4ea3c48929ad7660a1686e49ed255 -R b3820a24a997ecbc0d96c676f9253e0d +P 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 +Q +c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 +R b29f920038d17a9c6443057c1293e2bc U drh -Z 32815daf40ab0d51da0a9e14b1eae912 +Z f41176ae032dbd299c6d7102c4fb4542 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b59febd5a3..90a6d390c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 \ No newline at end of file +e773d6219bded9a5dfa9930882682dadaa7f1c6be344dbde904c9477a89f2d2c \ No newline at end of file From 44c44cd7c5aa4b479bdf7bef525512d45c4b1aa6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 29 Dec 2021 04:10:49 +0000 Subject: [PATCH 084/148] Make .read's help tell of piped input FossilOrigin-Name: 155c3e9c7ccd6fd644cc64b027cf460112c491e5f9202dd76cefe2000936ad80 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 7ab3b3981c..5af43f2762 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\san\sassert()\sin\sFTS3\sinto\sassert_fts3_nc(),\ssince\sit\sis\sa\sharmless\ncondition\sthat\scan\soccur\swhen\sprocessing\sa\scorrupt\sdatabase\sfile. -D 2021-12-29T04:10:03.195 +C Make\s.read's\shelp\stell\sof\spiped\sinput +D 2021-12-29T04:10:49.377 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a -F src/shell.c.in 1b567fc5463470fb22f3e45a5dbf05ee2ce9dd9066b2973c4a2bdd7daa74bb5f +F src/shell.c.in a1e82e4fa3a357debe3a5e19766064339e45a7b94382abd7553fcf36cd6edbc6 F src/sqlite.h.in 5124aa99d3eb9b6a4e5030cb035076ed060d2dac020cd8fc8fba3022725d54af F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 @@ -1934,9 +1934,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 37e6e10f4364f556c7503c80408fc62895cdccdd0372fb2b63aaca02c3a1ee30 -Q +c03205aee9015fd886b8db02c8190899cee699255ca370f939e547deaf5ba9e8 -R b29f920038d17a9c6443057c1293e2bc +P e773d6219bded9a5dfa9930882682dadaa7f1c6be344dbde904c9477a89f2d2c +Q +e4ddcd8aa582c1130c34e9f05cd3e5f96ebf03c97a36c09ca442e3612fee4a20 +R 14c1f60040b224770372f56c44f369ea U drh -Z f41176ae032dbd299c6d7102c4fb4542 +Z b1b19652da5b10420ed86fb57926a031 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 90a6d390c2..1c6ee2bf05 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e773d6219bded9a5dfa9930882682dadaa7f1c6be344dbde904c9477a89f2d2c \ No newline at end of file +155c3e9c7ccd6fd644cc64b027cf460112c491e5f9202dd76cefe2000936ad80 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c6f623f5b7..43882c7853 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4100,7 +4100,8 @@ static const char *(azHelp[]) = { #endif ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", - ".read FILE Read input from FILE", + ".read FILE Read input from FILE or command output", + " If FILE begins with \"|\", it is a command that generates the input.", #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", From 41584df57383d48f61588625045cc067f0099656 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 29 Dec 2021 04:31:54 +0000 Subject: [PATCH 085/148] Ensure that the affinity of columns is honored in the RETURNING clause. See [forum:/forumpost/e0c7574ab2|forum post e0c7574ab2] for the bug report. FossilOrigin-Name: 4711fb69547f4f17653ab116030c32fdcc2c836410349d1d025866ffc15704da --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/resolve.c | 1 + src/trigger.c | 5 +++++ test/returning1.test | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 11d3f29ca8..d0b37a0071 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_error_offset()\sinterface.\sUse\sit\sto\senhance\serror\sreporting\nin\sthe\sCLI. -D 2021-12-29T04:13:37.296 +C Ensure\sthat\sthe\saffinity\sof\scolumns\sis\shonored\sin\sthe\sRETURNING\sclause.\nSee\s[forum:/forumpost/e0c7574ab2|forum\spost\se0c7574ab2]\sfor\sthe\sbug\sreport. +D 2021-12-29T04:31:54.399 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -548,7 +548,7 @@ F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c -F src/resolve.c 6144db65157ff96fe27e3e6f784ab331b3de35db233cd0a6e93278a5d23fcf06 +F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a359 @@ -616,7 +616,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 865911afa00fed589cd03b25c140ca88544842aaef7b81f7d41ed769a7a54120 F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc -F src/trigger.c 2ef56f0b7b75349a5557d0604b475126329c2e1a02432e7d49c4c710613e8254 +F src/trigger.c eaaba4e34cdce18bf6c633a4536d35e93c62684d3107d5563f0eae209640860c F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 @@ -1309,7 +1309,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2 F test/releasetest_data.tcl 7cea6c852ae6bb3a9ff1a2b910e4dd13c16a05f74443984dfd52159b0b01ea55 F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb -F test/returning1.test 76e4e8016e92a6abeaf15503fbf36deabbdc8b988d11edc2f7f82e18a56e35bd +F test/returning1.test ee0b115162b17f59fe486767899596b1e8290bcd845db05d7d1d9e6c2dad1b8b F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a @@ -1934,9 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 155c3e9c7ccd6fd644cc64b027cf460112c491e5f9202dd76cefe2000936ad80 5f804da1820c98e7ff5c377e57e30b5154844b92ce622ed2ff888fe2c887e1ca -R 258b3a6c81183d6fd1aebc821d3d480b -T +closed 5f804da1820c98e7ff5c377e57e30b5154844b92ce622ed2ff888fe2c887e1ca +P 416602a85101c2cd1705eb5306a8933e54cb05ae1562400395ec2769173dec01 +R f4950d8eb5e68670553d3ef4a059c1eb U drh -Z 52cc78f07738120203d38f1772740b4b +Z dbbd31fc9de5d8d6d989728469f60373 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 852ff49438..b68b8c8374 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -416602a85101c2cd1705eb5306a8933e54cb05ae1562400395ec2769173dec01 \ No newline at end of file +4711fb69547f4f17653ab116030c32fdcc2c836410349d1d025866ffc15704da \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index bf6900f239..5bcaf8dcd6 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -453,6 +453,7 @@ static int lookupName( pExpr->y.pTab = pTab; if( pParse->bReturning ){ eNewExprOp = TK_REGISTER; + pExpr->op2 = TK_COLUMN; pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable + sqlite3TableColumnToStorage(pTab, iCol) + 1; }else{ diff --git a/src/trigger.c b/src/trigger.c index a80ad40734..b69fbd6bb8 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -953,7 +953,12 @@ static void codeReturningTrigger( pReturning->iRetReg = reg; for(i=0; ia[i].pExpr; + assert( pCol!=0 || pParse->db->mallocFailed ); + if( pCol==0 ) continue; sqlite3ExprCodeFactorable(pParse, pCol, reg+i); + if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); + } } sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i); sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1); diff --git a/test/returning1.test b/test/returning1.test index b471544fd4..2b97b42348 100644 --- a/test/returning1.test +++ b/test/returning1.test @@ -346,4 +346,20 @@ do_catchsql_test 14.1 { INSERT INTO child(parent_id) VALUES(123) RETURNING id; } {1 {FOREIGN KEY constraint failed}} +# 2021-12-28 Forum post https://sqlite.org/forum/forumpost/e0c7574ab2 +# Incorrect affinity for REAL values that can be represented as integers. +# +reset_db +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db +do_execsql_test 15.0 { + CREATE TABLE t1(x REAL); + INSERT INTO t1(x) VALUES(5.0) RETURNING x, affinity(x); +} {5.0 real} +do_execsql_test 15.1 { + UPDATE t1 SET x=x+1 RETURNING x, affinity(x); +} {6.0 real} +do_execsql_test 15.2 { + DELETE FROM t1 RETURNING x, affinity(x); +} {6.0 real} + finish_test From 092ba22cca926af20f52bb331f4ec9a2c084a8a7 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 29 Dec 2021 13:32:36 +0000 Subject: [PATCH 086/148] Minor changes to shell1.test test results to account for the new feature of the shell that points to the specific part of the input line where the error occurs. FossilOrigin-Name: d4870c08893ea9984b1fa1c3a7d04893ad5ed4a2130e9287d169a306cc8ef0a4 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/shell1.test | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index d0b37a0071..f40bc439fc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sthe\saffinity\sof\scolumns\sis\shonored\sin\sthe\sRETURNING\sclause.\nSee\s[forum:/forumpost/e0c7574ab2|forum\spost\se0c7574ab2]\sfor\sthe\sbug\sreport. -D 2021-12-29T04:31:54.399 +C Minor\schanges\sto\sshell1.test\stest\sresults\sto\saccount\sfor\sthe\snew\sfeature\nof\sthe\sshell\sthat\spoints\sto\sthe\sspecific\spart\sof\sthe\sinput\sline\swhere\sthe\nerror\soccurs. +D 2021-12-29T13:32:36.797 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1380,7 +1380,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test c354008b27c904f0166c2138abd7382013ea070b41114114ecbdfb32c726a807 +F test/shell1.test e6c8fb4b710f29239392876c72ecc5a7f1d5d23e1f23838e5a6a2ccc9903d74f F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566 F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be @@ -1934,8 +1934,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 416602a85101c2cd1705eb5306a8933e54cb05ae1562400395ec2769173dec01 -R f4950d8eb5e68670553d3ef4a059c1eb +P 4711fb69547f4f17653ab116030c32fdcc2c836410349d1d025866ffc15704da +R 5c3dff46ade5dadb3b517884aaa3c5ff U drh -Z dbbd31fc9de5d8d6d989728469f60373 +Z 1ae7e3c1e437bcf89c5150a79373950f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b68b8c8374..40568e1ed4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4711fb69547f4f17653ab116030c32fdcc2c836410349d1d025866ffc15704da \ No newline at end of file +d4870c08893ea9984b1fa1c3a7d04893ad5ed4a2130e9287d169a306cc8ef0a4 \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index c4e2ceb88b..17d34c3ed1 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -53,7 +53,7 @@ do_test shell1-1.1.2 { # error on extra options do_test shell1-1.1.3 { catchcmd "test.db FOO test.db BAD" ".quit" -} {1 {Error: in prepare, near "FOO": syntax error (1)}} +} {/1 .Error: in prepare, near "FOO": syntax error (1)*/} # -help do_test shell1-1.2.1 { @@ -78,7 +78,7 @@ do_test shell1-1.3.2 { } {0 {}} do_test shell1-1.3.3 { catchcmd "-init FOO test.db BAD .quit" "" -} {1 {Error: in prepare, near "BAD": syntax error (1)}} +} {/1 .Error: in prepare, near "BAD": syntax error (1)*/} # -echo print commands before execution do_test shell1-1.4.1 { From 38cebe07bb41051eeeda8b11b63c02ea825f2a8b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 30 Dec 2021 00:37:11 +0000 Subject: [PATCH 087/148] When implementing a multi-way compound SELECT using merge, try to balance the merge tree. FossilOrigin-Name: bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04 --- manifest | 17 +++--- manifest.uuid | 2 +- src/select.c | 44 ++++++++++----- src/sqliteInt.h | 1 + src/test1.c | 1 + test/merge1.test | 138 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 180 insertions(+), 23 deletions(-) create mode 100644 test/merge1.test diff --git a/manifest b/manifest index f40bc439fc..9fe6b54a49 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\schanges\sto\sshell1.test\stest\sresults\sto\saccount\sfor\sthe\snew\sfeature\nof\sthe\sshell\sthat\spoints\sto\sthe\sspecific\spart\sof\sthe\sinput\sline\swhere\sthe\nerror\soccurs. -D 2021-12-29T13:32:36.797 +C When\simplementing\sa\smulti-way\scompound\sSELECT\susing\smerge,\stry\sto\sbalance\nthe\smerge\stree. +D 2021-12-30T00:37:11.863 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -550,17 +550,17 @@ F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c a7a3d9f54eb24821ec5f67f2e5589b68a5d42d46fc5849d7376886777d93a85a +F src/select.c bc130367361e68d3705e0756f913bb8433bccfb0187e0756455308c558b5699a F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a359 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef -F src/sqliteInt.h 418dd1a178abcc40b86b39cee972083822b17e84888fe56ed7a3b00b473d8bb5 +F src/sqliteInt.h 850b013088c4cce47763ce795712135081d47bd21a105bfa62dd431dc66f93b7 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6 -F src/test1.c a02b46f382baadfdfb1a541caf55a26aae44619ad0cff4f6d27eeca84594636a +F src/test1.c f13fe747afc7d9af189ce0cdaaf641252c5803db2a32bd3525eec2905c7b4f37 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -1206,6 +1206,7 @@ F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 +F test/merge1.test c5abf7d4eca25b3d5ee96927efff18efc3cee5a8af54b8415cbddd6d4471fd70 F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a71a F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 @@ -1934,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4711fb69547f4f17653ab116030c32fdcc2c836410349d1d025866ffc15704da -R 5c3dff46ade5dadb3b517884aaa3c5ff +P d4870c08893ea9984b1fa1c3a7d04893ad5ed4a2130e9287d169a306cc8ef0a4 +R 92d42c20b7697c4ca818b90b713774b8 U drh -Z 1ae7e3c1e437bcf89c5150a79373950f +Z 36a1d0b63e6b59c361f9d34272782b8a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 40568e1ed4..923d31690c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4870c08893ea9984b1fa1c3a7d04893ad5ed4a2130e9287d169a306cc8ef0a4 \ No newline at end of file +bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 7f15c2acb2..b89f09a958 100644 --- a/src/select.c +++ b/src/select.c @@ -3296,6 +3296,8 @@ static int multiSelectOrderBy( ){ int i, j; /* Loop counters */ Select *pPrior; /* Another SELECT immediately to our left */ + Select *pSplit; /* Left-most SELECT in the right-hand group */ + int nSelect; /* Number of SELECT statements in the compound */ Vdbe *v; /* Generate code to this VDBE */ SelectDest destA; /* Destination for coroutine A */ SelectDest destB; /* Destination for coroutine B */ @@ -3341,8 +3343,7 @@ static int multiSelectOrderBy( /* Patch up the ORDER BY clause */ op = p->op; - pPrior = p->pPrior; - assert( pPrior->pOrderBy==0 ); + assert( p->pPrior->pOrderBy==0 ); pOrderBy = p->pOrderBy; assert( pOrderBy ); nOrderBy = pOrderBy->nExpr; @@ -3392,11 +3393,6 @@ static int multiSelectOrderBy( pKeyMerge = 0; } - /* Reattach the ORDER BY clause to the query. - */ - p->pOrderBy = pOrderBy; - pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); - /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). @@ -3421,9 +3417,30 @@ static int multiSelectOrderBy( /* Separate the left and the right query from one another */ - p->pPrior = 0; + nSelect = 1; + if( (op==TK_ALL || op==TK_UNION) + && OptimizationEnabled(db, SQLITE_BalancedMerge) + ){ + for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){ + nSelect++; + assert( pSplit->pPrior->pNext==pSplit ); + } + } + if( nSelect<=3 ){ + pSplit = p; + }else{ + pSplit = p; + for(i=2; ipPrior; } + } + pPrior = pSplit->pPrior; + pSplit->pPrior = 0; pPrior->pNext = 0; - sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); + assert( p->pOrderBy == pOrderBy ); + assert( pOrderBy!=0 || db->mallocFailed ); + pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); + if( p->pPrior==0 ){ + sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); + } if( pPrior->pPrior==0 ){ sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); } @@ -3577,12 +3594,11 @@ static int multiSelectOrderBy( /* Reassembly the compound query so that it will be freed correctly ** by the calling function */ - if( p->pPrior ){ - sqlite3SelectDelete(db, p->pPrior); + if( pSplit->pPrior ){ + sqlite3SelectDelete(db, pSplit->pPrior); } - p->pPrior = pPrior; - pPrior->pNext = p; - + pSplit->pPrior = pPrior; + pPrior->pNext = pSplit; sqlite3ExprListDelete(db, pPrior->pOrderBy); pPrior->pOrderBy = 0; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 092bbccdc6..ac2414a248 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1764,6 +1764,7 @@ struct sqlite3 { /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ +#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* diff --git a/src/test1.c b/src/test1.c index 520f4145ef..b7fdd2a4bf 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7512,6 +7512,7 @@ static int SQLITE_TCLAPI optimization_control( { "stat4", SQLITE_Stat4 }, { "skip-scan", SQLITE_SkipScan }, { "push-down", SQLITE_PushDown }, + { "balanced-merge", SQLITE_BalancedMerge }, }; if( objc!=4 ){ diff --git a/test/merge1.test b/test/merge1.test new file mode 100644 index 0000000000..e4a7d657b3 --- /dev/null +++ b/test/merge1.test @@ -0,0 +1,138 @@ +# 2021-12-29 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Testing the compound-SELECT merge algorithm to ensure that it works +# when it tries to balance the merge tree. + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix merge1 + +load_static_extension db series + + +optimization_control db all on +do_execsql_test 100 { + WITH data(v) AS ( + SELECT value FROM generate_series(1,35,3) + UNION ALL + SELECT value FROM generate_series(10,30,4) + UNION ALL + SELECT value FROM generate_series(20,50,5) + UNION ALL + SELECT value FROM generate_series(30,60,6) + UNION ALL + SELECT value FROM generate_series(1,50,7) + UNION ALL + SELECT value FROM generate_series(10,80,8) + ) + SELECT v FROM data ORDER BY v; +} {1 1 4 7 8 10 10 10 13 14 15 16 18 18 19 20 22 22 22 25 25 26 26 28 29 30 30 30 31 34 34 35 36 36 40 42 42 43 45 48 50 50 50 54 58 60 66 74} +do_eqp_test 101 { + WITH data(v) AS ( + SELECT value FROM generate_series(1,35,3) + UNION ALL + SELECT value FROM generate_series(10,30,4) + UNION ALL + SELECT value FROM generate_series(20,50,5) + UNION ALL + SELECT value FROM generate_series(30,60,6) + UNION ALL + SELECT value FROM generate_series(1,50,7) + UNION ALL + SELECT value FROM generate_series(10,80,8) + ) + SELECT v FROM data ORDER BY v; +} { + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | `--MERGE (UNION ALL) + | |--LEFT + | | `--MERGE (UNION ALL) + | | |--LEFT + | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | | `--RIGHT + | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | `--RIGHT + | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + `--RIGHT + `--MERGE (UNION ALL) + |--LEFT + | `--MERGE (UNION ALL) + | |--LEFT + | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | `--RIGHT + | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + `--RIGHT + `--SCAN generate_series VIRTUAL TABLE INDEX 23: +} + +# Same test with the blanced-merge optimization +# disabled. Should give the exact same answer. +# +optimization_control db balanced-merge off +db cache flush +do_execsql_test 110 { + WITH data(v) AS ( + SELECT value FROM generate_series(1,35,3) + UNION ALL + SELECT value FROM generate_series(10,30,4) + UNION ALL + SELECT value FROM generate_series(20,50,5) + UNION ALL + SELECT value FROM generate_series(30,60,6) + UNION ALL + SELECT value FROM generate_series(1,50,7) + UNION ALL + SELECT value FROM generate_series(10,80,8) + ) + SELECT v FROM data ORDER BY v; +} {1 1 4 7 8 10 10 10 13 14 15 16 18 18 19 20 22 22 22 25 25 26 26 28 29 30 30 30 31 34 34 35 36 36 40 42 42 43 45 48 50 50 50 54 58 60 66 74} +do_eqp_test 111 { + WITH data(v) AS ( + SELECT value FROM generate_series(1,35,3) + UNION ALL + SELECT value FROM generate_series(10,30,4) + UNION ALL + SELECT value FROM generate_series(20,50,5) + UNION ALL + SELECT value FROM generate_series(30,60,6) + UNION ALL + SELECT value FROM generate_series(1,50,7) + UNION ALL + SELECT value FROM generate_series(10,80,8) + ) + SELECT v FROM data ORDER BY v; +} { + QUERY PLAN + `--MERGE (UNION ALL) + |--LEFT + | `--MERGE (UNION ALL) + | |--LEFT + | | `--MERGE (UNION ALL) + | | |--LEFT + | | | `--MERGE (UNION ALL) + | | | |--LEFT + | | | | `--MERGE (UNION ALL) + | | | | |--LEFT + | | | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | | | | `--RIGHT + | | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | | | `--RIGHT + | | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | | `--RIGHT + | | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + | `--RIGHT + | `--SCAN generate_series VIRTUAL TABLE INDEX 23: + `--RIGHT + `--SCAN generate_series VIRTUAL TABLE INDEX 23: +} From 66306d86abcd27aae87b39581fa54f9d3eb68d92 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 30 Dec 2021 02:38:43 +0000 Subject: [PATCH 088/148] When a table has an INTEGER PRIMARY KEY ON CONFLICT REPLACE and some other uniqueness constraint, and it participates in an upsert on that other constraint, ensure that code that checks for conflicts on the INTEGER PRIMARY KEY is well-formed. Fix for the problem reported by [forum:/forumpost/06b16b8b29f8c8c3|forum post 06b16b8b29f8c8c3]. FossilOrigin-Name: 2f09b51b1ff37bf98f958564cc1224968caa7e33147e6666b5c1ba20b2a7813b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 2 ++ test/upsert1.test | 14 ++++++++++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9fe6b54a49..19d1f8c84e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\simplementing\sa\smulti-way\scompound\sSELECT\susing\smerge,\stry\sto\sbalance\nthe\smerge\stree. -D 2021-12-30T00:37:11.863 +C When\sa\stable\shas\san\sINTEGER\sPRIMARY\sKEY\sON\sCONFLICT\sREPLACE\sand\ssome\sother\nuniqueness\sconstraint,\sand\sit\sparticipates\sin\san\supsert\son\sthat\sother\nconstraint,\sensure\sthat\scode\sthat\schecks\sfor\sconflicts\son\sthe\sINTEGER\sPRIMARY\nKEY\sis\swell-formed.\s\sFix\sfor\sthe\sproblem\sreported\sby\n[forum:/forumpost/06b16b8b29f8c8c3|forum\spost\s06b16b8b29f8c8c3]. +D 2021-12-30T02:38:43.462 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -511,7 +511,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c e0293a6f686e18cb2c9dd0619a731518e0109d7e1f1db1932974659e7843cfd1 +F src/insert.c 89c51ecb327d83a5eaf6e781aec8c77e2daec8777ca19781a1258bdafbe67de6 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c aa24539f6c26460543d51027ea14b79cad35e34bc9d4907bc349b52b71066644 @@ -1676,7 +1676,7 @@ F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666 F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342bbd6b F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0 F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6 -F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266fb18 +F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2 F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d4870c08893ea9984b1fa1c3a7d04893ad5ed4a2130e9287d169a306cc8ef0a4 -R 92d42c20b7697c4ca818b90b713774b8 +P bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04 +R b0ae1f32fc54818f4c3193bd26e96d2b U drh -Z 36a1d0b63e6b59c361f9d34272782b8a +Z 676489b32b06402ed90daf3898799cb4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 923d31690c..39fb95940b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04 \ No newline at end of file +2f09b51b1ff37bf98f958564cc1224968caa7e33147e6666b5c1ba20b2a7813b \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 96e86c9fb2..6908aff4a9 100644 --- a/src/insert.c +++ b/src/insert.c @@ -2007,6 +2007,7 @@ void sqlite3GenerateConstraintChecks( if( onError==OE_Replace /* IPK rule is REPLACE */ && onError!=overrideError /* Rules for other constraints are different */ && pTab->pIndex /* There exist other constraints */ + && !upsertIpkDelay /* IPK check already deferred by UPSERT */ ){ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; VdbeComment((v, "defer IPK REPLACE until last")); @@ -2415,6 +2416,7 @@ void sqlite3GenerateConstraintChecks( if( ipkTop ){ sqlite3VdbeGoto(v, ipkTop); VdbeComment((v, "Do IPK REPLACE")); + assert( ipkBottom>0 ); sqlite3VdbeJumpHere(v, ipkBottom); } diff --git a/test/upsert1.test b/test/upsert1.test index 5250a5d2f5..a321d6171d 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -241,4 +241,18 @@ do_catchsql_test upsert1-1000 { ON CONFLICT(c2) DO UPDATE SET c1 = c0; } {1 {NOT NULL constraint failed: t0.c0}} +# 2021-12-29 forum post https://sqlite.org/forum/forumpost/06b16b8b29f8c8c3 +# By Jingzhou Fu. When there is both an INTEGER PRIMARY KEY ON CONFLICT REPLACE +# and an upsert on a constraint other than the INTEGER PRIMARY KEY, the +# constraint checking logic generates invalid bytecode which might result +# in a NULL pointer dereference. +# +reset_db +do_execsql_test upsert1-1100 { + CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE); + INSERT INTO t1(b) VALUES(22); + INSERT INTO t1 VALUES(2,22) ON CONFLICT (b) DO NOTHING; + SELECT * FROM t1; +} {1 22} + finish_test From e1961c55c393ff1c5ba6b88515cadac6e685a9ea Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 30 Dec 2021 17:36:54 +0000 Subject: [PATCH 089/148] When constructing the sqlite3_index_info object for the xBestIndex method of a virtual table, omit constant trims from the ORDER BY clause, as they will always be in the correct order. FossilOrigin-Name: 524c2b87d74c8cad6fb377aed7275788d61beafe61e675480de732519987102c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 15 +++++++++++---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 19d1f8c84e..a869e1965a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sa\stable\shas\san\sINTEGER\sPRIMARY\sKEY\sON\sCONFLICT\sREPLACE\sand\ssome\sother\nuniqueness\sconstraint,\sand\sit\sparticipates\sin\san\supsert\son\sthat\sother\nconstraint,\sensure\sthat\scode\sthat\schecks\sfor\sconflicts\son\sthe\sINTEGER\sPRIMARY\nKEY\sis\swell-formed.\s\sFix\sfor\sthe\sproblem\sreported\sby\n[forum:/forumpost/06b16b8b29f8c8c3|forum\spost\s06b16b8b29f8c8c3]. -D 2021-12-30T02:38:43.462 +C When\sconstructing\sthe\ssqlite3_index_info\sobject\sfor\sthe\sxBestIndex\smethod\nof\sa\svirtual\stable,\somit\sconstant\strims\sfrom\sthe\sORDER\sBY\sclause,\sas\sthey\nwill\salways\sbe\sin\sthe\scorrect\sorder. +D 2021-12-30T17:36:54.703 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -637,7 +637,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 18d32aa675078a6e3b181138c59d70c07c0f8b8f439124991f95bb6a84fab1d8 +F src/where.c eedf0311d59095bcd8523bd13bf25865e1caf1fab9beddbff9093340a1a409c7 F src/whereInt.h 91865afa4a3540bb3bd643619acc56fbceff7defeb8f249b8e157fd5325d88be F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6 F src/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04 -R b0ae1f32fc54818f4c3193bd26e96d2b +P 2f09b51b1ff37bf98f958564cc1224968caa7e33147e6666b5c1ba20b2a7813b +R 723804026d511a012324b02198fe2bb2 U drh -Z 676489b32b06402ed90daf3898799cb4 +Z 6d2de5fa4529370d9c153afd0702b588 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 39fb95940b..52a3dfcf19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2f09b51b1ff37bf98f958564cc1224968caa7e33147e6666b5c1ba20b2a7813b \ No newline at end of file +524c2b87d74c8cad6fb377aed7275788d61beafe61e675480de732519987102c \ No newline at end of file diff --git a/src/where.c b/src/where.c index 02964c92c7..35bad3f696 100644 --- a/src/where.c +++ b/src/where.c @@ -1164,6 +1164,11 @@ static sqlite3_index_info *allocateIndexInfo( Expr *pExpr = pOrderBy->a[i].pExpr; Expr *pE2; + /* Skip over constant terms in the ORDER BY clause */ + if( sqlite3ExprIsConstant(pExpr) ){ + continue; + } + /* Virtual tables are unable to deal with NULLS FIRST */ if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break; @@ -1211,7 +1216,6 @@ static sqlite3_index_info *allocateIndexInfo( pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - pIdxInfo->nOrderBy = nOrderBy; pIdxInfo->aConstraint = pIdxCons; pIdxInfo->aOrderBy = pIdxOrderBy; pIdxInfo->aConstraintUsage = pUsage; @@ -1258,14 +1262,17 @@ static sqlite3_index_info *allocateIndexInfo( } assert( j==nTerm ); pIdxInfo->nConstraint = j; - for(i=0; ia[i].pExpr; + if( sqlite3ExprIsConstant(pExpr) ) continue; assert( pExpr->op==TK_COLUMN || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN && pExpr->iColumn==pExpr->pLeft->iColumn) ); - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; + pIdxOrderBy[j].iColumn = pExpr->iColumn; + pIdxOrderBy[j].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; + j++; } + pIdxInfo->nOrderBy = j; *pmNoOmit = mNoOmit; return pIdxInfo; From 9aff824090261c4fa893bb860c36cfe2989508b4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 30 Dec 2021 17:46:15 +0000 Subject: [PATCH 090/148] Remove unnecessary conditionals around the ORDER BY resolver calls in multiSelectOrderBy(). FossilOrigin-Name: f2887e018be71bc406526935c7e99e42f12fc5d1d1c65a89dc2b9bfbca01d43d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 8 ++------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index a869e1965a..e50c8478d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sconstructing\sthe\ssqlite3_index_info\sobject\sfor\sthe\sxBestIndex\smethod\nof\sa\svirtual\stable,\somit\sconstant\strims\sfrom\sthe\sORDER\sBY\sclause,\sas\sthey\nwill\salways\sbe\sin\sthe\scorrect\sorder. -D 2021-12-30T17:36:54.703 +C Remove\sunnecessary\sconditionals\saround\sthe\sORDER\sBY\sresolver\scalls\sin\nmultiSelectOrderBy(). +D 2021-12-30T17:46:15.485 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -550,7 +550,7 @@ F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c bc130367361e68d3705e0756f913bb8433bccfb0187e0756455308c558b5699a +F src/select.c 342e096c2737a3ee60753e91de6e6660c7f59cd2988b3e1ab641d38fd885003f F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a359 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2f09b51b1ff37bf98f958564cc1224968caa7e33147e6666b5c1ba20b2a7813b -R 723804026d511a012324b02198fe2bb2 +P 524c2b87d74c8cad6fb377aed7275788d61beafe61e675480de732519987102c +R f797199d3004b4800cca92d57aa013a0 U drh -Z 6d2de5fa4529370d9c153afd0702b588 +Z 2ac044172bdb3856fa63346532f0ce74 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 52a3dfcf19..6462eeb7cf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -524c2b87d74c8cad6fb377aed7275788d61beafe61e675480de732519987102c \ No newline at end of file +f2887e018be71bc406526935c7e99e42f12fc5d1d1c65a89dc2b9bfbca01d43d \ No newline at end of file diff --git a/src/select.c b/src/select.c index b89f09a958..c33903f107 100644 --- a/src/select.c +++ b/src/select.c @@ -3438,12 +3438,8 @@ static int multiSelectOrderBy( assert( p->pOrderBy == pOrderBy ); assert( pOrderBy!=0 || db->mallocFailed ); pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); - if( p->pPrior==0 ){ - sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); - } - if( pPrior->pPrior==0 ){ - sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); - } + sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); + sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); /* Compute the limit registers */ computeLimitRegisters(pParse, p, labelEnd); From b296ab6f6ab89f0c13f1f42dc19983a973a4eef5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 31 Dec 2021 16:37:46 +0000 Subject: [PATCH 091/148] Move the pTriggerPrg and pCleanup elements of the Parse object up into the section of that object that is persisted across calls to sqlite3NestedParse(). This fixes a memory leak [forum:/info/24bd1fef7e9323ef|reported in forum post 24bd1fef7e9323ef]. FossilOrigin-Name: 562805cf488a455cdc57adcb110fef9b5416d813d5eaeabacd28bccb76d7f39d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e50c8478d0..ee16c3e68a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunnecessary\sconditionals\saround\sthe\sORDER\sBY\sresolver\scalls\sin\nmultiSelectOrderBy(). -D 2021-12-30T17:46:15.485 +C Move\sthe\spTriggerPrg\sand\spCleanup\selements\sof\sthe\sParse\sobject\sup\sinto\sthe\nsection\sof\sthat\sobject\sthat\sis\spersisted\sacross\scalls\sto\ssqlite3NestedParse().\nThis\sfixes\sa\smemory\sleak\n[forum:/info/24bd1fef7e9323ef|reported\sin\sforum\spost\s24bd1fef7e9323ef]. +D 2021-12-31T16:37:46.839 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -555,7 +555,7 @@ F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a35 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef -F src/sqliteInt.h 850b013088c4cce47763ce795712135081d47bd21a105bfa62dd431dc66f93b7 +F src/sqliteInt.h 443810b432d6af91178b3b2e79fe2f71502cff2372bb9c68be1a18e9ebfb4200 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 524c2b87d74c8cad6fb377aed7275788d61beafe61e675480de732519987102c -R f797199d3004b4800cca92d57aa013a0 +P f2887e018be71bc406526935c7e99e42f12fc5d1d1c65a89dc2b9bfbca01d43d +R f92b26ddc80815fd1b38eeec1ac33f28 U drh -Z 2ac044172bdb3856fa63346532f0ce74 +Z 599b2f8e047fc42e8e3708e7636d643f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6462eeb7cf..68de1d46fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2887e018be71bc406526935c7e99e42f12fc5d1d1c65a89dc2b9bfbca01d43d \ No newline at end of file +562805cf488a455cdc57adcb110fef9b5416d813d5eaeabacd28bccb76d7f39d \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ac2414a248..1b6f60211d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3559,6 +3559,8 @@ struct Parse { AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ union { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ @@ -3613,9 +3615,7 @@ struct Parse { Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif - TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ - ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif From 16118265ca18fc6ea57355c235802f0b65d98102 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 31 Dec 2021 17:54:48 +0000 Subject: [PATCH 092/148] Performance optimization and size reduction in sqlite3RunParser(). FossilOrigin-Name: 41ee2bac5731d8434322e92abba580f7c759a137e576dd286fe01ab23fc440ea --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/prepare.c | 4 ++++ src/tokenize.c | 23 ++++++----------------- src/vtab.c | 4 ++-- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index ee16c3e68a..23b746487b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sthe\spTriggerPrg\sand\spCleanup\selements\sof\sthe\sParse\sobject\sup\sinto\sthe\nsection\sof\sthat\sobject\sthat\sis\spersisted\sacross\scalls\sto\ssqlite3NestedParse().\nThis\sfixes\sa\smemory\sleak\n[forum:/info/24bd1fef7e9323ef|reported\sin\sforum\spost\s24bd1fef7e9323ef]. -D 2021-12-31T16:37:46.839 +C Performance\soptimization\sand\ssize\sreduction\sin\ssqlite3RunParser(). +D 2021-12-31T17:54:48.326 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -545,7 +545,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad -F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719 +F src/prepare.c 5954136ca8956eb69b515dc383abd38c2277e7c1aec898046955a430bd7243dc F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 @@ -614,7 +614,7 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 865911afa00fed589cd03b25c140ca88544842aaef7b81f7d41ed769a7a54120 +F src/tokenize.c 3c30e91482db69318c05e3d98510922df5d99367aed150ea01e0cd85a0a86171 F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc F src/trigger.c eaaba4e34cdce18bf6c633a4536d35e93c62684d3107d5563f0eae209640860c F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 @@ -632,7 +632,7 @@ F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c -F src/vtab.c 9d5c3f49d3a6959b6eef287bb8fa773563102a80a835c3314c57144412709e78 +F src/vtab.c 0eddd6bed345115fb87961eb591b5dd7466fd5a09bd71cfde8af5845cf1548e8 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f2887e018be71bc406526935c7e99e42f12fc5d1d1c65a89dc2b9bfbca01d43d -R f92b26ddc80815fd1b38eeec1ac33f28 +P 562805cf488a455cdc57adcb110fef9b5416d813d5eaeabacd28bccb76d7f39d +R 25305ed262ec223a33704138fc00f328 U drh -Z 599b2f8e047fc42e8e3708e7636d643f +Z 0b5fdf153f96ad1c566fd124031d0ac0 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 68de1d46fc..1cc3555c07 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -562805cf488a455cdc57adcb110fef9b5416d813d5eaeabacd28bccb76d7f39d \ No newline at end of file +41ee2bac5731d8434322e92abba580f7c759a137e576dd286fe01ab23fc440ea \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 183a749a5f..f9031d369b 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -570,6 +570,10 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ */ void sqlite3ParserReset(Parse *pParse){ sqlite3 *db = pParse->db; + assert( pParse->nested==0 ); +#ifndef SQLITE_OMIT_SHARED_CACHE + sqlite3DbFree(db, pParse->aTableLock); +#endif while( pParse->pCleanup ){ ParseCleanup *pCleanup = pParse->pCleanup; pParse->pCleanup = pCleanup->pNext; diff --git a/src/tokenize.c b/src/tokenize.c index e128d16148..a1fa2333d2 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -686,11 +686,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM_BKPT; } - if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ - pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); - } assert( pzErrMsg!=0 ); - if( pParse->zErrMsg ){ + if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){ + if( pParse->zErrMsg==0 ){ + pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); + } *pzErrMsg = pParse->zErrMsg; sqlite3_log(pParse->rc, "%s in \"%s\"", *pzErrMsg, pParse->zTail); @@ -698,29 +698,18 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ nErr++; } pParse->zTail = zSql; - if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ - sqlite3VdbeDelete(pParse->pVdbe); - pParse->pVdbe = 0; - } -#ifndef SQLITE_OMIT_SHARED_CACHE - if( pParse->nested==0 ){ - sqlite3DbFree(db, pParse->aTableLock); - pParse->aTableLock = 0; - pParse->nTableLock = 0; - } -#endif #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_free(pParse->apVtabLock); #endif - if( !IN_SPECIAL_PARSE ){ + if( pParse->pNewTable && !IN_SPECIAL_PARSE ){ /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(db, pParse->pNewTable); } - if( !IN_RENAME_OBJECT ){ + if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){ sqlite3DeleteTrigger(db, pParse->pNewTrigger); } sqlite3DbFree(db, pParse->pVList); diff --git a/src/vtab.c b/src/vtab.c index 2c787c6c44..81d39a6763 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -837,8 +837,8 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ db->init.busy = 0; sParse.nQueryLoop = 1; if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) - && sParse.pNewTable - && !db->mallocFailed + && ALWAYS(sParse.pNewTable!=0) + && ALWAYS(!db->mallocFailed) && IsOrdinaryTable(sParse.pNewTable) ){ if( !pTab->aCol ){ From 2b5fbb2836f1674ddcc493e149eb992ef04fb92d Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 31 Dec 2021 18:26:50 +0000 Subject: [PATCH 093/148] Fix harmless compiler warnings seen with MSVC. FossilOrigin-Name: a9bfb621091b6d92d1caeb69134d3809d9e0b43fe764608c5995db277ac785be --- ext/rtree/test_rtreedoc.c | 2 +- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/btree.c | 12 ++++++------ src/vdbeaux.c | 2 +- tool/logest.c | 2 +- tool/showdb.c | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ext/rtree/test_rtreedoc.c b/ext/rtree/test_rtreedoc.c index 3272d89eca..119be0e0ad 100644 --- a/ext/rtree/test_rtreedoc.c +++ b/ext/rtree/test_rtreedoc.c @@ -304,7 +304,7 @@ static int box_query(sqlite3_rtree_query_info *pInfo){ static void box_query_destroy(void *p){ BoxQueryCtx *pCtx = (BoxQueryCtx*)p; Tcl_DecrRefCount(pCtx->pScript); - ckfree(pCtx); + ckfree((char*)pCtx); } static int SQLITE_TCLAPI register_box_query( diff --git a/manifest b/manifest index 23b746487b..d276290439 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\sand\ssize\sreduction\sin\ssqlite3RunParser(). -D 2021-12-31T17:54:48.326 +C Fix\sharmless\scompiler\swarnings\sseen\swith\sMSVC. +D 2021-12-31T18:26:50.397 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -425,7 +425,7 @@ F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c F ext/rtree/rtreedoc3.test 555a878c4d79c4e37fa439a1c3b02ee65d3ebaf75d9e8d96a9c55d66db3efbf8 F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373 -F ext/rtree/test_rtreedoc.c 0167f9243a56d08e79230f604f3979d6b7cde4816355acf7a7d436d9d788bf38 +F ext/rtree/test_rtreedoc.c 5ad4029d6804eb9efafcac1598a9e0582f6119e48f818854f5b4db1788ca8bd4 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 06abea6fbd9e28f86c8fcb2edfd3fb3afde388750a4f7f5fa425935a789c1f5c +F src/btree.c ea774b39e4515a2fc3dd49288ec01d2939063645124a906876b45b9d9b74787f F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 107e1ecc98ca8965c2e08fc283a06067a1d829b1a82531a6f0a0e0fa60e7b0c1 @@ -626,7 +626,7 @@ F src/vdbe.c b63594839cbf770a29e2b3b81570971a3d2c1c995c0586aade09bb548142113a F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h a7f01b0cd0dcb496343eacd37b0839250f9a718199ab6096e3995db42dec3ec8 F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a -F src/vdbeaux.c 175f2dad949150abdf0d91d19b2b6db30ff3776af5a84008db4bfe5e12a60180 +F src/vdbeaux.c 44b4c238425726a7e790ce54dc4aef3be3fb7ef46a70f09adb5e84c0361824ec F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652 F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 @@ -1857,7 +1857,7 @@ F tool/lemon.c 258881835bd5bccd0c74fb110fe54244ff18e8e7ef3d949cbdab7187f02132bb F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 -F tool/logest.c 83dbfda91615f1db5dce38215303d8bb456f437342d2c64262406dbdd1c931e2 +F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669 F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8 @@ -1885,7 +1885,7 @@ F tool/replace.tcl 937c931ad560688e85bdd6258bdc754371bb1e2732e1fb28ef441e44c9228 F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076 -F tool/showdb.c 7cc12c6deeddfe40ba5d948b408730696d8365988da05fcb6b6a90ea4965e2b4 +F tool/showdb.c 72239e95e1d05a2941c6a1d86b4d857812be4dadd71f24e381db572f350fc172 F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818 F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564 F tool/showshm.c a0ab6ec32dd1f11218ca2a4018f8fb875b59414801ab8ceed8b2e69b7b45a809 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 562805cf488a455cdc57adcb110fef9b5416d813d5eaeabacd28bccb76d7f39d -R 25305ed262ec223a33704138fc00f328 -U drh -Z 0b5fdf153f96ad1c566fd124031d0ac0 +P 41ee2bac5731d8434322e92abba580f7c759a137e576dd286fe01ab23fc440ea +R b0a7dd44482c5be2e68108a439febe52 +U mistachkin +Z 46256d6e3bf1f3f7dad778b8be9d4e45 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1cc3555c07..16b317827c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -41ee2bac5731d8434322e92abba580f7c759a137e576dd286fe01ab23fc440ea \ No newline at end of file +a9bfb621091b6d92d1caeb69134d3809d9e0b43fe764608c5995db277ac785be \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6ffc6b6a1a..53643fcb85 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1246,7 +1246,7 @@ static void btreeParseCellPtr( pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); + testcase( nPayload==(u32)pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -1283,7 +1283,7 @@ static void btreeParseCellPtrIndex( pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); + testcase( nPayload==(u32)pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -1346,7 +1346,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ while( (*pIter++)&0x80 && pItermaxLocal ); - testcase( nSize==pPage->maxLocal+1 ); + testcase( nSize==(u32)pPage->maxLocal+1 ); if( nSize<=pPage->maxLocal ){ nSize += (u32)(pIter - pCell); if( nSize<4 ) nSize = 4; @@ -1354,7 +1354,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ int minLocal = pPage->minLocal; nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); testcase( nSize==pPage->maxLocal ); - testcase( nSize==pPage->maxLocal+1 ); + testcase( nSize==(u32)pPage->maxLocal+1 ); if( nSize>pPage->maxLocal ){ nSize = minLocal; } @@ -4253,7 +4253,7 @@ 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 ); + testcase( pBt->nPage!=(u32)nPage ); pBt->nPage = nPage; } @@ -6828,7 +6828,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ ptr = &pPage->aCellIdx[2*idx]; pc = get2byte(ptr); hdr = pPage->hdrOffset; - testcase( pc==get2byte(&data[hdr+5]) ); + testcase( pc==(u32)get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); if( pc+sz > pPage->pBt->usableSize ){ *pRC = SQLITE_CORRUPT_BKPT; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 6fe81e95fa..5441b79e80 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -4936,7 +4936,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ /* The index entry must begin with a header size */ getVarint32NR((u8*)m.z, szHdr); testcase( szHdr==3 ); - testcase( szHdr==m.n ); + testcase( szHdr==(u32)m.n ); testcase( szHdr>0x7fffffff ); assert( m.n>=0 ); if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ diff --git a/tool/logest.c b/tool/logest.c index 580a3a6f96..d916b43d39 100644 --- a/tool/logest.c +++ b/tool/logest.c @@ -75,7 +75,7 @@ static sqlite3_uint64 logEstToInt(LogEst x){ x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; - if( x>60 ) return ((sqlite3_uint64)0xffffffff)<<32 + 0xffffffff; + if( x>60 ) return (((sqlite3_uint64)0xffffffff)<<32)+(sqlite3_uint64)0xffffffff; if( x>=3 ) return (n+8)<<(x-3); return (n+8)>>(3-x); } diff --git a/tool/showdb.c b/tool/showdb.c index 3c91967ed1..611e603fe9 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -726,7 +726,7 @@ static void decode_btree_page( } if( showMap ){ printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n"); - for(i=0; i0 && pgno<=g.mxPage && (cnt++)0 && pgno<=g.mxPage && (u32)(cnt++) Date: Fri, 31 Dec 2021 19:08:20 +0000 Subject: [PATCH 094/148] Fix harmless compiler warnings in the shell. FossilOrigin-Name: f3ea36d79b6aa95470bf13e8d4ed5250a6b19bc16032b29e4dcdfc49b47a1edf --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 10 +++++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index d276290439..c07959aa9a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings\sseen\swith\sMSVC. -D 2021-12-31T18:26:50.397 +C Fix\sharmless\scompiler\swarnings\sin\sthe\sshell. +D 2021-12-31T19:08:20.353 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 342e096c2737a3ee60753e91de6e6660c7f59cd2988b3e1ab641d38fd885003f -F src/shell.c.in 41b0e1f3a0c2443cb0a8d25e5d40529c911c574b5fe5a91dc54e19f90947a359 +F src/shell.c.in de39d52ee7e8e09522c13ac2321616708f10ebe959b668da012ae8489cb7d1d4 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 41ee2bac5731d8434322e92abba580f7c759a137e576dd286fe01ab23fc440ea -R b0a7dd44482c5be2e68108a439febe52 +P a9bfb621091b6d92d1caeb69134d3809d9e0b43fe764608c5995db277ac785be +R 8f8baa71ff5df10e3e6517216cc3c3ae U mistachkin -Z 46256d6e3bf1f3f7dad778b8be9d4e45 +Z 10e25b5578b3a488f35983b9b1800460 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 16b317827c..d7d162aef6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a9bfb621091b6d92d1caeb69134d3809d9e0b43fe764608c5995db277ac785be \ No newline at end of file +f3ea36d79b6aa95470bf13e8d4ed5250a6b19bc16032b29e4dcdfc49b47a1edf \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 1bc57873da..ec39da54b7 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3391,7 +3391,10 @@ static void exec_prepared_stmt( if( pArg->cMode==MODE_Json ){ fputs("]\n", pArg->out); }else if( pArg->cMode==MODE_Count ){ - printf("%llu row%s\n", nRow, nRow!=1 ? "s" : ""); + char zBuf[200]; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n", + nRow, nRow!=1 ? "s" : ""); + printf("%s", zBuf); } } } @@ -9538,9 +9541,10 @@ static int do_meta_command(char *zLine, ShellState *p){ appendText(&sSelect, ") WHERE ", 0); if( zName ){ char *zQarg = sqlite3_mprintf("%Q", zName); + int bGlob; shell_check_oom(zQarg); - int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || - strchr(zName, '[') != 0; + bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || + strchr(zName, '[') != 0; if( strchr(zName, '.') ){ appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); }else{ From 54bc63815a14bc0c47d3d3f1bbecdf9eddd4feff Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 31 Dec 2021 19:20:42 +0000 Subject: [PATCH 095/148] Simplify the sqlite3RunParser() routine by omitting the third parameter. Results in a binary that is about 100 bytes smaller and 1.4M cycles faster. FossilOrigin-Name: 6fb2a1bb0280d6e31291e3fd06bbcbbb28ef5fb27d3898e2327a50ac738ae1f3 --- manifest | 24 ++++++++++++------------ manifest.uuid | 2 +- src/alter.c | 6 +----- src/build.c | 4 +--- src/prepare.c | 13 ++++++------- src/sqliteInt.h | 2 +- src/tokenize.c | 16 ++++------------ src/vtab.c | 9 +++++---- 8 files changed, 31 insertions(+), 45 deletions(-) diff --git a/manifest b/manifest index c07959aa9a..743fe4b858 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings\sin\sthe\sshell. -D 2021-12-31T19:08:20.353 +C Simplify\sthe\ssqlite3RunParser()\sroutine\sby\somitting\sthe\sthird\sparameter.\nResults\sin\sa\sbinary\sthat\sis\sabout\s100\sbytes\ssmaller\sand\s1.4M\scycles\sfaster. +D 2021-12-31T19:20:42.871 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -484,7 +484,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 23743384e59f9d36df870ce41adfdf7934fd0adb619d7fa6fd1aac77c28a7533 +F src/alter.c 16f8d91b1e4b3e6d897a5fa510c8dc1b07608271035a5dd8406bc98f651a40dc F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516 F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf @@ -494,7 +494,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c ea774b39e4515a2fc3dd49288ec01d2939063645124a906876b45b9d9b74787f F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c 107e1ecc98ca8965c2e08fc283a06067a1d829b1a82531a6f0a0e0fa60e7b0c1 +F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -545,7 +545,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad -F src/prepare.c 5954136ca8956eb69b515dc383abd38c2277e7c1aec898046955a430bd7243dc +F src/prepare.c 4c1c54616073050a1e03336355962103289db3b8ecbb233ae08c25b7f9324ab2 F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 @@ -555,7 +555,7 @@ F src/shell.c.in de39d52ee7e8e09522c13ac2321616708f10ebe959b668da012ae8489cb7d1d F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef -F src/sqliteInt.h 443810b432d6af91178b3b2e79fe2f71502cff2372bb9c68be1a18e9ebfb4200 +F src/sqliteInt.h 66637abecd93d743bea7a728d92c2eb5005dc838b203d676f008173a9c55c167 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -614,7 +614,7 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 3c30e91482db69318c05e3d98510922df5d99367aed150ea01e0cd85a0a86171 +F src/tokenize.c dc5367c6d42336b35d55f96d2f04cd6256e92bc6ecf74ed5d855d24e43343aff F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc F src/trigger.c eaaba4e34cdce18bf6c633a4536d35e93c62684d3107d5563f0eae209640860c F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 @@ -632,7 +632,7 @@ F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c -F src/vtab.c 0eddd6bed345115fb87961eb591b5dd7466fd5a09bd71cfde8af5845cf1548e8 +F src/vtab.c a47cc12ebaa350800c0c87b6b0095debbb5a6ed32727bcab9d82ad070a81b738 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c ed0398a7adf02c31e34aada42cc86c58f413a7afe5f741a5d373ad087abde028 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a9bfb621091b6d92d1caeb69134d3809d9e0b43fe764608c5995db277ac785be -R 8f8baa71ff5df10e3e6517216cc3c3ae -U mistachkin -Z 10e25b5578b3a488f35983b9b1800460 +P f3ea36d79b6aa95470bf13e8d4ed5250a6b19bc16032b29e4dcdfc49b47a1edf +R 9f315582dd5d865f63102dfe890440d6 +U drh +Z 5c22c4e1b2b7a7ad1f263c1472848dc2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d7d162aef6..dca455e62e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f3ea36d79b6aa95470bf13e8d4ed5250a6b19bc16032b29e4dcdfc49b47a1edf \ No newline at end of file +6fb2a1bb0280d6e31291e3fd06bbcbbb28ef5fb27d3898e2327a50ac738ae1f3 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index bb43edbeda..f76a59dea6 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1126,7 +1126,6 @@ static int renameParseSql( int bTemp /* True if SQL is from temp schema */ ){ int rc; - char *zErr = 0; db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); @@ -1137,10 +1136,7 @@ static int renameParseSql( p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; - rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM; - assert( p->zErrMsg==0 ); - assert( rc!=SQLITE_OK || zErr==0 ); - p->zErrMsg = zErr; + rc = zSql ? sqlite3RunParser(p, zSql) : SQLITE_NOMEM; if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 diff --git a/src/build.c b/src/build.c index c7ba85fe75..b93dd91e1c 100644 --- a/src/build.c +++ b/src/build.c @@ -307,7 +307,6 @@ void sqlite3FinishCoding(Parse *pParse){ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; - char *zErrMsg = 0; sqlite3 *db = pParse->db; u32 savedDbFlags = db->mDbFlags; char saveBuf[PARSE_TAIL_SZ]; @@ -329,9 +328,8 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); db->mDbFlags |= DBFLAG_PreferBuiltin; - sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3RunParser(pParse, zSql); db->mDbFlags = savedDbFlags; - sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; diff --git a/src/prepare.c b/src/prepare.c index f9031d369b..54176b4296 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -653,7 +653,6 @@ static int sqlite3Prepare( sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - char *zErrMsg = 0; /* Error message */ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ Parse sParse; /* Parsing context */ @@ -728,14 +727,14 @@ static int sqlite3Prepare( } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3RunParser(&sParse, zSqlCopy); sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; sqlite3DbFree(db, zSqlCopy); }else{ sParse.zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(&sParse, zSql, &zErrMsg); + sqlite3RunParser(&sParse, zSql); } assert( 0==sParse.nQueryLoop ); @@ -759,14 +758,14 @@ static int sqlite3Prepare( } assert( 0==(*ppStmt) ); rc = sParse.rc; - if( zErrMsg ){ - sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); - sqlite3DbFree(db, zErrMsg); + if( sParse.zErrMsg ){ + sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg); + sqlite3DbFree(db, sParse.zErrMsg); }else{ sqlite3Error(db, rc); } }else{ - assert( zErrMsg==0 ); + assert( sParse.zErrMsg==0 ); *ppStmt = (sqlite3_stmt*)sParse.pVdbe; rc = SQLITE_OK; sqlite3ErrorClear(db); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1b6f60211d..14f4e0c104 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4406,7 +4406,7 @@ void sqlite3DequoteExpr(Expr*); void sqlite3DequoteToken(Token*); void sqlite3TokenInit(Token*,char*); int sqlite3KeywordCode(const unsigned char*, int); -int sqlite3RunParser(Parse*, const char*, char **); +int sqlite3RunParser(Parse*, const char*); void sqlite3FinishCoding(Parse*); int sqlite3GetTempReg(Parse*); void sqlite3ReleaseTempReg(Parse*,int); diff --git a/src/tokenize.c b/src/tokenize.c index a1fa2333d2..5f41e5665e 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -559,13 +559,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ } /* -** Run the parser on the given SQL string. The parser structure is -** passed in. An SQLITE_ status code is returned. If an error occurs -** then an and attempt is made to write an error message into -** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that -** error message. +** Run the parser on the given SQL string. */ -int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ +int sqlite3RunParser(Parse *pParse, const char *zSql){ int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ @@ -586,7 +582,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ } pParse->rc = SQLITE_OK; pParse->zTail = zSql; - assert( pzErrMsg!=0 ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_ParserTrace ){ printf("parser: [[[%s]]]\n", zSql); @@ -629,6 +624,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ #endif /* SQLITE_OMIT_WINDOWFUNC */ if( AtomicLoad(&db->u1.isInterrupted) ){ pParse->rc = SQLITE_INTERRUPT; + pParse->nErr++; break; } if( tokenType==TK_SPACE ){ @@ -686,15 +682,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM_BKPT; } - assert( pzErrMsg!=0 ); if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){ if( pParse->zErrMsg==0 ){ pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); } - *pzErrMsg = pParse->zErrMsg; - sqlite3_log(pParse->rc, "%s in \"%s\"", - *pzErrMsg, pParse->zTail); - pParse->zErrMsg = 0; + sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail); nErr++; } pParse->zTail = zSql; diff --git a/src/vtab.c b/src/vtab.c index 81d39a6763..ef86dd6bd4 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -807,7 +807,6 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; int rc = SQLITE_OK; Table *pTab; - char *zErr = 0; Parse sParse; int initBusy; @@ -836,11 +835,12 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ initBusy = db->init.busy; db->init.busy = 0; sParse.nQueryLoop = 1; - if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) + if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) && ALWAYS(sParse.pNewTable!=0) && ALWAYS(!db->mallocFailed) && IsOrdinaryTable(sParse.pNewTable) ){ + assert( sParse.zErrMsg==0 ); if( !pTab->aCol ){ Table *pNew = sParse.pNewTable; Index *pIdx; @@ -870,8 +870,9 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } pCtx->bDeclared = 1; }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, + (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg); + sqlite3DbFree(db, sParse.zErrMsg); rc = SQLITE_ERROR; } sParse.eParseMode = PARSE_MODE_NORMAL; From 017e36378716dade19b23bde94cd3678ca2fdd4c Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 31 Dec 2021 22:53:15 +0000 Subject: [PATCH 096/148] Mark the REGEXP operator in the built-in extension as deterministic. FossilOrigin-Name: e654b57a9fc32021453eed48d1c1bba65c833fb1aac3946567968c877e4cbd10 --- ext/misc/regexp.c | 10 ++++++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ext/misc/regexp.c b/ext/misc/regexp.c index f282e777f0..b626ca424a 100644 --- a/ext/misc/regexp.c +++ b/ext/misc/regexp.c @@ -759,13 +759,15 @@ int sqlite3_regexp_init( int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused */ - rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, - 0, re_sql_func, 0, 0); + rc = sqlite3_create_function(db, "regexp", 2, + SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, + 0, re_sql_func, 0, 0); if( rc==SQLITE_OK ){ /* The regexpi(PATTERN,STRING) function is a case-insensitive version ** of regexp(PATTERN,STRING). */ - rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, - (void*)db, re_sql_func, 0, 0); + rc = sqlite3_create_function(db, "regexpi", 2, + SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, + (void*)db, re_sql_func, 0, 0); } return rc; } diff --git a/manifest b/manifest index 743fe4b858..e5460b6ec6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\ssqlite3RunParser()\sroutine\sby\somitting\sthe\sthird\sparameter.\nResults\sin\sa\sbinary\sthat\sis\sabout\s100\sbytes\ssmaller\sand\s1.4M\scycles\sfaster. -D 2021-12-31T19:20:42.871 +C Mark\sthe\sREGEXP\soperator\sin\sthe\sbuilt-in\sextension\sas\sdeterministic. +D 2021-12-31T22:53:15.455 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -316,7 +316,7 @@ F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1 F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691 F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196 -F ext/misc/regexp.c 8cd0d2d904bf7014ba28beab8c1d502b5154e04a8c738b079d88e4ecca1b3981 +F ext/misc/regexp.c b267fd05ff8d38b22f4c2809d7b7a2c61d522e9faf2feb928dbb9662e4a3a386 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946 @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f3ea36d79b6aa95470bf13e8d4ed5250a6b19bc16032b29e4dcdfc49b47a1edf -R 9f315582dd5d865f63102dfe890440d6 +P 6fb2a1bb0280d6e31291e3fd06bbcbbb28ef5fb27d3898e2327a50ac738ae1f3 +R 37524ca7e93af6feb4e0c3addac0faab U drh -Z 5c22c4e1b2b7a7ad1f263c1472848dc2 +Z 4c0eed7b705bf6eda3da29ad39dbce44 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index dca455e62e..f87f8afd4d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6fb2a1bb0280d6e31291e3fd06bbcbbb28ef5fb27d3898e2327a50ac738ae1f3 \ No newline at end of file +e654b57a9fc32021453eed48d1c1bba65c833fb1aac3946567968c877e4cbd10 \ No newline at end of file From 3907560848c1b98b71f801968f54903ecb144412 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 1 Jan 2022 12:26:01 +0000 Subject: [PATCH 097/148] Fix a faulty assert() statement - adding a CORRUPT_DB term - based on a test case derived from [562805cf488a455c]. Also add a test case to that prior issue. FossilOrigin-Name: 0dd6b5fccd554ebe4c0b081601863acd7b6ea81b51e14b508b23244f2a570e7e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 2 +- test/fkey1.test | 30 ++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e5460b6ec6..3484db080c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Mark\sthe\sREGEXP\soperator\sin\sthe\sbuilt-in\sextension\sas\sdeterministic. -D 2021-12-31T22:53:15.455 +C Fix\sa\sfaulty\sassert()\sstatement\s-\sadding\sa\sCORRUPT_DB\sterm\s-\sbased\son\sa\stest\ncase\sderived\sfrom\s[562805cf488a455c].\s\sAlso\sadd\sa\stest\scase\sto\sthat\sprior\nissue. +D 2022-01-01T12:26:01.367 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -511,7 +511,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 89c51ecb327d83a5eaf6e781aec8c77e2daec8777ca19781a1258bdafbe67de6 +F src/insert.c 5ab24fdf063051d85aa817fa28e70f903cd49e095babd5a55ae84293a0a001fe F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c aa24539f6c26460543d51027ea14b79cad35e34bc9d4907bc349b52b71066644 @@ -907,7 +907,7 @@ F test/filter1.test 6c483ecf7886c8843a8612c021aa23f33c581f584151f251842b3a3592c9 F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8 F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b -F test/fkey1.test 03503639d266d565db90ee3b8fe211ba446624030ac4eb24895cec265e9631d0 +F test/fkey1.test 55663090ab6735319a52647057b9f19f8ec8c6c7d7da25170b71a75e3e5bdeb7 F test/fkey2.test 1063d65e5923c054cfb8f0555a92a3ae0fa8c067275a33ee1715bd856cdb304c F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6fb2a1bb0280d6e31291e3fd06bbcbbb28ef5fb27d3898e2327a50ac738ae1f3 -R 37524ca7e93af6feb4e0c3addac0faab +P e654b57a9fc32021453eed48d1c1bba65c833fb1aac3946567968c877e4cbd10 +R 335bbf0c37894e30c180f2036d145b89 U drh -Z 4c0eed7b705bf6eda3da29ad39dbce44 +Z a949c1d59f03a232196d70c605423a0e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f87f8afd4d..59358243b1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e654b57a9fc32021453eed48d1c1bba65c833fb1aac3946567968c877e4cbd10 \ No newline at end of file +0dd6b5fccd554ebe4c0b081601863acd7b6ea81b51e14b508b23244f2a570e7e \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 6908aff4a9..54592fd9c0 100644 --- a/src/insert.c +++ b/src/insert.c @@ -43,7 +43,7 @@ void sqlite3OpenTable( }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); - assert( pPk->tnum==pTab->tnum ); + assert( pPk->tnum==pTab->tnum || CORRUPT_DB ); sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pPk); VdbeComment((v, "%s", pTab->zName)); diff --git a/test/fkey1.test b/test/fkey1.test index 13635db987..db93be501d 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -241,5 +241,35 @@ do_execsql_test 7.2 { PRAGMA foreign_key_check; } {} +# 2021-12-31 forum https://sqlite.org/forum/forumpost/24bd1fef7e9323ef +# Memory leak caused by sqlite3NestedParse() running on a corrupt system +# table. Discovered by Jingzhou Fu. +# +reset_db +do_execsql_test 8.1 { + PRAGMA writable_schema=ON; + PRAGMA foreign_keys = ON; + CREATE TABLE sqlite_stat1 (tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID; + PRAGMA writable_schema=OFF; + CREATE TABLE sqlsim4(stat PRIMARY KEY);; + CREATE TABLE t1(sqlsim7 REFERENCES sqlite_stat1 ON DELETE CASCADE); + DROP table "sqlsim4"; +} {} +# 2022-01-01 dbsqlfuzz 1c57440219f6f0aedf5e8f72a8ddd75f15aea381 +# Follow-up case to the above. Assertion is not true if the schema +# is corrupt. +reset_db +database_may_be_corrupt +do_execsql_test 8.2 { + CREATE TABLE t1(a REFERENCES sqlite_stat1 ON DELETE CASCADE); + CREATE TABLE t2(a TEXT PRIMARY KEY); + PRAGMA writable_schema=ON; + CREATE TABLE sqlite_stat1(tbl INTEGER PRIMARY KEY DESC, idx UNIQUE DEFAULT NULL) WITHOUT ROWID; + UPDATE sqlite_schema SET name='sqlite_autoindex_sqlite_stat1_1' WHERE name='sqlite_autoindex_sqlite_stat1_2'; + PRAGMA writable_schema=RESET; +} {} +do_catchsql_test 8.3 { + REINDEX; +} {1 {database disk image is malformed}} finish_test From 3ea82384ea99529a4cd3f0f9e97eaa1f3aa0fd21 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 1 Jan 2022 17:21:55 +0000 Subject: [PATCH 098/148] Remove an obsolete assert() statement that no longer does anything useful and which is not always true. Fix for PoC #1 of [forum:/forumpost/b03d86f951|forum post b03d86f951]. FossilOrigin-Name: c76a4c0b3cb625017ba09c8bccfcf1b5826df6873f1d3705d3345716079d5ec9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 1 - test/without_rowid1.test | 17 ++++++++++++++++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 3484db080c..1ade3a9399 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfaulty\sassert()\sstatement\s-\sadding\sa\sCORRUPT_DB\sterm\s-\sbased\son\sa\stest\ncase\sderived\sfrom\s[562805cf488a455c].\s\sAlso\sadd\sa\stest\scase\sto\sthat\sprior\nissue. -D 2022-01-01T12:26:01.367 +C Remove\san\sobsolete\sassert()\sstatement\sthat\sno\slonger\sdoes\sanything\suseful\nand\swhich\sis\snot\salways\strue.\s\sFix\sfor\sPoC\s#1\sof\n[forum:/forumpost/b03d86f951|forum\spost\sb03d86f951]. +D 2022-01-01T17:21:55.030 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -511,7 +511,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 5ab24fdf063051d85aa817fa28e70f903cd49e095babd5a55ae84293a0a001fe +F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c aa24539f6c26460543d51027ea14b79cad35e34bc9d4907bc349b52b71066644 @@ -1817,7 +1817,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982 F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8 F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 -F test/without_rowid1.test df3de14f1cc422d2b0f9b79969b5ef8e51c86ed87834ab35fb5139403e7f5a03 +F test/without_rowid1.test 78fd9b437f4cdb46f76e6a510d545334e4f58e3e4ce37aaf19384eda5b27de8c F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a @@ -1935,8 +1935,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e654b57a9fc32021453eed48d1c1bba65c833fb1aac3946567968c877e4cbd10 -R 335bbf0c37894e30c180f2036d145b89 +P 0dd6b5fccd554ebe4c0b081601863acd7b6ea81b51e14b508b23244f2a570e7e +R 93fe07409816797ce5872fd05e1ee3e9 U drh -Z a949c1d59f03a232196d70c605423a0e +Z 59c1a6b5d78ba93ba2850de6200793f1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 59358243b1..4b0a012579 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0dd6b5fccd554ebe4c0b081601863acd7b6ea81b51e14b508b23244f2a570e7e \ No newline at end of file +c76a4c0b3cb625017ba09c8bccfcf1b5826df6873f1d3705d3345716079d5ec9 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 54592fd9c0..9a02ec6954 100644 --- a/src/insert.c +++ b/src/insert.c @@ -2547,7 +2547,6 @@ void sqlite3CompleteInsertion( } pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); if( update_flags==0 ){ diff --git a/test/without_rowid1.test b/test/without_rowid1.test index c712392688..1191115527 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -470,5 +470,20 @@ ifcapable altertable { EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10; } {~/b=/} } - + +# 2022-01-01 https://sqlite.org/forum/forumpost/b03d86f951 PoC #1 +# Omit an assert() from 2013 that no longer serves any purpose and +# is no longer always true. +# +reset_db +do_execsql_test 15.1 { + PRAGMA writable_schema=ON; + CREATE TABLE sqlite_sequence (name PRIMARY KEY) WITHOUT ROWID; + PRAGMA writable_schema=OFF; + CREATE TABLE c1(x); + INSERT INTO sqlite_sequence(name) VALUES('c0'),('c1'),('c2'); + ALTER TABLE c1 RENAME TO a; + SELECT name FROM sqlite_sequence ORDER BY +name; +} {a c0 c2} + finish_test From 0f42f71da22bfa7bb8285f180c71c672e3448f43 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 1 Jan 2022 19:29:50 +0000 Subject: [PATCH 099/148] Fix an obscure problem with releasing savepoints stored in an in-memory journal that could cause subsequent savepoint rollback to fail. FossilOrigin-Name: 73c2b50211d3ae26aeb89976ec7b9fcd7de9f152b283ec7d0809ad18bddc603e --- manifest | 17 ++++++------ manifest.uuid | 2 +- src/memjournal.c | 2 +- src/pager.c | 2 +- test/memjournal2.test | 62 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 test/memjournal2.test diff --git a/manifest b/manifest index 1ade3a9399..7326a4f792 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sobsolete\sassert()\sstatement\sthat\sno\slonger\sdoes\sanything\suseful\nand\swhich\sis\snot\salways\strue.\s\sFix\sfor\sPoC\s#1\sof\n[forum:/forumpost/b03d86f951|forum\spost\sb03d86f951]. -D 2022-01-01T17:21:55.030 +C Fix\san\sobscure\sproblem\swith\sreleasing\ssavepoints\sstored\sin\san\sin-memory\sjournal\sthat\scould\scause\ssubsequent\ssavepoint\srollback\sto\sfail. +D 2022-01-01T19:29:50.963 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -522,7 +522,7 @@ F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75 F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6 F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memdb.c c2dc88f97c410eb68a24468344b65526685e18354ddfd15906750c1eaf9dc2dd -F src/memjournal.c a85f0dc5c02a42453d0bc3819ecfb5666cb6433e5deefcd93ccbe05c9f088b83 +F src/memjournal.c ff4336a98b05ede2adee7595f22d6f7d1cdc6bf0f0a5c3d77b0acdf017b2e8b2 F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8 F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25 F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a @@ -537,7 +537,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c bc10c191d18bffd3d76eda5f162799e43a9f875ecfe7c4869f752e2ddef87ea2 +F src/pager.c b0f75fde773ad69da997fe57153cdef53c5f0bcf4cd4c7dda19f5fd8e7fb488b F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1203,6 +1203,7 @@ F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 F test/memdb1.test 2c4e9cc10d21c6bf4e217d72b7f6b8ba9b2605971bb2c5e6df76018e189f98f5 F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c +F test/memjournal2.test 89a4e0d1084170a281efa4d54c2677599f986f44227f98f7dfae282802737b65 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1935,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0dd6b5fccd554ebe4c0b081601863acd7b6ea81b51e14b508b23244f2a570e7e -R 93fe07409816797ce5872fd05e1ee3e9 -U drh -Z 59c1a6b5d78ba93ba2850de6200793f1 +P c76a4c0b3cb625017ba09c8bccfcf1b5826df6873f1d3705d3345716079d5ec9 +R f593fb4a8952c091aa397b2514cd432f +U dan +Z 6c6040c92604f299f7398e773f45f985 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4b0a012579..603ee48d7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c76a4c0b3cb625017ba09c8bccfcf1b5826df6873f1d3705d3345716079d5ec9 \ No newline at end of file +73c2b50211d3ae26aeb89976ec7b9fcd7de9f152b283ec7d0809ad18bddc603e \ No newline at end of file diff --git a/src/memjournal.c b/src/memjournal.c index 598d5cc026..63ef2ad7b9 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -265,7 +265,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ p->pFirst = 0; }else{ i64 iOff = p->nChunkSize; - for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){ + for(pIter=p->pFirst; ALWAYS(pIter) && iOffpNext){ iOff += p->nChunkSize; } if( ALWAYS(pIter) ){ diff --git a/src/pager.c b/src/pager.c index 0ed5848343..1d295896bc 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3917,7 +3917,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ #if defined(SQLITE_DEBUG) static void assertTruncateConstraintCb(PgHdr *pPg){ assert( pPg->flags&PGHDR_DIRTY ); - assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); + assert( pPg->pgno<=pPg->pPager->dbSize || !subjRequiresPage(pPg) ); } static void assertTruncateConstraint(Pager *pPager){ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); diff --git a/test/memjournal2.test b/test/memjournal2.test new file mode 100644 index 0000000000..97d35a98d1 --- /dev/null +++ b/test/memjournal2.test @@ -0,0 +1,62 @@ +# 2022 Jan 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. +# +#*********************************************************************** +# Tests focused on the in-memory journal. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set testprefix memjournal2 + +do_execsql_test 1.0 { + PRAGMA journal_mode = memory; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE); +} {memory} + +set nRow [expr 2000] + +do_execsql_test 1.1 { + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<$nRow + ) + INSERT INTO t1 SELECT NULL, randomblob(700) FROM s; +} + +for {set jj 200} {$jj <= 300} {incr jj} { + do_execsql_test 1.2.$jj.1 { + SAVEPOINT one; + UPDATE t1 SET b=randomblob(700) WHERE a<=$jj; + } + do_execsql_test 1.2.$jj.2 { + SAVEPOINT two; + UPDATE t1 SET b=randomblob(700) WHERE a==1; + ROLLBACK TO two; + RELEASE two; + } + do_execsql_test 1.2.$jj.3 { + SAVEPOINT two; + UPDATE t1 SET b=randomblob(700) WHERE a==1; + ROLLBACK TO two; + RELEASE two; + } + + do_execsql_test 1.2.$jj.4 { + PRAGMA integrity_check; + ROLLBACK TO one; + RELEASE one; + } {ok} +} + + +finish_test + + From a6ca90c38ce1c3247fbd8ed9bd5377a1a67d2868 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 1 Jan 2022 19:55:29 +0000 Subject: [PATCH 100/148] Attempt to fix a harmless compiler warning in FTS5. FossilOrigin-Name: 8e619c21e2326be1538b60908e7cd211558ec840835c6eb69e768eb190e1fd0b --- ext/fts5/fts5_index.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index fe253984b3..6b88f31c02 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5565,7 +5565,7 @@ int sqlite3Fts5IndexQuery( if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ int iIdx = 0; /* Index to search */ int iPrefixIdx = 0; /* +1 prefix index */ - if( nToken ) memcpy(&buf.p[1], pToken, nToken); + if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken); /* Figure out which index to search and set iIdx accordingly. If this ** is a prefix query for which there is no prefix index, set iIdx to diff --git a/manifest b/manifest index 7326a4f792..b3a6634158 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sobscure\sproblem\swith\sreleasing\ssavepoints\sstored\sin\san\sin-memory\sjournal\sthat\scould\scause\ssubsequent\ssavepoint\srollback\sto\sfail. -D 2022-01-01T19:29:50.963 +C Attempt\sto\sfix\sa\sharmless\scompiler\swarning\sin\sFTS5. +D 2022-01-01T19:55:29.471 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -118,7 +118,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292 F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422f6c2078aa F ext/fts5/fts5_expr.c fcd0770d53028c2b53a15d0f53bf6d0e01b1bf3dd97630b9fedf0801f03aa3ec F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982 -F ext/fts5/fts5_index.c b1b2e5d4a9e3b54c740d8354cc47e3fa879f54c2176de55e0b882dab45ab7b07 +F ext/fts5/fts5_index.c fdfbc8a62827ec1d1b6f207a1e59c1c4986c3ce245592b5128ffe738867cfcd1 F ext/fts5/fts5_main.c 7c6092a53e6802962fa07b0fad3e61cb077b6c98b74b727d8d44ac2cf63bd914 F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c76a4c0b3cb625017ba09c8bccfcf1b5826df6873f1d3705d3345716079d5ec9 -R f593fb4a8952c091aa397b2514cd432f -U dan -Z 6c6040c92604f299f7398e773f45f985 +P 73c2b50211d3ae26aeb89976ec7b9fcd7de9f152b283ec7d0809ad18bddc603e +R 81090d8353ee3f936c93337e56dfc232 +U drh +Z 765a5c4cd45e00d0f6e7d0350955b24c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 603ee48d7c..5603314e9f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -73c2b50211d3ae26aeb89976ec7b9fcd7de9f152b283ec7d0809ad18bddc603e \ No newline at end of file +8e619c21e2326be1538b60908e7cd211558ec840835c6eb69e768eb190e1fd0b \ No newline at end of file From 4ce289d0886282d7906e473452ddd7c49956607d Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 1 Jan 2022 20:02:58 +0000 Subject: [PATCH 101/148] Fix an assert() in pager.c to avoid the possibility of side-effects. FossilOrigin-Name: 1d1fe03c752267f03f015ada975876f65e2a7b967e19f057b5c73f95d7df8a9c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pager.c | 13 ++++++++++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b3a6634158..0baf199afc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Attempt\sto\sfix\sa\sharmless\scompiler\swarning\sin\sFTS5. -D 2022-01-01T19:55:29.471 +C Fix\san\sassert()\sin\spager.c\sto\savoid\sthe\spossibility\sof\sside-effects. +D 2022-01-01T20:02:58.185 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -537,7 +537,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c b0f75fde773ad69da997fe57153cdef53c5f0bcf4cd4c7dda19f5fd8e7fb488b +F src/pager.c dda556cb412e66c3d4016214ef2dd63d9019ad24d1ceff871b79dcb860981f77 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 73c2b50211d3ae26aeb89976ec7b9fcd7de9f152b283ec7d0809ad18bddc603e -R 81090d8353ee3f936c93337e56dfc232 -U drh -Z 765a5c4cd45e00d0f6e7d0350955b24c +P 8e619c21e2326be1538b60908e7cd211558ec840835c6eb69e768eb190e1fd0b +R 6db54dc637e31deb110e7ca557bebf75 +U dan +Z 3630f18f1280e005938a7d4c214cb21c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5603314e9f..bc10a1482a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e619c21e2326be1538b60908e7cd211558ec840835c6eb69e768eb190e1fd0b \ No newline at end of file +1d1fe03c752267f03f015ada975876f65e2a7b967e19f057b5c73f95d7df8a9c \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 1d295896bc..045bd8040e 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3900,8 +3900,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ ** current database image, in pages, OR ** ** b) if the page content were written at this time, it would not -** be necessary to write the current content out to the sub-journal -** (as determined by function subjRequiresPage()). +** be necessary to write the current content out to the sub-journal. ** ** If the condition asserted by this function were not true, and the ** dirty page were to be discarded from the cache via the pagerStress() @@ -3916,8 +3915,16 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ */ #if defined(SQLITE_DEBUG) static void assertTruncateConstraintCb(PgHdr *pPg){ + Pager *pPager = pPg->pPager; assert( pPg->flags&PGHDR_DIRTY ); - assert( pPg->pgno<=pPg->pPager->dbSize || !subjRequiresPage(pPg) ); + if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */ + Pgno pgno = pPg->pgno; + int i; + for(i=0; ipPager->nSavepoint; i++){ + PagerSavepoint *p = &pPager->aSavepoint[i]; + assert( p->nOrigpInSavepoint,pgno) ); + } + } } static void assertTruncateConstraint(Pager *pPager){ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); From 24a82eadb34162b278e0a3c2115b167d2487d300 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 1 Jan 2022 22:55:31 +0000 Subject: [PATCH 102/148] Do not raise an SQLITE_SCHEMA error if in sqlite3Init(). Fix for PoC #2 in [forum:/forumpost/b03d86f951|forum post b03d86f951]. See TH3 for test cases. FossilOrigin-Name: e199a851e316bd471bfc54204b8c250d3ae93b829261214158a2c74acad4093e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/prepare.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0baf199afc..2a236160a5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sin\spager.c\sto\savoid\sthe\spossibility\sof\sside-effects. -D 2022-01-01T20:02:58.185 +C Do\snot\sraise\san\sSQLITE_SCHEMA\serror\sif\sin\ssqlite3Init().\s\sFix\sfor\sPoC\s#2\sin\n[forum:/forumpost/b03d86f951|forum\spost\sb03d86f951].\s\sSee\sTH3\sfor\stest\ncases. +D 2022-01-01T22:55:31.616 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -545,7 +545,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad -F src/prepare.c 4c1c54616073050a1e03336355962103289db3b8ecbb233ae08c25b7f9324ab2 +F src/prepare.c 45fe7408eb78d80eca8392669070a6e5caf231b09e5c7b1ff65c1ad64a3734c5 F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8e619c21e2326be1538b60908e7cd211558ec840835c6eb69e768eb190e1fd0b -R 6db54dc637e31deb110e7ca557bebf75 -U dan -Z 3630f18f1280e005938a7d4c214cb21c +P 1d1fe03c752267f03f015ada975876f65e2a7b967e19f057b5c73f95d7df8a9c +R f15a1845feed9e7d6592a8459d433a16 +U drh +Z c10bc7ddd6a7f2304a3228c439a3f0e6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bc10a1482a..4e75864d0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d1fe03c752267f03f015ada975876f65e2a7b967e19f057b5c73f95d7df8a9c \ No newline at end of file +e199a851e316bd471bfc54204b8c250d3ae93b829261214158a2c74acad4093e \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 54176b4296..d2cc2d098c 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -750,7 +750,7 @@ static int sqlite3Prepare( sParse.checkSchema = 0; } if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){ - if( sParse.checkSchema ){ + if( sParse.checkSchema && db->init.busy==0 ){ schemaIsValid(&sParse); } if( sParse.pVdbe ){ From 2dfe9664a900b05ec7ca5a24c29f8fce6e36d984 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 11:25:51 +0000 Subject: [PATCH 103/148] Earlier detection of corruption in sqlite3BtreeDelete(). Fix for the assertion fault reported by [forum:/forumpost/9d78389221|forum post 9d78389221]. FossilOrigin-Name: 13e9ff9e84a114374b49986484dbee05953a496f3017dd5089fba6f495a17c40 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 11 +++++++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2a236160a5..7770701f04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sraise\san\sSQLITE_SCHEMA\serror\sif\sin\ssqlite3Init().\s\sFix\sfor\sPoC\s#2\sin\n[forum:/forumpost/b03d86f951|forum\spost\sb03d86f951].\s\sSee\sTH3\sfor\stest\ncases. -D 2022-01-01T22:55:31.616 +C Earlier\sdetection\sof\scorruption\sin\ssqlite3BtreeDelete().\s\sFix\sfor\nthe\sassertion\sfault\sreported\sby\n[forum:/forumpost/9d78389221|forum\spost\s9d78389221]. +D 2022-01-02T11:25:51.036 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c ea774b39e4515a2fc3dd49288ec01d2939063645124a906876b45b9d9b74787f +F src/btree.c fab3d2a9e2a187373c393b9f35e68e996010a1aae1354763f7c5846915a99b83 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1d1fe03c752267f03f015ada975876f65e2a7b967e19f057b5c73f95d7df8a9c -R f15a1845feed9e7d6592a8459d433a16 +P e199a851e316bd471bfc54204b8c250d3ae93b829261214158a2c74acad4093e +R c8fd3582e0c7f6d2a8919913e7670fb0 U drh -Z c10bc7ddd6a7f2304a3228c439a3f0e6 +Z 02df45f52682e2fefdb79cf7aae0eb67 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4e75864d0a..e97006cd52 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e199a851e316bd471bfc54204b8c250d3ae93b829261214158a2c74acad4093e \ No newline at end of file +13e9ff9e84a114374b49986484dbee05953a496f3017dd5089fba6f495a17c40 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 53643fcb85..cfaffb7d7e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6819,13 +6819,15 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; - assert( idx>=0 && idxnCell ); + assert( idx>=0 ); + assert( idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->nFree>=0 ); data = pPage->aData; ptr = &pPage->aCellIdx[2*idx]; + assert( pPage->pBt->usableSize > (int)(ptr-data) ); pc = get2byte(ptr); hdr = pPage->hdrOffset; testcase( pc==(u32)get2byte(&data[hdr+5]) ); @@ -9254,7 +9256,12 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ iCellIdx = pCur->ix; pPage = pCur->pPage; pCell = findCell(pPage, iCellIdx); - if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT; + if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->nCell<=iCellIdx ){ + return SQLITE_CORRUPT_BKPT; + } /* If the bPreserve flag is set to true, then the cursor position must ** be preserved following this delete operation. If the current delete From 44a5c0257f8bcfd164472b34cf8c38e9a228c9a1 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 12:01:03 +0000 Subject: [PATCH 104/148] Clear the cache of triggers used to implement CASCADE foreign key constraints whenever the schema changes. Fix for the problem identified by [forum:/forumpost/2831335356|forum post 2831335356]. FossilOrigin-Name: 5232c9777fe4fb13e1ecfe5b5d644e2c45d0514f95884dbed49a03fb9b67304c --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/fkey.c | 19 +++++++++++++++++++ src/sqliteInt.h | 2 ++ src/vdbe.c | 1 + 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 7770701f04..28d5395d04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Earlier\sdetection\sof\scorruption\sin\ssqlite3BtreeDelete().\s\sFix\sfor\nthe\sassertion\sfault\sreported\sby\n[forum:/forumpost/9d78389221|forum\spost\s9d78389221]. -D 2022-01-02T11:25:51.036 +C Clear\sthe\scache\sof\striggers\sused\sto\simplement\sCASCADE\sforeign\skey\sconstraints\nwhenever\sthe\sschema\schanges.\s\sFix\sfor\sthe\sproblem\sidentified\sby\n[forum:/forumpost/2831335356|forum\spost\s2831335356]. +D 2022-01-02T12:01:03.636 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -504,7 +504,7 @@ F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5 +F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560 F src/func.c 0f576a0c102485676266e63a796223e63c3cdb04baf3678ccc8bfeedba4a6fd4 F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 @@ -555,7 +555,7 @@ F src/shell.c.in de39d52ee7e8e09522c13ac2321616708f10ebe959b668da012ae8489cb7d1d F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef -F src/sqliteInt.h 66637abecd93d743bea7a728d92c2eb5005dc838b203d676f008173a9c55c167 +F src/sqliteInt.h 9782b7b22a9b10e43b7f375dcdfb93cd1ed7797d831122a07d065efacf9af668 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -622,7 +622,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 89e51820bcb468ff3877a8d942f5cc807208087f021227e0927693e928a195bc F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c b63594839cbf770a29e2b3b81570971a3d2c1c995c0586aade09bb548142113a +F src/vdbe.c 05c8fd957820626aae224656b3db272fb4e69bf000e7bcdf62d00307cc9be873 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h a7f01b0cd0dcb496343eacd37b0839250f9a718199ab6096e3995db42dec3ec8 F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e199a851e316bd471bfc54204b8c250d3ae93b829261214158a2c74acad4093e -R c8fd3582e0c7f6d2a8919913e7670fb0 +P 13e9ff9e84a114374b49986484dbee05953a496f3017dd5089fba6f495a17c40 +R 55a4ceae34dc12d0aa858af0c296a260 U drh -Z 02df45f52682e2fefdb79cf7aae0eb67 +Z 356b59ab85226987dbc745e5cdcb40e4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e97006cd52..4b00d43ad0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -13e9ff9e84a114374b49986484dbee05953a496f3017dd5089fba6f495a17c40 \ No newline at end of file +5232c9777fe4fb13e1ecfe5b5d644e2c45d0514f95884dbed49a03fb9b67304c \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 13b08dfe19..6ee35bf320 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -702,6 +702,25 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ } } +/* +** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys +** in a particular database. This needs to happen when the schema +** changes. +*/ +void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){ + HashElem *k; + Hash *pHash = &db->aDb[iDb].pSchema->tblHash; + for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){ + Table *pTab = sqliteHashData(k); + FKey *pFKey; + if( !IsOrdinaryTable(pTab) ) continue; + for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ + fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0; + fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0; + } + } +} + /* ** This function is called to generate code that runs when table pTab is ** being dropped from the database. The SrcList passed as the second argument diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 14f4e0c104..3525605753 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5147,6 +5147,7 @@ const char *sqlite3JournalModename(int); int sqlite3FkRequired(Parse*, Table*, int*, int); u32 sqlite3FkOldmask(Parse*, Table*); FKey *sqlite3FkReferences(Table *); + void sqlite3FkClearTriggerCache(sqlite3*,int); #else #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d,e,f) @@ -5154,6 +5155,7 @@ const char *sqlite3JournalModename(int); #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #define sqlite3FkReferences(a) 0 + #define sqlite3FkClearTriggerCache(a,b) #endif #ifndef SQLITE_OMIT_FOREIGN_KEY void sqlite3FkDelete(sqlite3 *, Table*); diff --git a/src/vdbe.c b/src/vdbe.c index 66ce3438f7..d6f90d1fad 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3841,6 +3841,7 @@ case OP_SetCookie: { /* When the schema cookie changes, record the new cookie internally */ pDb->pSchema->schema_cookie = pOp->p3 - pOp->p5; db->mDbFlags |= DBFLAG_SchemaChange; + sqlite3FkClearTriggerCache(db, pOp->p1); }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ pDb->pSchema->file_format = pOp->p3; From 7e17a3abbe7f1b644661c7e5ededd4679dd1b409 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 14:55:43 +0000 Subject: [PATCH 105/148] Small performance optimization and size reduction in sqlite3BtreeDelete(). FossilOrigin-Name: da0af4dd9ba4180a16543fac1549fd4ccecdc66dcf6d275f77de21fd80708882 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 41 ++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 28d5395d04..fee691766c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clear\sthe\scache\sof\striggers\sused\sto\simplement\sCASCADE\sforeign\skey\sconstraints\nwhenever\sthe\sschema\schanges.\s\sFix\sfor\sthe\sproblem\sidentified\sby\n[forum:/forumpost/2831335356|forum\spost\s2831335356]. -D 2022-01-02T12:01:03.636 +C Small\sperformance\soptimization\sand\ssize\sreduction\sin\ssqlite3BtreeDelete(). +D 2022-01-02T14:55:43.095 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c fab3d2a9e2a187373c393b9f35e68e996010a1aae1354763f7c5846915a99b83 +F src/btree.c d4b6e026d85b47018dd4c31b42dd490ed22d4320917e705d6502e589d1a8227d F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 13e9ff9e84a114374b49986484dbee05953a496f3017dd5089fba6f495a17c40 -R 55a4ceae34dc12d0aa858af0c296a260 +P 5232c9777fe4fb13e1ecfe5b5d644e2c45d0514f95884dbed49a03fb9b67304c +R aa110e7b5297811807e4f693fefdef54 U drh -Z 356b59ab85226987dbc745e5cdcb40e4 +Z a31d2467491c7884583c9d9e2a7c5425 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4b00d43ad0..71edf50ae9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5232c9777fe4fb13e1ecfe5b5d644e2c45d0514f95884dbed49a03fb9b67304c \ No newline at end of file +da0af4dd9ba4180a16543fac1549fd4ccecdc66dcf6d275f77de21fd80708882 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index cfaffb7d7e..4f777f0f75 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9229,14 +9229,13 @@ int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - int rc; /* Return code */ - MemPage *pPage; /* Page to delete cell from */ - unsigned char *pCell; /* Pointer to cell to delete */ - int iCellIdx; /* Index of cell to delete */ - int iCellDepth; /* Depth of node containing pCell */ - CellInfo info; /* Size of the cell being deleted */ - int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ - u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ + int rc; /* Return code */ + MemPage *pPage; /* Page to delete cell from */ + unsigned char *pCell; /* Pointer to cell to delete */ + int iCellIdx; /* Index of cell to delete */ + int iCellDepth; /* Depth of node containing pCell */ + CellInfo info; /* Size of the cell being deleted */ + u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -9255,23 +9254,31 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ iCellDepth = pCur->iPage; iCellIdx = pCur->ix; pPage = pCur->pPage; + if( pPage->nCell<=iCellIdx ){ + return SQLITE_CORRUPT_BKPT; + } pCell = findCell(pPage, iCellIdx); if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ return SQLITE_CORRUPT_BKPT; } - if( pPage->nCell<=iCellIdx ){ - return SQLITE_CORRUPT_BKPT; - } - /* If the bPreserve flag is set to true, then the cursor position must + /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must ** be preserved following this delete operation. If the current delete ** will cause a b-tree rebalance, then this is done by saving the cursor ** key and leaving the cursor in CURSOR_REQUIRESEEK state before ** returning. ** - ** Or, if the current delete will not cause a rebalance, then the cursor + ** If the current delete will not cause a rebalance, then the cursor ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. In this case set bSkipnext to true. */ + ** before or after the deleted entry. + ** + ** The bPreserve value records which path is required: + ** + ** bPreserve==0 Not necessary to save the cursor position + ** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position + ** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT. + */ + bPreserve = (flags & BTREE_SAVEPOSITION)!=0; if( bPreserve ){ if( !pPage->leaf || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) @@ -9282,7 +9289,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ rc = saveCursorKey(pCur); if( rc ) return rc; }else{ - bSkipnext = 1; + bPreserve = 2; } } @@ -9382,8 +9389,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ } if( rc==SQLITE_OK ){ - if( bSkipnext ){ - assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); + if( bPreserve>1 ){ + assert( (pCur->iPage==iCellDepth || CORRUPT_DB) ); assert( pPage==pCur->pPage || CORRUPT_DB ); assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); pCur->eState = CURSOR_SKIPNEXT; From 29bbc2b51f2477a5a45fe1a99cf56b5d7ea0ca82 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 16:48:00 +0000 Subject: [PATCH 106/148] Performance optimization in btreeParseCellPtr() by unrolling the loop that decodes the rowid. FossilOrigin-Name: fef72368a2eef5cb68ffc56e4f01be212d5e3318ebdb56a23ab26e1ef454272e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 32 +++++++++++++++++++++++--------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index fee691766c..89b61494cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\soptimization\sand\ssize\sreduction\sin\ssqlite3BtreeDelete(). -D 2022-01-02T14:55:43.095 +C Performance\soptimization\sin\sbtreeParseCellPtr()\sby\sunrolling\sthe\sloop\sthat\ndecodes\sthe\srowid. +D 2022-01-02T16:48:00.312 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c d4b6e026d85b47018dd4c31b42dd490ed22d4320917e705d6502e589d1a8227d +F src/btree.c 75aed1a53f45c9020d57ead65397693fe28e408526c08d2b15803629619eb4b7 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5232c9777fe4fb13e1ecfe5b5d644e2c45d0514f95884dbed49a03fb9b67304c -R aa110e7b5297811807e4f693fefdef54 +P da0af4dd9ba4180a16543fac1549fd4ccecdc66dcf6d275f77de21fd80708882 +R 8e54a2cff16f34421db02383c81bf96e U drh -Z a31d2467491c7884583c9d9e2a7c5425 +Z 07304ae249bd8afb301d4ea202109e15 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 71edf50ae9..a2fb6d3baa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -da0af4dd9ba4180a16543fac1549fd4ccecdc66dcf6d275f77de21fd80708882 \ No newline at end of file +fef72368a2eef5cb68ffc56e4f01be212d5e3318ebdb56a23ab26e1ef454272e \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4f777f0f75..b99045c41e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1225,18 +1225,32 @@ static void btreeParseCellPtr( ** ** pIter += getVarint(pIter, (u64*)&pInfo->nKey); ** - ** The code is inlined to avoid a function call. + ** The code is inlined and the loop is unrolled for performance. + ** This routine is a high-runner. */ iKey = *pIter; if( iKey>=0x80 ){ - u8 *pEnd = &pIter[7]; - iKey &= 0x7f; - while(1){ - iKey = (iKey<<7) | (*++pIter & 0x7f); - if( (*pIter)<0x80 ) break; - if( pIter>=pEnd ){ - iKey = (iKey<<8) | *++pIter; - break; + u8 x; + iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x =*++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<8) | (*++pIter); + } + } + } + } + } } } } From d0fa3484c62e927e7be7d692421bfdd1a32c8381 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 19:10:49 +0000 Subject: [PATCH 107/148] Improve formatting of an assert(). No functional changes. FossilOrigin-Name: 4bb78ce8b50af3c6f04ffdf4de4438e61370a73ccfa971479af5d58a0a7e5fbb --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 13 ++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 89b61494cb..8f95d5a5d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\sin\sbtreeParseCellPtr()\sby\sunrolling\sthe\sloop\sthat\ndecodes\sthe\srowid. -D 2022-01-02T16:48:00.312 +C Improve\sformatting\sof\san\sassert().\s\sNo\sfunctional\schanges. +D 2022-01-02T19:10:49.431 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -537,7 +537,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c dda556cb412e66c3d4016214ef2dd63d9019ad24d1ceff871b79dcb860981f77 +F src/pager.c a860d7c8540d0fa67796a8d23bc3e7fd81275040281dafa708040818147a44c9 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P da0af4dd9ba4180a16543fac1549fd4ccecdc66dcf6d275f77de21fd80708882 -R 8e54a2cff16f34421db02383c81bf96e +P fef72368a2eef5cb68ffc56e4f01be212d5e3318ebdb56a23ab26e1ef454272e +R 7fdca3ee0f8febfdbd8987229e4c3537 U drh -Z 07304ae249bd8afb301d4ea202109e15 +Z 58fdfe0ec8d3b58e9bcfff6359000f66 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a2fb6d3baa..45e703a068 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fef72368a2eef5cb68ffc56e4f01be212d5e3318ebdb56a23ab26e1ef454272e \ No newline at end of file +4bb78ce8b50af3c6f04ffdf4de4438e61370a73ccfa971479af5d58a0a7e5fbb \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 045bd8040e..984d28ffd6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7272,12 +7272,12 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ u8 eOld = pPager->journalMode; /* Prior journalmode */ /* The eMode parameter is always valid */ - assert( eMode==PAGER_JOURNALMODE_DELETE - || eMode==PAGER_JOURNALMODE_TRUNCATE - || eMode==PAGER_JOURNALMODE_PERSIST - || eMode==PAGER_JOURNALMODE_OFF - || eMode==PAGER_JOURNALMODE_WAL - || eMode==PAGER_JOURNALMODE_MEMORY ); + assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */ + || eMode==PAGER_JOURNALMODE_PERSIST /* 1 */ + || eMode==PAGER_JOURNALMODE_OFF /* 2 */ + || eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */ + || eMode==PAGER_JOURNALMODE_MEMORY /* 4 */ + || eMode==PAGER_JOURNALMODE_WAL /* 5 */ ); /* This routine is only called from the OP_JournalMode opcode, and ** the logic there will never allow a temporary file to be changed @@ -7314,7 +7314,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ assert( isOpen(pPager->fd) || pPager->exclusiveMode ); if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ - /* In this case we would like to delete the journal file. If it is ** not possible, then that is not a problem. Deleting the journal file ** here is an optimization only. From bda4d2008031629359b5d1251188525804de6104 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 19:32:43 +0000 Subject: [PATCH 108/148] Do not open a rollback journal file when the journal_mode is OFF, even if such a file exists on disk. See [forum/forumpost/ec2a102440|forum post ec2a102440] for a description. I so far have been unable to find any harm to come of the problem, other than the assertion fault when in DEBUG mode. FossilOrigin-Name: fdf9ed665b2fb07d26f3852bfd2170f2fb56851edd2851d47672116a8ea58463 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8f95d5a5d0..6a54536440 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sformatting\sof\san\sassert().\s\sNo\sfunctional\schanges. -D 2022-01-02T19:10:49.431 +C Do\snot\sopen\sa\srollback\sjournal\sfile\swhen\sthe\sjournal_mode\sis\sOFF,\seven\sif\nsuch\sa\sfile\sexists\son\sdisk.\sSee\n[forum/forumpost/ec2a102440|forum\spost\sec2a102440]\sfor\sa\sdescription.\s\sI\sso\nfar\shave\sbeen\sunable\sto\sfind\sany\sharm\sto\scome\sof\sthe\sproblem,\sother\sthan\sthe\nassertion\sfault\swhen\sin\sDEBUG\smode. +D 2022-01-02T19:32:43.030 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -537,7 +537,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c a860d7c8540d0fa67796a8d23bc3e7fd81275040281dafa708040818147a44c9 +F src/pager.c 55a9a8c745c47a49e6541b1d634f6152e3f72f76c6dbb04fe24413986a928091 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fef72368a2eef5cb68ffc56e4f01be212d5e3318ebdb56a23ab26e1ef454272e -R 7fdca3ee0f8febfdbd8987229e4c3537 +P 4bb78ce8b50af3c6f04ffdf4de4438e61370a73ccfa971479af5d58a0a7e5fbb +R 992de5604e46c8c75e045be72cbcb1d3 U drh -Z 58fdfe0ec8d3b58e9bcfff6359000f66 +Z 6823f2139f56a62ab1cf2ba296036bb4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 45e703a068..58e536f708 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4bb78ce8b50af3c6f04ffdf4de4438e61370a73ccfa971479af5d58a0a7e5fbb \ No newline at end of file +fdf9ed665b2fb07d26f3852bfd2170f2fb56851edd2851d47672116a8ea58463 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 984d28ffd6..24a2ce2c4c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5265,7 +5265,7 @@ int sqlite3PagerSharedLock(Pager *pPager){ ** may mean that the pager was in the error-state when this ** function was called and the journal file does not exist. */ - if( !isOpen(pPager->jfd) ){ + if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ sqlite3_vfs * const pVfs = pPager->pVfs; int bExists; /* True if journal file exists */ rc = sqlite3OsAccess( From 5d1bf4f560300d236ed1084f518e53d4e0131f48 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 20:54:33 +0000 Subject: [PATCH 109/148] In the CLI, fix ".mode quote" output for UTF16 BLOBs. [forum:/forumpost/b4bfe62fe6|Forum post b4bfe62fe6]. FossilOrigin-Name: 728e9dcc6d211acd787837c41cb62275284b5e02f55bd28bf5a44e233bcb057a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6a54536440..e8a351b50a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sopen\sa\srollback\sjournal\sfile\swhen\sthe\sjournal_mode\sis\sOFF,\seven\sif\nsuch\sa\sfile\sexists\son\sdisk.\sSee\n[forum/forumpost/ec2a102440|forum\spost\sec2a102440]\sfor\sa\sdescription.\s\sI\sso\nfar\shave\sbeen\sunable\sto\sfind\sany\sharm\sto\scome\sof\sthe\sproblem,\sother\sthan\sthe\nassertion\sfault\swhen\sin\sDEBUG\smode. -D 2022-01-02T19:32:43.030 +C In\sthe\sCLI,\sfix\s".mode\squote"\soutput\sfor\sUTF16\sBLOBs.\n[forum:/forumpost/b4bfe62fe6|Forum\spost\sb4bfe62fe6]. +D 2022-01-02T20:54:33.787 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 342e096c2737a3ee60753e91de6e6660c7f59cd2988b3e1ab641d38fd885003f -F src/shell.c.in de39d52ee7e8e09522c13ac2321616708f10ebe959b668da012ae8489cb7d1d4 +F src/shell.c.in f5111900d646a07da18e6438d57be20f112397daba6bfc85b117a0da586e55da F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4bb78ce8b50af3c6f04ffdf4de4438e61370a73ccfa971479af5d58a0a7e5fbb -R 992de5604e46c8c75e045be72cbcb1d3 +P fdf9ed665b2fb07d26f3852bfd2170f2fb56851edd2851d47672116a8ea58463 +R c19b8b7c6b9827270ebb21ea2cc50c5f U drh -Z 6823f2139f56a62ab1cf2ba296036bb4 +Z 3c82b93914a4204ff343c58de0981267 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 58e536f708..4a24aea9ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fdf9ed665b2fb07d26f3852bfd2170f2fb56851edd2851d47672116a8ea58463 \ No newline at end of file +728e9dcc6d211acd787837c41cb62275284b5e02f55bd28bf5a44e233bcb057a \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index ec39da54b7..3d15cc1f89 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3366,7 +3366,10 @@ static void exec_prepared_stmt( /* extract the data and data types */ for(i=0; icMode==MODE_Insert ){ + if( x==SQLITE_BLOB + && pArg + && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote) + ){ azVals[i] = ""; }else{ azVals[i] = (char*)sqlite3_column_text(pStmt, i); From 80d99e19b69814b7a9bebcc792fc9b7e959bbd0e Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 2 Jan 2022 21:53:54 +0000 Subject: [PATCH 110/148] Remove unnecessary assignment operations in the btree search algorithm, for a small size reduction and performance increase. FossilOrigin-Name: 01bd266eb682feed901a0995c2232b62d8444d19dbb227095dfbfe8edeaa5d88 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e8a351b50a..9243bda886 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sCLI,\sfix\s".mode\squote"\soutput\sfor\sUTF16\sBLOBs.\n[forum:/forumpost/b4bfe62fe6|Forum\spost\sb4bfe62fe6]. -D 2022-01-02T20:54:33.787 +C Remove\sunnecessary\sassignment\soperations\sin\sthe\sbtree\ssearch\salgorithm,\nfor\sa\ssmall\ssize\sreduction\sand\sperformance\sincrease. +D 2022-01-02T21:53:54.680 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 75aed1a53f45c9020d57ead65397693fe28e408526c08d2b15803629619eb4b7 +F src/btree.c 224f59b5de2d9916452b65724ef677fb0609f8021e1ab1a068dfa8e2c9e97632 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fdf9ed665b2fb07d26f3852bfd2170f2fb56851edd2851d47672116a8ea58463 -R c19b8b7c6b9827270ebb21ea2cc50c5f +P 728e9dcc6d211acd787837c41cb62275284b5e02f55bd28bf5a44e233bcb057a +R 8e972dcab3c6d036a102fca8bdbc15cf U drh -Z 3c82b93914a4204ff343c58de0981267 +Z 70eaf19d957dcced1788f060f027844f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4a24aea9ba..178a39fd5d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -728e9dcc6d211acd787837c41cb62275284b5e02f55bd28bf5a44e233bcb057a \ No newline at end of file +01bd266eb682feed901a0995c2232b62d8444d19dbb227095dfbfe8edeaa5d88 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b99045c41e..0bac906904 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5575,7 +5575,6 @@ int sqlite3BtreeTableMoveto( upr = pPage->nCell-1; assert( biasRight==0 || biasRight==1 ); idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ - pCur->ix = (u16)idx; for(;;){ i64 nCellKey; pCell = findCellPastPtr(pPage, idx); @@ -5717,7 +5716,6 @@ int sqlite3BtreeIndexMoveto( lwr = 0; upr = pPage->nCell-1; idx = upr>>1; /* idx = (lwr+upr)/2; */ - pCur->ix = (u16)idx; for(;;){ int nCell; /* Size of the pCell cell in bytes */ pCell = findCellPastPtr(pPage, idx); From b248668bc9353ce90915b653fbf592d748ccb9d6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 3 Jan 2022 01:43:28 +0000 Subject: [PATCH 111/148] Small performance and size optimization to allocateCursor(). FossilOrigin-Name: 23f042669aff535afa6ee9de367656848d01e90a1c9dab9359fa938a615b4195 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/vdbe.c | 38 +++++++++++++++++++------------------- src/vdbeInt.h | 8 +++++--- src/vdbeaux.c | 4 +--- src/vdbesort.c | 3 ++- 6 files changed, 37 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 9243bda886..bf2bf1e34b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunnecessary\sassignment\soperations\sin\sthe\sbtree\ssearch\salgorithm,\nfor\sa\ssmall\ssize\sreduction\sand\sperformance\sincrease. -D 2022-01-02T21:53:54.680 +C Small\sperformance\sand\ssize\soptimization\sto\sallocateCursor(). +D 2022-01-03T01:43:28.096 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -622,14 +622,14 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 89e51820bcb468ff3877a8d942f5cc807208087f021227e0927693e928a195bc F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 05c8fd957820626aae224656b3db272fb4e69bf000e7bcdf62d00307cc9be873 +F src/vdbe.c 23116cc5d99ada73e8e11addabc380c27758688a16d84d0efa6dbe94c1293a4f F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe -F src/vdbeInt.h a7f01b0cd0dcb496343eacd37b0839250f9a718199ab6096e3995db42dec3ec8 +F src/vdbeInt.h d89d5d2150500cfb08615329fd20aea9d746bba5f2c3ecb8a17e2d2d9be029e5 F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a -F src/vdbeaux.c 44b4c238425726a7e790ce54dc4aef3be3fb7ef46a70f09adb5e84c0361824ec +F src/vdbeaux.c c1b452cc17f5887b3d36bc277a2181914d6bed508ea45827b5f348160491e6a6 F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652 F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec -F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7 +F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c a47cc12ebaa350800c0c87b6b0095debbb5a6ed32727bcab9d82ad070a81b738 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 728e9dcc6d211acd787837c41cb62275284b5e02f55bd28bf5a44e233bcb057a -R 8e972dcab3c6d036a102fca8bdbc15cf +P 01bd266eb682feed901a0995c2232b62d8444d19dbb227095dfbfe8edeaa5d88 +R 8bbbbc86742a232c4562b5ad64d27946 U drh -Z 70eaf19d957dcced1788f060f027844f +Z 57988afa28021d7cb9d1163c06091947 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 178a39fd5d..e47633d413 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -01bd266eb682feed901a0995c2232b62d8444d19dbb227095dfbfe8edeaa5d88 \ No newline at end of file +23f042669aff535afa6ee9de367656848d01e90a1c9dab9359fa938a615b4195 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index d6f90d1fad..1347ee9a52 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -241,7 +241,6 @@ static VdbeCursor *allocateCursor( Vdbe *p, /* The virtual machine */ int iCur, /* Index of the new VdbeCursor */ int nField, /* Number of fields in the table or index */ - int iDb, /* Database the cursor belongs to, or -1 */ u8 eCurType /* Type of the new cursor */ ){ /* Find the memory cell that will be used to store the blob of memory @@ -298,7 +297,6 @@ static VdbeCursor *allocateCursor( p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc; memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); pCx->eCurType = eCurType; - pCx->iDb = iDb; pCx->nField = nField; pCx->aOffset = &pCx->aType[nField]; if( eCurType==CURTYPE_BTREE ){ @@ -2692,6 +2690,7 @@ case OP_Column: { assert( pC!=0 ); assert( p2<(u32)pC->nField ); aOffset = pC->aOffset; + assert( aOffset==pC->aType+pC->nField ); assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); @@ -4019,8 +4018,9 @@ case OP_OpenWrite: assert( pOp->p1>=0 ); assert( nField>=0 ); testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); + pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE); if( pCur==0 ) goto no_mem; + pCur->iDb = iDb; pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; @@ -4062,7 +4062,7 @@ case OP_OpenDup: { assert( pOrig ); assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */ - pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE); + pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; @@ -4070,10 +4070,10 @@ case OP_OpenDup: { pCx->isTable = pOrig->isTable; pCx->pgnoRoot = pOrig->pgnoRoot; pCx->isOrdered = pOrig->isOrdered; - pCx->pBtx = pOrig->pBtx; + pCx->ub.pBtx = pOrig->ub.pBtx; pCx->hasBeenDuped = 1; pOrig->hasBeenDuped = 1; - rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, pCx->pKeyInfo, pCx->uc.pCursor); /* The sqlite3BtreeCursor() routine can only fail for the first cursor ** opened for a database. Since there is already an open cursor when this @@ -4146,16 +4146,16 @@ case OP_OpenEphemeral: { assert( pCx->isEphemeral ); pCx->seqCount = 0; pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0); }else{ - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); + pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0); + rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before @@ -4164,26 +4164,26 @@ case OP_OpenEphemeral: { */ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot, + rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pCx->pgnoRoot==SCHEMA_ROOT+1 ); assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); - rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, pKeyInfo, pCx->uc.pCursor); } pCx->isTable = 0; }else{ pCx->pgnoRoot = SCHEMA_ROOT; - rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR, 0, pCx->uc.pCursor); pCx->isTable = 1; } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); if( rc ){ - sqlite3BtreeClose(pCx->pBtx); + sqlite3BtreeClose(pCx->ub.pBtx); } } } @@ -4207,7 +4207,7 @@ case OP_SorterOpen: { assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER); + pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; assert( pCx->pKeyInfo->db==db ); @@ -4256,7 +4256,7 @@ case OP_OpenPseudo: { assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); + pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->seekResult = pOp->p2; @@ -6196,9 +6196,9 @@ case OP_IdxRowid: { /* out2 */ pTabCur->movetoTarget = rowid; pTabCur->deferredMoveto = 1; assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); - pTabCur->aAltMap = pOp->p4.ai; - assert( !pC->isEphemeral ); assert( !pTabCur->isEphemeral ); + pTabCur->ub.aAltMap = pOp->p4.ai; + assert( !pC->isEphemeral ); pTabCur->pAltCursor = pC; }else{ pOut = out2Prerelease(p, pOp); @@ -7720,7 +7720,7 @@ case OP_VOpen: { pVCur->pVtab = pVtab; /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); + pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB); if( pCur ){ pCur->uc.pVCur = pVCur; pVtab->nRef++; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 481c93ddb0..376c9edac9 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -75,7 +75,7 @@ typedef struct AuxData AuxData; typedef struct VdbeCursor VdbeCursor; struct VdbeCursor { u8 eCurType; /* One of the CURTYPE_* values above */ - i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ + i8 iDb; /* Index of cursor database in db->aDb[] */ u8 nullRow; /* True if pointing to a row with no data */ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ u8 isTable; /* True for rowid tables. False for indexes */ @@ -88,9 +88,11 @@ struct VdbeCursor { Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */ - Btree *pBtx; /* Separate file holding temporary table */ + union { /* pBtx for isEphermeral. pAltMap otherwise */ + Btree *pBtx; /* Separate file holding temporary table */ + u32 *aAltMap; /* Mapping from table to index column numbers */ + } ub; i64 seqCount; /* Sequence counter */ - u32 *aAltMap; /* Mapping from table to index column numbers */ /* Cached OP_Column parse information is only valid if cacheStatus matches ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 5441b79e80..3b8b25e1d8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2470,8 +2470,6 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } - assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE ); - assert( pCx->pBtx==0 || pCx->isEphemeral ); switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); @@ -3573,7 +3571,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){ if( p->deferredMoveto ){ u32 iMap; assert( !p->isEphemeral ); - if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){ + if( p->ub.aAltMap && (iMap = p->ub.aAltMap[1+*piCol])>0 && !p->nullRow ){ *pp = p->pAltCursor; *piCol = iMap - 1; return SQLITE_OK; diff --git a/src/vdbesort.c b/src/vdbesort.c index 8bf7b57173..3958662cc6 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -960,7 +960,8 @@ int sqlite3VdbeSorterInit( } #endif - assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); + assert( pCsr->pKeyInfo ); + assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); From d0a9a46215224963a00663923d6433ce34edc462 Mon Sep 17 00:00:00 2001 From: larrybr Date: Mon, 3 Jan 2022 19:33:44 +0000 Subject: [PATCH 112/148] Test .mode quote blob output FossilOrigin-Name: ef4dcd1080241a62a50eff28ef12c49da0116032f10843aaf048ae7ad3cdfd0e --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/shell1.test | 6 ++++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index bf2bf1e34b..d1f3f98ef8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\sperformance\sand\ssize\soptimization\sto\sallocateCursor(). -D 2022-01-03T01:43:28.096 +C Test\s.mode\squote\sblob\soutput +D 2022-01-03T19:33:44.186 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1382,7 +1382,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test e6c8fb4b710f29239392876c72ecc5a7f1d5d23e1f23838e5a6a2ccc9903d74f +F test/shell1.test 70f46b5d07776a107335c3c2c9cbd0431d44637bfeae1f6b9ded5e33b4c7c0bf F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566 F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 01bd266eb682feed901a0995c2232b62d8444d19dbb227095dfbfe8edeaa5d88 -R 8bbbbc86742a232c4562b5ad64d27946 -U drh -Z 57988afa28021d7cb9d1163c06091947 +P 23f042669aff535afa6ee9de367656848d01e90a1c9dab9359fa938a615b4195 +R dc74bbd43cff3bf3754c71889c919686 +U larrybr +Z ad2e9814bd694aca1391f041108f6f60 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e47633d413..183a433ff7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -23f042669aff535afa6ee9de367656848d01e90a1c9dab9359fa938a615b4195 \ No newline at end of file +ef4dcd1080241a62a50eff28ef12c49da0116032f10843aaf048ae7ad3cdfd0e \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 17d34c3ed1..75118b9419 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -1024,6 +1024,12 @@ do_test shell1-4.6 { ";" "$"} 7} +# Test the output of ".mode quote" +# +do_test shell1-4.7 { + catchcmd test.db ".mode quote\nselect x'0123456789ABCDEF';" +} {0 X'0123456789abcdef'} + # Test using arbitrary byte data with the shell via standard input/output. # do_test shell1-5.0 { From ebc4434e997e428bdb13ebd6cd06d41d3cbf5d40 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 5 Jan 2022 11:49:58 +0000 Subject: [PATCH 113/148] Improved handling of OOM errors in sqlite3ExpandReturning(). dbsqlfuzz 1040b720f0bbc3bdcfe7336acffbf71517e3ef82. FossilOrigin-Name: 33c6b8e94bda12df13b4d2dd782b3120c3628596b86ef531d20b3100bf159b50 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/trigger.c | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index d1f3f98ef8..10adb9a0a1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\s.mode\squote\sblob\soutput -D 2022-01-03T19:33:44.186 +C Improved\shandling\sof\sOOM\serrors\sin\ssqlite3ExpandReturning().\ndbsqlfuzz\s1040b720f0bbc3bdcfe7336acffbf71517e3ef82. +D 2022-01-05T11:49:58.515 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -616,7 +616,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c dc5367c6d42336b35d55f96d2f04cd6256e92bc6ecf74ed5d855d24e43343aff F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc -F src/trigger.c eaaba4e34cdce18bf6c633a4536d35e93c62684d3107d5563f0eae209640860c +F src/trigger.c ad65f2dae751e8ee59d61f35e0fc624ec5f264964fbf2d1c23041535b6850083 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 @@ -1936,8 +1936,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 23f042669aff535afa6ee9de367656848d01e90a1c9dab9359fa938a615b4195 -R dc74bbd43cff3bf3754c71889c919686 -U larrybr -Z ad2e9814bd694aca1391f041108f6f60 +P ef4dcd1080241a62a50eff28ef12c49da0116032f10843aaf048ae7ad3cdfd0e +R 4941045e693d9c4d50be43c3ecb13482 +U drh +Z 2349087c33b28fcb010dc116adddeda9 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 183a433ff7..aecbb3a89f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef4dcd1080241a62a50eff28ef12c49da0116032f10843aaf048ae7ad3cdfd0e \ No newline at end of file +33c6b8e94bda12df13b4d2dd782b3120c3628596b86ef531d20b3100bf159b50 \ No newline at end of file diff --git a/src/trigger.c b/src/trigger.c index b69fbd6bb8..8d1e18e7d9 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -933,7 +933,7 @@ static void codeReturningTrigger( } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); - if( pNew ){ + if( !db->mallocFailed ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); if( pReturning->nRetCol==0 ){ @@ -954,7 +954,7 @@ static void codeReturningTrigger( for(i=0; ia[i].pExpr; assert( pCol!=0 || pParse->db->mallocFailed ); - if( pCol==0 ) continue; + if( NEVER(pCol==0) ) continue; sqlite3ExprCodeFactorable(pParse, pCol, reg+i); if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); @@ -964,10 +964,10 @@ static void codeReturningTrigger( sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1); sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1); } - sqlite3ExprListDelete(db, pNew); - pParse->eTriggerOp = 0; - pParse->pTriggerTab = 0; } + sqlite3ExprListDelete(db, pNew); + pParse->eTriggerOp = 0; + pParse->pTriggerTab = 0; } From c6977c1c0d5da2d3d1d1ebd23547856e25a24d54 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 5 Jan 2022 15:54:02 +0000 Subject: [PATCH 114/148] Fix an assert() failure that could follow an OOM when coding a RETURNING trigger. dbsqlfuzz case 5d3e2438f15dc32b473d9f29413157857efa1212. FossilOrigin-Name: 7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 --- manifest | 15 ++++++++------- manifest.uuid | 2 +- src/trigger.c | 7 ++++--- test/returningfault.test | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 test/returningfault.test diff --git a/manifest b/manifest index 10adb9a0a1..263107c7b3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\shandling\sof\sOOM\serrors\sin\ssqlite3ExpandReturning().\ndbsqlfuzz\s1040b720f0bbc3bdcfe7336acffbf71517e3ef82. -D 2022-01-05T11:49:58.515 +C Fix\san\sassert()\sfailure\sthat\scould\sfollow\san\sOOM\swhen\scoding\sa\sRETURNING\strigger.\sdbsqlfuzz\scase\s5d3e2438f15dc32b473d9f29413157857efa1212. +D 2022-01-05T15:54:02.738 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -616,7 +616,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c dc5367c6d42336b35d55f96d2f04cd6256e92bc6ecf74ed5d855d24e43343aff F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc -F src/trigger.c ad65f2dae751e8ee59d61f35e0fc624ec5f264964fbf2d1c23041535b6850083 +F src/trigger.c 40e7c3dcff57a770d5fa38ba21ed4725572fd2e224c58af61eb980598b60f9c8 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 @@ -1312,6 +1312,7 @@ F test/releasetest_data.tcl 7cea6c852ae6bb3a9ff1a2b910e4dd13c16a05f74443984dfd52 F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/returning1.test ee0b115162b17f59fe486767899596b1e8290bcd845db05d7d1d9e6c2dad1b8b +F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4 F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a @@ -1936,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ef4dcd1080241a62a50eff28ef12c49da0116032f10843aaf048ae7ad3cdfd0e -R 4941045e693d9c4d50be43c3ecb13482 -U drh -Z 2349087c33b28fcb010dc116adddeda9 +P 33c6b8e94bda12df13b4d2dd782b3120c3628596b86ef531d20b3100bf159b50 +R a91b1eccec18d8badfaa5b59ed7bab51 +U dan +Z a0129ada76a11e9feee65928113d1cba # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index aecbb3a89f..a9ec4b79e3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -33c6b8e94bda12df13b4d2dd782b3120c3628596b86ef531d20b3100bf159b50 \ No newline at end of file +7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 \ No newline at end of file diff --git a/src/trigger.c b/src/trigger.c index 8d1e18e7d9..6b71c9816e 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -945,7 +945,9 @@ static void codeReturningTrigger( sNC.ncFlags = NC_UBaseReg; pParse->eTriggerOp = pTrigger->op; pParse->pTriggerTab = pTab; - if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){ + if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK + && !db->mallocFailed + ){ int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; @@ -953,8 +955,7 @@ static void codeReturningTrigger( pReturning->iRetReg = reg; for(i=0; ia[i].pExpr; - assert( pCol!=0 || pParse->db->mallocFailed ); - if( NEVER(pCol==0) ) continue; + assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */ sqlite3ExprCodeFactorable(pParse, pCol, reg+i); if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); diff --git a/test/returningfault.test b/test/returningfault.test new file mode 100644 index 0000000000..8bf6fbfe06 --- /dev/null +++ b/test/returningfault.test @@ -0,0 +1,36 @@ +# 2022 January 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 +source $testdir/malloc_common.tcl + + +do_execsql_test 1.0 { + CREATE TABLE t1 (b); +} {} +faultsim_save_and_close + +do_faultsim_test pagerfault-1 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + execsql { + INSERT INTO t1(b) VALUES(65) RETURNING ( + SELECT * FROM sqlite_temp_schema + ) AS aaa; + } +} -test { + faultsim_test_result {1 {sub-select returns 5 columns - expected 1}} +} + + +finish_test From 10f7365748d12b1391e087db7bfde36867f4c1fb Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 5 Jan 2022 21:01:26 +0000 Subject: [PATCH 115/148] Remove two NEVER() macros that can sometimes be true if the database is corrupt. dbsqlfuzz 0414d2c18290fc80fd5fb540def7d3e46c1ae9c6. FossilOrigin-Name: b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 263107c7b3..f0032d5289 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sfailure\sthat\scould\sfollow\san\sOOM\swhen\scoding\sa\sRETURNING\strigger.\sdbsqlfuzz\scase\s5d3e2438f15dc32b473d9f29413157857efa1212. -D 2022-01-05T15:54:02.738 +C Remove\stwo\sNEVER()\smacros\sthat\scan\ssometimes\sbe\strue\sif\sthe\sdatabase\sis\ncorrupt.\s\sdbsqlfuzz\s0414d2c18290fc80fd5fb540def7d3e46c1ae9c6. +D 2022-01-05T21:01:26.927 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 224f59b5de2d9916452b65724ef677fb0609f8021e1ab1a068dfa8e2c9e97632 +F src/btree.c 0e9f84f974e970fb373c15caa1624a281b3c33098cb9dd9021d6801c04eb4fde F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 33c6b8e94bda12df13b4d2dd782b3120c3628596b86ef531d20b3100bf159b50 -R a91b1eccec18d8badfaa5b59ed7bab51 -U dan -Z a0129ada76a11e9feee65928113d1cba +P 7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 +R 7175e1e9a16516f1ab12321ca929e683 +U drh +Z 45714cdd1039a8cc38c8df2ff917256e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a9ec4b79e3..3671abe1cd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 \ No newline at end of file +b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0bac906904..70f4039faf 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7134,7 +7134,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(kpPg->aDataEnd) ) goto editpage_fail; + if( pData>pPg->aDataEnd ) goto editpage_fail; /* Add cells to the start of the page */ if( iNew Date: Thu, 6 Jan 2022 01:40:09 +0000 Subject: [PATCH 116/148] An attempt to integrate the JSON functions directly into the SQLite core, rather than holding them as an extension. FossilOrigin-Name: 583b47d865fb8d2c9ae4d3a4e70356a8a758978efb0a282f6b19775bf41fb748 --- Makefile.in | 10 +- Makefile.msc | 10 +- configure | 42 ++--- configure.ac | 25 +-- ext/rtree/geopoly.c | 11 +- main.mk | 7 +- manifest | 37 +++-- manifest.uuid | 2 +- src/ctime.c | 8 +- src/func.c | 1 + ext/misc/json1.c => src/json.c | 293 ++++++++++----------------------- src/main.c | 7 +- src/sqliteInt.h | 10 +- tool/mksqlite3c.tcl | 2 +- 14 files changed, 175 insertions(+), 290 deletions(-) rename ext/misc/json1.c => src/json.c (90%) diff --git a/Makefile.in b/Makefile.in index b3ea4628b3..9d37f883e9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -180,7 +180,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ fts5.lo \ func.lo global.lo hash.lo \ - icu.lo insert.lo json1.lo legacy.lo loadext.lo \ + icu.lo insert.lo json.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ @@ -234,6 +234,7 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ $(TOP)/src/insert.c \ + $(TOP)/src/json.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ @@ -366,7 +367,6 @@ SRC += \ $(TOP)/ext/rbu/sqlite3rbu.h \ $(TOP)/ext/rbu/sqlite3rbu.c SRC += \ - $(TOP)/ext/misc/json1.c \ $(TOP)/ext/misc/stmt.c # Generated source code files @@ -873,6 +873,9 @@ hash.lo: $(TOP)/src/hash.c $(HDR) insert.lo: $(TOP)/src/insert.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/insert.c +json.lo: $(TOP)/src/json.c + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/json.c + legacy.lo: $(TOP)/src/legacy.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/legacy.c @@ -1176,9 +1179,6 @@ userauth.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR) sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c -json1.lo: $(TOP)/ext/misc/json1.c - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c - stmt.lo: $(TOP)/ext/misc/stmt.c $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c diff --git a/Makefile.msc b/Makefile.msc index 3cbf560d7c..50f63619b2 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1248,7 +1248,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ fts5.lo \ func.lo global.lo hash.lo \ - icu.lo insert.lo json1.lo legacy.lo loadext.lo \ + icu.lo insert.lo json.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ @@ -1315,6 +1315,7 @@ SRC00 = \ $(TOP)\src\global.c \ $(TOP)\src\hash.c \ $(TOP)\src\insert.c \ + $(TOP)\src\json.c \ $(TOP)\src\legacy.c \ $(TOP)\src\loadext.c \ $(TOP)\src\main.c \ @@ -1445,7 +1446,6 @@ SRC07 = \ $(TOP)\ext\rtree\rtree.c \ $(TOP)\ext\session\sqlite3session.c \ $(TOP)\ext\rbu\sqlite3rbu.c \ - $(TOP)\ext\misc\json1.c \ $(TOP)\ext\misc\stmt.c # Extension header files, part 1. @@ -1990,6 +1990,9 @@ hash.lo: $(TOP)\src\hash.c $(HDR) insert.lo: $(TOP)\src\insert.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c +json.lo: $(TOP)\src\json.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\json.c + legacy.lo: $(TOP)\src\legacy.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c @@ -2298,9 +2301,6 @@ fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR) fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c -json1.lo: $(TOP)\ext\misc\json1.c $(HDR) $(EXTHDR) - $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\json1.c - stmt.lo: $(TOP)\ext\misc\stmt.c $(HDR) $(EXTHDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\misc\stmt.c diff --git a/configure b/configure index 74dddfe76e..abb182d5eb 100755 --- a/configure +++ b/configure @@ -905,13 +905,13 @@ enable_debug enable_amalgamation enable_load_extension enable_math +enable_json enable_all enable_memsys5 enable_memsys3 enable_fts3 enable_fts4 enable_fts5 -enable_json1 enable_update_limit enable_geopoly enable_rtree @@ -1560,13 +1560,13 @@ Optional Features: --disable-load-extension Disable loading of external extensions --disable-math Disable math functions - --enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions + --disable-json Disable JSON functions + --enable-all Enable FTS4, FTS5, Geopoly, RTree, Sessions --enable-memsys5 Enable MEMSYS5 --enable-memsys3 Enable MEMSYS3 --enable-fts3 Enable the FTS3 extension --enable-fts4 Enable the FTS4 extension --enable-fts5 Enable the FTS5 extension - --enable-json1 Enable the JSON1 extension --enable-update-limit Enable the UPDATE/DELETE LIMIT clause --enable-geopoly Enable the GEOPOLY extension --enable-rtree Enable the RTREE extension @@ -11497,6 +11497,24 @@ fi fi +########## +# Do we want to support JSON functions +# +# Check whether --enable-json was given. +if test "${enable_json+set}" = set; then : + enableval=$enable_json; +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON functions" >&5 +$as_echo_n "checking whether to support JSON functions... " >&6; } +if test "$enable_json" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi ######## # The --enable-all argument is short-hand to enable @@ -11701,24 +11719,6 @@ else $as_echo "no" >&6; } fi -######### -# See whether we should enable JSON1 -# Check whether --enable-json1 was given. -if test "${enable_json1+set}" = set; then : - enableval=$enable_json1; -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support JSON" >&5 -$as_echo_n "checking whether to support JSON... " >&6; } -if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then - OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - ######### # See whether we should enable the LIMIT clause on UPDATE and DELETE # statements. diff --git a/configure.ac b/configure.ac index 32fe0d229a..cc805a00d5 100644 --- a/configure.ac +++ b/configure.ac @@ -605,12 +605,24 @@ else AC_SEARCH_LIBS(ceil, m) fi +########## +# Do we want to support JSON functions +# +AC_ARG_ENABLE(json, +AC_HELP_STRING([--disable-json],[Disable JSON functions])) +AC_MSG_CHECKING([whether to support JSON functions]) +if test "$enable_json" = "no"; then + AC_MSG_RESULT([no]) + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON" +else + AC_MSG_RESULT([yes]) +fi ######## # The --enable-all argument is short-hand to enable # multiple extensions. AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all], - [Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions])) + [Enable FTS4, FTS5, Geopoly, RTree, Sessions])) ########## # Do we want to support memsys3 and/or memsys5 @@ -666,17 +678,6 @@ else AC_MSG_RESULT([no]) fi -######### -# See whether we should enable JSON1 -AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],[Enable the JSON1 extension])) -AC_MSG_CHECKING([whether to support JSON]) -if test "${enable_json1}" = "yes" -o "${enable_all}" = "yes" ; then - OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1" - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - ######### # See whether we should enable the LIMIT clause on UPDATE and DELETE # statements. diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 98ea718f5a..68cde87344 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -26,11 +26,7 @@ # define GEODEBUG(X) #endif -#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ -/* -** Versions of isspace(), isalnum() and isdigit() to which it is safe -** to pass signed char values. -*/ +/* Character class routines */ #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ @@ -45,6 +41,7 @@ # define safe_isxdigit(x) isxdigit((unsigned char)(x)) #endif +#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ /* ** Growing our own isspace() routine this way is twice as fast as ** the library isspace() function. @@ -67,7 +64,7 @@ static const char geopolyIsSpace[] = { 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, }; -#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x]) +#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x]) #endif /* JSON NULL - back to original code */ /* Compiler and version */ @@ -156,7 +153,7 @@ static void geopolySwab32(unsigned char *a){ /* Skip whitespace. Return the next non-whitespace character. */ static char geopolySkipSpace(GeoParse *p){ - while( safe_isspace(p->z[0]) ) p->z++; + while( fast_isspace(p->z[0]) ) p->z++; return p->z[0]; } diff --git a/main.mk b/main.mk index a3a4f33bd3..e09505aee2 100644 --- a/main.mk +++ b/main.mk @@ -64,7 +64,7 @@ LIBOBJ+= vdbe.o parse.o \ fts3_tokenize_vtab.o \ fts3_unicode.o fts3_unicode2.o \ fts3_write.o fts5.o func.o global.o hash.o \ - icu.o insert.o json1.o legacy.o loadext.o \ + icu.o insert.o json.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memdb.o memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ @@ -111,6 +111,7 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ $(TOP)/src/insert.c \ + $(TOP)/src/json.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ @@ -244,7 +245,6 @@ SRC += \ $(TOP)/ext/rbu/sqlite3rbu.c \ $(TOP)/ext/rbu/sqlite3rbu.h SRC += \ - $(TOP)/ext/misc/json1.c \ $(TOP)/ext/misc/stmt.c @@ -828,9 +828,6 @@ fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR) fts5.o: fts5.c sqlite3ext.h sqlite3.h $(TCCX) -DSQLITE_CORE -c fts5.c -json1.o: $(TOP)/ext/misc/json1.c sqlite3ext.h sqlite3.h - $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c - stmt.o: $(TOP)/ext/misc/stmt.c sqlite3ext.h sqlite3.h $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c diff --git a/manifest b/manifest index f0032d5289..c39afa35cd 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Remove\stwo\sNEVER()\smacros\sthat\scan\ssometimes\sbe\strue\sif\sthe\sdatabase\sis\ncorrupt.\s\sdbsqlfuzz\s0414d2c18290fc80fd5fb540def7d3e46c1ae9c6. -D 2022-01-05T21:01:26.927 +C An\sattempt\sto\sintegrate\sthe\sJSON\sfunctions\sdirectly\sinto\sthe\sSQLite\score,\nrather\sthan\sholding\sthem\sas\san\sextension. +D 2022-01-06T01:40:09.292 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd +F Makefile.in fd537743957bfe87997dc5727783d8eec82098921e15eab984d6711cd46f001b F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f +F Makefile.msc 8ba680ec26e6d6f348954e0fee719607688075ef6c242e50e20d28e8ded7cc08 F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c F VERSION 392c2f83569705069415a5d98b1c138ec8fe8a56a663a0d94cea019e806537b2 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -34,8 +34,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559 -F configure 56f2a6637cdba53788673ccc229c4f95ab3ab6fe67036e0b1291dc615e531a58 x -F configure.ac c8ba54bac7e73e000acdfef5e394fe21a3876aa09d0f5c07131bf5ac5a525299 +F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x +F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 @@ -306,7 +306,6 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c a4ea54d9b228901695a7f51df338dddb29a2a574b870d0c0cb58539cc90e9a31 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -394,7 +393,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c a7021cb524621573ccda213a35b0339371849dd4acc4909f689786ee1f964b7f +F ext/rtree/geopoly.c cc3f89c11abcf114fa60d74709ae8b5bc1eae5a261b30bc1bb7085089c03bfab F ext/rtree/rtree.c d7b4b8b81d8d54376a7f81de5be85ec58b37c11604bcf42984a8418b34158d93 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 35c3bc0def71317b7601ee0d1149e7df2cd8fc4f13ec89a64761ac3f46ca123f @@ -472,7 +471,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 24547d9000c965553e6f5c875d91935eac250ca19ae6d9afa57fe093e3edd257 +F main.mk 32e8c752386520016933873a23a9c649f1a9cfd5c75c218614e622f0510b8f42 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -497,7 +496,7 @@ F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 +F src/ctime.c b09ce320b78718d5e0c4a7a59b8705abe8ee4683d9fa4b33768fe347e1b2a42a F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d @@ -505,16 +504,17 @@ F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560 -F src/func.c 0f576a0c102485676266e63a796223e63c3cdb04baf3678ccc8bfeedba4a6fd4 +F src/func.c 67944b79d9c06fcb86a2944082ca1dd9d46eed7bd5c6721bcb19094dd7f81358 F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 +F src/json.c 973b36a733cc5d3c8347bbdb3479c1124c0916ee7416341d0126895d055d2447 w ext/misc/json1.c F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d -F src/main.c aa24539f6c26460543d51027ea14b79cad35e34bc9d4907bc349b52b71066644 +F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -555,7 +555,7 @@ F src/shell.c.in f5111900d646a07da18e6438d57be20f112397daba6bfc85b117a0da586e55d F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef -F src/sqliteInt.h 9782b7b22a9b10e43b7f375dcdfb93cd1ed7797d831122a07d065efacf9af668 +F src/sqliteInt.h 21a31abf60222f50c1d654cdc27ad9d4040249f0341129dd8286b8b5b32bcd30 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1875,7 +1875,7 @@ F tool/mkshellc.tcl df5d249617f9cc94d5c48eb0401673eb3f31f383ecbc54e8a13ca3dd97e8 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f -F tool/mksqlite3c.tcl bf9b40811aba68f73f2a8848fad9b1fb09fd54ab5b77e5227f18eea87ab60d92 +F tool/mksqlite3c.tcl 6f9e05facb51e906a1a7ef9f95274ef2ec91bf88b96732a9aed40647c605f419 F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5 @@ -1937,8 +1937,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 7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 -R 7175e1e9a16516f1ab12321ca929e683 +P b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f +R 512e6db3c5e4ab4d0c8ece9f791ebefa +T *branch * json-in-core +T *sym-json-in-core * +T -sym-trunk * U drh -Z 45714cdd1039a8cc38c8df2ff917256e +Z a41c104f7d21d7e5237fb8ae1a000e0b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3671abe1cd..8d5afef0f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f \ No newline at end of file +583b47d865fb8d2c9ae4d3a4e70356a8a758978efb0a282f6b19775bf41fb748 \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index de68ea7f57..708d6ac2bf 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -179,6 +179,11 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_DISABLE_INTRINSIC "DISABLE_INTRINSIC", #endif +#ifdef SQLITE_DISABLE_JSON + "DISABLE_JSON", +#else + "ENABLE_JSON1", /* Legacy */ +#endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif @@ -257,9 +262,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_IOTRACE "ENABLE_IOTRACE", #endif -#ifdef SQLITE_ENABLE_JSON1 - "ENABLE_JSON1", -#endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION "ENABLE_LOAD_EXTENSION", #endif diff --git a/src/func.c b/src/func.c index eeab1d2647..360967a084 100644 --- a/src/func.c +++ b/src/func.c @@ -2347,6 +2347,7 @@ void sqlite3RegisterBuiltinFunctions(void){ #endif sqlite3WindowFunctions(); sqlite3RegisterDateTimeFunctions(); + sqlite3RegisterJsonFunctions(); sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc)); #if 0 /* Enable to print out how the built-in functions are hashed */ diff --git a/ext/misc/json1.c b/src/json.c similarity index 90% rename from ext/misc/json1.c rename to src/json.c index 787b46982e..5f39902c0e 100644 --- a/ext/misc/json1.c +++ b/src/json.c @@ -10,10 +10,10 @@ ** ****************************************************************************** ** -** This SQLite extension implements JSON functions. The interface is -** modeled after MySQL JSON functions: +** This SQLite JSON functions. ** -** https://dev.mysql.com/doc/refman/5.7/en/json.html +** This file began as an extension in ext/misc/json1.c in 2015. That +** extension proved so useful that it has now been moved into the core. ** ** For the time being, all JSON is stored as pure text. (We might add ** a JSONB type in the future which stores a binary encoding of JSON in @@ -21,57 +21,8 @@ ** This implementation parses JSON text at 250 MB/s, so it is hard to see ** how JSONB might improve on that.) */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) -#if !defined(SQLITEINT_H) -#include "sqlite3ext.h" -#endif -SQLITE_EXTENSION_INIT1 - -/* If compiling this extension separately (why would anybody do that when -** it is built into the amalgamation?) we must set NDEBUG if SQLITE_DEBUG -** is not defined *before* including , in order to disable asserts(). -*/ -#if !defined(SQLITE_AMALGAMATION) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -#include -#include -#include -#include - -/* Mark a function parameter as unused, to suppress nuisance compiler -** warnings. */ -#ifndef UNUSED_PARAM -# define UNUSED_PARAM(X) (void)(X) -#endif - -#ifndef LARGEST_INT64 -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - -#ifndef deliberate_fall_through -# define deliberate_fall_through -#endif - -/* -** Versions of isspace(), isalnum() and isdigit() to which it is safe -** to pass signed char values. -*/ -#ifdef sqlite3Isdigit - /* Use the SQLite core versions if this routine is part of the - ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) -# define safe_isxdigit(x) sqlite3Isxdigit(x) -#else - /* Use the standard library for separate compilation */ -#include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) -# define safe_isxdigit(x) isxdigit((unsigned char)(x)) -#endif +#ifndef SQLITE_OMIT_JSON +#include "sqliteInt.h" /* ** Growing our own isspace() routine this way is twice as fast as @@ -96,44 +47,14 @@ static const char jsonIsSpace[] = { 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, }; -#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) +#define fast_isspace(x) (jsonIsSpace[(unsigned char)x]) -#ifndef SQLITE_AMALGAMATION - /* Unsigned integer types. These are already defined in the sqliteInt.h, - ** but the definitions need to be repeated for separate compilation. */ - typedef sqlite3_uint64 u64; - typedef unsigned int u32; - typedef unsigned short int u16; - typedef unsigned char u8; -# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -# endif -# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -# elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) -# else -# define ALWAYS(X) (X) -# define NEVER(X) (X) -# endif -# define testcase(X) -#endif #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else # define VVA(X) X #endif -/* -** Some of the testcase() macros in this file are problematic for gcov -** in that they generate false-miss errors randomly. This is a gcov problem, -** not a problem in this case. But to work around it, we disable the -** problematic test cases for production builds. -*/ -#define json_testcase(X) - /* Objects */ typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; @@ -591,10 +512,10 @@ static u8 jsonHexToInt(int h){ */ static u32 jsonHexToInt4(const char *z){ u32 v; - assert( safe_isxdigit(z[0]) ); - assert( safe_isxdigit(z[1]) ); - assert( safe_isxdigit(z[2]) ); - assert( safe_isxdigit(z[3]) ); + assert( sqlite3Isxdigit(z[0]) ); + assert( sqlite3Isxdigit(z[1]) ); + assert( sqlite3Isxdigit(z[2]) ); + assert( sqlite3Isxdigit(z[3]) ); v = (jsonHexToInt(z[0])<<12) + (jsonHexToInt(z[1])<<8) + (jsonHexToInt(z[2])<<4) @@ -829,7 +750,7 @@ static int jsonParseAddNode( */ static int jsonIs4Hex(const char *z){ int i; - for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0; return 1; } @@ -848,13 +769,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ int x; JsonNode *pNode; const char *z = pParse->zJson; - while( safe_isspace(z[i]) ){ i++; } + while( fast_isspace(z[i]) ){ i++; } if( (c = z[i])=='{' ){ /* Parse object */ iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); if( iThis<0 ) return -1; for(j=i+1;;j++){ - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); if( x<0 ){ @@ -867,14 +788,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( pNode->eType!=JSON_STRING ) return -1; pNode->jnFlags |= JNODE_LABEL; j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( z[j]!=':' ) return -1; j++; x = jsonParseValue(pParse, j); pParse->iDepth--; if( x<0 ) return -1; j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!='}' ) return -1; @@ -888,7 +809,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( iThis<0 ) return -1; memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u)); for(j=i+1;;j++){ - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); pParse->iDepth--; @@ -897,7 +818,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ return -1; } j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!=']' ) return -1; @@ -934,17 +855,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ return j+1; }else if( c=='n' && strncmp(z+i,"null",4)==0 - && !safe_isalnum(z[i+4]) ){ + && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_NULL, 0, 0); return i+4; }else if( c=='t' && strncmp(z+i,"true",4)==0 - && !safe_isalnum(z[i+4]) ){ + && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_TRUE, 0, 0); return i+4; }else if( c=='f' && strncmp(z+i,"false",5)==0 - && !safe_isalnum(z[i+5]) ){ + && !sqlite3Isalnum(z[i+5]) ){ jsonParseAddNode(pParse, JSON_FALSE, 0, 0); return i+5; }else if( c=='-' || (c>='0' && c<='9') ){ @@ -1015,7 +936,7 @@ static int jsonParse( if( pParse->oom ) i = -1; if( i>0 ){ assert( pParse->iDepth==0 ); - while( safe_isspace(zJson[i]) ) i++; + while( fast_isspace(zJson[i]) ) i++; if( zJson[i] ) i = -1; } if( i<=0 ){ @@ -1243,7 +1164,7 @@ static JsonNode *jsonLookupStep( }else if( zPath[0]=='[' ){ i = 0; j = 1; - while( safe_isdigit(zPath[j]) ){ + while( sqlite3Isdigit(zPath[j]) ){ i = i*10 + zPath[j] - '0'; j++; } @@ -1264,13 +1185,13 @@ static JsonNode *jsonLookupStep( j = 1; } j = 2; - if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){ + if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ unsigned int x = 0; j = 3; do{ x = x*10 + zPath[j] - '0'; j++; - }while( safe_isdigit(zPath[j]) ); + }while( sqlite3Isdigit(zPath[j]) ); if( x>i ) return 0; i -= x; } @@ -1489,7 +1410,7 @@ static void jsonTest1Func( int argc, sqlite3_value **argv ){ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); } #endif /* SQLITE_DEBUG */ @@ -1510,7 +1431,7 @@ static void jsonQuoteFunc( sqlite3_value **argv ){ JsonString jx; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); jsonInit(&jx, ctx); jsonAppendValue(&jx, argv[0]); @@ -1721,7 +1642,7 @@ static void jsonPatchFunc( JsonParse y; /* The patch */ JsonNode *pResult; /* The result of the merge */ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ jsonParseReset(&x); @@ -1842,7 +1763,7 @@ static void jsonReplaceFunc( if( x.nErr ) goto replace_err; if( pNode ){ assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 ); - json_testcase( pNode->eU!=0 && pNode->eU!=1 ); + testcase( pNode->eU!=0 && pNode->eU!=1 ); pNode->jnFlags |= (u8)JNODE_REPLACE; VVA( pNode->eU = 4 ); pNode->u.iReplace = i + 1; @@ -1880,7 +1801,7 @@ static void jsonSetFunc( const char *zPath; u32 i; int bApnd; - int bIsSet = *(int*)sqlite3_user_data(ctx); + int bIsSet = sqlite3_user_data(ctx)!=0; if( argc<1 ) return; if( (argc&1)==0 ) { @@ -1899,7 +1820,7 @@ static void jsonSetFunc( }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ - json_testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 ); + testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 ); assert( pNode->eU!=3 || pNode->eU!=5 ); VVA( pNode->eU = 4 ); pNode->jnFlags |= (u8)JNODE_REPLACE; @@ -1957,7 +1878,7 @@ static void jsonValidFunc( sqlite3_value **argv ){ JsonParse *p; /* The parse */ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); p = jsonParseCached(ctx, argv, 0); sqlite3_result_int(ctx, p!=0); } @@ -1977,7 +1898,7 @@ static void jsonArrayStep( sqlite3_value **argv ){ JsonString *pStr; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ @@ -2037,8 +1958,8 @@ static void jsonGroupInverse( char *z; char c; JsonString *pStr; - UNUSED_PARAM(argc); - UNUSED_PARAM(argv); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will @@ -2082,7 +2003,7 @@ static void jsonObjectStep( JsonString *pStr; const char *z; u32 n; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ @@ -2173,10 +2094,10 @@ static int jsonEachConnect( #define JEACH_JSON 8 #define JEACH_ROOT 9 - UNUSED_PARAM(pzErr); - UNUSED_PARAM(argv); - UNUSED_PARAM(argc); - UNUSED_PARAM(pAux); + UNUSED_PARAMETER(pzErr); + UNUSED_PARAMETER(argv); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(pAux); rc = sqlite3_declare_vtab(db, "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," "json HIDDEN,root HIDDEN)"); @@ -2199,7 +2120,7 @@ static int jsonEachDisconnect(sqlite3_vtab *pVtab){ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ JsonEachCursor *pCur; - UNUSED_PARAM(p); + UNUSED_PARAMETER(p); pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); @@ -2259,7 +2180,7 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){ p->eType = pUp->eType; if( pUp->eType==JSON_ARRAY ){ assert( pUp->eU==0 || pUp->eU==3 ); - json_testcase( pUp->eU==3 ); + testcase( pUp->eU==3 ); VVA( pUp->eU = 3 ); if( iUp==p->i-1 ){ pUp->u.iKey = 0; @@ -2446,7 +2367,7 @@ static int jsonEachBestIndex( /* This implementation assumes that JSON and ROOT are the last two ** columns in the table */ assert( JEACH_ROOT == JEACH_JSON+1 ); - UNUSED_PARAM(tab); + UNUSED_PARAMETER(tab); aIdx[0] = aIdx[1] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; inConstraint; i++, pConstraint++){ @@ -2502,8 +2423,8 @@ static int jsonEachFilter( const char *zRoot = 0; sqlite3_int64 n; - UNUSED_PARAM(idxStr); - UNUSED_PARAM(argc); + UNUSED_PARAMETER(idxStr); + UNUSED_PARAMETER(argc); jsonEachCursorReset(p); if( idxNum==0 ) return SQLITE_OK; z = (const char*)sqlite3_value_text(argv[0]); @@ -2628,57 +2549,50 @@ static sqlite3_module jsonTreeModule = { 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#endif /* !defined(SQLITE_OMIT_JSON) */ -/**************************************************************************** -** The following routines are the only publically visible identifiers in this -** file. Call the following routines in order to register the various SQL -** functions and the virtual table implemented by this file. -****************************************************************************/ - -int sqlite3Json1Init(sqlite3 *db){ - int rc = SQLITE_OK; - unsigned int i; - static const struct { - const char *zName; - int nArg; - int flag; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "json", 1, 0, jsonRemoveFunc }, - { "json_array", -1, 0, jsonArrayFunc }, - { "json_array_length", 1, 0, jsonArrayLengthFunc }, - { "json_array_length", 2, 0, jsonArrayLengthFunc }, - { "json_extract", -1, 0, jsonExtractFunc }, - { "json_insert", -1, 0, jsonSetFunc }, - { "json_object", -1, 0, jsonObjectFunc }, - { "json_patch", 2, 0, jsonPatchFunc }, - { "json_quote", 1, 0, jsonQuoteFunc }, - { "json_remove", -1, 0, jsonRemoveFunc }, - { "json_replace", -1, 0, jsonReplaceFunc }, - { "json_set", -1, 1, jsonSetFunc }, - { "json_type", 1, 0, jsonTypeFunc }, - { "json_type", 2, 0, jsonTypeFunc }, - { "json_valid", 1, 0, jsonValidFunc }, - +/* +** Register JSON functions. +*/ +void sqlite3RegisterJsonFunctions(void){ +#ifndef SQLITE_OMIT_JSON + static FuncDef aJsonFunc[] = { + JFUNCTION(json, 1, 0, jsonRemoveFunc), + JFUNCTION(json_array, -1, 0, jsonArrayFunc), + JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), + JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), + JFUNCTION(json_extract, -1, 0, jsonExtractFunc), + JFUNCTION(json_insert, -1, 0, jsonSetFunc), + JFUNCTION(json_object, -1, 0, jsonObjectFunc), + JFUNCTION(json_patch, 2, 0, jsonPatchFunc), + JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), + JFUNCTION(json_remove, -1, 0, jsonRemoveFunc), + JFUNCTION(json_replace, -1, 0, jsonReplaceFunc), + JFUNCTION(json_set, -1, 1, jsonSetFunc), + JFUNCTION(json_type, 1, 0, jsonTypeFunc), + JFUNCTION(json_type, 2, 0, jsonTypeFunc), + JFUNCTION(json_valid, 1, 0, jsonValidFunc), #if SQLITE_DEBUG - /* DEBUG and TESTING functions */ - { "json_parse", 1, 0, jsonParseFunc }, - { "json_test1", 1, 0, jsonTest1Func }, + JFUNCTION(json_parse, 1, 0, jsonParseFunc), + JFUNCTION(json_test1, 1, 0, jsonTest1Func), #endif + WAGGREGATE(json_group_array, 1, 0, 0, + jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS), + WAGGREGATE(json_group_object, 2, 0, 0, + jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS) }; - static const struct { - const char *zName; - int nArg; - void (*xStep)(sqlite3_context*,int,sqlite3_value**); - void (*xFinal)(sqlite3_context*); - void (*xValue)(sqlite3_context*); - } aAgg[] = { - { "json_group_array", 1, - jsonArrayStep, jsonArrayFinal, jsonArrayValue }, - { "json_group_object", 2, - jsonObjectStep, jsonObjectFinal, jsonObjectValue }, - }; -#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); +#endif +} + +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) +/* +** Register the JSON table-valued functions +*/ +int sqlite3JsonTableFunctions(sqlite3 *db){ + int rc = SQLITE_OK; static const struct { const char *zName; sqlite3_module *pModule; @@ -2686,45 +2600,10 @@ int sqlite3Json1Init(sqlite3 *db){ { "json_each", &jsonEachModule }, { "json_tree", &jsonTreeModule }, }; -#endif - static const int enc = - SQLITE_UTF8 | - SQLITE_DETERMINISTIC | - SQLITE_INNOCUOUS; - for(i=0; i Date: Thu, 6 Jan 2022 17:13:56 +0000 Subject: [PATCH 117/148] Add the '-guard:cf' compiler option for Windows 10, per [forum:/forumpost/8d3b4ad694|forum post 8d3b4ad694]. FossilOrigin-Name: 2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f --- Makefile.msc | 12 ++++++------ autoconf/Makefile.msc | 8 ++++---- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 3cbf560d7c..42f4648875 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -580,17 +580,17 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) # !IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0 !IF "$(PLATFORM)"=="x86" -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall # <> -TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl +TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl # <> !ELSE !IFNDEF PLATFORM -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall # <> -TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl +TEST_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl # <> !ELSE CORE_CCONV_OPTS = diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 40d0e8113d..524aeb6f41 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -502,12 +502,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS) # !IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0 !IF "$(PLATFORM)"=="x86" -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall !ELSE !IFNDEF PLATFORM -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +CORE_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall +SHELL_CCONV_OPTS = -Gz -guard:cf -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall !ELSE CORE_CCONV_OPTS = SHELL_CCONV_OPTS = diff --git a/manifest b/manifest index f0032d5289..66cd8be755 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Remove\stwo\sNEVER()\smacros\sthat\scan\ssometimes\sbe\strue\sif\sthe\sdatabase\sis\ncorrupt.\s\sdbsqlfuzz\s0414d2c18290fc80fd5fb540def7d3e46c1ae9c6. -D 2022-01-05T21:01:26.927 +C Add\sthe\s'-guard:cf'\scompiler\soption\sfor\sWindows\s10,\sper\s[forum:/forumpost/8d3b4ad694|forum\spost\s8d3b4ad694]. +D 2022-01-06T17:13:56.835 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0e91c42a1dd13a569b1fa4f4dfb7d3632f3164a1c05c71341533d67db5b641dd F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 88f05063ee36a5fb77d69b877ef824d0743b5325c95bfbf74d6ff17bd1c9fb1f +F Makefile.msc 517f22463b99b56f6c4c81afcf09c7bf3a0289d08f2dadcc0d5322819dbd6017 F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c F VERSION 392c2f83569705069415a5d98b1c138ec8fe8a56a663a0d94cea019e806537b2 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8 F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac -F autoconf/Makefile.msc d146a08ebbdf7f881ba600a49cd8dce40c4c807addcdb4b9b6a507e4b40ce837 +F autoconf/Makefile.msc 262dad10223b39a6853c4faefadb0f71931ca55c742fa285f8ee8d56b7543ddc F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1 F autoconf/configure.ac a8ba2a9e61216f5093d44f3b7d2cb8fe1890d6b7dc330a02f802d8efaa1fdc79 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7ae596dd4a73a09585c5dc9f4faf75d126d0733fc2fb32c1de64126a1088d967 -R 7175e1e9a16516f1ab12321ca929e683 -U drh -Z 45714cdd1039a8cc38c8df2ff917256e +P b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f +R 77a4280a2931dd249bcf6514bda5d68b +U mistachkin +Z 912599d00221acb9d08acd46c2ac9173 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3671abe1cd..ba34d0d3e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f \ No newline at end of file +2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f \ No newline at end of file From d5326c333f2189542d844350b3268804028d501a Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 14:58:47 +0000 Subject: [PATCH 118/148] Add new binary operators "->" and "->>" to the parser that evaluate to 2-argument SQL functions by the same name. Add new "->" and "->>" functions to the JSON extension that are aliases for json_extract(). FossilOrigin-Name: c4e4e3a3fc5da0381ccb7930706e57d7831d87f9c63bafe49ae64117701e1cfe --- ext/misc/json1.c | 2 ++ manifest | 23 +++++++++++++---------- manifest.uuid | 2 +- src/parse.y | 10 ++++++++-- src/tokenize.c | 3 +++ test/func.test | 15 +++++++++++++++ 6 files changed, 42 insertions(+), 13 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 787b46982e..5addd7dbcc 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -2649,6 +2649,8 @@ int sqlite3Json1Init(sqlite3 *db){ { "json_array_length", 1, 0, jsonArrayLengthFunc }, { "json_array_length", 2, 0, jsonArrayLengthFunc }, { "json_extract", -1, 0, jsonExtractFunc }, + { "->", 2, 1, jsonExtractFunc }, + { "->>", 2, 1, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_object", -1, 0, jsonObjectFunc }, { "json_patch", 2, 0, jsonPatchFunc }, diff --git a/manifest b/manifest index 66cd8be755..b962a3d961 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s'-guard:cf'\scompiler\soption\sfor\sWindows\s10,\sper\s[forum:/forumpost/8d3b4ad694|forum\spost\s8d3b4ad694]. -D 2022-01-06T17:13:56.835 +C Add\snew\sbinary\soperators\s"->"\sand\s"->>"\sto\sthe\sparser\sthat\sevaluate\sto\n2-argument\sSQL\sfunctions\sby\sthe\ssame\sname.\s\sAdd\snew\s"->"\sand\s"->>"\sfunctions\nto\sthe\sJSON\sextension\sthat\sare\saliases\sfor\sjson_extract(). +D 2022-01-07T14:58:47.701 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c a4ea54d9b228901695a7f51df338dddb29a2a574b870d0c0cb58539cc90e9a31 +F ext/misc/json1.c ee5d8250f78d598e0c8b81fc37e8fa1b52098e5f7bb71f0db3cd39c1acc4ca78 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -539,7 +539,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 55a9a8c745c47a49e6541b1d634f6152e3f72f76c6dbb04fe24413986a928091 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f -F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a +F src/parse.y 04f61db1cdd7036c6d74baad1c342d3e3110cb0765c48fcfd3bdf4e974a1e5bb F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 @@ -614,7 +614,7 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c dc5367c6d42336b35d55f96d2f04cd6256e92bc6ecf74ed5d855d24e43343aff +F src/tokenize.c b74d878aa7c82ec8460779468061a96185e22257f68ab785b69abce354b70446 F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc F src/trigger.c 40e7c3dcff57a770d5fa38ba21ed4725572fd2e224c58af61eb980598b60f9c8 F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328 @@ -1045,7 +1045,7 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75 F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9 F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test 3a65ddb6c1998f71aa86492501a6be87904197e62bfb5b70b2493552b558abd1 +F test/func.test 0a305e88a4fbdce6be8c6f4863d6dab9ecb2975b95e94734621e2c900779b712 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31 @@ -1937,8 +1937,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 b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f -R 77a4280a2931dd249bcf6514bda5d68b -U mistachkin -Z 912599d00221acb9d08acd46c2ac9173 +P 2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f +R a976b35db7b5d2f5710ec976fab3e1b7 +T *branch * json-enhancements +T *sym-json-enhancements * +T -sym-trunk * +U drh +Z e4a5223ea04d8f66a6958c2ae1a2641b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ba34d0d3e9..20f17305ae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f \ No newline at end of file +c4e4e3a3fc5da0381ccb7930706e57d7831d87f9c63bafe49ae64117701e1cfe \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 559057f9ae..5b83b16b60 100644 --- a/src/parse.y +++ b/src/parse.y @@ -236,7 +236,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);} // %token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST. %token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL. -%token OR AND NOT MATCH LIKE_KW BETWEEN IS IN ISNULL NOTNULL NE EQ. +%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. %token GT LE LT GE ESCAPE. // The following directive causes tokens ABORT, AFTER, ASC, etc. to @@ -286,7 +286,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);} %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. %left STAR SLASH REM. -%left CONCAT. +%left CONCAT PTR. %left COLLATE. %right BITNOT. %nonassoc ON. @@ -1235,6 +1235,12 @@ expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] { /*A-overwrites-B*/ } +expr(A) ::= expr(B) PTR(C) expr(D). { + ExprList *pList = sqlite3ExprListAppend(pParse, 0, B); + pList = sqlite3ExprListAppend(pParse, pList, D); + A = sqlite3ExprFunction(pParse, pList, &C, 0); +} + %type between_op {int} between_op(A) ::= BETWEEN. {A = 0;} between_op(A) ::= NOT BETWEEN. {A = 1;} diff --git a/src/tokenize.c b/src/tokenize.c index 5f41e5665e..347fd57323 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -290,6 +290,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ for(i=2; (c=z[i])!=0 && c!='\n'; i++){} *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ return i; + }else if( z[1]=='>' ){ + *tokenType = TK_PTR; + return 2 + (z[2]=='>'); } *tokenType = TK_MINUS; return 1; diff --git a/test/func.test b/test/func.test index ca1027f508..008819baa5 100644 --- a/test/func.test +++ b/test/func.test @@ -1507,4 +1507,19 @@ do_execsql_test func-35.200 { PRAGMA integrity_check; } {ok} +# 2021-01-07: The -> and ->> operators. +# +proc ptr1 {a b} { return "$a->$b" } +db func -> ptr1 +proc ptr2 {a b} { return "$a->>$b" } +db func ->> ptr2 +do_execsql_test func-36.100 { + SELECT 123 -> 456 +} {123->456} +do_execsql_test func-36.110 { + SELECT 123 ->> 456 +} {123->>456} + + + finish_test From 12b9fa979cfd1e4c20423c80d4931591269da27b Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 15:47:12 +0000 Subject: [PATCH 119/148] Accept abbreviated JSON Paths on the right-hand side of the -> and ->> operators. FossilOrigin-Name: d15410900dccbb7159683c29f640fa321b1e019718827334f5fefe89da623008 --- ext/misc/json1.c | 60 ++++++++++++++++++++++++++++++++++------------- manifest | 17 ++++++-------- manifest.uuid | 2 +- test/json102.test | 27 +++++++++++++++++++++ 4 files changed, 79 insertions(+), 27 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 5addd7dbcc..6f66d4e70c 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1598,34 +1598,62 @@ static void jsonExtractFunc( JsonNode *pNode; const char *zPath; JsonString jx; - int i; if( argc<2 ) return; p = jsonParseCached(ctx, argv, ctx); if( p==0 ) return; - jsonInit(&jx, ctx); - jsonAppendChar(&jx, '['); - for(i=1; inErr ) break; - if( argc>2 ){ + if( argc==2 ){ + /* With a single PATH argument, the return is the unquoted SQL value */ + zPath = (const char*)sqlite3_value_text(argv[1]); + if( zPath && zPath[0]!='$' && zPath[0]!=0 + && *(int*)sqlite3_user_data(ctx) + ){ + /* The -> and ->> operators accept abbreviated PATH arguments: + ** NUMBER ==> $[NUMBER] + ** LABEL ==> $.LABEL + ** [NUMBER] ==> $[NUMBER] + */ + jsonInit(&jx, ctx); + if( safe_isdigit(zPath[0]) ){ + jsonAppendRaw(&jx, "$[", 2); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendRaw(&jx, "]", 2); + }else{ + jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendChar(&jx, 0); + } + pNode = jsonLookup(p, jx.zBuf, 0, ctx); + jsonReset(&jx); + }else{ + pNode = jsonLookup(p, zPath, 0, ctx); + } + if( p->nErr ) return; + if( pNode ) jsonReturn(pNode, ctx, 0); + }else{ + /* Two or more PATH arguments results in a JSON array with each + ** element of the array being the value selected by one of the PATHs */ + int i; + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '['); + for(i=1; inErr ) break; jsonAppendSeparator(&jx); if( pNode ){ jsonRenderNode(pNode, &jx, 0); }else{ jsonAppendRaw(&jx, "null", 4); } - }else if( pNode ){ - jsonReturn(pNode, ctx, 0); } + if( i==argc ){ + jsonAppendChar(&jx, ']'); + jsonResult(&jx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } + jsonReset(&jx); } - if( argc>2 && i==argc ){ - jsonAppendChar(&jx, ']'); - jsonResult(&jx); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - jsonReset(&jx); } /* This is the RFC 7396 MergePatch algorithm. diff --git a/manifest b/manifest index b962a3d961..3fa4543e06 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sbinary\soperators\s"->"\sand\s"->>"\sto\sthe\sparser\sthat\sevaluate\sto\n2-argument\sSQL\sfunctions\sby\sthe\ssame\sname.\s\sAdd\snew\s"->"\sand\s"->>"\sfunctions\nto\sthe\sJSON\sextension\sthat\sare\saliases\sfor\sjson_extract(). -D 2022-01-07T14:58:47.701 +C Accept\sabbreviated\sJSON\sPaths\son\sthe\sright-hand\sside\sof\sthe\s->\sand\s->>\soperators. +D 2022-01-07T15:47:12.461 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c ee5d8250f78d598e0c8b81fc37e8fa1b52098e5f7bb71f0db3cd39c1acc4ca78 +F ext/misc/json1.c 81a11151fbeefd8870c31a9e77576daeacc9ef1c66153950ea2eb084193235c6 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1147,7 +1147,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1 +F test/json102.test 8ee925a282f03f47526ca4e260b8e4af9f4e5b562f38647aa4f32dc84c19a0a3 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1937,11 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f -R a976b35db7b5d2f5710ec976fab3e1b7 -T *branch * json-enhancements -T *sym-json-enhancements * -T -sym-trunk * +P c4e4e3a3fc5da0381ccb7930706e57d7831d87f9c63bafe49ae64117701e1cfe +R dd2f603ec9049bd111aea3757f3d8f8e U drh -Z e4a5223ea04d8f66a6958c2ae1a2641b +Z 9891da1f488bb126e807d6977835eae4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 20f17305ae..6b7aeda36e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4e4e3a3fc5da0381ccb7930706e57d7831d87f9c63bafe49ae64117701e1cfe \ No newline at end of file +d15410900dccbb7159683c29f640fa321b1e019718827334f5fefe89da623008 \ No newline at end of file diff --git a/test/json102.test b/test/json102.test index 18a6bbf5cc..6afe2307b3 100644 --- a/test/json102.test +++ b/test/json102.test @@ -71,21 +71,48 @@ do_execsql_test json102-240 { do_execsql_test json102-250 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$'); } {{{"a":2,"c":[4,5,{"f":7}]}}} +do_execsql_test json102-251 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$'; +} {{{"a":2,"c":[4,5,{"f":7}]}}} do_execsql_test json102-260 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c'); } {{[4,5,{"f":7}]}} +do_execsql_test json102-261 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c'; +} {{[4,5,{"f":7}]}} +do_execsql_test json102-262 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c'; +} {{[4,5,{"f":7}]}} do_execsql_test json102-270 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]'); } {{{"f":7}}} +do_execsql_test json102-271 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2]'; +} {{{"f":7}}} +do_execsql_test json102-272 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2; +} {{{"f":7}}} do_execsql_test json102-280 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f'); } {{7}} +do_execsql_test json102-281 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2 -> 'f'; +} {{7}} +do_execsql_test json102-282 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> '[2]' -> 'f'; +} {{7}} do_execsql_test json102-290 { SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a'); } {{[[4,5],2]}} do_execsql_test json102-300 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x'); } {{}} +do_execsql_test json102-301 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'x'; +} {{}} +do_execsql_test json102-302 { + SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> NULL; +} {{}} do_execsql_test json102-310 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a'); } {{[null,2]}} From a4e4e18494f745b50f69e87de1275bbed5dd75e4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 16:03:00 +0000 Subject: [PATCH 120/148] Add the json_ntype() SQL function. Works like the 1-argument json_type() except that it returns NULL if the argument is not well-formed JSON, rather than raising an error. FossilOrigin-Name: ed9956f5ddca68141eded81d5362847db603257329801622c4eb3b0732112f14 --- ext/misc/json1.c | 10 +++++++--- manifest | 14 +++++++------- manifest.uuid | 2 +- test/json102.test | 9 +++++++++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 6f66d4e70c..926f0a8b68 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1946,10 +1946,13 @@ jsonSetDone: /* ** json_type(JSON) +** json_ntype(JSON) ** json_type(JSON, PATH) ** -** Return the top-level "type" of a JSON string. Throw an error if -** either the JSON or PATH inputs are not well-formed. +** Return the top-level "type" of a JSON string. json_type() raises an +** error if either the JSON or PATH inputs are not well-formed. json_ntype() +** works like the one-argument version of json_type() except that it +** returns NULL if the JSON argument is not well-formed. */ static void jsonTypeFunc( sqlite3_context *ctx, @@ -1960,7 +1963,7 @@ static void jsonTypeFunc( const char *zPath; JsonNode *pNode; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv, *(int*)sqlite3_user_data(ctx) ? 0 : ctx); if( p==0 ) return; if( argc==2 ){ zPath = (const char*)sqlite3_value_text(argv[1]); @@ -2680,6 +2683,7 @@ int sqlite3Json1Init(sqlite3 *db){ { "->", 2, 1, jsonExtractFunc }, { "->>", 2, 1, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, + { "json_ntype", 1, 1, jsonTypeFunc }, { "json_object", -1, 0, jsonObjectFunc }, { "json_patch", 2, 0, jsonPatchFunc }, { "json_quote", 1, 0, jsonQuoteFunc }, diff --git a/manifest b/manifest index 3fa4543e06..7dff65acd8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Accept\sabbreviated\sJSON\sPaths\son\sthe\sright-hand\sside\sof\sthe\s->\sand\s->>\soperators. -D 2022-01-07T15:47:12.461 +C Add\sthe\sjson_ntype()\sSQL\sfunction.\s\sWorks\slike\sthe\s1-argument\sjson_type()\nexcept\sthat\sit\sreturns\sNULL\sif\sthe\sargument\sis\snot\swell-formed\sJSON,\srather\nthan\sraising\san\serror. +D 2022-01-07T16:03:00.989 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c 81a11151fbeefd8870c31a9e77576daeacc9ef1c66153950ea2eb084193235c6 +F ext/misc/json1.c 5416dd330d6d4cfade184dd3d123ab720ca99ac72b21bd419b76cdbe69ac68d9 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1147,7 +1147,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test 8ee925a282f03f47526ca4e260b8e4af9f4e5b562f38647aa4f32dc84c19a0a3 +F test/json102.test c0c45152f516036dd444b8650dd55a06c455792e35ab1c3180537b77d00f7f10 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c4e4e3a3fc5da0381ccb7930706e57d7831d87f9c63bafe49ae64117701e1cfe -R dd2f603ec9049bd111aea3757f3d8f8e +P d15410900dccbb7159683c29f640fa321b1e019718827334f5fefe89da623008 +R 33189226ed8931e2d3369f37d0903d14 U drh -Z 9891da1f488bb126e807d6977835eae4 +Z aa887589cd33ea857ca5f9e682543a02 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6b7aeda36e..8efe23711e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d15410900dccbb7159683c29f640fa321b1e019718827334f5fefe89da623008 \ No newline at end of file +ed9956f5ddca68141eded81d5362847db603257329801622c4eb3b0732112f14 \ No newline at end of file diff --git a/test/json102.test b/test/json102.test index 6afe2307b3..ce1da6993a 100644 --- a/test/json102.test +++ b/test/json102.test @@ -176,6 +176,9 @@ do_execsql_test json102-500 { do_execsql_test json102-510 { SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}'); } {{object}} +do_execsql_test json102-511 { + SELECT json_ntype('{"a":[2,3.5,true,false,null,"x"]}'); +} {{object}} do_execsql_test json102-520 { SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$'); } {{object}} @@ -209,6 +212,12 @@ do_execsql_test json102-610 { do_execsql_test json102-620 { SELECT json_valid(char(123)||'"x":35'); } {{0}} +do_catchsql_test json102-630 { + SELECT json_type('["a",'); +} {1 {malformed JSON}} +do_catchsql_test json102-631 { + SELECT json_ntype('["a",'); +} {0 {{}}} ifcapable vtab { do_execsql_test json102-1000 { From 338b1fde623427ee8bbdc7921cff8d8714518fda Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 17:08:48 +0000 Subject: [PATCH 121/148] New json_nextract() function that works like json_extract() except that it returns NULL instead of raising an error if the first argument is not well-formed JSON. Or if the first argument is not well-formed JSON and the second argument is '$', then return the first argument quoted. The "->" and "->>" operators are converted to use json_nextract(). FossilOrigin-Name: dc00f5286d26524b149de071490320afaa203fec5777b3eb813f07963614861a --- ext/misc/json1.c | 25 ++++++++++++++++++------- manifest | 14 +++++++------- manifest.uuid | 2 +- test/json102.test | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 926f0a8b68..2cb9d700b0 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1597,17 +1597,27 @@ static void jsonExtractFunc( JsonParse *p; /* The parse */ JsonNode *pNode; const char *zPath; + int flags = *(int*)sqlite3_user_data(ctx); JsonString jx; if( argc<2 ) return; - p = jsonParseCached(ctx, argv, ctx); - if( p==0 ) return; + p = jsonParseCached(ctx, argv, (flags & 1)!=0 ? 0 : ctx); + if( p==0 ){ + /* If the form is "json_nextract(IN,'$')" and IN is not well-formed JSON, + ** then return IN as a quoted JSON string. */ + if( (flags & 1)!=0 + && argc==2 + && (zPath = (const char*)sqlite3_value_text(argv[1]))!=0 + && zPath[0]=='$' && zPath[1]==0 + ){ + jsonQuoteFunc(ctx, argc, argv); + } + return; + } if( argc==2 ){ /* With a single PATH argument, the return is the unquoted SQL value */ zPath = (const char*)sqlite3_value_text(argv[1]); - if( zPath && zPath[0]!='$' && zPath[0]!=0 - && *(int*)sqlite3_user_data(ctx) - ){ + if( zPath && zPath[0]!='$' && zPath[0]!=0 && (flags & 2)!=0 ){ /* The -> and ->> operators accept abbreviated PATH arguments: ** NUMBER ==> $[NUMBER] ** LABEL ==> $.LABEL @@ -2680,8 +2690,9 @@ int sqlite3Json1Init(sqlite3 *db){ { "json_array_length", 1, 0, jsonArrayLengthFunc }, { "json_array_length", 2, 0, jsonArrayLengthFunc }, { "json_extract", -1, 0, jsonExtractFunc }, - { "->", 2, 1, jsonExtractFunc }, - { "->>", 2, 1, jsonExtractFunc }, + { "json_nextract", -1, 1, jsonExtractFunc }, + { "->", 2, 3, jsonExtractFunc }, + { "->>", 2, 3, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_ntype", 1, 1, jsonTypeFunc }, { "json_object", -1, 0, jsonObjectFunc }, diff --git a/manifest b/manifest index 7dff65acd8..a1aa869c97 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sjson_ntype()\sSQL\sfunction.\s\sWorks\slike\sthe\s1-argument\sjson_type()\nexcept\sthat\sit\sreturns\sNULL\sif\sthe\sargument\sis\snot\swell-formed\sJSON,\srather\nthan\sraising\san\serror. -D 2022-01-07T16:03:00.989 +C New\sjson_nextract()\sfunction\sthat\sworks\slike\sjson_extract()\sexcept\sthat\sit\nreturns\sNULL\sinstead\sof\sraising\san\serror\sif\sthe\sfirst\sargument\sis\snot\nwell-formed\sJSON.\s\sOr\sif\sthe\sfirst\sargument\sis\snot\swell-formed\sJSON\sand\nthe\ssecond\sargument\sis\s'$',\sthen\sreturn\sthe\sfirst\sargument\squoted.\s\sThe\n"->"\sand\s"->>"\soperators\sare\sconverted\sto\suse\sjson_nextract(). +D 2022-01-07T17:08:48.125 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c 5416dd330d6d4cfade184dd3d123ab720ca99ac72b21bd419b76cdbe69ac68d9 +F ext/misc/json1.c f2dc0952d66ebb6c9913e41170f574a4fb4a46d80d4c30ec2b7bc7635d565aae F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1147,7 +1147,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test c0c45152f516036dd444b8650dd55a06c455792e35ab1c3180537b77d00f7f10 +F test/json102.test 40a408ffbb9294bffc9a62ea32f3ecdc2b9b40df16c69b73dc18f1684540512c F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d15410900dccbb7159683c29f640fa321b1e019718827334f5fefe89da623008 -R 33189226ed8931e2d3369f37d0903d14 +P ed9956f5ddca68141eded81d5362847db603257329801622c4eb3b0732112f14 +R f26fe71ed976f3035850cd240318b4a2 U drh -Z aa887589cd33ea857ca5f9e682543a02 +Z 13ae4c74ef71f6a4a05f3faff51e35b4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8efe23711e..d63d456dde 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed9956f5ddca68141eded81d5362847db603257329801622c4eb3b0732112f14 \ No newline at end of file +dc00f5286d26524b149de071490320afaa203fec5777b3eb813f07963614861a \ No newline at end of file diff --git a/test/json102.test b/test/json102.test index ce1da6993a..fbd9711c5d 100644 --- a/test/json102.test +++ b/test/json102.test @@ -72,6 +72,9 @@ do_execsql_test json102-250 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$'); } {{{"a":2,"c":[4,5,{"f":7}]}}} do_execsql_test json102-251 { + SELECT json_nextract('{"a":2,"c":[4,5,{"f":7}]}', '$'); +} {{{"a":2,"c":[4,5,{"f":7}]}}} +do_execsql_test json102-252 { SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$'; } {{{"a":2,"c":[4,5,{"f":7}]}}} do_execsql_test json102-260 { @@ -83,6 +86,22 @@ do_execsql_test json102-261 { do_execsql_test json102-262 { SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c'; } {{[4,5,{"f":7}]}} +do_catchsql_test json102-265 { + SELECT json_extract('[1,2,3', '$[2]'); +} {1 {malformed JSON}} +do_catchsql_test json102-266 { + SELECT json_nextract('[1,2,3', '$[2]'); +} {0 {{}}} +do_catchsql_test json102-267 { + SELECT json_extract('[1,2,3', '$'); +} {1 {malformed JSON}} +do_catchsql_test json102-268 { + SELECT json_nextract('[1,2,3', '$'); +} {0 {{"[1,2,3"}}} +do_catchsql_test json102-269 { + SELECT '[1,2,3' ->> '$'; +} {0 {{"[1,2,3"}}} + do_execsql_test json102-270 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]'); } {{{"f":7}}} From 9956c18a814de7928821fb446249c692c9e64df4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 17:14:35 +0000 Subject: [PATCH 122/148] Change the -> operator to use json_extract(). The ->> operator continues to use json_nextract(). FossilOrigin-Name: b4c8a62381755b9f1447e10ab95df7209eebda91f9a4583ef1c093a13f6b4725 --- ext/misc/json1.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- test/json102.test | 5 ++++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 2cb9d700b0..e35d4ed576 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -2691,7 +2691,7 @@ int sqlite3Json1Init(sqlite3 *db){ { "json_array_length", 2, 0, jsonArrayLengthFunc }, { "json_extract", -1, 0, jsonExtractFunc }, { "json_nextract", -1, 1, jsonExtractFunc }, - { "->", 2, 3, jsonExtractFunc }, + { "->", 2, 2, jsonExtractFunc }, { "->>", 2, 3, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_ntype", 1, 1, jsonTypeFunc }, diff --git a/manifest b/manifest index a1aa869c97..647b8c22a9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\sjson_nextract()\sfunction\sthat\sworks\slike\sjson_extract()\sexcept\sthat\sit\nreturns\sNULL\sinstead\sof\sraising\san\serror\sif\sthe\sfirst\sargument\sis\snot\nwell-formed\sJSON.\s\sOr\sif\sthe\sfirst\sargument\sis\snot\swell-formed\sJSON\sand\nthe\ssecond\sargument\sis\s'$',\sthen\sreturn\sthe\sfirst\sargument\squoted.\s\sThe\n"->"\sand\s"->>"\soperators\sare\sconverted\sto\suse\sjson_nextract(). -D 2022-01-07T17:08:48.125 +C Change\sthe\s->\soperator\sto\suse\sjson_extract().\s\sThe\s->>\soperator\scontinues\nto\suse\sjson_nextract(). +D 2022-01-07T17:14:35.839 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c f2dc0952d66ebb6c9913e41170f574a4fb4a46d80d4c30ec2b7bc7635d565aae +F ext/misc/json1.c bec23aa378f56320246ce0bed2d841bef9d73a467f0f7a188eed1f753c61d113 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1147,7 +1147,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test 40a408ffbb9294bffc9a62ea32f3ecdc2b9b40df16c69b73dc18f1684540512c +F test/json102.test 94a91c6ba5df84397d887af8e7278d3e8344486e9fe6fba2916473d2b89819e1 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed9956f5ddca68141eded81d5362847db603257329801622c4eb3b0732112f14 -R f26fe71ed976f3035850cd240318b4a2 +P dc00f5286d26524b149de071490320afaa203fec5777b3eb813f07963614861a +R c2278f0d888348e91e31b99a70b490f1 U drh -Z 13ae4c74ef71f6a4a05f3faff51e35b4 +Z e2f5d3c5e50a6c66708d727e107dbfb6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d63d456dde..cb3b4bb5de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc00f5286d26524b149de071490320afaa203fec5777b3eb813f07963614861a \ No newline at end of file +b4c8a62381755b9f1447e10ab95df7209eebda91f9a4583ef1c093a13f6b4725 \ No newline at end of file diff --git a/test/json102.test b/test/json102.test index fbd9711c5d..521373a833 100644 --- a/test/json102.test +++ b/test/json102.test @@ -98,7 +98,10 @@ do_catchsql_test json102-267 { do_catchsql_test json102-268 { SELECT json_nextract('[1,2,3', '$'); } {0 {{"[1,2,3"}}} -do_catchsql_test json102-269 { +do_catchsql_test json102-269a { + SELECT '[1,2,3' -> '$'; +} {1 {malformed JSON}} +do_catchsql_test json102-269b { SELECT '[1,2,3' ->> '$'; } {0 {{"[1,2,3"}}} From a3f51d7b3e7cd531e33779bcb7fec8f259c99cc6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 17:26:40 +0000 Subject: [PATCH 123/148] Reverse the meaningn of -> and ->>. ->> raises an error on invalid JSON but -> does not. This allows ->> to behave the same as PG and MySQL. FossilOrigin-Name: 85f8170555ee0d4d28cb7e120a7062e9f64c331a936fdfa29fc0e67224eea7c6 --- ext/misc/json1.c | 4 ++-- manifest | 14 +++++++------- manifest.uuid | 2 +- test/json102.test | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index e35d4ed576..86a486c21c 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -2691,8 +2691,8 @@ int sqlite3Json1Init(sqlite3 *db){ { "json_array_length", 2, 0, jsonArrayLengthFunc }, { "json_extract", -1, 0, jsonExtractFunc }, { "json_nextract", -1, 1, jsonExtractFunc }, - { "->", 2, 2, jsonExtractFunc }, - { "->>", 2, 3, jsonExtractFunc }, + { "->", 2, 3, jsonExtractFunc }, + { "->>", 2, 2, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_ntype", 1, 1, jsonTypeFunc }, { "json_object", -1, 0, jsonObjectFunc }, diff --git a/manifest b/manifest index 647b8c22a9..3227004e9a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\s->\soperator\sto\suse\sjson_extract().\s\sThe\s->>\soperator\scontinues\nto\suse\sjson_nextract(). -D 2022-01-07T17:14:35.839 +C Reverse\sthe\smeaningn\sof\s->\sand\s->>.\s\s->>\sraises\san\serror\son\sinvalid\sJSON\nbut\s->\sdoes\snot.\s\sThis\sallows\s->>\sto\sbehave\sthe\ssame\sas\sPG\sand\sMySQL. +D 2022-01-07T17:26:40.622 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -306,7 +306,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c bec23aa378f56320246ce0bed2d841bef9d73a467f0f7a188eed1f753c61d113 +F ext/misc/json1.c bfee5581c6f8443d2b4d73939c1aaad887111b7bb5f3a8c5dbd1572f627de83c F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1147,7 +1147,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test 94a91c6ba5df84397d887af8e7278d3e8344486e9fe6fba2916473d2b89819e1 +F test/json102.test a44a20b7dfa446e67f47d0c02927fe93f80d6ebf3080a5d827757e8d4921c081 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dc00f5286d26524b149de071490320afaa203fec5777b3eb813f07963614861a -R c2278f0d888348e91e31b99a70b490f1 +P b4c8a62381755b9f1447e10ab95df7209eebda91f9a4583ef1c093a13f6b4725 +R 5e00922e334b2eca45d33167fc947357 U drh -Z e2f5d3c5e50a6c66708d727e107dbfb6 +Z ca8d93554520c6d97db646c26d2dff94 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index cb3b4bb5de..89e07a6e91 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b4c8a62381755b9f1447e10ab95df7209eebda91f9a4583ef1c093a13f6b4725 \ No newline at end of file +85f8170555ee0d4d28cb7e120a7062e9f64c331a936fdfa29fc0e67224eea7c6 \ No newline at end of file diff --git a/test/json102.test b/test/json102.test index 521373a833..7ae99353bf 100644 --- a/test/json102.test +++ b/test/json102.test @@ -99,10 +99,10 @@ do_catchsql_test json102-268 { SELECT json_nextract('[1,2,3', '$'); } {0 {{"[1,2,3"}}} do_catchsql_test json102-269a { - SELECT '[1,2,3' -> '$'; + SELECT '[1,2,3' ->> '$'; } {1 {malformed JSON}} do_catchsql_test json102-269b { - SELECT '[1,2,3' ->> '$'; + SELECT '[1,2,3' -> '$'; } {0 {{"[1,2,3"}}} do_execsql_test json102-270 { From 4f3557e4c95b78bc15229afc06799b2bf1ef99dd Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 7 Jan 2022 18:09:56 +0000 Subject: [PATCH 124/148] Notes on the JSON enhancement proposals. FossilOrigin-Name: 18160985ea6b2bbf27de25e0f4f3a1ebcdb079a36af039fc06e37a834e49e772 --- doc/json-enhancements.md | 123 +++++++++++++++++++++++++++++++++++++++ manifest | 11 ++-- manifest.uuid | 2 +- 3 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 doc/json-enhancements.md diff --git a/doc/json-enhancements.md b/doc/json-enhancements.md new file mode 100644 index 0000000000..4c226a2c96 --- /dev/null +++ b/doc/json-enhancements.md @@ -0,0 +1,123 @@ +# Proposed Enhancements To JSON Functions + +## 1.0 New function json_nextract() + +The new function json_nextract() works the same as json_extract() except +when the input JSON is not well-formed. This is what the routines do +when the input JSON in the first argument is not well-formed: + + 1. **json_extract()** → raises an error and aborts the query. + + 2. **json_nextract()** with 2 arguments the second argument is + exactly `'$'` → work like json_quote() and return the first + argument as a JSON quoted string. + + 3. **json_nextract()** otherwise → return NULL. + +If the input is known to be JSON, then json_extract() should work just +fine for all your needs. But sometimes a table might have a column that +sometimes holds JSON and sometimes holds some other content. Suppose, +for example, an application started out holding a single phone number for +each user, but later was enhanced so that the same database file could +hold a JSON array of phone numbers. The USER table might have some entries +that are JSON arrays and some entries which are just text strings containing +phone numbers. The application can use json_nextract() to be robust in +extracting values from that column. + +The feature (2) above is envisioned to be useful for sanitizing table +content. Suppose a table is populated from dirty CSV, and some of the +JSON is mis-formatted. You could convert all entries in a table to use +well-formed JSON using something like this: + +> ~~~ +UPDATE data SET jsonData = json_nextract(jsonData,'$'); +~~~ + +In the query above, well-formed JSON would be unchanged, and mis-formatted +JSON would be converted into a well-formatted JSON string. + +## 2.0 Add the `->` and '->>` operators as aliases for json_extract(). + +Two new binary operators "`->`" and "`->>`" operators are the same +as json_nextract() and json_extract(), respectively. + +> ~~~ +SELECT '{"a":5,"b":17}' -> '$.a', '[4,1,-6]' ->> '$[0]'; +~~~ + +Is equivalent to (and generates the same bytecode as): + +> ~~~ +SELECT json_nextract('{"a":5,"b":17}','$.a'), json_extract('[4,1,-6]','$[0]'); +~~~ + +The ->> operator works the same as the ->> operator in MySQL +and mostly compatible with PostgreSQL (hereafter "PG"). Addition enhancements +in section 3.0 below are required to bring ->> into compatibility with PG. + +The -> operator is mostly compatible with MySQL and PG too. The main +difference is that in MySQL and PG, the result from -> is not a primitive +SQL datatype type but rather more JSON. It is unclear how this would ever +be useful for anything, and so I am unsure why they do this. But that is +the way it is done in those system. + +SQLite strives to be compatible with MySQL and PG with the ->> operator, +but not with the -> operator. + +## 3.0 Abbreviated JSON path specifications for use with -> and ->> + +The "->" and "->>" and operators allow abbreviated +forms of JSON path specs that omit unnecessary $-prefix text. For +example, the following queries are equivalent: + +> ~~~ +SELECT '{"a":17, "b":4.5}' ->> '$.a'; +SELECT '{"a":17, "b":4.5}' ->> 'a'; +~~~ + +Similarly, these queries mean exactly the same thing: + +> ~~~ +SELECT '[17,4.5,"hello",0]' ->> '$[1]'; +SELECT '[17,4.5,"hello",0]' ->> 1; +~~~ + +The abbreviated JSON path specs are allowed with the -> and ->> operators +only. The json_extract() and json_nextract() functions, and all the other +JSON functions, still use the full path spec and will raise an error if +the full path spec is not provided. + +This enhancement provides compatibility with PG. +PG does not support JSON path specs on its ->> operator. With PG, the +right-hand side of ->> must be either an integer (if the left-hand side +is a JSON array) or a text string which is interpreted as a field name +(if the left-hand side is a JSON object). So the ->> operator in PG is +rather limited. With this enhancement, the ->> operator in SQLite +covers all the functionality of PG, plus a lot more. + +MySQL also supports the ->> operator, but it requires a full JSON path +spec on the right-hand side. SQLite also supports this, so SQLite is +compatibility with MySQL as well. Note, however, that MySQL and PG +are incompatible with each other. You can (in theory) write SQL that +uses the ->> operator that is compatible between SQLite and MySQL, +or that is compatible between SQLite and PG, but not that is compatible +with all three. + +## 4.0 New json_ntype() SQL function + +A new function "json_ntype(JSON)" works like the existing one-argument +version of the "json_type(JSON)" function, except that json_ntype(JSON) +returns NULL if the argument is not well-formed JSON, whereas the +existing json_type() function raises an error in that case. + +In other words, "`json_ntype($json)`" is equivalent to +"`CASE WHEN json_valid($json) THEN json_type($json) END`". + +This function is seen as useful for figuring out which rows of a table +have a JSON type in a column and which do not. For example, to find +all rows in a table in which the value of the the "phonenumber" column +contains a JSON array, you could write: + +> ~~~ +SELECT * FROM users WHERE json_ntype(phonenumber) IS 'array'; +~~~ diff --git a/manifest b/manifest index 3227004e9a..0c197632b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reverse\sthe\smeaningn\sof\s->\sand\s->>.\s\s->>\sraises\san\serror\son\sinvalid\sJSON\nbut\s->\sdoes\snot.\s\sThis\sallows\s->>\sto\sbehave\sthe\ssame\sas\sPG\sand\sMySQL. -D 2022-01-07T17:26:40.622 +C Notes\son\sthe\sJSON\senhancement\sproposals. +D 2022-01-07T18:09:56.414 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -38,6 +38,7 @@ F configure 56f2a6637cdba53788673ccc229c4f95ab3ab6fe67036e0b1291dc615e531a58 x F configure.ac c8ba54bac7e73e000acdfef5e394fe21a3876aa09d0f5c07131bf5ac5a525299 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd +F doc/json-enhancements.md b026346e18a18a90d84dbda457e3127282468ad26baaefc005a1656429fa4232 F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a @@ -1937,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b4c8a62381755b9f1447e10ab95df7209eebda91f9a4583ef1c093a13f6b4725 -R 5e00922e334b2eca45d33167fc947357 +P 85f8170555ee0d4d28cb7e120a7062e9f64c331a936fdfa29fc0e67224eea7c6 +R f0bbc4fbd1752207d287e4842cece932 U drh -Z ca8d93554520c6d97db646c26d2dff94 +Z d04dbd17b8376af71e0674b428869308 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 89e07a6e91..3de7da8f44 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85f8170555ee0d4d28cb7e120a7062e9f64c331a936fdfa29fc0e67224eea7c6 \ No newline at end of file +18160985ea6b2bbf27de25e0f4f3a1ebcdb079a36af039fc06e37a834e49e772 \ No newline at end of file From dc60c68cc02aa94d1fbfeeff999d42e1b5f99a4b Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 8 Jan 2022 15:05:53 +0000 Subject: [PATCH 125/148] Improved commenting of changes in the json1.c extension. FossilOrigin-Name: 4d81425e1bf2cff6fa961d0a7936b5f62d3f8ffe9bffea89c1e8b8ddf8fad6f4 --- ext/misc/json1.c | 102 +++++++++++++++++++++++++++++++---------------- manifest | 12 +++--- manifest.uuid | 2 +- 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 86a486c21c..26f08e9168 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1581,13 +1581,44 @@ static void jsonArrayLengthFunc( sqlite3_result_int64(ctx, n); } +/* +** Bit values for the flags passed into jsonExtractFunc() or +** jsonSetFunc() via the user-data value. +*/ +#define JSON_NULLERR 0x01 /* Return NULL if input is not JSON */ +#define JSON_ABPATH 0x02 /* Allow abbreviated JSON path specs */ +#define JSON_ISSET 0x04 /* json_set(), not json_insert() */ + /* ** json_extract(JSON, PATH, ...) +** json_nextract(JSON, PATH, ...) +** "->"(JSON,PATH) +** "->>"(JSON,PATH) ** -** Return the element described by PATH. Return NULL if there is no -** PATH element. If there are multiple PATHs, then return a JSON array -** with the result from each path. Throw an error if the JSON or any PATH -** is malformed. +** Return the element described by PATH. Return NULL if that PATH element +** is not found. For leaf nodes of the JSON, the value returned is a pure +** SQL value. In other words, quotes have been removed from strings. +** +** If there are multiple PATHs, then the value returned is a JSON array +** with one entry in the array for each PATH term. +** +** Throw an error if any PATH is malformed. +** +** If JSON is not well-formed JSON then: +** +** (1) raise an error if the JSON_NULLERR flag is not set. +** +** (2) Otherwise (if the JSON_NULLERR flags is set and) if there +** is a single PATH argument with the value '$', simply quote +** the JSON input as if by json_quote(). In other words, treat +** the JSON input as a string and convert it into a valid JSON +** string. +** +** (3) Otherwise (if JSON_NULLERR is set and the PATH is not '$') +** return NULL +** +** If the JSON_ABPATH flag is set and there is only a single PATH, then +** allow abbreviated PATH specs that omit the leading "$". */ static void jsonExtractFunc( sqlite3_context *ctx, @@ -1601,11 +1632,11 @@ static void jsonExtractFunc( JsonString jx; if( argc<2 ) return; - p = jsonParseCached(ctx, argv, (flags & 1)!=0 ? 0 : ctx); + p = jsonParseCached(ctx, argv, (flags & JSON_NULLERR)!=0 ? 0 : ctx); if( p==0 ){ /* If the form is "json_nextract(IN,'$')" and IN is not well-formed JSON, ** then return IN as a quoted JSON string. */ - if( (flags & 1)!=0 + if( (flags & JSON_NULLERR)!=0 && argc==2 && (zPath = (const char*)sqlite3_value_text(argv[1]))!=0 && zPath[0]=='$' && zPath[1]==0 @@ -1617,11 +1648,13 @@ static void jsonExtractFunc( if( argc==2 ){ /* With a single PATH argument, the return is the unquoted SQL value */ zPath = (const char*)sqlite3_value_text(argv[1]); - if( zPath && zPath[0]!='$' && zPath[0]!=0 && (flags & 2)!=0 ){ - /* The -> and ->> operators accept abbreviated PATH arguments: - ** NUMBER ==> $[NUMBER] - ** LABEL ==> $.LABEL - ** [NUMBER] ==> $[NUMBER] + if( zPath && zPath[0]!='$' && zPath[0]!=0 && (flags & JSON_ABPATH)!=0 ){ + /* The -> and ->> operators accept abbreviated PATH arguments. This + ** is mostly for compatibility with PostgreSQL, but also for convenience. + ** + ** NUMBER ==> $[NUMBER] // PG compatible + ** LABEL ==> $.LABEL // PG compatible + ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience */ jsonInit(&jx, ctx); if( safe_isdigit(zPath[0]) ){ @@ -1633,7 +1666,7 @@ static void jsonExtractFunc( jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); jsonAppendChar(&jx, 0); } - pNode = jsonLookup(p, jx.zBuf, 0, ctx); + pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx); jsonReset(&jx); }else{ pNode = jsonLookup(p, zPath, 0, ctx); @@ -1896,6 +1929,7 @@ replace_err: jsonParseReset(&x); } + /* ** json_set(JSON, PATH, VALUE, ...) ** @@ -2681,34 +2715,34 @@ int sqlite3Json1Init(sqlite3 *db){ unsigned int i; static const struct { const char *zName; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); int nArg; int flag; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } aFunc[] = { - { "json", 1, 0, jsonRemoveFunc }, - { "json_array", -1, 0, jsonArrayFunc }, - { "json_array_length", 1, 0, jsonArrayLengthFunc }, - { "json_array_length", 2, 0, jsonArrayLengthFunc }, - { "json_extract", -1, 0, jsonExtractFunc }, - { "json_nextract", -1, 1, jsonExtractFunc }, - { "->", 2, 3, jsonExtractFunc }, - { "->>", 2, 2, jsonExtractFunc }, - { "json_insert", -1, 0, jsonSetFunc }, - { "json_ntype", 1, 1, jsonTypeFunc }, - { "json_object", -1, 0, jsonObjectFunc }, - { "json_patch", 2, 0, jsonPatchFunc }, - { "json_quote", 1, 0, jsonQuoteFunc }, - { "json_remove", -1, 0, jsonRemoveFunc }, - { "json_replace", -1, 0, jsonReplaceFunc }, - { "json_set", -1, 1, jsonSetFunc }, - { "json_type", 1, 0, jsonTypeFunc }, - { "json_type", 2, 0, jsonTypeFunc }, - { "json_valid", 1, 0, jsonValidFunc }, + { "json", jsonRemoveFunc, 1, 0 }, + { "json_array", jsonArrayFunc, -1, 0 }, + { "json_array_length", jsonArrayLengthFunc, 1, 0 }, + { "json_array_length", jsonArrayLengthFunc, 2, 0 }, + { "json_extract", jsonExtractFunc, -1, 0 }, + { "json_nextract", jsonExtractFunc, -1, JSON_NULLERR }, + { "->", jsonExtractFunc, 2, JSON_NULLERR|JSON_ABPATH }, + { "->>", jsonExtractFunc, 2, JSON_ABPATH }, + { "json_insert", jsonSetFunc, -1, 0 }, + { "json_object", jsonObjectFunc, -1, 0 }, + { "json_patch", jsonPatchFunc, 2, 0 }, + { "json_quote", jsonQuoteFunc, 1, 0 }, + { "json_remove", jsonRemoveFunc, -1, 0 }, + { "json_replace", jsonReplaceFunc, -1, 0 }, + { "json_set", jsonSetFunc, -1, JSON_ISSET }, + { "json_type", jsonTypeFunc, 1, 0 }, + { "json_ntype", jsonTypeFunc, 1, JSON_NULLERR }, + { "json_type", jsonTypeFunc, 2, 0 }, + { "json_valid", jsonValidFunc, 1, 0 }, #if SQLITE_DEBUG /* DEBUG and TESTING functions */ - { "json_parse", 1, 0, jsonParseFunc }, - { "json_test1", 1, 0, jsonTest1Func }, + { "json_parse", jsonParseFunc, 1, 0 }, + { "json_test1", jsonTest1Func, 1, 0 }, #endif }; static const struct { diff --git a/manifest b/manifest index 0c197632b6..38810b62bc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Notes\son\sthe\sJSON\senhancement\sproposals. -D 2022-01-07T18:09:56.414 +C Improved\scommenting\sof\schanges\sin\sthe\sjson1.c\sextension. +D 2022-01-08T15:05:53.556 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -307,7 +307,7 @@ F ext/misc/fileio.c 4e7f7cd30de8df4820c552f14af3c9ca451c5ffe1f2e7bef34d598a12ebf F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5 F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511 -F ext/misc/json1.c bfee5581c6f8443d2b4d73939c1aaad887111b7bb5f3a8c5dbd1572f627de83c +F ext/misc/json1.c a35ebe08f25515e4ab03c4ac7e06dd8a837c461f96df040ef7566a6ee4edbb84 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 85f8170555ee0d4d28cb7e120a7062e9f64c331a936fdfa29fc0e67224eea7c6 -R f0bbc4fbd1752207d287e4842cece932 +P 18160985ea6b2bbf27de25e0f4f3a1ebcdb079a36af039fc06e37a834e49e772 +R ea25b8b6843a230f65190e794ee89370 U drh -Z d04dbd17b8376af71e0674b428869308 +Z 72ca0ba8118c37c05f41d020549c1f4e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3de7da8f44..dc1aa1ea0e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -18160985ea6b2bbf27de25e0f4f3a1ebcdb079a36af039fc06e37a834e49e772 \ No newline at end of file +4d81425e1bf2cff6fa961d0a7936b5f62d3f8ffe9bffea89c1e8b8ddf8fad6f4 \ No newline at end of file From 6bcd58572b4bdbf390ea58f8dea3fba4689b0251 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 8 Jan 2022 21:00:38 +0000 Subject: [PATCH 126/148] Add function format() as an alias for printf(), for compatibility with other systems. FossilOrigin-Name: 68bffc612c467b2419bf5fe85a8ca16b787003e0e8c11f7c051a879f5865b847 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/func.c | 3 ++- test/upsert2.test | 8 ++++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 66cd8be755..783d4d8a41 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s'-guard:cf'\scompiler\soption\sfor\sWindows\s10,\sper\s[forum:/forumpost/8d3b4ad694|forum\spost\s8d3b4ad694]. -D 2022-01-06T17:13:56.835 +C Add\sfunction\sformat()\sas\san\salias\sfor\sprintf(),\sfor\scompatibility\swith\sother\nsystems. +D 2022-01-08T21:00:38.029 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -505,7 +505,7 @@ F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560 -F src/func.c 0f576a0c102485676266e63a796223e63c3cdb04baf3678ccc8bfeedba4a6fd4 +F src/func.c bd0feae5c5b1680773930f07604474329e543f63502cb1e0fb127823c2a817da F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 @@ -1679,7 +1679,7 @@ F test/upfrom2.test 88d39cb755db5789541e645d4e2764abc697a56958f28a3f8451a0e9342b F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0 F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6 F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2 -F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09 +F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5 F test/upsert5.test fff0dcfce73c649204543088d8e5bde01172676063ec9b8f8fc7f195abc386fe @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b6a82f3c3b9d89fdf628c7f117b6a4a64383a36c84fe84d47c80e845c9bd8a4f -R 77a4280a2931dd249bcf6514bda5d68b -U mistachkin -Z 912599d00221acb9d08acd46c2ac9173 +P 2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f +R 1f1cd983b6be5244fac36816d9cfafc2 +U drh +Z ff3107555aaf2fc0a321eb713cb1078c # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ba34d0d3e9..d5ae970681 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f \ No newline at end of file +68bffc612c467b2419bf5fe85a8ca16b787003e0e8c11f7c051a879f5865b847 \ No newline at end of file diff --git a/src/func.c b/src/func.c index eeab1d2647..166bd6f0e4 100644 --- a/src/func.c +++ b/src/func.c @@ -258,7 +258,7 @@ endInstrOOM: } /* -** Implementation of the printf() function. +** Implementation of the printf() (a.k.a. format()) SQL function. */ static void printfFunc( sqlite3_context *context, @@ -2249,6 +2249,7 @@ void sqlite3RegisterBuiltinFunctions(void){ FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), + FUNCTION(format, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), diff --git a/test/upsert2.test b/test/upsert2.test index 1aa499e606..5cbc4656a4 100644 --- a/test/upsert2.test +++ b/test/upsert2.test @@ -72,7 +72,7 @@ do_execsql_test upsert2-300 { CREATE TABLE record(x TEXT, y TEXT); CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN INSERT INTO record(x,y) - VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c)); + VALUES('before-insert',format('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN INSERT INTO record(x,y) @@ -80,7 +80,7 @@ do_execsql_test upsert2-300 { END; CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN INSERT INTO record(x,y) - VALUES('before-update',printf('%d,%d,%d/%d,%d,%d', + VALUES('before-update',format('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN @@ -123,7 +123,7 @@ do_execsql_test upsert2-400 { CREATE TABLE t1(a INT PRIMARY KEY, b int, c DEFAULT 0) WITHOUT ROWID; CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN INSERT INTO record(x,y) - VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c)); + VALUES('before-insert',format('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN INSERT INTO record(x,y) @@ -131,7 +131,7 @@ do_execsql_test upsert2-400 { END; CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN INSERT INTO record(x,y) - VALUES('before-update',printf('%d,%d,%d/%d,%d,%d', + VALUES('before-update',format('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN From 5622c7f97106314719740098cf0854e7eaa81802 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 8 Jan 2022 21:50:00 +0000 Subject: [PATCH 127/148] Add NEVER() macros to two branches that became unreachable due to [e199a851e316bd47]. FossilOrigin-Name: 71272caff5874137ad0b1ddfc22ced4bb66e6c97f7868fdae0347a186f589b38 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 4 ++-- src/pager.c | 1 + 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 783d4d8a41..a1c90a1f9a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sfunction\sformat()\sas\san\salias\sfor\sprintf(),\sfor\scompatibility\swith\sother\nsystems. -D 2022-01-08T21:00:38.029 +C Add\sNEVER()\smacros\sto\stwo\sbranches\sthat\sbecame\sunreachable\sdue\sto\n[e199a851e316bd47]. +D 2022-01-08T21:50:00.551 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -494,7 +494,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 0e9f84f974e970fb373c15caa1624a281b3c33098cb9dd9021d6801c04eb4fde F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 -F src/build.c 6e16f7b539bfc55149a039bf0cda26b089640339df6147070b072df2d1c4f771 +F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -537,7 +537,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 55a9a8c745c47a49e6541b1d634f6152e3f72f76c6dbb04fe24413986a928091 +F src/pager.c 5130bd602719ad9de1436def895da73973ee74382db02036be21238d0aa2ccfd F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 761b5d30a7ea9bd2db3b3571438cfcceb5f7dbf4fcad6881c8de65bdda07135a F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1937,8 +1937,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2d6a16caa7d28ad5c766036b2eb6c2020683fcc9389b3c7df2013739929dd36f -R 1f1cd983b6be5244fac36816d9cfafc2 +P 68bffc612c467b2419bf5fe85a8ca16b787003e0e8c11f7c051a879f5865b847 +R c94d976a37a2f277f5140b8791189b0b U drh -Z ff3107555aaf2fc0a321eb713cb1078c +Z 7446237fb7eda07b8f82330a10b1e8d5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d5ae970681..36029f2538 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -68bffc612c467b2419bf5fe85a8ca16b787003e0e8c11f7c051a879f5865b847 \ No newline at end of file +71272caff5874137ad0b1ddfc22ced4bb66e6c97f7868fdae0347a186f589b38 \ No newline at end of file diff --git a/src/build.c b/src/build.c index b93dd91e1c..ce1c720800 100644 --- a/src/build.c +++ b/src/build.c @@ -170,7 +170,7 @@ void sqlite3FinishCoding(Parse *pParse){ int i; int reg; - if( pReturning->nRetCol==0 ){ + if( NEVER(pReturning->nRetCol==0) ){ assert( CORRUPT_DB ); }else{ sqlite3VdbeAddOp0(v, OP_FkCheck); @@ -266,7 +266,7 @@ void sqlite3FinishCoding(Parse *pParse){ if( pParse->bReturning ){ Returning *pRet = pParse->u1.pReturning; - if( pRet->nRetCol==0 ){ + if( NEVER(pRet->nRetCol==0) ){ assert( CORRUPT_DB ); }else{ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); diff --git a/src/pager.c b/src/pager.c index 24a2ce2c4c..26b8289605 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5667,6 +5667,7 @@ int sqlite3PagerGet( DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ + /* printf("PAGE %u\n", pgno); fflush(stdout); */ return pPager->xGet(pPager, pgno, ppPage, flags); } From 9d44f18b3ccf2ca757ee27ae294b859cb32ec127 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 9 Jan 2022 16:54:02 +0000 Subject: [PATCH 128/148] Add a new built-in subtype() function. FossilOrigin-Name: a25f4ce255c034fc694c33728aedb98289ebccda9c48920829ef780b92b8faee --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/func.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index b3ac61a7f5..d04f8b0c46 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sJSON\sfunction\senhancements\sfrom\sthe\sjson-enhancements\sbranch\sinto\njson-in-core. -D 2022-01-08T15:37:13.201 +C Add\sa\snew\sbuilt-in\ssubtype()\sfunction. +D 2022-01-09T16:54:02.203 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -505,7 +505,7 @@ F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560 -F src/func.c 67944b79d9c06fcb86a2944082ca1dd9d46eed7bd5c6721bcb19094dd7f81358 +F src/func.c 76a9ac772f67be5af9476e02ae0866f4919d1981f97ff16dedfe37a1c62cbf8e F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 583b47d865fb8d2c9ae4d3a4e70356a8a758978efb0a282f6b19775bf41fb748 4d81425e1bf2cff6fa961d0a7936b5f62d3f8ffe9bffea89c1e8b8ddf8fad6f4 -R 9de2cc0789b4af5e569fa6f6937afbf5 +P e116501c2f0e594eb7a3dd804daa943cc508f32ded3078aed21b695ec83bcd4c +R 28e65f1e2d788c0c1b31d4dbdc4f0a91 U drh -Z 5d4090391a2a7b92e27e5b55336ae1bf +Z fde45050a7eb088af98952ef4d939a27 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3d3e816e87..7d48848f7b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e116501c2f0e594eb7a3dd804daa943cc508f32ded3078aed21b695ec83bcd4c \ No newline at end of file +a25f4ce255c034fc694c33728aedb98289ebccda9c48920829ef780b92b8faee \ No newline at end of file diff --git a/src/func.c b/src/func.c index 360967a084..596a1bb3ab 100644 --- a/src/func.c +++ b/src/func.c @@ -97,6 +97,17 @@ static void typeofFunc( sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC); } +/* subtype(X) +** +** Return the subtype of X +*/ +static void subtypeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_int(context, sqlite3_value_subtype(argv[0])); +} /* ** Implementation of the length() function @@ -2246,6 +2257,7 @@ void sqlite3RegisterBuiltinFunctions(void){ WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), From d3110034dc12341a30fd1e2291088035c237182f Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 9 Jan 2022 19:44:36 +0000 Subject: [PATCH 129/148] Do not enclude ENABLE_JSON1 in the compile-time options. FossilOrigin-Name: 8bf41bc5cb19fcde569ed2c788553a848ebd9c79065bd3d2aa99e5a6bfed9696 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/ctime.c | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e36c760a79..48688d7bc6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\senhancements\sinto\sthe\sjson-in-core\sbranch. -D 2022-01-09T19:36:39.850 +C Do\snot\senclude\sENABLE_JSON1\sin\sthe\scompile-time\soptions. +D 2022-01-09T19:44:36.695 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -497,7 +497,7 @@ F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c b09ce320b78718d5e0c4a7a59b8705abe8ee4683d9fa4b33768fe347e1b2a42a +F src/ctime.c 638e75c9a02b276c782cb27f59f3abf2ab94a33514107ffd165b2f69d1bc2aaa F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a25f4ce255c034fc694c33728aedb98289ebccda9c48920829ef780b92b8faee 71272caff5874137ad0b1ddfc22ced4bb66e6c97f7868fdae0347a186f589b38 -R 49fcbfca4503349519b1d6e2c92f7acf +P ea755771699dcbffe0ddfd204d42fae9b6e79e107485c725b8eb6caab92aacb8 +R 70859f0c399b3e8f43d2059a10792076 U drh -Z 4bb2ffcd67d474872b040ea5d2948b38 +Z f2d44a3082cc3593041829311c626937 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f20238fd7c..f5e15eac91 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea755771699dcbffe0ddfd204d42fae9b6e79e107485c725b8eb6caab92aacb8 \ No newline at end of file +8bf41bc5cb19fcde569ed2c788553a848ebd9c79065bd3d2aa99e5a6bfed9696 \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index 708d6ac2bf..4377528006 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -181,8 +181,6 @@ static const char * const sqlite3azCompileOpt[] = { #endif #ifdef SQLITE_DISABLE_JSON "DISABLE_JSON", -#else - "ENABLE_JSON1", /* Legacy */ #endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", From f2afe4e888b786fc4d8b8e78bed13ea774cb0b09 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 9 Jan 2022 20:42:55 +0000 Subject: [PATCH 130/148] Update the doc/json-enhancements.md document to better explain the features of this branch. FossilOrigin-Name: b8ac938f41eff8e5a23037c0e8b035a65e1b9505eca2a601221c195225595788 --- doc/json-enhancements.md | 206 +++++++++++++++++++-------------------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 110 insertions(+), 110 deletions(-) diff --git a/doc/json-enhancements.md b/doc/json-enhancements.md index 4c226a2c96..fababa8be2 100644 --- a/doc/json-enhancements.md +++ b/doc/json-enhancements.md @@ -1,123 +1,123 @@ -# Proposed Enhancements To JSON Functions +# JSON Functions Enhancements (2022) -## 1.0 New function json_nextract() +This document summaries enhancements to the SQLite JSON support added in +early 2022. -The new function json_nextract() works the same as json_extract() except -when the input JSON is not well-formed. This is what the routines do -when the input JSON in the first argument is not well-formed: +## 1.0 New feature summary: - 1. **json_extract()** → raises an error and aborts the query. + 1. New **->** and **->>** operators that work like MySQL and PostgreSQL (PG). + 2. New functions: **json_nextract()** and **json_ntype()**. + 3. JSON functions are built-in rather than being an extension. They + are included by default, but can be omitted using the + -DSQLITE_OMIT_JSON compile-time option. - 2. **json_nextract()** with 2 arguments the second argument is - exactly `'$'` → work like json_quote() and return the first - argument as a JSON quoted string. +## 2.0 The **json_nextract()** function. - 3. **json_nextract()** otherwise → return NULL. +The new **json_nextract()** function works like **json_extract()** with +one exception: if the input text in first argument is not well-formed +JSON, then json_nextract() returns NULL whereas json_extract() raises +an error. The extra "n" in the name of json_nextract() can be throught +of as meaning "null-if-error". -If the input is known to be JSON, then json_extract() should work just -fine for all your needs. But sometimes a table might have a column that -sometimes holds JSON and sometimes holds some other content. Suppose, -for example, an application started out holding a single phone number for -each user, but later was enhanced so that the same database file could -hold a JSON array of phone numbers. The USER table might have some entries -that are JSON arrays and some entries which are just text strings containing -phone numbers. The application can use json_nextract() to be robust in -extracting values from that column. - -The feature (2) above is envisioned to be useful for sanitizing table -content. Suppose a table is populated from dirty CSV, and some of the -JSON is mis-formatted. You could convert all entries in a table to use -well-formed JSON using something like this: +A call to json_nextract($JSON,$PATH) is logically equivalent to: > ~~~ -UPDATE data SET jsonData = json_nextract(jsonData,'$'); +CASE WHEN json_valid($JSON) THEN json_extract($JSON,$PATH) END ~~~ -In the query above, well-formed JSON would be unchanged, and mis-formatted -JSON would be converted into a well-formatted JSON string. +The json_nextract() function is intended for use in tables where a +column might hold a mixture of datatypes - some rows holding JSON and other +rows holding primitive SQL datatypes such as INT, REAL, and TEXT. The +json_nextract() function makes it easier to write robust queries +against such tables. -## 2.0 Add the `->` and '->>` operators as aliases for json_extract(). +## 3.0 New operators **->** and **->>** -Two new binary operators "`->`" and "`->>`" operators are the same -as json_nextract() and json_extract(), respectively. +The SQLite language adds two new binary operators **->** and **->>**. +The -> operator works like the two-argument version of json_nextract() +and the ->> operator works like the two-argument version of json_extract(). +The left-hand operand of -> and ->> is JSON. The right-hand operand +is a JSON path expression. These operators extract and return a value +from the left-hand JSON that is specified by right-hand path expression. + +The operators work exactly the same if the left-hand side is well-formed +JSON. The only difference is that if the left-hand side is not well-formed +JSON, the ->> raises an error whereas the -> operator simply returns NULL. + +### 3.1 Compatibility with MySQL + +The ->> operator should be compatible with MySQL in the sense that +a ->> operator that works in MySQL should work the same way in SQLite. +But (see below) the SQLite ->> operator is also extended to support PG +syntax so not every use of ->> that wworks in SQLite will work for MySQL. + +The -> operator is *mostly* compatible with MySQL. Key differences +between the SQLite -> operator and the MySQL -> operator are: + + * The SQLite -> operator returns NULL if the left-hand side is + not well-formed JSON whereas MySQL will raise an error. + + * When the JSON path expression on the right-hand side selects a + text value from the JSON, the -> operator in MySQL returns the + string quoted as if for JSON, whereas the SQLite -> operator + returns an unquoted SQL text value. + +This second difference - the handling of text values extracted from JSON - +is also a difference in the json_extract() function between SQLite and +MySQL. Because json_extract() has been in active use for 6 years, and +because the SQLite semantics seem to be more useful, there +are no plans to change json_extract() to make it compatible with MySQL. + +### 3.2 Compatibility with PostgreSQL (PG) + +The ->> operator in PG does not accept a JSON path expression as its +right-hand operand. Instead, PG looks for either a text string X +(which is then interpreted as the path "$.X") or an integer N (which +is then interpreted as "$[N]"). In order to make the SQLite ->> operator +compatible with the PG ->> operator, the SQLite ->> operator has been +extended so that its right-hand operand can be either a text label or +a integer array index, as it is in PG. The SQLite ->> operator also +accepts full JSON path expressions as well. + +The enhancement of accepting JSON path expression that consist of just +a bare object label or array index is unique to the -> and ->> operators. +All other places in the SQLite JSON interface that require JSON path +expressions continue to require well-formed JSON path expressions. +Only -> and ->> accept the PG-compatible abbreviated path expressions. + +The -> operator in SQLite is *mostly* compatible with the -> operator +in PG. The differences are the same as for MySQL. + +## 4.0 The **json_ntype()** function. + +The **json_ntype()** function works like **json_type()** except that when +the argument is not well-formed JSON, the json_ntype() function returns +NULL whereas json_type() raises an error. The extra "n" in the name can +be understood as standing for "null-if-error". + +The json_ntype($JSON) function is logically equivalent to: > ~~~ -SELECT '{"a":5,"b":17}' -> '$.a', '[4,1,-6]' ->> '$[0]'; +CASE WHEN json_valid($JSON) THEN json_type($JSON) END ~~~ -Is equivalent to (and generates the same bytecode as): +The json_ntype() function can be seen as an enhanced version of +the json_valid() function, that in addition to indicating whether or +not the string is well-formed JSON, also indicates the top-level type +of that JSON. -> ~~~ -SELECT json_nextract('{"a":5,"b":17}','$.a'), json_extract('[4,1,-6]','$[0]'); -~~~ +## 5.0 JSON moved into the core -The ->> operator works the same as the ->> operator in MySQL -and mostly compatible with PostgreSQL (hereafter "PG"). Addition enhancements -in section 3.0 below are required to bring ->> into compatibility with PG. +The JSON interface is now moved into the SQLite core. -The -> operator is mostly compatible with MySQL and PG too. The main -difference is that in MySQL and PG, the result from -> is not a primitive -SQL datatype type but rather more JSON. It is unclear how this would ever -be useful for anything, and so I am unsure why they do this. But that is -the way it is done in those system. +When originally written in 2015, the JSON functions were an extension +that could be optionally included at compile-time, or loaded at run-time. +The implementation was in a source file named ext/misc/json1.c in the +source tree. JSON functions were only compiled in if the +-DSQLITE_ENABLE_JSON1 compile-time option was used. -SQLite strives to be compatible with MySQL and PG with the ->> operator, -but not with the -> operator. - -## 3.0 Abbreviated JSON path specifications for use with -> and ->> - -The "->" and "->>" and operators allow abbreviated -forms of JSON path specs that omit unnecessary $-prefix text. For -example, the following queries are equivalent: - -> ~~~ -SELECT '{"a":17, "b":4.5}' ->> '$.a'; -SELECT '{"a":17, "b":4.5}' ->> 'a'; -~~~ - -Similarly, these queries mean exactly the same thing: - -> ~~~ -SELECT '[17,4.5,"hello",0]' ->> '$[1]'; -SELECT '[17,4.5,"hello",0]' ->> 1; -~~~ - -The abbreviated JSON path specs are allowed with the -> and ->> operators -only. The json_extract() and json_nextract() functions, and all the other -JSON functions, still use the full path spec and will raise an error if -the full path spec is not provided. - -This enhancement provides compatibility with PG. -PG does not support JSON path specs on its ->> operator. With PG, the -right-hand side of ->> must be either an integer (if the left-hand side -is a JSON array) or a text string which is interpreted as a field name -(if the left-hand side is a JSON object). So the ->> operator in PG is -rather limited. With this enhancement, the ->> operator in SQLite -covers all the functionality of PG, plus a lot more. - -MySQL also supports the ->> operator, but it requires a full JSON path -spec on the right-hand side. SQLite also supports this, so SQLite is -compatibility with MySQL as well. Note, however, that MySQL and PG -are incompatible with each other. You can (in theory) write SQL that -uses the ->> operator that is compatible between SQLite and MySQL, -or that is compatible between SQLite and PG, but not that is compatible -with all three. - -## 4.0 New json_ntype() SQL function - -A new function "json_ntype(JSON)" works like the existing one-argument -version of the "json_type(JSON)" function, except that json_ntype(JSON) -returns NULL if the argument is not well-formed JSON, whereas the -existing json_type() function raises an error in that case. - -In other words, "`json_ntype($json)`" is equivalent to -"`CASE WHEN json_valid($json) THEN json_type($json) END`". - -This function is seen as useful for figuring out which rows of a table -have a JSON type in a column and which do not. For example, to find -all rows in a table in which the value of the the "phonenumber" column -contains a JSON array, you could write: - -> ~~~ -SELECT * FROM users WHERE json_ntype(phonenumber) IS 'array'; -~~~ +After these enhancements, the JSON functions are now built-ins. +The source file that implements the JSON functions is moved to src/json.c. +No special compile-time options are needed to load JSON into the build. +Instead, there is a new -DSQLITE_OMIT_JSON compile-time option to leave +them out. diff --git a/manifest b/manifest index 48688d7bc6..b1040bffa8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\senclude\sENABLE_JSON1\sin\sthe\scompile-time\soptions. -D 2022-01-09T19:44:36.695 +C Update\sthe\sdoc/json-enhancements.md\sdocument\sto\sbetter\sexplain\sthe\sfeatures\nof\sthis\sbranch. +D 2022-01-09T20:42:55.486 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -38,7 +38,7 @@ F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd -F doc/json-enhancements.md b026346e18a18a90d84dbda457e3127282468ad26baaefc005a1656429fa4232 +F doc/json-enhancements.md 07822849342a976455b8d9c7d564d347b97e13ca8f7444388312a8f7a0d5e846 F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ea755771699dcbffe0ddfd204d42fae9b6e79e107485c725b8eb6caab92aacb8 -R 70859f0c399b3e8f43d2059a10792076 +P 8bf41bc5cb19fcde569ed2c788553a848ebd9c79065bd3d2aa99e5a6bfed9696 +R 83ea098ded25ea5f04c457b4cfe21d79 U drh -Z f2d44a3082cc3593041829311c626937 +Z b469d7ebc54649e5bb73aa5daf50477b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f5e15eac91..13ef2c36e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8bf41bc5cb19fcde569ed2c788553a848ebd9c79065bd3d2aa99e5a6bfed9696 \ No newline at end of file +b8ac938f41eff8e5a23037c0e8b035a65e1b9505eca2a601221c195225595788 \ No newline at end of file From 18ccc5c5ab3762b7fd1478525707dba4c15c9d43 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 9 Jan 2022 20:51:59 +0000 Subject: [PATCH 131/148] Typo fix in doc/json-enhancements.md. FossilOrigin-Name: c3b01d496479b3250a8895c245f79ab43ac469148d163593fea00894db195a37 --- doc/json-enhancements.md | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/json-enhancements.md b/doc/json-enhancements.md index fababa8be2..8d83554ad2 100644 --- a/doc/json-enhancements.md +++ b/doc/json-enhancements.md @@ -14,7 +14,7 @@ early 2022. ## 2.0 The **json_nextract()** function. The new **json_nextract()** function works like **json_extract()** with -one exception: if the input text in first argument is not well-formed +one exception: if the input text in the first argument is not well-formed JSON, then json_nextract() returns NULL whereas json_extract() raises an error. The extra "n" in the name of json_nextract() can be throught of as meaning "null-if-error". diff --git a/manifest b/manifest index b1040bffa8..2111bfa40b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sdoc/json-enhancements.md\sdocument\sto\sbetter\sexplain\sthe\sfeatures\nof\sthis\sbranch. -D 2022-01-09T20:42:55.486 +C Typo\sfix\sin\sdoc/json-enhancements.md. +D 2022-01-09T20:51:59.795 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -38,7 +38,7 @@ F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd -F doc/json-enhancements.md 07822849342a976455b8d9c7d564d347b97e13ca8f7444388312a8f7a0d5e846 +F doc/json-enhancements.md b1731f584a8594660dcee86555e77559dbc447a88c010f010a7f5274bb050459 F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8bf41bc5cb19fcde569ed2c788553a848ebd9c79065bd3d2aa99e5a6bfed9696 -R 83ea098ded25ea5f04c457b4cfe21d79 +P b8ac938f41eff8e5a23037c0e8b035a65e1b9505eca2a601221c195225595788 +R bb97ccd30a4bea2e78fa0684b28c1c7a U drh -Z b469d7ebc54649e5bb73aa5daf50477b +Z 59da2a31f3cfc387aa42335fd8788184 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 13ef2c36e9..173df7a789 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b8ac938f41eff8e5a23037c0e8b035a65e1b9505eca2a601221c195225595788 \ No newline at end of file +c3b01d496479b3250a8895c245f79ab43ac469148d163593fea00894db195a37 \ No newline at end of file From d3c6c3459b5aff110877428770e52df354c63360 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jan 2022 13:55:08 +0000 Subject: [PATCH 132/148] New proposal for -> and ->> operators. FossilOrigin-Name: 1108e12a2244edc6247050a0e9ad25b912bba6c57c71c51c2bc55167a6955175 --- doc/json-enhancements.md | 179 ++++++++++++++++++++++----------------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 107 insertions(+), 86 deletions(-) diff --git a/doc/json-enhancements.md b/doc/json-enhancements.md index 8d83554ad2..d3ab6e0a43 100644 --- a/doc/json-enhancements.md +++ b/doc/json-enhancements.md @@ -3,110 +3,131 @@ This document summaries enhancements to the SQLite JSON support added in early 2022. -## 1.0 New feature summary: +## 1.0 Change summary: 1. New **->** and **->>** operators that work like MySQL and PostgreSQL (PG). - 2. New functions: **json_nextract()** and **json_ntype()**. - 3. JSON functions are built-in rather than being an extension. They + 2. JSON functions are built-in rather than being an extension. They are included by default, but can be omitted using the -DSQLITE_OMIT_JSON compile-time option. -## 2.0 The **json_nextract()** function. -The new **json_nextract()** function works like **json_extract()** with -one exception: if the input text in the first argument is not well-formed -JSON, then json_nextract() returns NULL whereas json_extract() raises -an error. The extra "n" in the name of json_nextract() can be throught -of as meaning "null-if-error". - -A call to json_nextract($JSON,$PATH) is logically equivalent to: - -> ~~~ -CASE WHEN json_valid($JSON) THEN json_extract($JSON,$PATH) END -~~~ - -The json_nextract() function is intended for use in tables where a -column might hold a mixture of datatypes - some rows holding JSON and other -rows holding primitive SQL datatypes such as INT, REAL, and TEXT. The -json_nextract() function makes it easier to write robust queries -against such tables. - -## 3.0 New operators **->** and **->>** +## 2.0 New operators **->** and **->>** The SQLite language adds two new binary operators **->** and **->>**. -The -> operator works like the two-argument version of json_nextract() -and the ->> operator works like the two-argument version of json_extract(). -The left-hand operand of -> and ->> is JSON. The right-hand operand -is a JSON path expression. These operators extract and return a value -from the left-hand JSON that is specified by right-hand path expression. +Both operators are similar to json_extract(). The left operand is +JSON and the right operand is a JSON path expression (possibly abbreviated +for compatibility with PG - see below). So they are similar to a +two-argument call to json_extract(). -The operators work exactly the same if the left-hand side is well-formed -JSON. The only difference is that if the left-hand side is not well-formed -JSON, the ->> raises an error whereas the -> operator simply returns NULL. +The difference between -> and ->> (and json_extract()) is as follows: -### 3.1 Compatibility with MySQL + * The -> operator always returns JSON. -The ->> operator should be compatible with MySQL in the sense that -a ->> operator that works in MySQL should work the same way in SQLite. -But (see below) the SQLite ->> operator is also extended to support PG -syntax so not every use of ->> that wworks in SQLite will work for MySQL. + * The ->> operator converts the answer into a primitive SQL datatype + such as TEXT, INTEGER, REAL, or NULL. If a JSON object or array + is selected, that object or array is rendered as text. If a JSON + value is selected, that value is converted into its corresponding + SQL type -The -> operator is *mostly* compatible with MySQL. Key differences -between the SQLite -> operator and the MySQL -> operator are: + * The json_extract() interface returns JSON when a JSON object or + array is selected, or a primitive SQL datatype when a JSON value + is selected. This is different from MySQL, in which json_extract() + always returns JSON, but the difference is retained because it has + worked that way for 6 years and changing it now would likely break + a lot of legacy code. - * The SQLite -> operator returns NULL if the left-hand side is - not well-formed JSON whereas MySQL will raise an error. +In MySQL and PG, the ->> operator always returns TEXT (or NULL) and never +INTEGER or REAL. This is due to limitations in the type handling capabilities +of those systems. In MySQL and PG, the result type a function or operator +may only depend on the type of its arguments, never the value of its arguments. +But the underlying JSON type depends on the value of the JSON path +expression, not the type of the JSON path expression (which is always TEXT). +Hence, the result type of ->> in MySQL and PG is unable to vary according +to the type of the JSON value being extracted. - * When the JSON path expression on the right-hand side selects a - text value from the JSON, the -> operator in MySQL returns the - string quoted as if for JSON, whereas the SQLite -> operator - returns an unquoted SQL text value. +The type system in SQLite is more general. Functions in SQLite are able +to return different datatypes depending on the value of their arguments. +So the ->> operator in SQLite is able to return TEXT, INTEGER, REAL, or NULL +depending on the JSON type of the value being extracted. This means that +the behavior of the ->> is slightly different in SQLite versus MySQL and PG +in that it will sometimes return INTEGER and REAL values, depending on its +inputs. It is possible to implement the ->> operator in SQLite so that it +always operates exactly like MySQL and PG and always returns TEXT or NULL, +but I have been unable to think of any situations where returning the +actual JSON value this would cause problems, so I'm including the enhanced +functionality in SQLite. -This second difference - the handling of text values extracted from JSON - -is also a difference in the json_extract() function between SQLite and -MySQL. Because json_extract() has been in active use for 6 years, and -because the SQLite semantics seem to be more useful, there -are no plans to change json_extract() to make it compatible with MySQL. +The table below attempts to summarize the differences between the +-> and ->> operators and the json_extract() function, for SQLite, MySQL, +and PG. JSON values are shown using their SQL text representation but +in a bold font. -### 3.2 Compatibility with PostgreSQL (PG) -The ->> operator in PG does not accept a JSON path expression as its -right-hand operand. Instead, PG looks for either a text string X -(which is then interpreted as the path "$.X") or an integer N (which -is then interpreted as "$[N]"). In order to make the SQLite ->> operator -compatible with the PG ->> operator, the SQLite ->> operator has been -extended so that its right-hand operand can be either a text label or -a integer array index, as it is in PG. The SQLite ->> operator also -accepts full JSON path expressions as well. + +
JSONPATH-> operator
(all)
->> operator
(MySQL/PG) +
->> operator
(SQLite)
json_extract()
(SQLite) +
**'{"a":123}'** '$.a' **'123'** '123' 123 123 +
**'{"a":4.5}'** '$.a' **'4.5'** '4.5' 4.5 4.5 +
**'{"a":"xyz"}'** '$.a' **'"xyz"'** 'xyz' 'xyz' 'xyz' +
**'{"a":null}'** '$.a' **'null'** NULL NULL NULL +
**'{"a":[6,7,8]}'** '$.a' **'[6,7,8]'** '[6,7,8]' '[6,7,8]' **'[6,7,9]'** +
**'{"a":{"x":9}}'** '$.a' **'{"x":9}'** '{"x":9}' '{"x":9}' **'{"x":9}'** +
**'{"b":999}'** '$.a' NULL NULL NULL NULL +
-The enhancement of accepting JSON path expression that consist of just -a bare object label or array index is unique to the -> and ->> operators. -All other places in the SQLite JSON interface that require JSON path -expressions continue to require well-formed JSON path expressions. -Only -> and ->> accept the PG-compatible abbreviated path expressions. +Important points about the table above: -The -> operator in SQLite is *mostly* compatible with the -> operator -in PG. The differences are the same as for MySQL. + * The -> operator always returns either JSON or NULL. -## 4.0 The **json_ntype()** function. + * The ->> operator never returns JSON. It always returns TEXT or NULL, or in the + case of SQLite, INTEGER or REAL. -The **json_ntype()** function works like **json_type()** except that when -the argument is not well-formed JSON, the json_ntype() function returns -NULL whereas json_type() raises an error. The extra "n" in the name can -be understood as standing for "null-if-error". + * The MySQL json_extract() function works exactly the same + as the MySQL -> operator. -The json_ntype($JSON) function is logically equivalent to: + * The SQLite json_extract() operator works like -> for JSON objects and + arrays, and like ->> for JSON values. -> ~~~ -CASE WHEN json_valid($JSON) THEN json_type($JSON) END -~~~ + * The -> operator works the same for all systems. -The json_ntype() function can be seen as an enhanced version of -the json_valid() function, that in addition to indicating whether or -not the string is well-formed JSON, also indicates the top-level type -of that JSON. + * The only difference in ->> between SQLite and other systems is that + when the JSON value is numeric, SQLite returns a numeric SQL value, + whereas the other systems return a text representation of the numeric + value. -## 5.0 JSON moved into the core +### 2.1 Abbreviated JSON path expressions for PG compatibility + +The table above always shows the full JSON path expression: '$.a'. But +PG does not accept this syntax. PG only allows a single JSON object label +name or a single integer array index. In order to provide compatibility +with PG, The -> and ->> operators in SQLite are extended to also support +a JSON object label or an integer array index for the right-hand side +operand, in addition to a full JSON path expression. + +Thus, a -> or ->> operator that works on MySQL will work in +SQLite. And a -> or ->> operator that works in PG will work in SQLite. +But because SQLite supports the union of the disjoint capabilities of +MySQL and PG, there will always be -> and ->> operators that work in +SQLite that do not work in one of MySQL and PG. This is an unavoidable +consequence of the different syntax for -> and ->> in MySQL and PG. + +In the following table, assume that "value1" is a JSON object and +"value2" is a JSON array. + + +
SQL expression Works in MySQL?Works in PG?Works in SQLite +
value1->'$.a' yes no yes +
value1->'a' no yes yes +
value2->'$[2]' yes no yes +
value2->2 no yes yes +
+ +The abbreviated JSON path expressions only work for the -> and ->> operators +in SQLite. The json_extract() function, and all other built-in SQLite +JSON functions, continue to require complete JSON path expressions for their +PATH arguments. + +## 3.0 JSON moved into the core The JSON interface is now moved into the SQLite core. diff --git a/manifest b/manifest index 2111bfa40b..2019f703d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Typo\sfix\sin\sdoc/json-enhancements.md. -D 2022-01-09T20:51:59.795 +C New\sproposal\sfor\s->\sand\s->>\soperators. +D 2022-01-10T13:55:08.463 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -38,7 +38,7 @@ F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd -F doc/json-enhancements.md b1731f584a8594660dcee86555e77559dbc447a88c010f010a7f5274bb050459 +F doc/json-enhancements.md 7f67a2e75de23958b9e767a15f6fb6abf918ef53f45f7dbb6d70ec7b55d71810 F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b8ac938f41eff8e5a23037c0e8b035a65e1b9505eca2a601221c195225595788 -R bb97ccd30a4bea2e78fa0684b28c1c7a +P c3b01d496479b3250a8895c245f79ab43ac469148d163593fea00894db195a37 +R 992262dfca636fa297052ec77a843cce U drh -Z 59da2a31f3cfc387aa42335fd8788184 +Z 83712db3104322990e05c7028e4a9b88 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 173df7a789..d1f9996545 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c3b01d496479b3250a8895c245f79ab43ac469148d163593fea00894db195a37 \ No newline at end of file +1108e12a2244edc6247050a0e9ad25b912bba6c57c71c51c2bc55167a6955175 \ No newline at end of file From d83c90bd63aaf20808355aa815c3d4be1424d5f8 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jan 2022 15:43:13 +0000 Subject: [PATCH 133/148] Implement the new PG-compliant versions of the -> and ->> operators. FossilOrigin-Name: 39eff3b9bf1f318d3606d8e5361a2adb2ba8bc1ca2a436ce4f9a204aa4cf20dd --- manifest | 14 +++--- manifest.uuid | 2 +- src/json.c | 77 +++++++++++++------------------ test/json102.test | 114 +++++++++++++++++++++++----------------------- 4 files changed, 96 insertions(+), 111 deletions(-) diff --git a/manifest b/manifest index 2019f703d9..990e4b9844 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\sproposal\sfor\s->\sand\s->>\soperators. -D 2022-01-10T13:55:08.463 +C Implement\sthe\snew\sPG-compliant\sversions\sof\sthe\s->\sand\s->>\soperators. +D 2022-01-10T15:43:13.387 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -512,7 +512,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 -F src/json.c 726f1901ecc66bc359d785c268e70c2f10fcec22b212613b00d7da5aa561d462 +F src/json.c d3134d392d88cb21ab352dd877b901ee5d46e6404fc1321f77cf67bb4d4dc9d3 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 @@ -1148,7 +1148,7 @@ F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9 F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test bb71538005f2d9e18620bdd3b76839a93ca0be61903eb8d751a64e78cf99b8fb -F test/json102.test a44a20b7dfa446e67f47d0c02927fe93f80d6ebf3080a5d827757e8d4921c081 +F test/json102.test 86edc7d283085addff8593b178997e75875530d1385f5926717543d3475e6b01 F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b F test/json104.test 2cb7ff2cca2c8214d3e5260eeb9ce45faec0926f68b3e40c1aaa6ca247284144 F test/json105.test 45f7d6a9a54c85f8a9589b68d3e7a1f42d02f2359911a8cdbad1f9988f571173 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c3b01d496479b3250a8895c245f79ab43ac469148d163593fea00894db195a37 -R 992262dfca636fa297052ec77a843cce +P 1108e12a2244edc6247050a0e9ad25b912bba6c57c71c51c2bc55167a6955175 +R 7d182b8fa0a61a014b08b226b8a1030b U drh -Z 83712db3104322990e05c7028e4a9b88 +Z b4595bb8abe65d415fc97060e1191b94 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d1f9996545..2dee764db7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1108e12a2244edc6247050a0e9ad25b912bba6c57c71c51c2bc55167a6955175 \ No newline at end of file +39eff3b9bf1f318d3606d8e5361a2adb2ba8bc1ca2a436ce4f9a204aa4cf20dd \ No newline at end of file diff --git a/src/json.c b/src/json.c index aad4507767..e2dbc7e307 100644 --- a/src/json.c +++ b/src/json.c @@ -1506,40 +1506,30 @@ static void jsonArrayLengthFunc( ** Bit values for the flags passed into jsonExtractFunc() or ** jsonSetFunc() via the user-data value. */ -#define JSON_NULLERR 0x01 /* Return NULL if input is not JSON */ -#define JSON_ABPATH 0x02 /* Allow abbreviated JSON path specs */ +#define JSON_JSON 0x01 /* Result is always JSON */ +#define JSON_SQL 0x02 /* Result is always SQL */ +#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ #define JSON_ISSET 0x04 /* json_set(), not json_insert() */ /* ** json_extract(JSON, PATH, ...) -** json_nextract(JSON, PATH, ...) ** "->"(JSON,PATH) ** "->>"(JSON,PATH) ** ** Return the element described by PATH. Return NULL if that PATH element -** is not found. For leaf nodes of the JSON, the value returned is a pure -** SQL value. In other words, quotes have been removed from strings. +** is not found. ** -** If there are multiple PATHs, then the value returned is a JSON array -** with one entry in the array for each PATH term. +** If JSON_JSON is set or if more that one PATH argument is supplied then +** always return a JSON representation of the result. If JSON_SQL is set, +** then always return an SQL representation of the result. If neither flag +** is present and argc==2, then return JSON for objects and arrays and SQL +** for all other values. ** -** Throw an error if any PATH is malformed. +** When multiple PATH arguments are supplied, the result is a JSON array +** containing the result of each PATH. ** -** If JSON is not well-formed JSON then: -** -** (1) raise an error if the JSON_NULLERR flag is not set. -** -** (2) Otherwise (if the JSON_NULLERR flags is set and) if there -** is a single PATH argument with the value '$', simply quote -** the JSON input as if by json_quote(). In other words, treat -** the JSON input as a string and convert it into a valid JSON -** string. -** -** (3) Otherwise (if JSON_NULLERR is set and the PATH is not '$') -** return NULL -** -** If the JSON_ABPATH flag is set and there is only a single PATH, then -** allow abbreviated PATH specs that omit the leading "$". +** Abbreviated JSON path expressions are allows if JSON_ABPATH, for +** compatibility with PG. */ static void jsonExtractFunc( sqlite3_context *ctx, @@ -1553,23 +1543,13 @@ static void jsonExtractFunc( JsonString jx; if( argc<2 ) return; - p = jsonParseCached(ctx, argv, (flags & JSON_NULLERR)!=0 ? 0 : ctx); - if( p==0 ){ - /* If the form is "json_nextract(IN,'$')" and IN is not well-formed JSON, - ** then return IN as a quoted JSON string. */ - if( (flags & JSON_NULLERR)!=0 - && argc==2 - && (zPath = (const char*)sqlite3_value_text(argv[1]))!=0 - && zPath[0]=='$' && zPath[1]==0 - ){ - jsonQuoteFunc(ctx, argc, argv); - } - return; - } + p = jsonParseCached(ctx, argv, ctx); + if( p==0 ) return; if( argc==2 ){ - /* With a single PATH argument, the return is the unquoted SQL value */ + /* With a single PATH argument */ zPath = (const char*)sqlite3_value_text(argv[1]); - if( zPath && zPath[0]!='$' && zPath[0]!=0 && (flags & JSON_ABPATH)!=0 ){ + if( zPath==0 ) return; + if( zPath[0]!='$' && (flags & JSON_ABPATH)!=0 ){ /* The -> and ->> operators accept abbreviated PATH arguments. This ** is mostly for compatibility with PostgreSQL, but also for convenience. ** @@ -1587,13 +1567,22 @@ static void jsonExtractFunc( jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); jsonAppendChar(&jx, 0); } - pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx); + if( jx.bErr==0 ){ + pNode = jsonLookup(p, jx.zBuf, 0, ctx); + if( pNode==0 ){ + /* No-op. jsonLookup will have left an error for us */ + }else if( flags & JSON_JSON ){ + jsonReturnJson(pNode, ctx, 0); + }else{ + jsonReturn(pNode, ctx, 0); + sqlite3_result_subtype(ctx, 0); + } + } jsonReset(&jx); }else{ pNode = jsonLookup(p, zPath, 0, ctx); + if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0); } - if( p->nErr ) return; - if( pNode ) jsonReturn(pNode, ctx, 0); }else{ /* Two or more PATH arguments results in a JSON array with each ** element of the array being the value selected by one of the PATHs */ @@ -2637,11 +2626,9 @@ void sqlite3RegisterJsonFunctions(void){ JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), JFUNCTION(json_extract, -1, 0, jsonExtractFunc), - JFUNCTION(json_nextract, -1, JSON_NULLERR, jsonExtractFunc), - JFUNCTION(->, 2, JSON_NULLERR|JSON_ABPATH, jsonExtractFunc), - JFUNCTION(->>, 2, JSON_ABPATH, jsonExtractFunc), + JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), + JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), JFUNCTION(json_insert, -1, 0, jsonSetFunc), - JFUNCTION(json_ntype, 1, JSON_NULLERR, jsonTypeFunc), JFUNCTION(json_object, -1, 0, jsonObjectFunc), JFUNCTION(json_patch, 2, 0, jsonPatchFunc), JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), diff --git a/test/json102.test b/test/json102.test index 7ae99353bf..9f8f482b85 100644 --- a/test/json102.test +++ b/test/json102.test @@ -71,70 +71,21 @@ do_execsql_test json102-240 { do_execsql_test json102-250 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$'); } {{{"a":2,"c":[4,5,{"f":7}]}}} -do_execsql_test json102-251 { - SELECT json_nextract('{"a":2,"c":[4,5,{"f":7}]}', '$'); -} {{{"a":2,"c":[4,5,{"f":7}]}}} -do_execsql_test json102-252 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$'; -} {{{"a":2,"c":[4,5,{"f":7}]}}} do_execsql_test json102-260 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c'); } {{[4,5,{"f":7}]}} -do_execsql_test json102-261 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c'; -} {{[4,5,{"f":7}]}} -do_execsql_test json102-262 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c'; -} {{[4,5,{"f":7}]}} -do_catchsql_test json102-265 { - SELECT json_extract('[1,2,3', '$[2]'); -} {1 {malformed JSON}} -do_catchsql_test json102-266 { - SELECT json_nextract('[1,2,3', '$[2]'); -} {0 {{}}} -do_catchsql_test json102-267 { - SELECT json_extract('[1,2,3', '$'); -} {1 {malformed JSON}} -do_catchsql_test json102-268 { - SELECT json_nextract('[1,2,3', '$'); -} {0 {{"[1,2,3"}}} -do_catchsql_test json102-269a { - SELECT '[1,2,3' ->> '$'; -} {1 {malformed JSON}} -do_catchsql_test json102-269b { - SELECT '[1,2,3' -> '$'; -} {0 {{"[1,2,3"}}} - do_execsql_test json102-270 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]'); } {{{"f":7}}} -do_execsql_test json102-271 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2]'; -} {{{"f":7}}} -do_execsql_test json102-272 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2; -} {{{"f":7}}} do_execsql_test json102-280 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f'); } {{7}} -do_execsql_test json102-281 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2 -> 'f'; -} {{7}} -do_execsql_test json102-282 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> '[2]' -> 'f'; -} {{7}} do_execsql_test json102-290 { SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a'); } {{[[4,5],2]}} do_execsql_test json102-300 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x'); } {{}} -do_execsql_test json102-301 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> 'x'; -} {{}} -do_execsql_test json102-302 { - SELECT '{"a":2,"c":[4,5,{"f":7}]}' -> NULL; -} {{}} do_execsql_test json102-310 { SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a'); } {{[null,2]}} @@ -198,9 +149,6 @@ do_execsql_test json102-500 { do_execsql_test json102-510 { SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}'); } {{object}} -do_execsql_test json102-511 { - SELECT json_ntype('{"a":[2,3.5,true,false,null,"x"]}'); -} {{object}} do_execsql_test json102-520 { SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$'); } {{object}} @@ -234,12 +182,6 @@ do_execsql_test json102-610 { do_execsql_test json102-620 { SELECT json_valid(char(123)||'"x":35'); } {{0}} -do_catchsql_test json102-630 { - SELECT json_type('["a",'); -} {1 {malformed JSON}} -do_catchsql_test json102-631 { - SELECT json_ntype('["a",'); -} {0 {{}}} ifcapable vtab { do_execsql_test json102-1000 { @@ -395,4 +337,60 @@ do_execsql_test json102-1501 { SELECT sum(json_valid(json_quote('a'||char(x)||'z'))) FROM c ORDER BY x; } {31} +# 2022-01-10 tests for -> and ->> operators +# +reset_db +do_execsql_test json102-1600 { + CREATE TABLE t1(id INTEGER PRIMARY KEY, x JSON); + INSERT INTO t1(id,x) VALUES + (1, '{"a":null}'), + (2, '{"a":123}'), + (3, '{"a":4.5}'), + (4, '{"a":"six"}'), + (5, '{"a":[7,8]}'), + (6, '{"a":{"b":9}}'), + (7, '{"b":999}'); + SELECT + id, + x->'a' AS '->', + CASE WHEN subtype(x->'a') THEN 'json' ELSE typeof(x->'a') END AS 'type', + x->>'a' AS '->>', + CASE WHEN subtype(x->>'a') THEN 'json' ELSE typeof(x->>'a') END AS 'type', + json_extract(x,'$.a') AS 'json_extract', + CASE WHEN subtype(json_extract(x,'$.a')) + THEN 'json' ELSE typeof(json_extract(x,'$.a')) END AS 'type' + FROM t1 ORDER BY id; +} [list \ + 1 null json {} null {} null \ + 2 123 json 123 integer 123 integer \ + 3 4.5 json 4.5 real 4.5 real \ + 4 {"six"} json six text six text \ + 5 {[7,8]} json {[7,8]} text {[7,8]} json \ + 6 {{"b":9}} json {{"b":9}} text {{"b":9}} json \ + 7 {} null {} null {} null +] +do_execsql_test json102-1610 { + DELETE FROM t1; + INSERT INTO t1(x) VALUES('[null,123,4.5,"six",[7,8],{"b":9}]'); + WITH c(y) AS (VALUES(0),(1),(2),(3),(4),(5),(6)) + SELECT + y, + x->y AS '->', + CASE WHEN subtype(x->y) THEN 'json' ELSE typeof(x->y) END AS 'type', + x->>y AS '->>', + CASE WHEN subtype(x->>y) THEN 'json' ELSE typeof(x->>y) END AS 'type', + json_extract(x,format('$[%d]',y)) AS 'json_extract', + CASE WHEN subtype(json_extract(x,format('$[%d]',y))) + THEN 'json' ELSE typeof(json_extract(x,format('$[%d]',y))) END AS 'type' + FROM c, t1 ORDER BY y; +} [list \ + 0 null json {} null {} null \ + 1 123 json 123 integer 123 integer \ + 2 4.5 json 4.5 real 4.5 real \ + 3 {"six"} json six text six text \ + 4 {[7,8]} json {[7,8]} text {[7,8]} json \ + 5 {{"b":9}} json {{"b":9}} text {{"b":9}} json \ + 6 {} null {} null {} null +] + finish_test From 875912c246f38376a102521e48e3efe1c647d26d Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jan 2022 17:43:54 +0000 Subject: [PATCH 134/148] Fix typo in the json-enhancements.md document. FossilOrigin-Name: feba24ef774d80ebbaf87a93fc106cb7e482edcc3f237edd4c9d4e918ffb3131 --- doc/json-enhancements.md | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/json-enhancements.md b/doc/json-enhancements.md index d3ab6e0a43..bc03e8978c 100644 --- a/doc/json-enhancements.md +++ b/doc/json-enhancements.md @@ -70,7 +70,7 @@ in a bold font. **'{"a":4.5}'** '$.a' **'4.5'** '4.5' 4.5 4.5 **'{"a":"xyz"}'** '$.a' **'"xyz"'** 'xyz' 'xyz' 'xyz' **'{"a":null}'** '$.a' **'null'** NULL NULL NULL - **'{"a":[6,7,8]}'** '$.a' **'[6,7,8]'** '[6,7,8]' '[6,7,8]' **'[6,7,9]'** + **'{"a":[6,7,8]}'** '$.a' **'[6,7,8]'** '[6,7,8]' '[6,7,8]' **'[6,7,8]'** **'{"a":{"x":9}}'** '$.a' **'{"x":9}'** '{"x":9}' '{"x":9}' **'{"x":9}'** **'{"b":999}'** '$.a' NULL NULL NULL NULL diff --git a/manifest b/manifest index 990e4b9844..4fe6fba3c0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Implement\sthe\snew\sPG-compliant\sversions\sof\sthe\s->\sand\s->>\soperators. -D 2022-01-10T15:43:13.387 +C Fix\stypo\sin\sthe\sjson-enhancements.md\sdocument. +D 2022-01-10T17:43:54.652 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -38,7 +38,7 @@ F configure a2877fe63cc821af0df41abe70f1f7c4e97cb7e23a42e0a1402e8a2f55a88aa2 x F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd -F doc/json-enhancements.md 7f67a2e75de23958b9e767a15f6fb6abf918ef53f45f7dbb6d70ec7b55d71810 +F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f F doc/lemon.html efc0cd2345d66905505d98f862e1c571512def0ceb5b016cb658fd4918eb76a3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1108e12a2244edc6247050a0e9ad25b912bba6c57c71c51c2bc55167a6955175 -R 7d182b8fa0a61a014b08b226b8a1030b +P 39eff3b9bf1f318d3606d8e5361a2adb2ba8bc1ca2a436ce4f9a204aa4cf20dd +R 8ac564d1981cf04622f1f15a60ba0e5b U drh -Z b4595bb8abe65d415fc97060e1191b94 +Z c237913f633491314765f45ba87ab8df # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2dee764db7..af50a8820d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39eff3b9bf1f318d3606d8e5361a2adb2ba8bc1ca2a436ce4f9a204aa4cf20dd \ No newline at end of file +feba24ef774d80ebbaf87a93fc106cb7e482edcc3f237edd4c9d4e918ffb3131 \ No newline at end of file From aa97b57b111b20c0d1fa4e5d0d7576506a81142e Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 11 Jan 2022 18:01:17 +0000 Subject: [PATCH 135/148] Fix the PG-compatible -> and ->> path parsing. FossilOrigin-Name: 22d5138315fb77eeea1c7e66ccc4190bcae18d058a99aa37ddd119e54b52f723 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 47 +++++++++++++++++++++++++---------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index 4fe6fba3c0..1af7555428 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sin\sthe\sjson-enhancements.md\sdocument. -D 2022-01-10T17:43:54.652 +C Fix\sthe\sPG-compatible\s->\sand\s->>\spath\sparsing. +D 2022-01-11T18:01:17.466 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -512,7 +512,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 -F src/json.c d3134d392d88cb21ab352dd877b901ee5d46e6404fc1321f77cf67bb4d4dc9d3 +F src/json.c 5dee750a85262600817f20e3ced050f9c2a47d8c3db77f31f4ee379c0f843a8a F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 39eff3b9bf1f318d3606d8e5361a2adb2ba8bc1ca2a436ce4f9a204aa4cf20dd -R 8ac564d1981cf04622f1f15a60ba0e5b +P feba24ef774d80ebbaf87a93fc106cb7e482edcc3f237edd4c9d4e918ffb3131 +R 0007d377d0ed1c0dc1f81b209b625ab0 U drh -Z c237913f633491314765f45ba87ab8df +Z e45b9675c3fefc0ecfe81398e8f3bbb1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index af50a8820d..d47038dcfc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -feba24ef774d80ebbaf87a93fc106cb7e482edcc3f237edd4c9d4e918ffb3131 \ No newline at end of file +22d5138315fb77eeea1c7e66ccc4190bcae18d058a99aa37ddd119e54b52f723 \ No newline at end of file diff --git a/src/json.c b/src/json.c index e2dbc7e307..6fe5fa411c 100644 --- a/src/json.c +++ b/src/json.c @@ -1549,36 +1549,39 @@ static void jsonExtractFunc( /* With a single PATH argument */ zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) return; - if( zPath[0]!='$' && (flags & JSON_ABPATH)!=0 ){ - /* The -> and ->> operators accept abbreviated PATH arguments. This - ** is mostly for compatibility with PostgreSQL, but also for convenience. - ** - ** NUMBER ==> $[NUMBER] // PG compatible - ** LABEL ==> $.LABEL // PG compatible - ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience - */ - jsonInit(&jx, ctx); - if( sqlite3Isdigit(zPath[0]) ){ - jsonAppendRaw(&jx, "$[", 2); - jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendRaw(&jx, "]", 2); + if( flags & JSON_ABPATH ){ + if( zPath[0]!='$' ){ + /* The -> and ->> operators accept abbreviated PATH arguments. This + ** is mostly for compatibility with PostgreSQL, but also for + ** convenience. + ** + ** NUMBER ==> $[NUMBER] // PG compatible + ** LABEL ==> $.LABEL // PG compatible + ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience + */ + jsonInit(&jx, ctx); + if( sqlite3Isdigit(zPath[0]) ){ + jsonAppendRaw(&jx, "$[", 2); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendRaw(&jx, "]", 2); + }else{ + jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendChar(&jx, 0); + } + pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx); + jsonReset(&jx); }else{ - jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); - jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendChar(&jx, 0); + pNode = jsonLookup(p, zPath, 0, ctx); } - if( jx.bErr==0 ){ - pNode = jsonLookup(p, jx.zBuf, 0, ctx); - if( pNode==0 ){ - /* No-op. jsonLookup will have left an error for us */ - }else if( flags & JSON_JSON ){ + if( pNode ){ + if( flags & JSON_JSON ){ jsonReturnJson(pNode, ctx, 0); }else{ jsonReturn(pNode, ctx, 0); sqlite3_result_subtype(ctx, 0); } } - jsonReset(&jx); }else{ pNode = jsonLookup(p, zPath, 0, ctx); if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0); From a6c596b1941296377f22cc4173991c963d14a97e Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 11 Jan 2022 22:06:25 +0000 Subject: [PATCH 136/148] Remove vestigial traces of json_ntype(). FossilOrigin-Name: 8da07c8b09ff83436a34e539e4cce8ba9524390017ca14f4af8344a12e351550 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 7 ++----- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 1af7555428..c17e656e6b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sPG-compatible\s->\sand\s->>\spath\sparsing. -D 2022-01-11T18:01:17.466 +C Remove\svestigial\straces\sof\sjson_ntype(). +D 2022-01-11T22:06:25.550 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -512,7 +512,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 -F src/json.c 5dee750a85262600817f20e3ced050f9c2a47d8c3db77f31f4ee379c0f843a8a +F src/json.c f3bbaf6a4df6f5ada5b71e01666f5cd67642c616cd8be47dbfa5b5768dfa71d4 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P feba24ef774d80ebbaf87a93fc106cb7e482edcc3f237edd4c9d4e918ffb3131 -R 0007d377d0ed1c0dc1f81b209b625ab0 +P 22d5138315fb77eeea1c7e66ccc4190bcae18d058a99aa37ddd119e54b52f723 +R 4fe2152bcfc77f35d559181df42337b8 U drh -Z e45b9675c3fefc0ecfe81398e8f3bbb1 +Z 2256adb4b917a0fe76784837651ce52b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d47038dcfc..f7e85f0d18 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22d5138315fb77eeea1c7e66ccc4190bcae18d058a99aa37ddd119e54b52f723 \ No newline at end of file +8da07c8b09ff83436a34e539e4cce8ba9524390017ca14f4af8344a12e351550 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 6fe5fa411c..dbc3faaef3 100644 --- a/src/json.c +++ b/src/json.c @@ -1903,13 +1903,10 @@ jsonSetDone: /* ** json_type(JSON) -** json_ntype(JSON) ** json_type(JSON, PATH) ** ** Return the top-level "type" of a JSON string. json_type() raises an -** error if either the JSON or PATH inputs are not well-formed. json_ntype() -** works like the one-argument version of json_type() except that it -** returns NULL if the JSON argument is not well-formed. +** error if either the JSON or PATH inputs are not well-formed. */ static void jsonTypeFunc( sqlite3_context *ctx, @@ -1920,7 +1917,7 @@ static void jsonTypeFunc( const char *zPath; JsonNode *pNode; - p = jsonParseCached(ctx, argv, sqlite3_user_data(ctx)!=0 ? 0 : ctx); + p = jsonParseCached(ctx, argv, ctx); if( p==0 ) return; if( argc==2 ){ zPath = (const char*)sqlite3_value_text(argv[1]); From beacaac2b5a6d997549be06de9d4242618a539d1 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 12 Jan 2022 00:28:12 +0000 Subject: [PATCH 137/148] Fix harmless compiler warning seen with MSVC. FossilOrigin-Name: adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 460c6519aa..180aca84cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sJSON\sinterface\sinto\sthe\score.\s\sAdd\s->\sand\s->>\soperators\sfor\sJSON\nthat\sare\scompatible\swith\sby\sMySQL\sand\sPG. -D 2022-01-11T23:28:12.800 +C Fix\sharmless\scompiler\swarning\sseen\swith\sMSVC. +D 2022-01-12T00:28:12.478 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 0e9f84f974e970fb373c15caa1624a281b3c33098cb9dd9021d6801c04eb4fde +F src/btree.c 9d9949b3faccdeab6261b30f75d2e5cf6aaf27be052df2f4e5d4b3dbaa6591f5 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f @@ -512,7 +512,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 -F src/json.c f3bbaf6a4df6f5ada5b71e01666f5cd67642c616cd8be47dbfa5b5768dfa71d4 w ext/misc/json1.c +F src/json.c f3bbaf6a4df6f5ada5b71e01666f5cd67642c616cd8be47dbfa5b5768dfa71d4 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 @@ -1938,9 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 71272caff5874137ad0b1ddfc22ced4bb66e6c97f7868fdae0347a186f589b38 8da07c8b09ff83436a34e539e4cce8ba9524390017ca14f4af8344a12e351550 -R 4fe2152bcfc77f35d559181df42337b8 -T +closed 8da07c8b09ff83436a34e539e4cce8ba9524390017ca14f4af8344a12e351550 -U drh -Z 9fbdecd5bae6b7208ce6f6c24caebc4c +P 4cbb3e3efeb40cc41df15e96c7a0c9d6a8c12ca9f2c139ff1b31ea5416735d34 +R 10531aa62fc33b11ea2aa989725bff0c +U mistachkin +Z 973b826235a10c72dc4bc9890af679b4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f5ad138bbb..965d5fec4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4cbb3e3efeb40cc41df15e96c7a0c9d6a8c12ca9f2c139ff1b31ea5416735d34 \ No newline at end of file +adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 70f4039faf..16dc63b7b8 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6839,7 +6839,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ assert( pPage->nFree>=0 ); data = pPage->aData; ptr = &pPage->aCellIdx[2*idx]; - assert( pPage->pBt->usableSize > (int)(ptr-data) ); + assert( pPage->pBt->usableSize > (u32)(ptr-data) ); pc = get2byte(ptr); hdr = pPage->hdrOffset; testcase( pc==(u32)get2byte(&data[hdr+5]) ); From c5432c43e800999d5e0959f275bd6e1854962827 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 12 Jan 2022 00:52:34 +0000 Subject: [PATCH 138/148] Fix mkctimec.tcl with the updated compile-time options for JSON. FossilOrigin-Name: 8ded3f5b0025eb6cc11669c1208681e592862ce352dfff11173dff68daafad30 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/ctime.c | 6 +++--- tool/mkctimec.tcl | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 180aca84cc..8113c2b57c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning\sseen\swith\sMSVC. -D 2022-01-12T00:28:12.478 +C Fix\smkctimec.tcl\swith\sthe\supdated\scompile-time\soptions\sfor\sJSON. +D 2022-01-12T00:52:34.194 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -497,7 +497,7 @@ F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 638e75c9a02b276c782cb27f59f3abf2ab94a33514107ffd165b2f69d1bc2aaa +F src/ctime.c ef91281f85e032f7a544ce2e4b4df29eaa45d236dabb28792af8c4398b960817 F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d @@ -1865,7 +1865,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8 F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x -F tool/mkctimec.tcl 5ef1891ed3d0e8143ff39bad7c01ed60c2817a2fb2d9a09487f7ccad2df621e4 +F tool/mkctimec.tcl 4d8e3f967f243456bc69e5d37fde6cf174beaaa7a4e2db3515a5a6b92086e7ee F tool/mkkeywordhash.c 35bfc41adacc4aa6ef6fca7fd0c63e0ec0534b78daf4d0cfdebe398216bbffc3 F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33 F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4cbb3e3efeb40cc41df15e96c7a0c9d6a8c12ca9f2c139ff1b31ea5416735d34 -R 10531aa62fc33b11ea2aa989725bff0c -U mistachkin -Z 973b826235a10c72dc4bc9890af679b4 +P adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec +R 69b7f6a0b4d0fcc284cb15152e397fee +U drh +Z 474724af0a4417c46de4dcd375fa43ca # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 965d5fec4a..10d9833208 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec \ No newline at end of file +8ded3f5b0025eb6cc11669c1208681e592862ce352dfff11173dff68daafad30 \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index 4377528006..bb6896574f 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -179,9 +179,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_DISABLE_INTRINSIC "DISABLE_INTRINSIC", #endif -#ifdef SQLITE_DISABLE_JSON - "DISABLE_JSON", -#endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif @@ -583,6 +580,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif +#ifdef SQLITE_OMIT_JSON + "OMIT_JSON", +#endif #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif diff --git a/tool/mkctimec.tcl b/tool/mkctimec.tcl index 6294609451..a0d151116f 100644 --- a/tool/mkctimec.tcl +++ b/tool/mkctimec.tcl @@ -70,7 +70,6 @@ set boolean_defnil_options { SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_ENABLE_ICU SQLITE_ENABLE_IOTRACE - SQLITE_ENABLE_JSON1 SQLITE_ENABLE_LOAD_EXTENSION SQLITE_ENABLE_LOCKING_STYLE SQLITE_ENABLE_MATH_FUNCTIONS @@ -151,6 +150,7 @@ set boolean_defnil_options { SQLITE_OMIT_INCRBLOB SQLITE_OMIT_INTEGRITY_CHECK SQLITE_OMIT_INTROSPECTION_PRAGMAS + SQLITE_OMIT_JSON SQLITE_OMIT_LIKE_OPTIMIZATION SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_LOCALTIME From 04f97602e2c48db69e7ca7ac28ac570ae4587a59 Mon Sep 17 00:00:00 2001 From: larrybr Date: Wed, 12 Jan 2022 01:42:50 +0000 Subject: [PATCH 139/148] Make tool/mctimec.tcl effect more regular and obvious FossilOrigin-Name: 02aaa10f34ab17e76feb7b6f79048309536c0794fcb534b934e06f3daedfeaba --- manifest | 16 +++--- manifest.uuid | 2 +- src/ctime.c | 17 ++++--- tool/mkctimec.tcl | 123 +++++++++++++++++++++++++++++----------------- 4 files changed, 96 insertions(+), 62 deletions(-) mode change 100644 => 100755 tool/mkctimec.tcl diff --git a/manifest b/manifest index 8113c2b57c..a57d94552a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smkctimec.tcl\swith\sthe\supdated\scompile-time\soptions\sfor\sJSON. -D 2022-01-12T00:52:34.194 +C Make\stool/mctimec.tcl\seffect\smore\sregular\sand\sobvious +D 2022-01-12T01:42:50.451 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -497,7 +497,7 @@ F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c ef91281f85e032f7a544ce2e4b4df29eaa45d236dabb28792af8c4398b960817 +F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1 F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d @@ -1865,7 +1865,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8 F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x -F tool/mkctimec.tcl 4d8e3f967f243456bc69e5d37fde6cf174beaaa7a4e2db3515a5a6b92086e7ee +F tool/mkctimec.tcl 3147e9dfc4ad774e94f80084789ebaada9da9b6e66ddab16438cfc07999b6047 x F tool/mkkeywordhash.c 35bfc41adacc4aa6ef6fca7fd0c63e0ec0534b78daf4d0cfdebe398216bbffc3 F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33 F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec -R 69b7f6a0b4d0fcc284cb15152e397fee -U drh -Z 474724af0a4417c46de4dcd375fa43ca +P 8ded3f5b0025eb6cc11669c1208681e592862ce352dfff11173dff68daafad30 +R 99e0bf97f8dc74f258301b85c4857b96 +U larrybr +Z da4e437349126128425252d5fe5b1489 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 10d9833208..00e119201f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8ded3f5b0025eb6cc11669c1208681e592862ce352dfff11173dff68daafad30 \ No newline at end of file +02aaa10f34ab17e76feb7b6f79048309536c0794fcb534b934e06f3daedfeaba \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index bb6896574f..1463e4f552 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -1,3 +1,11 @@ +/* DO NOT EDIT! +** This file is automatically generated by the script in the canonical +** SQLite source tree at tool/mkctimec.tcl. +** +** To modify this header, edit any of the various lists in that script +** which specify categories of generated conditionals in this file. +*/ + /* ** 2010 February 23 ** @@ -46,9 +54,6 @@ */ static const char * const sqlite3azCompileOpt[] = { -/* -** BEGIN CODE GENERATED BY tool/mkctime.tcl -*/ #ifdef SQLITE_32BIT_ROWID "32BIT_ROWID", #endif @@ -771,10 +776,8 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC", #endif -/* -** END CODE GENERATED BY tool/mkctime.tcl -*/ -}; + +} ; const char **sqlite3CompileOptions(int *pnOpt){ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); diff --git a/tool/mkctimec.tcl b/tool/mkctimec.tcl old mode 100644 new mode 100755 index a0d151116f..745a59a229 --- a/tool/mkctimec.tcl +++ b/tool/mkctimec.tcl @@ -5,9 +5,82 @@ # const char **azCompileOpt[] # # definition used in src/ctime.c, run this script from -# the checkout root. It alters src/ctime.c in-place. +# the checkout root. It generates src/ctime.c . # + +set ::headWarning {/* DO NOT EDIT! +** This file is automatically generated by the script in the canonical +** SQLite source tree at tool/mkctimec.tcl. +** +** To modify this header, edit any of the various lists in that script +** which specify categories of generated conditionals in this file. +*/} + +# Make { and } easier to put into literals (even on EBCDIC machines.) +regexp {(\{)(\})} "{}" ma ::lb ::rb + +set ::headCode " +/* +** 2010 February 23 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements routines used to report what compile-time options +** SQLite was built with. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */ + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +#include \"config.h\" +#define SQLITECONFIG_H 1 +#endif + +/* These macros are provided to \"stringify\" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + +/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This +** option requires a separate macro because legal values contain a single +** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE=\"100,100\") */ +#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 \",\" #opt2 +#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) +#include \"sqliteInt.h\" + +/* +** An array of names of all compile-time options. This array should +** be sorted A-Z. +** +** This array looks large, but in a typical installation actually uses +** only a handful of compile-time options, so most times this array is usually +** rather short and uses little memory space. +*/ +static const char * const sqlite3azCompileOpt\[\] = $::lb +" + +set ::tailCode " +$::rb ; + +const char **sqlite3CompileOptions(int *pnOpt){ + *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt\[0\]); + return (const char**)sqlite3azCompileOpt; +} + +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ +" + # All Boolean compile time options which default to something # other than 0 or empty. The default is paired with the PP # symbol so that a differing define can be detected. @@ -354,60 +427,18 @@ foreach v $value2_options { }] } -# Split a string on a regex, return all parts in order. -# Any elements with an even index may be empty. -# Elements with odd indices will match the regex. -proc split_on_re {re str {nrepps 1}} { - set chunks {} - set cix 0 - set resm [regexp -all -inline -indices $re $str] - if {[llength $resm]==0} { - return $str - } - set rix 0 - while {$rix < [llength $resm]} { - set mre [lindex $resm $rix] - incr rix $nrepps - set mbx [lindex $mre 0] - set mex [lindex $mre 1] - lappend chunks [string range $str $cix [expr $mbx - 1]] - lappend chunks [string range $str $mbx $mex] - set cix [expr $mex + 1] - } - lappend chunks [string range $str $cix end] - return $chunks -} - - set ctime_c "src/ctime.c" -if {[catch {set cfd [open $ctime_c r]}]!=0} { - puts stderr "File '$ctime_c' unreadable. Run this script from checkout root." - exit 1; -} - -set ctfc [read $cfd] -close $cfd - -set re {/\*\s+\*+\s*((BEGIN)|(END)) CODE GENERATED BY (\S+)\s+\*/\s+} -set renpp 5 - -set ctfcChunks [split_on_re $re $ctfc $renpp] -if {[llength $ctfcChunks] != 5} { - puts stderr "File '$ctime_c' has too few generated code markers." - exit 1; -} if {[catch {set cfd [open $ctime_c w]}]!=0} { puts stderr "File '$ctime_c' unwritable." exit 1; } -puts -nonewline $cfd [lindex $ctfcChunks 0] -puts -nonewline $cfd [lindex $ctfcChunks 1] +puts $cfd $::headWarning; +puts $cfd $::headCode; foreach o [lsort [array names options]] { puts $cfd [string trim $options($o)] } -puts -nonewline $cfd [lindex $ctfcChunks 3] -puts -nonewline $cfd [lindex $ctfcChunks 4] +puts -nonewline $cfd $::tailCode; close $cfd From 8efc6a8c09b359fd3c231df6884c4df6198d7de6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 12 Jan 2022 20:31:14 +0000 Subject: [PATCH 140/148] When the result of a subquery is to be stored in a register and that subquery has an ORDER BY clause and an OFFSET, NULL out the destination register before starting the ORDER BY so that the register will be set correctly even if the OFFSET is larger than the number of output rows. Fix for the problem reported in [forum:/forumpost/0ec80f12d02acb3f|forum post 0ec80f12d02acb3f]. FossilOrigin-Name: 9282bcde301cee2a5c3c068b5b0b7ce992c155ece894413a6a9a51a81e4133fd --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/select.c | 3 +++ test/subquery.test | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a57d94552a..d1ea5b07f7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\stool/mctimec.tcl\seffect\smore\sregular\sand\sobvious -D 2022-01-12T01:42:50.451 +C When\sthe\sresult\sof\sa\ssubquery\sis\sto\sbe\sstored\sin\sa\sregister\sand\sthat\nsubquery\shas\san\sORDER\sBY\sclause\sand\san\sOFFSET,\sNULL\sout\sthe\sdestination\nregister\sbefore\sstarting\sthe\sORDER\sBY\sso\sthat\sthe\sregister\swill\sbe\sset\ncorrectly\seven\sif\sthe\sOFFSET\sis\slarger\sthan\sthe\snumber\sof\soutput\srows.\nFix\sfor\sthe\sproblem\sreported\sin\n[forum:/forumpost/0ec80f12d02acb3f|forum\spost\s0ec80f12d02acb3f]. +D 2022-01-12T20:31:14.514 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -551,7 +551,7 @@ F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 342e096c2737a3ee60753e91de6e6660c7f59cd2988b3e1ab641d38fd885003f +F src/select.c a4a23a70f0a24a1103ac9698f6be181a6ec7ff6c19e03e8899c43cb6d2af09d6 F src/shell.c.in f5111900d646a07da18e6438d57be20f112397daba6bfc85b117a0da586e55da F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1441,7 +1441,7 @@ F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b3594 F test/strict1.test a3ec495471f24c1a6e1a1664bd23e24ccdb27ae93b1a763ee1942ec955b68e71 F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070 F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49 -F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f +F test/subquery.test e6fb2ad0a7e5a58cd1619b3e8354484195d6b4473f1cb60b7d2cbf78f501e951 F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12 F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303 F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8ded3f5b0025eb6cc11669c1208681e592862ce352dfff11173dff68daafad30 -R 99e0bf97f8dc74f258301b85c4857b96 -U larrybr -Z da4e437349126128425252d5fe5b1489 +P 02aaa10f34ab17e76feb7b6f79048309536c0794fcb534b934e06f3daedfeaba +R 926926c5df28210b2eccf7396e21106e +U drh +Z bb0f2b9d8929fd104a37ff3ae2f31816 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 00e119201f..2ecb5cbd7f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02aaa10f34ab17e76feb7b6f79048309536c0794fcb534b934e06f3daedfeaba \ No newline at end of file +9282bcde301cee2a5c3c068b5b0b7ce992c155ece894413a6a9a51a81e4133fd \ No newline at end of file diff --git a/src/select.c b/src/select.c index c33903f107..2d1b54b3ae 100644 --- a/src/select.c +++ b/src/select.c @@ -1575,6 +1575,9 @@ static void generateSortTail( iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ + if( eDest==SRT_Mem && p->iOffset ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst); + } regRowid = 0; regRow = pDest->iSdst; }else{ diff --git a/test/subquery.test b/test/subquery.test index 06facbbae0..e3b4281ede 100644 --- a/test/subquery.test +++ b/test/subquery.test @@ -594,4 +594,23 @@ do_execsql_test subquery-8.1 { SELECT (SELECT 0 FROM (SELECT * FROM (SELECT 0))) AS x WHERE x; } {} +# 2022-01-12 https://sqlite.org/forum/forumpost/0ec80f12d02acb3f +# +reset_db +do_execsql_test subquery-9.1 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1),(1),(1); + SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 100) FROM t1; +} {{} {} {}} +do_execsql_test subquery-9.2 { + SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 0) FROM t1; +} {1 1 1} +do_execsql_test subquery-9.3 { + INSERT INTO t1 VALUES(2); + SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 1) FROM t1; +} {2 2 2 2} +do_execsql_test subquery-9.4 { + SELECT (SELECT DISTINCT x FROM t1 ORDER BY +x LIMIT 1 OFFSET 2) FROM t1; +} {{} {} {} {}} + finish_test From 738d7b9fc0d178d2ac76acb753e017e8ea8a0274 Mon Sep 17 00:00:00 2001 From: larrybr Date: Thu, 13 Jan 2022 21:22:54 +0000 Subject: [PATCH 141/148] Add --schema S option to .import FossilOrigin-Name: 38d9dbca166078013a44214c88805fc7cca578976ceed9fc62f5159a38ec96a7 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c.in | 16 +++++++++++----- test/shell5.test | 23 ++++++++++++++--------- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index d1ea5b07f7..66a6286ee2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\sthe\sresult\sof\sa\ssubquery\sis\sto\sbe\sstored\sin\sa\sregister\sand\sthat\nsubquery\shas\san\sORDER\sBY\sclause\sand\san\sOFFSET,\sNULL\sout\sthe\sdestination\nregister\sbefore\sstarting\sthe\sORDER\sBY\sso\sthat\sthe\sregister\swill\sbe\sset\ncorrectly\seven\sif\sthe\sOFFSET\sis\slarger\sthan\sthe\snumber\sof\soutput\srows.\nFix\sfor\sthe\sproblem\sreported\sin\n[forum:/forumpost/0ec80f12d02acb3f|forum\spost\s0ec80f12d02acb3f]. -D 2022-01-12T20:31:14.514 +C Add\s--schema\sS\soption\sto\s.import +D 2022-01-13T21:22:54.666 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a4a23a70f0a24a1103ac9698f6be181a6ec7ff6c19e03e8899c43cb6d2af09d6 -F src/shell.c.in f5111900d646a07da18e6438d57be20f112397daba6bfc85b117a0da586e55da +F src/shell.c.in 851ce2b310888c68f3f66d876b7392cc822f0cb0e316b1a89997abb1d7ec67f0 F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef @@ -1388,7 +1388,7 @@ F test/shell1.test 70f46b5d07776a107335c3c2c9cbd0431d44637bfeae1f6b9ded5e33b4c7c F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566 F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be -F test/shell5.test 6e4aa0e531dcb8dcf74b7920a2a7442c6712d4dff8422bbc81f768f9dee8a0e3 +F test/shell5.test b85069bfcf3159b225228629ab2c3e69aa923d098fea8ea074b5dcd743522e2c F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 02aaa10f34ab17e76feb7b6f79048309536c0794fcb534b934e06f3daedfeaba -R 926926c5df28210b2eccf7396e21106e -U drh -Z bb0f2b9d8929fd104a37ff3ae2f31816 +P 9282bcde301cee2a5c3c068b5b0b7ce992c155ece894413a6a9a51a81e4133fd +R 85600e55f5465c0d7b90f18f16da5617 +U larrybr +Z 49bd76acfcc3b273011e69ab0fa8281f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2ecb5cbd7f..f826775084 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9282bcde301cee2a5c3c068b5b0b7ce992c155ece894413a6a9a51a81e4133fd \ No newline at end of file +38d9dbca166078013a44214c88805fc7cca578976ceed9fc62f5159a38ec96a7 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 3d15cc1f89..430d9e1640 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4070,6 +4070,7 @@ static const char *(azHelp[]) = { " --ascii Use \\037 and \\036 as column and row separators", " --csv Use , and \\n as column and row separators", " --skip N Skip the first N rows of input", + " --schema S Target table to be S.TABLE", " -v \"Verbose\" - increase auxiliary output", " Notes:", " * If TABLE does not exist, it is created. The first row of input", @@ -8382,6 +8383,7 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ char *zTable = 0; /* Insert data into this table */ + char *zSchema = "main"; /* within this schema */ char *zFile = 0; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ @@ -8424,6 +8426,8 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else if( strcmp(z,"-v")==0 ){ eVerbose++; + }else if( strcmp(z,"-schema")==0 && i=2 || (eVerbose>=1 && useOutputMode) ){ char zSep[2]; zSep[1] = 0; @@ -8529,7 +8534,7 @@ static int do_meta_command(char *zLine, ShellState *p){ while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } - zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + zSql = sqlite3_mprintf("SELECT * FROM %s.\"%w\"", zSchema, zTable); if( zSql==0 ){ import_cleanup(&sCtx); shell_out_of_memory(); @@ -8538,7 +8543,7 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ - char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable); + char *zCreate = sqlite3_mprintf("CREATE TABLE %s.\"%w\"", zSchema,zTable); char cSep = '('; while( xRead(&sCtx) ){ zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); @@ -8559,8 +8564,8 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); sqlite3_free(zCreate); if( rc ){ - utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable, - sqlite3_errmsg(p->db)); + utf8_printf(stderr, "CREATE TABLE %s.\"%s\"(...) failed: %s\n", + zSchema, zTable, sqlite3_errmsg(p->db)); import_cleanup(&sCtx); rc = 1; goto meta_command_exit; @@ -8584,7 +8589,8 @@ static int do_meta_command(char *zLine, ShellState *p){ import_cleanup(&sCtx); shell_out_of_memory(); } - sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s.\"%w\" VALUES(?", + zSchema, zTable); j = strlen30(zSql); for(i=1; i Date: Fri, 14 Jan 2022 16:29:45 +0000 Subject: [PATCH 142/148] For .import schema, quote it as for other identifiers. FossilOrigin-Name: bff9153ceedcc7be77f2daf5139fee29c2fab742ff1fce49877965423a7d4be3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 13 +++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 66a6286ee2..b4ad6e2287 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s--schema\sS\soption\sto\s.import -D 2022-01-13T21:22:54.666 +C For\s.import\sschema,\squote\sit\sas\sfor\sother\sidentifiers. +D 2022-01-14T16:29:45.154 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c a4a23a70f0a24a1103ac9698f6be181a6ec7ff6c19e03e8899c43cb6d2af09d6 -F src/shell.c.in 851ce2b310888c68f3f66d876b7392cc822f0cb0e316b1a89997abb1d7ec67f0 +F src/shell.c.in 4690f216dc4da0c104a8fd9f9e12bec0483242e630324aa7a3ccd155922e346e F src/sqlite.h.in a5e0d6bd47e67aabf1475986d36bdcc7bfa9e06566790ebf8e3aa7fa551c9f99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 01eb85e4f2759a5ee79c183f4b2877889d4ffdc49d27ae74529c9579e3c8c0ef @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9282bcde301cee2a5c3c068b5b0b7ce992c155ece894413a6a9a51a81e4133fd -R 85600e55f5465c0d7b90f18f16da5617 +P 38d9dbca166078013a44214c88805fc7cca578976ceed9fc62f5159a38ec96a7 +R e7948e84541b04c653db4c07ea64a3d2 U larrybr -Z 49bd76acfcc3b273011e69ab0fa8281f +Z de2e0419e48292104e905a3447c66b63 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f826775084..95e710345f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -38d9dbca166078013a44214c88805fc7cca578976ceed9fc62f5159a38ec96a7 \ No newline at end of file +bff9153ceedcc7be77f2daf5139fee29c2fab742ff1fce49877965423a7d4be3 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 430d9e1640..c15d2e54d4 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8534,7 +8534,7 @@ static int do_meta_command(char *zLine, ShellState *p){ while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } - zSql = sqlite3_mprintf("SELECT * FROM %s.\"%w\"", zSchema, zTable); + zSql = sqlite3_mprintf("SELECT * FROM \"%w\".\"%w\"", zSchema, zTable); if( zSql==0 ){ import_cleanup(&sCtx); shell_out_of_memory(); @@ -8543,7 +8543,8 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ - char *zCreate = sqlite3_mprintf("CREATE TABLE %s.\"%w\"", zSchema,zTable); + char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", + zSchema, zTable); char cSep = '('; while( xRead(&sCtx) ){ zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); @@ -8562,14 +8563,14 @@ static int do_meta_command(char *zLine, ShellState *p){ utf8_printf(p->out, "%s\n", zCreate); } rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); if( rc ){ - utf8_printf(stderr, "CREATE TABLE %s.\"%s\"(...) failed: %s\n", - zSchema, zTable, sqlite3_errmsg(p->db)); + utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); + sqlite3_free(zCreate); import_cleanup(&sCtx); rc = 1; goto meta_command_exit; } + sqlite3_free(zCreate); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } sqlite3_free(zSql); @@ -8589,7 +8590,7 @@ static int do_meta_command(char *zLine, ShellState *p){ import_cleanup(&sCtx); shell_out_of_memory(); } - sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s.\"%w\" VALUES(?", + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", zSchema, zTable); j = strlen30(zSql); for(i=1; i Date: Fri, 14 Jan 2022 21:34:49 +0000 Subject: [PATCH 143/148] Fix a NEVER() in the byte-code engine that can sometimes be true. Test case in TH3. FossilOrigin-Name: 7ac91b5339f820f49b0eb52055d42b6a55905444883426caf792fada63079516 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b4ad6e2287..12c4a5ee53 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C For\s.import\sschema,\squote\sit\sas\sfor\sother\sidentifiers. -D 2022-01-14T16:29:45.154 +C Fix\sa\sNEVER()\sin\sthe\sbyte-code\sengine\sthat\scan\ssometimes\sbe\strue.\nTest\scase\sin\sTH3. +D 2022-01-14T21:34:49.566 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -623,7 +623,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 89e51820bcb468ff3877a8d942f5cc807208087f021227e0927693e928a195bc F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c 23116cc5d99ada73e8e11addabc380c27758688a16d84d0efa6dbe94c1293a4f +F src/vdbe.c 93b2403c28a9b902da1bc4dff82350c72eeb982976c95afca32b660a2dd33273 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h d89d5d2150500cfb08615329fd20aea9d746bba5f2c3ecb8a17e2d2d9be029e5 F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 38d9dbca166078013a44214c88805fc7cca578976ceed9fc62f5159a38ec96a7 -R e7948e84541b04c653db4c07ea64a3d2 -U larrybr -Z de2e0419e48292104e905a3447c66b63 +P bff9153ceedcc7be77f2daf5139fee29c2fab742ff1fce49877965423a7d4be3 +R 2f1d0218c0e4dfbf854acd661cc4df02 +U drh +Z e916f24e97798ecb1bcf0d0b63bac360 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 95e710345f..f780ba0e83 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bff9153ceedcc7be77f2daf5139fee29c2fab742ff1fce49877965423a7d4be3 \ No newline at end of file +7ac91b5339f820f49b0eb52055d42b6a55905444883426caf792fada63079516 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 1347ee9a52..015acfc0f0 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2160,7 +2160,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); - if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str; + if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str; } if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn3->flags & MEM_Int ); From ddbb3cb5ec7a2d4e74e45f12c884a039790ca427 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 14 Jan 2022 23:28:11 +0000 Subject: [PATCH 144/148] Remove code from lemon.c that was made superfluous by [1b22b42e59793af1|check-in 1b22b42e59793af1] in late 2017. FossilOrigin-Name: 6d2f95a474a0c196f36317d88557bfb449ce125c1d012fc1844378c450697a05 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lemon.c | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 12c4a5ee53..8a89d2047f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sNEVER()\sin\sthe\sbyte-code\sengine\sthat\scan\ssometimes\sbe\strue.\nTest\scase\sin\sTH3. -D 2022-01-14T21:34:49.566 +C Remove\scode\sfrom\slemon.c\sthat\swas\smade\ssuperfluous\sby\n[1b22b42e59793af1|check-in\s1b22b42e59793af1]\sin\slate\s2017. +D 2022-01-14T23:28:11.398 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1856,7 +1856,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5 F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c 258881835bd5bccd0c74fb110fe54244ff18e8e7ef3d949cbdab7187f02132bb +F tool/lemon.c 1c5a14f6044193e42864c36de48359026fa2cdcf205a43cc1a31116101e27258 F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bff9153ceedcc7be77f2daf5139fee29c2fab742ff1fce49877965423a7d4be3 -R 2f1d0218c0e4dfbf854acd661cc4df02 +P 7ac91b5339f820f49b0eb52055d42b6a55905444883426caf792fada63079516 +R ff666181f2a85a04957bd203bbe88b01 U drh -Z e916f24e97798ecb1bcf0d0b63bac360 +Z 853e6d43a6efc62c14e9df65e39f1443 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f780ba0e83..7fa604a86b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ac91b5339f820f49b0eb52055d42b6a55905444883426caf792fada63079516 \ No newline at end of file +6d2f95a474a0c196f36317d88557bfb449ce125c1d012fc1844378c450697a05 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index d4e157a1cd..11e25c8a1c 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -4290,7 +4290,6 @@ void ReportTable( int sqlFlag /* Generate the *.sql file too */ ){ FILE *out, *in, *sql; - char line[LINESIZE]; int lineno; struct state *stp; struct action *ap; @@ -4765,7 +4764,6 @@ void ReportTable( /* Generate a table containing the symbolic name of every symbol */ for(i=0; insymbol; i++){ - lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); From 72e30421c89695319fa43de906a70ff862fcfe89 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 16 Jan 2022 15:15:39 +0000 Subject: [PATCH 145/148] Fix ALTER TABLE so that it works even when compiled using -DSQLITE_DQS=0. [forum:/forumpost/3c1a00b66fca81fe|Forum post 3c1a00b66fca81fe]. FossilOrigin-Name: 092ad64faa4ae93b1e09ccd52159621d619e6817bcb4573331e9053d97f731fd --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/alter.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8a89d2047f..ee75ef3514 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\scode\sfrom\slemon.c\sthat\swas\smade\ssuperfluous\sby\n[1b22b42e59793af1|check-in\s1b22b42e59793af1]\sin\slate\s2017. -D 2022-01-14T23:28:11.398 +C Fix\sALTER\sTABLE\sso\sthat\sit\sworks\seven\swhen\scompiled\susing\s-DSQLITE_DQS=0.\n[forum:/forumpost/3c1a00b66fca81fe|Forum\spost\s3c1a00b66fca81fe]. +D 2022-01-16T15:15:39.462 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -484,7 +484,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 16f8d91b1e4b3e6d897a5fa510c8dc1b07608271035a5dd8406bc98f651a40dc +F src/alter.c 67ef8e685f547038b7ad93a7c6571f790d0a5bb1c00632d5466ffb4ccf3ee6e8 F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516 F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7ac91b5339f820f49b0eb52055d42b6a55905444883426caf792fada63079516 -R ff666181f2a85a04957bd203bbe88b01 +P 6d2f95a474a0c196f36317d88557bfb449ce125c1d012fc1844378c450697a05 +R edf422449e950a9b96ca2ad2b3d1f178 U drh -Z 853e6d43a6efc62c14e9df65e39f1443 +Z 5c0bbd29d71814fcf121ab4dcce9c42d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 7fa604a86b..81200ecd82 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6d2f95a474a0c196f36317d88557bfb449ce125c1d012fc1844378c450697a05 \ No newline at end of file +092ad64faa4ae93b1e09ccd52159621d619e6817bcb4573331e9053d97f731fd \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index f76a59dea6..f3f4f570e6 100644 --- a/src/alter.c +++ b/src/alter.c @@ -450,7 +450,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ " THEN raise(ABORT,'CHECK constraint failed')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" - " FROM pragma_quick_check(\"%w\",\"%w\")" + " FROM pragma_quick_check(%Q,%Q)" " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'", zTab, zDb ); From 7d44b22d45a55a2783a32e67d5bd4487fcb4d00c Mon Sep 17 00:00:00 2001 From: drh <> Date: Sun, 16 Jan 2022 19:11:13 +0000 Subject: [PATCH 146/148] Fix test cases so that they all still work even with -DSQLITE_DQS=0. FossilOrigin-Name: 4883776669ee2f2310ea82b0d6df4d008eebaa7cb252102539cf21a635402ebb --- ext/fts5/test/fts5eb.test | 2 +- ext/fts5/test/fts5integrity.test | 4 +- ext/rtree/rtreeA.test | 6 +-- ext/rtree/rtreecheck.test | 4 +- ext/session/session8.test | 2 +- manifest | 76 ++++++++++++++++---------------- manifest.uuid | 2 +- test/altercol.test | 2 + test/alterqf.test | 4 ++ test/check.test | 4 ++ test/collate1.test | 1 + test/ctime.test | 1 + test/eval.test | 2 +- test/expr.test | 1 + test/fts3aj.test | 20 ++++----- test/fts3ak.test | 26 +++++------ test/fts3corrupt.test | 2 +- test/fts4noti.test | 4 +- test/func.test | 14 +++--- test/fuzz-oss1.test | 2 + test/in.test | 5 ++- test/index.test | 2 +- test/join.test | 1 + test/misc1.test | 2 +- test/quote.test | 1 + test/select6.test | 1 - test/subquery.test | 2 +- test/swarmvtab.test | 12 ++--- test/tkt-7bbfb7d442.test | 2 +- test/tkt3442.test | 1 + test/tkt3841.test | 1 + test/update.test | 2 +- test/utf16align.test | 1 + test/vtab6.test | 1 + test/window6.test | 1 + 35 files changed, 117 insertions(+), 97 deletions(-) diff --git a/ext/fts5/test/fts5eb.test b/ext/fts5/test/fts5eb.test index 9d6f251ed1..ce40e471aa 100644 --- a/ext/fts5/test/fts5eb.test +++ b/ext/fts5/test/fts5eb.test @@ -83,7 +83,7 @@ for {set i 0} {$i < 255} {incr i} { do_execsql_test 3.0 { CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61'); - INSERT INTO e1 VALUES ("just a few words with a / inside"); + INSERT INTO e1 VALUES ('just a few words with a / inside'); } do_execsql_test 3.1 { SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank; diff --git a/ext/fts5/test/fts5integrity.test b/ext/fts5/test/fts5integrity.test index d922ad3b86..4038830861 100644 --- a/ext/fts5/test/fts5integrity.test +++ b/ext/fts5/test/fts5integrity.test @@ -188,11 +188,11 @@ foreach {tn pgsz} { INSERT INTO hh(hh, rank) VALUES('pgsz', $pgsz); WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999) - INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1) + INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1) FROM s; WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999) - INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1) + INSERT INTO hh SELECT printf('%.3d%.3d%.3d %.3d%.3d%.3d',i,i,i,i+1,i+1,i+1) FROM s; INSERT INTO hh(hh) VALUES('optimize'); diff --git a/ext/rtree/rtreeA.test b/ext/rtree/rtreeA.test index 921ba0b510..301cd4fc62 100644 --- a/ext/rtree/rtreeA.test +++ b/ext/rtree/rtreeA.test @@ -165,7 +165,7 @@ do_corruption_tests rtreeA-3.1 { } do_execsql_test rtreeA-3.1.0.3 { - SELECT rtreecheck('main', 't1')!="ok" + SELECT rtreecheck('main', 't1')!='ok' } {1} do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000} @@ -221,7 +221,7 @@ do_corruption_tests rtreeA-5.1 { } do_execsql_test rtreeA-5.2 { - SELECT rtreecheck('main', 't1')!="ok" + SELECT rtreecheck('main', 't1')!='ok' } {1} #------------------------------------------------------------------------- @@ -238,7 +238,7 @@ do_corruption_tests rtreeA-6.1 { } do_execsql_test rtreeA-6.2 { - SELECT rtreecheck('main', 't1')!="ok" + SELECT rtreecheck('main', 't1')!='ok' } {1} #------------------------------------------------------------------------- diff --git a/ext/rtree/rtreecheck.test b/ext/rtree/rtreecheck.test index 545f4478a9..17f359aa8a 100644 --- a/ext/rtree/rtreecheck.test +++ b/ext/rtree/rtreecheck.test @@ -117,13 +117,13 @@ sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { BEGIN; UPDATE r2_node SET data = X'123456'; - SELECT rtreecheck('r2')!="ok"; + SELECT rtreecheck('r2')!='ok'; } {1} do_execsql_test 3.3 { ROLLBACK; UPDATE r2_node SET data = X'00001234'; - SELECT rtreecheck('r2')!="ok"; + SELECT rtreecheck('r2')!='ok'; } {1} do_execsql_test 4.0 { diff --git a/ext/session/session8.test b/ext/session/session8.test index 9f70fe2829..884da0e775 100644 --- a/ext/session/session8.test +++ b/ext/session/session8.test @@ -63,7 +63,7 @@ proc do_then_undo {tn sql} { do_execsql_test 1.1 { CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 2); - INSERT INTO t1 VALUES("abc", "xyz"); + INSERT INTO t1 VALUES('abc', 'xyz'); } do_then_undo 1.2 { INSERT INTO t1 VALUES(3, 4); } do_then_undo 1.3 { DELETE FROM t1 WHERE b=2; } diff --git a/manifest b/manifest index ee75ef3514..1ba1d89134 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sALTER\sTABLE\sso\sthat\sit\sworks\seven\swhen\scompiled\susing\s-DSQLITE_DQS=0.\n[forum:/forumpost/3c1a00b66fca81fe|Forum\spost\s3c1a00b66fca81fe]. -D 2022-01-16T15:15:39.462 +C Fix\stest\scases\sso\sthat\sthey\sall\sstill\swork\seven\swith\s-DSQLITE_DQS=0. +D 2022-01-16T19:11:13.524 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -170,7 +170,7 @@ F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3 F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e F ext/fts5/test/fts5doclist.test faa9e9cc3c0645fa6203667cb5f007c359447c6ee66753f71a58175c2497cacd F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0 -F ext/fts5/test/fts5eb.test 239bb2f02571f8cccfc7018d08f502df1cd8cc6a69b65ed1dde5f6a070e3f669 +F ext/fts5/test/fts5eb.test a973baadac524dbbb4ad9b0e99030e12cabde2c6b28e0ac437298007b642cd12 F ext/fts5/test/fts5fault1.test d28a65caee75db6897c3cf1358c5230d3bb2a3bf7fb31062c19c7e5382b3d2bd F ext/fts5/test/fts5fault2.test 69c8fdbef830cd0d450908d4504d5bb86609e255af99c421c20a0756251fe344 F ext/fts5/test/fts5fault3.test da2f9e3e56ff5740d68ebdd6877c97089e7ed28ddff28a0da87a6afea27e5522 @@ -188,7 +188,7 @@ F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b99 F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717 F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f -F ext/fts5/test/fts5integrity.test e387b2bd1c83e50f4a12f58a5fd399111bbab36be2f1c9fd5bb974be08a32de6 +F ext/fts5/test/fts5integrity.test 62147a1e85405b986691177e0312be5a64ec9e67b17994e83892d9afa6247600 F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227 F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28 F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad @@ -406,7 +406,7 @@ F ext/rtree/rtree6.test 9ce3691c1aac43070a9f194f0ebf54372db346c5a82241fd11b525ed F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5 F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e F ext/rtree/rtree9.test fd3c9384ef8aabbc127b3878764070398f136eebc551cd20484b570f2cc1956a -F ext/rtree/rtreeA.test c0d8e91e25052d5f3fbda17632ca843b82ca13c4181fb6000a0d63bd2d7e70ce +F ext/rtree/rtreeA.test a7fd235d8194115fa2e14d300337931eb2e960fe8a46cdfb66add2206412ea41 F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9 F ext/rtree/rtreeC.test c4bfa9a61c6788c03e4a9ce40ab2cfc6100982559effd9842d1b658e1d47aa5f F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc @@ -417,7 +417,7 @@ F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7 F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed -F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35 +F ext/rtree/rtreecheck.test 1f542257f21c8a22ce3462c852ec1a0847fa8b3133053abfab3972764210e8bc F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9 @@ -439,7 +439,7 @@ F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479 F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169 F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926 -F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b +F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904 F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c @@ -656,7 +656,7 @@ F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680f F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d -F test/altercol.test b11fa1b131e80ab5b6ecfb3b725fb0419c14ca6efba5adb57aeabfc9baa0c8f3 +F test/altercol.test 9471187fe155d9c4211ae185e104ff48ce8f114262ee1256cf1e110b339c725f F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12 F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41 @@ -665,7 +665,7 @@ F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e2 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test ca3ebc01670d9313953a2b7628d8cc00dc5ea9988f229b3cbbbe1cca506dae45 F test/altermalloc3.test 4660ac6240a8c82ba3947b927612dcc7c05a8eec3fe3c9f38e047ca69a789a33 -F test/alterqf.test 6b2482a957692606b23567ebd2cf80eb773e3c826086f5f151eee9c5a962623d +F test/alterqf.test 3008318ba9e16b4ac0b5f83cf7683caa4b0a3154aafe3b4099838a250d4ba74a F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912 F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b F test/altertab3.test 5929f522fd6fd708396ad9f317d4af9ff1a93e460df85bb1d54d4499eeb94960 @@ -766,13 +766,13 @@ F test/carray01.test d55d57bf66b1af1c7ac55fae66ff4910884a8f5d21a90a18797ce386212 F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b -F test/check.test 4a2a91ed67eee84a6be16057c48d5198b6fb24849cd6da6cd855981de3fbb416 +F test/check.test 56e4ed457e9f8683b9fc56f5b964f461f6e8a8dd5a13f3d495408215d66419ed F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014 F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760 F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 -F test/collate1.test 532b4992f78e91dd80c2e3c7bd944fada8cbe3d6c0ded0b20f7182b4dfca0006 +F test/collate1.test 71a6f27fdc93a92f14d8ab80c05e1937656a5a03197e1a10157314554d630ce8 F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5 F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd @@ -830,7 +830,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165 F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c F test/csv01.test c9c3af0d58c34e9ac970c5875a77939edb958762c8aafb95409e19a3f088b6cd -F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3 +F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c4773 F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614c7fe201 F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8 @@ -890,12 +890,12 @@ F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6 F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020 F test/eqp.test bfe979eb1f4b8ab7a3bd7db6d16c2e6c6be0e5a3aada2227716f3fd3a9d76b69 F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9 -F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c +F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0 F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650bf0747 F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac -F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf +F test/expr.test e1afcdb1038e4d3fa67a3df323347c38750946e2e1b4e385bdc75d26284f2dac F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8 F test/exprfault.test 497cc0b8fe6a677f49b55cb485e040f709ec2834b84f25912fe9c2dfeeda33db F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 @@ -965,8 +965,8 @@ F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c F test/fts3ag.test c003672a215124df7fc6000036d896f498b26b53 F test/fts3ah.test dc9f66c32c296f1bc8bcc4535126bddfeca62894 F test/fts3ai.test 24058fdc6e9e5102c1fd8459591b114b6a85d285 -F test/fts3aj.test 0ed71e1dd9b03b843a857dc3eb9b15630e0104fc -F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d +F test/fts3aj.test 1560a7ce5642dc887e8ecfcc4693bcfce1dbb3d1771a735c845f0061e525deb2 +F test/fts3ak.test 36ea92f609efb390cf018cdb5d389c12e62b650abe31cfc88261b252daf88174 F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 @@ -979,7 +979,7 @@ F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd4 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b -F test/fts3corrupt.test 79a32ffdcd5254e2f7fa121d9656e61949ad049c3c6554229911b7ceac37c9c6 +F test/fts3corrupt.test 43c6c89b994e90997590ece4dfa9c9325c9b61cddd7c97e158498da8b1de79f8 F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f F test/fts3corrupt4.test 799ff994b964fed7201be6b6b62c7ff2ef7bb3da6c02b9eaf0d96a5a4d9b6ca3 @@ -1037,7 +1037,7 @@ F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4merge5.test 69932d85cda8a1c4dcfb742865900ed8fbda51724b8cf9a45bbe226dfd06c596 F test/fts4min.test 1c11e4bde16674a0c795953509cbc3731a7d9cbd1ddc7f35467bf39d632d749f -F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 +F test/fts4noti.test d5d933705b1b1516b67a5e3f8e514ecb19c6522fb3357bb744776d48427c2292 F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7 F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb @@ -1046,14 +1046,14 @@ F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f75 F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9 F test/fts4upfrom.test f25835162c989dffd5e2ef91ec24c4848cc9973093e2d492d1c7b32afac1b49d F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test 0a305e88a4fbdce6be8c6f4863d6dab9ecb2975b95e94734621e2c900779b712 +F test/func.test 4be8bed4be235e333f1e0ea31e32f5be3c9f456c30780363e7fcb15e3ff3e6bc F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 600a632c305a88f3946d38f9a51efe145c989b2e13bd2b2a488db47fe76bab6a F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31 F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c -F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa +F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0 F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 @@ -1083,7 +1083,7 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8 F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1 F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 -F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3 +F test/in.test 15de58ee017f43d36390812e9a51217d1b2db7758f97d0df48296ef178ea560b F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test fdd1d8134da8376985c2edba6035a2de1f6c731524d2ffa651419e8fe2cd1c5a @@ -1100,7 +1100,7 @@ F test/incrvacuum.test 3fa6145f5e71f603554fd7b8ec3da4290b1341029682313285cb5f9e1 F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635 -F test/index.test a2e948ed949e575487b5c1d521767d4584ac42d352f2dcd8e48004638e7bc7dc +F test/index.test d866054c88b394fd42cbf2825628f127ca24dfac525fa019069a936674d92cbe F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 @@ -1135,7 +1135,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9 -F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238 +F test/join.test 25cf0ac11c3b81fedfd166f9062166bdb39dea92f5a7c16cacbf6dc1f7f67020 F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 @@ -1213,7 +1213,7 @@ F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87 -F test/misc1.test e3fa5732080cc9a2b77bd5dd4ebb55bd6785b02565f8806092686b83ac58d600 +F test/misc1.test 294c97185354030c4ce40e7141b72f7a589585f2a44b666825381eb3df98f07c F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350 F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e @@ -1300,7 +1300,7 @@ 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 f33f95990e4032d1227b98c0ef314c0a077d162f3f2e61b3039ed69e6f8adbbf +F test/quote.test ffb40f0eb7a25c1d8cfe11ee2fe67f8e85fbf3fed348810834114be1fdada142 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 @@ -1357,7 +1357,7 @@ F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b F test/select5.test 8afc5e5dcdebc2be54472e73ebd9cd1adef1225fd15d37a1c62f969159f390ae -F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801 +F test/select6.test 9b2fb4ffedf52e1b5703cfcae1212e7a4a063f014c0458d78d29aca3db766d1f F test/select7.test f659f231489349e8c5734e610803d7654207318f F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d F test/select9.test f7586b207ce2304ab80dc93d3146469a28fd4403621dd3a82d06644563d3c812 @@ -1441,13 +1441,13 @@ F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b3594 F test/strict1.test a3ec495471f24c1a6e1a1664bd23e24ccdb27ae93b1a763ee1942ec955b68e71 F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070 F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49 -F test/subquery.test e6fb2ad0a7e5a58cd1619b3e8354484195d6b4473f1cb60b7d2cbf78f501e951 +F test/subquery.test 3a1a5b600b8d4f504d2a2c61f33db820983dba94a0ef3e4aedca8f0165eaecb8 F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12 F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303 F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8 F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 -F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf +F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e1e8e26 F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c F test/swarmvtab3.test 247aa38b6ebd2b99db2075847ae47e789ac34f1c2ab5c720dfcffd990004c544 F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95 @@ -1509,7 +1509,7 @@ F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336 F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf F test/tkt-78e04e52ea.test b731f2ab7d1c2482ac5152097da02ef4805a45147ba9498d3cd9da27072f34d1 F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f -F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18 +F test/tkt-7bbfb7d442.test e87b59e620700b5a52ecd92f05d56686c1cad9e1aa17456eada55e0bb821b698 F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8 F test/tkt-80e031a00f.test 9ee36348b761bf7c14261e002b75a4c0d5a04d4c F test/tkt-8454a207b9.test aff2e76143cfa443ddce6f7d85968a2e9b57a3deb0b881b730120740555f9e2f @@ -1592,7 +1592,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812 -F test/tkt3442.test 6287173de5bb2d43693b1f822426018a209f9df49ce2f454808bac1771852330 +F test/tkt3442.test c9d95b4c8f4f35a51b523f35d2afd0ce124937812af296545ad551ff763504fd F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2 F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19 F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218 @@ -1616,7 +1616,7 @@ F test/tkt3810.test 3a3be9965d1861bd84019875851ad5ea90fd8d76b638361514a36a48ea53 F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0 F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4 -F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f +F test/tkt3841.test c4be3870f777f82aa788a588e40b4fb6627c3874e19f336d0d92894f929ffbfe F test/tkt3871.test d921703d07c68f4fd5312073215a17fa34b0401d F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90 F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633 @@ -1672,7 +1672,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2 F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2 -F test/update.test ef3ebbafeb4be5c96db831f40796e2e77ee846da5ee8b61cfedb1ff1b9e0cc23 +F test/update.test eb7f4eb172ce270e51bb67d7867521f33a63635bb671e261bbafccaef3bd6db2 F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3 F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041 F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1 @@ -1688,7 +1688,7 @@ F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018d F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568 F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7 F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9 -F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae +F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da F test/vacuum-into.test f0b8c091df5305728b6973e9cce4166c861955b650dd3c599cb045d7160d3971 F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520 @@ -1706,7 +1706,7 @@ F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c840 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391 -F test/vtab6.test 8e789f526e6594cf7ae933d1adee0caa87dc9f78 +F test/vtab6.test 82d5bb8fd3c0643102c1209e9ea353b168b7eb9c8db4406ab2ee2cbbdaead62c F test/vtab7.test 70c6f4a1d6177144a8236e4172d5fba92e683440374664ad1f04851fbb335d3c F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b @@ -1800,7 +1800,7 @@ F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856e F test/window4.tcl 6f85307eb67242b654d051f7da32a996a66aee039a09c5ae358541aa61720742 F test/window4.test fbead87f681400ac07ef3555e0488b544a47d35491f8bf09a7474b6f76ce9b4e F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e -F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32 +F test/window6.test 311de885bd7e453134fa6747680bfb4a1be87c91720bf58703db945891e7d30b F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6d2f95a474a0c196f36317d88557bfb449ce125c1d012fc1844378c450697a05 -R edf422449e950a9b96ca2ad2b3d1f178 +P 092ad64faa4ae93b1e09ccd52159621d619e6817bcb4573331e9053d97f731fd +R 3f20ad9a9f1d809380bd91f8dd5db646 U drh -Z 5c0bbd29d71814fcf121ab4dcce9c42d +Z f5dfc5249ab1cb55ce73ad103fb81155 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 81200ecd82..6addecdf0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -092ad64faa4ae93b1e09ccd52159621d619e6817bcb4573331e9053d97f731fd \ No newline at end of file +4883776669ee2f2310ea82b0d6df4d008eebaa7cb252102539cf21a635402ebb \ No newline at end of file diff --git a/test/altercol.test b/test/altercol.test index d0c5c40ea6..10ff9e773f 100644 --- a/test/altercol.test +++ b/test/altercol.test @@ -838,6 +838,8 @@ do_execsql_test 22.0 { #------------------------------------------------------------------------- # reset_db +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test 22.0 { CREATE TABLE t1(a, b); CREATE INDEX x1 on t1("c"=b); diff --git a/test/alterqf.test b/test/alterqf.test index 6a89641865..400c4b6e79 100644 --- a/test/alterqf.test +++ b/test/alterqf.test @@ -25,6 +25,8 @@ ifcapable !altertable { sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); @@ -89,6 +91,8 @@ foreach {tn before after} { #------------------------------------------------------------------------- reset_db +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test 2.0 { CREATE TABLE x1( one, two, three, PRIMARY KEY(one), diff --git a/test/check.test b/test/check.test index 94fe1d14e4..10d1cf4be6 100644 --- a/test/check.test +++ b/test/check.test @@ -21,6 +21,8 @@ ifcapable !check { finish_test return } +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_test check-1.1 { execsql { @@ -138,6 +140,8 @@ do_test check-2.2 { } {1 2.2 three} db close sqlite3 db test.db +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_test check-2.3 { execsql { INSERT INTO t2 VALUES(NULL, NULL, NULL); diff --git a/test/collate1.test b/test/collate1.test index 007dd7c370..b65b850474 100644 --- a/test/collate1.test +++ b/test/collate1.test @@ -338,6 +338,7 @@ do_test collate1-5.3 { #------------------------------------------------------------------------- # Fix problems with handling collation sequences named '"""'. # +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test 6.1 { SELECT """"""""; } {\"\"\"} diff --git a/test/ctime.test b/test/ctime.test index 1f07c1a947..26b2fa2ee2 100644 --- a/test/ctime.test +++ b/test/ctime.test @@ -81,6 +81,7 @@ ifcapable threadsafe2 { # SQLITE_THREADSAFE should pretty much always be defined # one way or the other, and it must have a value of 0 or 1. +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_test ctime-1.4.1 { catchsql { SELECT sqlite_compileoption_used('SQLITE_THREADSAFE'); diff --git a/test/eval.test b/test/eval.test index 360d158f3c..159e8754dc 100644 --- a/test/eval.test +++ b/test/eval.test @@ -81,7 +81,7 @@ do_test eval-3.1 { } {1 {} 102 2 {} 103 3 {} 104 4 {} 105} do_test eval-4.1 { - execsql { SELECT test_eval('SELECT "abcdefghij"') } + execsql { SELECT test_eval('SELECT ''abcdefghij''') } } {abcdefghij} finish_test diff --git a/test/expr.test b/test/expr.test index ec5c55c2e4..c64b6cb706 100644 --- a/test/expr.test +++ b/test/expr.test @@ -970,6 +970,7 @@ do_realnum_test expr-13.7 { } } {9.22337203685478e+18} +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test expr-13.8 { SELECT "" <= ''; } {1} diff --git a/test/fts3aj.test b/test/fts3aj.test index f3d46f2ad8..0c89691162 100644 --- a/test/fts3aj.test +++ b/test/fts3aj.test @@ -6,8 +6,6 @@ # This file implements regression tests for SQLite library. This # tests creating fts3 tables in an attached database. # -# $Id: fts3aj.test,v 1.1 2007/08/20 17:38:42 shess Exp $ -# set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -25,14 +23,14 @@ sqlite3 db2 test2.db db eval { CREATE VIRTUAL TABLE t3 USING fts3(content); - INSERT INTO t3 (rowid, content) VALUES(1, "hello world"); + INSERT INTO t3 (rowid, content) VALUES(1, 'hello world'); } db2 eval { CREATE VIRTUAL TABLE t1 USING fts3(content); - INSERT INTO t1 (rowid, content) VALUES(1, "hello world"); - INSERT INTO t1 (rowid, content) VALUES(2, "hello there"); - INSERT INTO t1 (rowid, content) VALUES(3, "cruel world"); + INSERT INTO t1 (rowid, content) VALUES(1, 'hello world'); + INSERT INTO t1 (rowid, content) VALUES(2, 'hello there'); + INSERT INTO t1 (rowid, content) VALUES(3, 'cruel world'); } # This has always worked because the t1_* tables used by fts3 will be @@ -56,9 +54,9 @@ do_test fts3aj-1.2 { execsql { ATTACH DATABASE 'test2.db' AS two; CREATE VIRTUAL TABLE two.t2 USING fts3(content); - INSERT INTO t2 (rowid, content) VALUES(1, "hello world"); - INSERT INTO t2 (rowid, content) VALUES(2, "hello there"); - INSERT INTO t2 (rowid, content) VALUES(3, "cruel world"); + INSERT INTO t2 (rowid, content) VALUES(1, 'hello world'); + INSERT INTO t2 (rowid, content) VALUES(2, 'hello there'); + INSERT INTO t2 (rowid, content) VALUES(3, 'cruel world'); SELECT rowid FROM t2 WHERE t2 MATCH 'hello'; DETACH DATABASE two; } @@ -74,8 +72,8 @@ do_test fts3aj-1.3 { ATTACH DATABASE 'test2.db' AS two; CREATE VIRTUAL TABLE two.t3 USING fts3(content); - INSERT INTO two.t3 (rowid, content) VALUES(2, "hello there"); - INSERT INTO two.t3 (rowid, content) VALUES(3, "cruel world"); + INSERT INTO two.t3 (rowid, content) VALUES(2, 'hello there'); + INSERT INTO two.t3 (rowid, content) VALUES(3, 'cruel world'); SELECT rowid FROM two.t3 WHERE t3 MATCH 'hello'; DETACH DATABASE two; diff --git a/test/fts3ak.test b/test/fts3ak.test index a263f0b740..080efe52b5 100644 --- a/test/fts3ak.test +++ b/test/fts3ak.test @@ -21,17 +21,17 @@ ifcapable !fts3 { db eval { CREATE VIRTUAL TABLE t1 USING fts3(content); - INSERT INTO t1 (rowid, content) VALUES(1, "hello world"); - INSERT INTO t1 (rowid, content) VALUES(2, "hello there"); - INSERT INTO t1 (rowid, content) VALUES(3, "cruel world"); + INSERT INTO t1 (rowid, content) VALUES(1, 'hello world'); + INSERT INTO t1 (rowid, content) VALUES(2, 'hello there'); + INSERT INTO t1 (rowid, content) VALUES(3, 'cruel world'); } # Test that possibly-buffered inserts went through after commit. do_test fts3ak-1.1 { execsql { BEGIN TRANSACTION; - INSERT INTO t1 (rowid, content) VALUES(4, "false world"); - INSERT INTO t1 (rowid, content) VALUES(5, "false door"); + INSERT INTO t1 (rowid, content) VALUES(4, 'false world'); + INSERT INTO t1 (rowid, content) VALUES(5, 'false door'); COMMIT TRANSACTION; SELECT rowid FROM t1 WHERE t1 MATCH 'world'; } @@ -42,8 +42,8 @@ do_test fts3ak-1.1 { do_test fts3ak-1.2 { execsql { BEGIN TRANSACTION; - INSERT INTO t1 (rowid, content) VALUES(6, "another world"); - INSERT INTO t1 (rowid, content) VALUES(7, "another test"); + INSERT INTO t1 (rowid, content) VALUES(6, 'another world'); + INSERT INTO t1 (rowid, content) VALUES(7, 'another test'); SELECT rowid FROM t1 WHERE t1 MATCH 'world'; COMMIT TRANSACTION; } @@ -54,8 +54,8 @@ do_test fts3ak-1.2 { do_test fts3ak-1.3 { execsql { BEGIN TRANSACTION; - INSERT INTO t1 (rowid, content) VALUES(8, "second world"); - INSERT INTO t1 (rowid, content) VALUES(9, "second sight"); + INSERT INTO t1 (rowid, content) VALUES(8, 'second world'); + INSERT INTO t1 (rowid, content) VALUES(9, 'second sight'); SELECT rowid FROM t1 WHERE t1 MATCH 'world'; ROLLBACK TRANSACTION; } @@ -73,8 +73,8 @@ do_test fts3ak-1.4 { do_test fts3ak-1.5 { execsql { BEGIN TRANSACTION; - INSERT INTO t1 (rowid, content) VALUES(10, "second world"); - INSERT INTO t1 (rowid, content) VALUES(11, "second sight"); + INSERT INTO t1 (rowid, content) VALUES(10, 'second world'); + INSERT INTO t1 (rowid, content) VALUES(11, 'second sight'); ROLLBACK TRANSACTION; SELECT rowid FROM t1 WHERE t1 MATCH 'world'; } @@ -84,7 +84,7 @@ do_test fts3ak-1.5 { do_test fts3ak-1.6 { execsql { BEGIN; - INSERT INTO t1 (rowid, content) VALUES(12, "third world"); + INSERT INTO t1 (rowid, content) VALUES(12, 'third world'); COMMIT; SELECT rowid FROM t1 WHERE t1 MATCH 'third'; } @@ -95,7 +95,7 @@ do_test fts3ak-1.6 { do_test fts3ak-1.7 { execsql { BEGIN; - INSERT INTO t1 (rowid, content) VALUES(13, "third dimension"); + INSERT INTO t1 (rowid, content) VALUES(13, 'third dimension'); CREATE TABLE x (c); COMMIT; SELECT rowid FROM t1 WHERE t1 MATCH 'dimension'; diff --git a/test/fts3corrupt.test b/test/fts3corrupt.test index 828964b1bc..8b958db5fa 100644 --- a/test/fts3corrupt.test +++ b/test/fts3corrupt.test @@ -178,7 +178,7 @@ do_catchsql_test 6.10 { INSERT INTO f_segments (blockid) values (16); INSERT INTO f_segments values (0, x''); INSERT INTO f_stat VALUES (1,x'cf0f01'); - INSERT INTO f(f) VALUES ("merge=1"); + INSERT INTO f(f) VALUES ('merge=1'); } {1 {database disk image is malformed}} # 2020-03-02 https://bugs.chromium.org/p/chromium/issues/detail?id=1057441 diff --git a/test/fts4noti.test b/test/fts4noti.test index 6707203970..87a05714bf 100644 --- a/test/fts4noti.test +++ b/test/fts4noti.test @@ -173,7 +173,7 @@ do_execsql_test 6.1.1 { CREATE VIRTUAL TABLE t1 USING fts4( poiCategory, poiCategoryId, notindexed=poiCategoryId ); - INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021); + INSERT INTO t1(poiCategory, poiCategoryId) values ('Restaurant', 6021); } do_execsql_test 6.1.2 { @@ -194,7 +194,7 @@ do_execsql_test 6.2.1 { CREATE VIRTUAL TABLE t1 USING fts4( poiCategory, poiCategoryId, notindexed=poiCategory ); - INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021); + INSERT INTO t1(poiCategory, poiCategoryId) values ('Restaurant', 6021); } do_execsql_test 6.2.2 { diff --git a/test/func.test b/test/func.test index 008819baa5..df9d4dacfa 100644 --- a/test/func.test +++ b/test/func.test @@ -1007,32 +1007,32 @@ do_test func-21.2 { } {1 {wrong number of arguments to function replace()}} do_test func-21.3 { execsql { - SELECT typeof(replace("This is the main test string", NULL, "ALT")); + SELECT typeof(replace('This is the main test string', NULL, 'ALT')); } } {null} do_test func-21.4 { execsql { - SELECT typeof(replace(NULL, "main", "ALT")); + SELECT typeof(replace(NULL, 'main', 'ALT')); } } {null} do_test func-21.5 { execsql { - SELECT typeof(replace("This is the main test string", "main", NULL)); + SELECT typeof(replace('This is the main test string', 'main', NULL)); } } {null} do_test func-21.6 { execsql { - SELECT replace("This is the main test string", "main", "ALT"); + SELECT replace('This is the main test string', 'main', 'ALT'); } } {{This is the ALT test string}} do_test func-21.7 { execsql { - SELECT replace("This is the main test string", "main", "larger-main"); + SELECT replace('This is the main test string', 'main', 'larger-main'); } } {{This is the larger-main test string}} do_test func-21.8 { execsql { - SELECT replace("aaaaaaa", "a", "0123456789"); + SELECT replace('aaaaaaa', 'a', '0123456789'); } } {0123456789012345678901234567890123456789012345678901234567890123456789} @@ -1315,7 +1315,7 @@ do_test func-29.1 { CREATE TABLE t29(id INTEGER PRIMARY KEY, x, y); INSERT INTO t29 VALUES(1, 2, 3), (2, NULL, 4), (3, 4.5, 5); INSERT INTO t29 VALUES(4, randomblob(1000000), 6); - INSERT INTO t29 VALUES(5, "hello", 7); + INSERT INTO t29 VALUES(5, 'hello', 7); } db close sqlite3 db test.db diff --git a/test/fuzz-oss1.test b/test/fuzz-oss1.test index e77b7ed0f8..46feeb62eb 100644 --- a/test/fuzz-oss1.test +++ b/test/fuzz-oss1.test @@ -329,6 +329,8 @@ ifcapable !fts3 { db close forcedelete test.db sqlite3 db test.db +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_test fuzz-oss1-gnomeshell { db eval { CREATE TABLE Resource (ID INTEGER NOT NULL PRIMARY KEY, Uri TEXT NOT diff --git a/test/in.test b/test/in.test index efbfbd0379..b0eb371cb7 100644 --- a/test/in.test +++ b/test/in.test @@ -281,12 +281,13 @@ do_test in-7.8.2 { db status step } {0} -do_test in-8.1 { +do_test in-8.3 { execsql { SELECT b FROM t1 WHERE a IN ('hello','there') } } {world} -do_test in-8.2 { +do_test in-8.4 { + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 execsql { SELECT b FROM t1 WHERE a IN ("hello",'there') } diff --git a/test/index.test b/test/index.test index 15120a40c9..11d3d7191c 100644 --- a/test/index.test +++ b/test/index.test @@ -428,7 +428,7 @@ do_test index-13.1 { } {1 2.0 3} do_test index-13.2 { set ::idxlist [execsql { - SELECT name FROM sqlite_master WHERE type="index" AND tbl_name="t5"; + SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='t5'; }] llength $::idxlist } {3} diff --git a/test/join.test b/test/join.test index cb3ccc65d5..221dbdd098 100644 --- a/test/join.test +++ b/test/join.test @@ -439,6 +439,7 @@ do_test join-5.1 { # A test for ticket #247. # do_test join-7.1 { + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 execsql { CREATE TABLE t7 (x, y); INSERT INTO t7 VALUES ("pa1", 1); diff --git a/test/misc1.test b/test/misc1.test index 758d4082e0..b1b1b083c3 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -652,7 +652,7 @@ do_catchsql_test misc1-21.2 { # 2015-04-15 do_execsql_test misc1-22.1 { - SELECT ""+3 FROM (SELECT ""+5); + SELECT ''+3 FROM (SELECT ''+5); } {3} # 2015-04-19: NULL pointer dereference on a corrupt schema diff --git a/test/quote.test b/test/quote.test index 9810a3ca03..6d7b317ea1 100644 --- a/test/quote.test +++ b/test/quote.test @@ -173,6 +173,7 @@ ifcapable altertable { INSERT INTO t1 VALUES(1,2,3),(1,4,5); ALTER TABLE t1 DROP COLUMN b; } {1 {error in index x1 after drop column: no such column: b}} + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DDL 1 do_catchsql_test 3.5 { DROP TABLE t1; CREATE TABLE t1(a, b, c); diff --git a/test/select6.test b/test/select6.test index ef5c5b2f07..612afefa6f 100644 --- a/test/select6.test +++ b/test/select6.test @@ -169,7 +169,6 @@ do_test select6-3.2 { FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a, (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b WHERE a.q=b.s ORDER BY a.q) - ORDER BY "a.q" } } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20} do_test select6-3.3 { diff --git a/test/subquery.test b/test/subquery.test index e3b4281ede..a048f9ed4e 100644 --- a/test/subquery.test +++ b/test/subquery.test @@ -477,7 +477,7 @@ do_test subquery-5.1 { INSERT INTO t5 VALUES(3,33); INSERT INTO t5 VALUES(4,44); SELECT b FROM t5 WHERE a IN - (SELECT callcnt(y)+0 FROM t4 WHERE x="two") + (SELECT callcnt(y)+0 FROM t4 WHERE x='two') } } {22} do_test subquery-5.2 { diff --git a/test/swarmvtab.test b/test/swarmvtab.test index 9d2919bee1..b4b94487ac 100644 --- a/test/swarmvtab.test +++ b/test/swarmvtab.test @@ -209,8 +209,8 @@ db func fetch_db fetch_db do_catchsql_test 3.1 { CREATE VIRTUAL TABLE temp.xyz USING swarmvtab( 'VALUES - ("test.db1", "t1", 1, 10), - ("test.db2", "t1", 11, 20) + (''test.db1'', ''t1'', 1, 10), + (''test.db2'', ''t1'', 11, 20) ', 'fetch_db_no_such_function' ); } {1 {sql error: no such function: fetch_db_no_such_function}} @@ -218,8 +218,8 @@ do_catchsql_test 3.1 { do_catchsql_test 3.2 { CREATE VIRTUAL TABLE temp.xyz USING swarmvtab( 'VALUES - ("test.db1", "t1", 1, 10), - ("test.db2", "t1", 11, 20) + (''test.db1'', ''t1'', 1, 10), + (''test.db2'', ''t1'', 11, 20) ', 'fetch_db' ); } {1 {fetch_db error!}} @@ -233,8 +233,8 @@ do_execsql_test 3.3.1 { DETACH aux; CREATE VIRTUAL TABLE temp.xyz USING swarmvtab( 'VALUES - ("test.db1", "t1", 1, 10), - ("test.db2", "t1", 11, 20) + (''test.db1'', ''t1'', 1, 10), + (''test.db2'', ''t1'', 11, 20) ', 'fetch_db' ); } {} diff --git a/test/tkt-7bbfb7d442.test b/test/tkt-7bbfb7d442.test index 56d4caeb3e..c020b515e2 100644 --- a/test/tkt-7bbfb7d442.test +++ b/test/tkt-7bbfb7d442.test @@ -146,7 +146,7 @@ do_execsql_test 2.2 { } {31 10} do_execsql_test 2.3 { - SELECT CASE WHEN DeliveredQty=10 THEN "TEST PASSED!" ELSE "TEST FAILED!" END + SELECT CASE WHEN DeliveredQty=10 THEN 'TEST PASSED!' ELSE 'TEST FAILED!' END FROM InventoryControl WHERE SKU=31; } {{TEST PASSED!}} diff --git a/test/tkt3442.test b/test/tkt3442.test index 13d29a1b05..aaf2662398 100644 --- a/test/tkt3442.test +++ b/test/tkt3442.test @@ -38,6 +38,7 @@ do_test tkt3442-1.1 { # SELECT referenced in ticket #3442 (both '5000' and "5000") # and verify that the query plan is the same. # +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_eqp_test tkt3442-1.2 { SELECT node FROM listhash WHERE id='5000' LIMIT 1; } {SEARCH listhash USING INDEX ididx (id=?)} diff --git a/test/tkt3841.test b/test/tkt3841.test index df6de5c2f3..542c1bb5e7 100644 --- a/test/tkt3841.test +++ b/test/tkt3841.test @@ -22,6 +22,7 @@ ifcapable !subquery { return } +sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_test tkt3841.1 { execsql { CREATE TABLE table2 (key TEXT, x TEXT); diff --git a/test/update.test b/test/update.test index 7be360726f..66efd10ec8 100644 --- a/test/update.test +++ b/test/update.test @@ -627,7 +627,7 @@ ifcapable altertable { CREATE INDEX t15c ON t15(c); INSERT INTO t15(a,b) VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo'); - UPDATE t15 SET c=printf("y%d",a) WHERE c IS NULL; + UPDATE t15 SET c=printf('y%d',a) WHERE c IS NULL; SELECT a,b,c,'|' FROM t15 ORDER BY a; } {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |} } diff --git a/test/utf16align.test b/test/utf16align.test index f026d9575d..ef10bc659d 100644 --- a/test/utf16align.test +++ b/test/utf16align.test @@ -32,6 +32,7 @@ ifcapable !utf16 { do_test utf16align-1.0 { set unaligned_string_counter 0 add_alignment_test_collations [sqlite3_connection_pointer db] + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 execsql { PRAGMA encoding=UTF16; CREATE TABLE t1( diff --git a/test/vtab6.test b/test/vtab6.test index f4504b017d..ffbe430c6e 100644 --- a/test/vtab6.test +++ b/test/vtab6.test @@ -351,6 +351,7 @@ do_test vtab6-4.10 { # A test for ticket #247. # do_test vtab6-7.1 { + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 execsql { INSERT INTO t7 VALUES ("pa1", 1); INSERT INTO t7 VALUES ("pa2", NULL); diff --git a/test/window6.test b/test/window6.test index c6889c72ac..b5e677208f 100644 --- a/test/window6.test +++ b/test/window6.test @@ -148,6 +148,7 @@ do_execsql_test 5.5 { # ifcapable !icu { + sqlite3_db_config db SQLITE_DBCONFIG_DQS_DML 1 do_execsql_test 6.0 { SELECT LIKE('!', '', '!') x WHERE x; } {} From 5a6f818d84e6eecffbd25a212654392479eb22b6 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 17 Jan 2022 14:42:38 +0000 Subject: [PATCH 147/148] Never allow the b-tree layers view of the number of pages in the database file exceed the actual number of pages in the database file, even when PRAGMA writeable_schema=ON. This helps with earlier detection of corruption, and prevents excess memory usage and CPU cycles in some integrity_check ops. FossilOrigin-Name: 0407c8793700491b8519a649b9624f569b0e7e9b94d0db79d4a08139e0ecdb69 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 10 +++++++--- src/pager.c | 3 +-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 1ba1d89134..46a9aead13 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stest\scases\sso\sthat\sthey\sall\sstill\swork\seven\swith\s-DSQLITE_DQS=0. -D 2022-01-16T19:11:13.524 +C Never\sallow\sthe\sb-tree\slayers\sview\sof\sthe\snumber\sof\spages\sin\sthe\sdatabase\nfile\sexceed\sthe\sactual\snumber\sof\spages\sin\sthe\sdatabase\sfile,\seven\swhen\nPRAGMA\swriteable_schema=ON.\s\sThis\shelps\swith\searlier\sdetection\sof\scorruption,\nand\sprevents\sexcess\smemory\susage\sand\sCPU\scycles\sin\ssome\sintegrity_check\sops. +D 2022-01-17T14:42:38.524 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 9d9949b3faccdeab6261b30f75d2e5cf6aaf27be052df2f4e5d4b3dbaa6591f5 +F src/btree.c ddab31c38d5f16114bc68392430556b1063fe14e0020f9a56d2c35ddd58ba7e3 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f @@ -538,7 +538,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c f5ad51cfd024116db8531feab9efd831c2621436dca1464e4ff1e8af9bf3252e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 5130bd602719ad9de1436def895da73973ee74382db02036be21238d0aa2ccfd +F src/pager.c f6183fb7370425cd8642759693d9994649217cf7111caef89bc2c4946afbc36d F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/parse.y 04f61db1cdd7036c6d74baad1c342d3e3110cb0765c48fcfd3bdf4e974a1e5bb F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 092ad64faa4ae93b1e09ccd52159621d619e6817bcb4573331e9053d97f731fd -R 3f20ad9a9f1d809380bd91f8dd5db646 +P 4883776669ee2f2310ea82b0d6df4d008eebaa7cb252102539cf21a635402ebb +R 79b5483cfb0216197d9fed248f1ec5f0 U drh -Z f5dfc5249ab1cb55ce73ad103fb81155 +Z 126502bd3de79c968ac87da08f9189cd # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6addecdf0a..68bc6ecc53 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4883776669ee2f2310ea82b0d6df4d008eebaa7cb252102539cf21a635402ebb \ No newline at end of file +0407c8793700491b8519a649b9624f569b0e7e9b94d0db79d4a08139e0ecdb69 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 16dc63b7b8..fdf0ac22c9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3235,9 +3235,13 @@ static int lockBtree(BtShared *pBt){ pageSize-usableSize); return rc; } - if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ - rc = SQLITE_CORRUPT_BKPT; - goto page1_init_failed; + if( nPage>nPageFile ){ + if( sqlite3WritableSchema(pBt->db)==0 ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; + }else{ + nPage = nPageFile; + } } /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to ** be less than 480. In other words, if the page size is 512, then the diff --git a/src/pager.c b/src/pager.c index 26b8289605..97e6ddb62a 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3945,8 +3945,7 @@ static void assertTruncateConstraint(Pager *pPager){ ** then continue writing to the database. */ void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ - assert( pPager->dbSize>=nPage || CORRUPT_DB ); - testcase( pPager->dbSizedbSize>=nPage ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; From 14818366c72d612b660cf7b44da88786dd2f77bd Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 17 Jan 2022 15:23:57 +0000 Subject: [PATCH 148/148] Fix incorrect testcase() and assert() macros in json.c. They were not causing problems. The assert() was simply unreachable. The testcase() added an unreachable condition. FossilOrigin-Name: 5623497adc8af9950fd79392000a68ba6fdca43594603eadaa7e19c8fb845a7d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 46a9aead13..c6e2b868e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Never\sallow\sthe\sb-tree\slayers\sview\sof\sthe\snumber\sof\spages\sin\sthe\sdatabase\nfile\sexceed\sthe\sactual\snumber\sof\spages\sin\sthe\sdatabase\sfile,\seven\swhen\nPRAGMA\swriteable_schema=ON.\s\sThis\shelps\swith\searlier\sdetection\sof\scorruption,\nand\sprevents\sexcess\smemory\susage\sand\sCPU\scycles\sin\ssome\sintegrity_check\sops. -D 2022-01-17T14:42:38.524 +C Fix\sincorrect\stestcase()\sand\sassert()\smacros\sin\sjson.c.\s\sThey\swere\snot\scausing\nproblems.\s\sThe\sassert()\swas\ssimply\sunreachable.\s\sThe\stestcase()\sadded\san\nunreachable\scondition. +D 2022-01-17T15:23:57.622 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -512,7 +512,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743 -F src/json.c f3bbaf6a4df6f5ada5b71e01666f5cd67642c616cd8be47dbfa5b5768dfa71d4 +F src/json.c 78fdec9af3a8bfb5ae685707b2701276fec1942b8f5f26689b2701debe32bcd2 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 95db1fe62c5973f1c5d9c53f6083e21a73ece14cdd47eeca0639691332e85c4d F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960 @@ -1938,8 +1938,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4883776669ee2f2310ea82b0d6df4d008eebaa7cb252102539cf21a635402ebb -R 79b5483cfb0216197d9fed248f1ec5f0 +P 0407c8793700491b8519a649b9624f569b0e7e9b94d0db79d4a08139e0ecdb69 +R 670ac84bd1cbcf3ee71909c2b9111d9c U drh -Z 126502bd3de79c968ac87da08f9189cd +Z c2bcb8ac21e89e27e00a6871302a21a2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 68bc6ecc53..993ab344b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0407c8793700491b8519a649b9624f569b0e7e9b94d0db79d4a08139e0ecdb69 \ No newline at end of file +5623497adc8af9950fd79392000a68ba6fdca43594603eadaa7e19c8fb845a7d \ No newline at end of file diff --git a/src/json.c b/src/json.c index dbc3faaef3..3f12f03fd1 100644 --- a/src/json.c +++ b/src/json.c @@ -1884,8 +1884,8 @@ static void jsonSetFunc( }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ - testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 ); - assert( pNode->eU!=3 || pNode->eU!=5 ); + testcase( pNode->eU!=0 && pNode->eU!=1 ); + assert( pNode->eU!=3 && pNode->eU!=5 ); VVA( pNode->eU = 4 ); pNode->jnFlags |= (u8)JNODE_REPLACE; pNode->u.iReplace = i + 1;